1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/builtins/builtins_object.h" 17 18#include "ecmascript/builtins/builtins_map.h" 19#include "ecmascript/interpreter/interpreter.h" 20#include "ecmascript/js_primitive_ref.h" 21#include "ecmascript/object_fast_operator-inl.h" 22 23namespace panda::ecmascript::builtins { 24// 19.1.1.1 Object ( [ value ] ) 25JSTaggedValue BuiltinsObject::ObjectConstructor(EcmaRuntimeCallInfo *argv) 26{ 27 ASSERT(argv); 28 JSThread *thread = argv->GetThread(); 29 BUILTINS_API_TRACE(thread, Object, Constructor); 30 [[maybe_unused]] EcmaHandleScope handleScope(thread); 31 auto ecmaVm = thread->GetEcmaVM(); 32 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv(); 33 34 // 1.If NewTarget is neither undefined nor the active function, then 35 // a.Return OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%"). 36 JSHandle<JSTaggedValue> constructor = GetConstructor(argv); 37 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv); 38 if (!newTarget->IsUndefined() && !(newTarget.GetTaggedValue() == constructor.GetTaggedValue())) { 39 JSHandle<JSObject> obj = 40 ecmaVm->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget); 41 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 42 return obj.GetTaggedValue(); 43 } 44 45 // 2.If value is null, undefined or not supplied, return ObjectCreate(%ObjectPrototype%). 46 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0); 47 if (value->IsNull() || value->IsUndefined()) { 48 JSHandle<JSObject> obj = ecmaVm->GetFactory()->OrdinaryNewJSObjectCreate(env->GetObjectFunctionPrototype()); 49 return obj.GetTaggedValue(); 50 } 51 52 // 3.Return ToObject(value). 53 return JSTaggedValue::ToObject(thread, value).GetTaggedValue(); 54} 55 56JSTaggedValue BuiltinsObject::AssignTaggedValue(JSThread *thread, const JSHandle<JSTaggedValue> &source, 57 const JSHandle<JSObject> &toAssign) 58{ 59 JSHandle<JSObject> from = JSTaggedValue::ToObject(thread, source); 60 JSHandle<TaggedArray> keys = JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>::Cast(from)); 61 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 62 63 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 64 uint32_t keysLen = keys->GetLength(); 65 for (uint32_t j = 0; j < keysLen; j++) { 66 PropertyDescriptor desc(thread); 67 key.Update(keys->Get(j)); 68 bool success = JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(from), key, desc); 69 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 70 71 if (success && desc.IsEnumerable()) { 72 JSTaggedValue value = desc.GetValue().GetTaggedValue(); 73 if (value.IsUndefined() || JSHandle<JSTaggedValue>::Cast(from)->IsJSProxy()) { 74 value = ObjectFastOperator::FastGetPropertyByValue(thread, from.GetTaggedValue(), 75 key.GetTaggedValue()); 76 } 77 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 78 79 ObjectFastOperator::FastSetPropertyByValue(thread, toAssign.GetTaggedValue(), key.GetTaggedValue(), 80 value); 81 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 82 } 83 } 84 return JSTaggedValue::Undefined(); 85} 86 87// 19.1.2.1 Object.assign ( target, ...sources ) 88JSTaggedValue BuiltinsObject::Assign(EcmaRuntimeCallInfo *argv) 89{ 90 ASSERT(argv); 91 JSThread *thread = argv->GetThread(); 92 BUILTINS_API_TRACE(thread, Object, Assign); 93 [[maybe_unused]] EcmaHandleScope handleScope(thread); 94 95 uint32_t numArgs = argv->GetArgsNumber(); 96 // 1.Let to be ToObject(target). 97 JSHandle<JSTaggedValue> target = GetCallArg(argv, 0); 98 JSHandle<JSObject> toAssign = JSTaggedValue::ToObject(thread, target); 99 // 2.ReturnIfAbrupt(to). 100 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 101 102 // 3.If only one argument was passed, return to. 103 // 4.Let sources be the List of argument values starting with the second argument. 104 // 5.For each element nextSource of sources, in ascending index order 105 // a.If nextSource is undefined or null, let keys be an empty List. 106 // b.Else, 107 // i.Let from be ToObject(nextSource). 108 // ii.Let keys be from.[[OwnPropertyKeys]](). 109 // iii.ReturnIfAbrupt(keys). 110 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 111 for (uint32_t i = 1; i < numArgs; i++) { 112 JSHandle<JSTaggedValue> source = GetCallArg(argv, i); 113 if (!source->IsNull() && !source->IsUndefined()) { 114 JSHandle<JSObject> from = JSTaggedValue::ToObject(thread, source); 115 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 116 117 JSHandle<TaggedArray> keys = JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>::Cast(from)); 118 // ReturnIfAbrupt(keys) 119 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 120 121 // c.Repeat for each element nextKey of keys in List order, 122 // i.Let desc be from.[[GetOwnProperty]](nextKey). 123 // ii.ReturnIfAbrupt(desc). 124 // iii.if desc is not undefined and desc.[[Enumerable]] is true, then 125 // 1.Let propValue be Get(from, nextKey). 126 // 2.ReturnIfAbrupt(propValue). 127 // 3.Let status be Set(to, nextKey, propValue, true). 128 // 4.ReturnIfAbrupt(status). 129 uint32_t keysLen = keys->GetLength(); 130 for (uint32_t j = 0; j < keysLen; j++) { 131 PropertyDescriptor desc(thread); 132 key.Update(keys->Get(j)); 133 bool success = JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(from), key, desc); 134 // ReturnIfAbrupt(desc) 135 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 136 137 if (success && desc.IsEnumerable()) { 138 JSTaggedValue value = desc.GetValue().GetTaggedValue(); 139 if (value.IsUndefined() || JSHandle<JSTaggedValue>::Cast(from)->IsJSProxy()) { 140 value = ObjectFastOperator::FastGetPropertyByValue(thread, from.GetTaggedValue(), 141 key.GetTaggedValue()); 142 } 143 // ReturnIfAbrupt(prop_value) 144 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 145 146 ObjectFastOperator::FastSetPropertyByValue(thread, toAssign.GetTaggedValue(), key.GetTaggedValue(), 147 value); 148 // ReturnIfAbrupt(status) 149 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 150 } 151 } 152 } 153 } 154 155 // 6.Return to. 156 return toAssign.GetTaggedValue(); 157} 158 159// Runtime Semantics 160JSTaggedValue BuiltinsObject::ObjectDefineProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 161 const JSHandle<JSTaggedValue> &prop) 162{ 163 BUILTINS_API_TRACE(thread, Object, DefineProperties); 164 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 165 // 1.If Type(O) is not Object, throw a TypeError exception. 166 if (!obj->IsECMAObject()) { 167 // throw a TypeError exception 168 THROW_TYPE_ERROR_AND_RETURN(thread, "is not an object", JSTaggedValue::Exception()); 169 } 170 171 // 2.Let props be ToObject(Properties). 172 JSHandle<JSObject> props = JSTaggedValue::ToObject(thread, prop); 173 174 // 3.ReturnIfAbrupt(props). 175 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 176 177 // 4.Let keys be props.[[OwnPropertyKeys]](). 178 JSHandle<TaggedArray> handleKeys = JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>::Cast(props)); 179 180 // 5.ReturnIfAbrupt(keys). 181 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 182 183 // 6.Let descriptors be an empty List. 184 // new an empty array and append 185 uint32_t length = handleKeys->GetLength(); 186 [[maybe_unused]] JSHandle<TaggedArray> descriptors = 187 factory->NewTaggedArray(2 * length); // 2: 2 means two element list 188 189 // 7.Repeat for each element nextKey of keys in List order, 190 // a.Let propDesc be props.[[GetOwnProperty]](nextKey). 191 // b.ReturnIfAbrupt(propDesc). 192 // c.If propDesc is not undefined and propDesc.[[Enumerable]] is true, then 193 // i.Let descObj be Get( props, nextKey). 194 // ii.ReturnIfAbrupt(descObj). 195 // iii.Let desc be ToPropertyDescriptor(descObj). 196 // iv.ReturnIfAbrupt(desc). 197 // v.Append the pair (a two element List) consisting of nextKey and desc to the end of descriptors. 198 199 std::vector<PropertyDescriptor> desArr; 200 for (uint32_t i = 0; i < length; i++) { 201 PropertyDescriptor propDesc(thread); 202 JSHandle<JSTaggedValue> handleKey(thread, handleKeys->Get(i)); 203 204 bool success = JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(props), handleKey, propDesc); 205 // ReturnIfAbrupt(propDesc) 206 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 207 208 if (success && propDesc.IsEnumerable()) { 209 JSHandle<JSTaggedValue> descObj = 210 JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(props), handleKey).GetValue(); 211 // ReturnIfAbrupt(descObj) 212 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 213 214 PropertyDescriptor desc(thread); 215 JSObject::ToPropertyDescriptor(thread, descObj, desc); 216 // ReturnIfAbrupt(desc) 217 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 218 desc.SetKey(handleKey); 219 desArr.emplace_back(desc); 220 } 221 } 222 uint32_t desLength = desArr.size(); 223 for (uint32_t i = 0; i < desLength; i++) { 224 // 8.For each pair from descriptors in list order, 225 // a.Let P be the first element of pair. 226 // b.Let desc be the second element of pair. 227 // c.Let status be DefinePropertyOrThrow(O,P, desc). 228 // d.ReturnIfAbrupt(status). 229 [[maybe_unused]] bool setSuccess = 230 JSTaggedValue::DefinePropertyOrThrow(thread, obj, desArr[i].GetKey(), desArr[i]); 231 232 // ReturnIfAbrupt(status) 233 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 234 } 235 // 9.Return O. 236 return obj.GetTaggedValue(); 237} 238 239// 19.1.2.2 Object.create ( O [ , Properties ] ) 240JSTaggedValue BuiltinsObject::Create(EcmaRuntimeCallInfo *argv) 241{ 242 ASSERT(argv); 243 JSThread *thread = argv->GetThread(); 244 BUILTINS_API_TRACE(thread, Object, Create); 245 [[maybe_unused]] EcmaHandleScope handleScope(thread); 246 // 1.If Type(O) is neither Object nor Null, throw a TypeError exception. 247 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 248 if (!obj->IsECMAObject() && !obj->IsNull()) { 249 // throw a TypeError exception 250 THROW_TYPE_ERROR_AND_RETURN(thread, "Create: O is neither Object nor Null", JSTaggedValue::Exception()); 251 } 252 253 if (obj->IsJSShared()) { 254 THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(CreateObjectWithSendableProto), 255 JSTaggedValue::Exception()); 256 } 257 258 JSHandle<JSTaggedValue> properties = GetCallArg(argv, 1); 259 260 // 2.Let obj be ObjectCreate(O). 261 JSHandle<JSObject> objCreate = thread->GetEcmaVM()->GetFactory()->OrdinaryNewJSObjectCreate(obj); 262 263 // 3.If the argument Properties is present and not undefined, then 264 // a.Return ObjectDefineProperties(obj, Properties). 265 if (!properties->IsUndefined()) { 266 return ObjectDefineProperties(thread, JSHandle<JSTaggedValue>::Cast(objCreate), properties); 267 } 268 269 // 4.Return obj. 270 return objCreate.GetTaggedValue(); 271} 272 273// 19.1.2.3 Object.defineProperties ( O, Properties ) 274JSTaggedValue BuiltinsObject::DefineProperties(EcmaRuntimeCallInfo *argv) 275{ 276 ASSERT(argv); 277 JSThread *thread = argv->GetThread(); 278 BUILTINS_API_TRACE(thread, Object, DefineProperties); 279 [[maybe_unused]] EcmaHandleScope handleScope(thread); 280 // 1.Return ObjectDefineProperties(O, Properties). 281 return ObjectDefineProperties(thread, GetCallArg(argv, 0), GetCallArg(argv, 1)); 282} 283 284// 19.1.2.4 Object.defineProperty ( O, P, Attributes ) 285JSTaggedValue BuiltinsObject::DefineProperty(EcmaRuntimeCallInfo *argv) 286{ 287 ASSERT(argv); 288 JSThread *thread = argv->GetThread(); 289 BUILTINS_API_TRACE(thread, Object, DefineProperty); 290 [[maybe_unused]] EcmaHandleScope handleScope(thread); 291 292 // 1.If Type(O) is not Object, throw a TypeError exception. 293 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 294 if (!obj->IsECMAObject()) { 295 // throw a TypeError 296 THROW_TYPE_ERROR_AND_RETURN(thread, "DefineProperty: O is not Object", JSTaggedValue::Exception()); 297 } 298 299 // 2.Let key be ToPropertyKey(P). 300 JSHandle<JSTaggedValue> prop = GetCallArg(argv, 1); 301 JSHandle<JSTaggedValue> key = JSTaggedValue::ToPropertyKey(thread, prop); 302 303 // 3.ReturnIfAbrupt(key). 304 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 305 // 4.Let desc be ToPropertyDescriptor(Attributes). 306 PropertyDescriptor desc(thread); 307 JSObject::ToPropertyDescriptor(thread, GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD), desc); 308 309 // 5.ReturnIfAbrupt(desc). 310 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 311 312 // 6.Let success be DefinePropertyOrThrow(O,key, desc). 313 [[maybe_unused]] bool success = JSTaggedValue::DefinePropertyOrThrow(thread, obj, key, desc); 314 315 // 7.ReturnIfAbrupt(success). 316 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 317 // 8.Return O. 318 return obj.GetTaggedValue(); 319} 320 321// 19.1.2.5 Object.freeze ( O ) 322JSTaggedValue BuiltinsObject::Freeze(EcmaRuntimeCallInfo *argv) 323{ 324 ASSERT(argv); 325 JSThread *thread = argv->GetThread(); 326 BUILTINS_API_TRACE(thread, Object, Freeze); 327 328 // 1.If Type(O) is not Object, return O. 329 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 330 if (!obj->IsECMAObject()) { 331 return obj.GetTaggedValue(); 332 } 333 334 [[maybe_unused]] EcmaHandleScope handleScope(thread); 335 bool status = false; 336 // 2.Let status be SetIntegrityLevel( O, "frozen"). 337 if (obj->IsJSSharedObject() || obj->IsJSSharedFunction() || obj->IsJSSharedAsyncFunction()) { 338 status = JSObject::FreezeSharedObject(thread, JSHandle<JSObject>(obj)); 339 } else if (obj->IsJSSharedArray()) { 340 THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(UpdateSendableAttributes), JSTaggedValue::Exception()); 341 } else { 342 status = JSObject::SetIntegrityLevel(thread, JSHandle<JSObject>(obj), IntegrityLevel::FROZEN); 343 } 344 345 // 3.ReturnIfAbrupt(status). 346 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 347 348 // 4.If status is false, throw a TypeError exception. 349 if (!status) { 350 // throw a TypeError exception 351 THROW_TYPE_ERROR_AND_RETURN(thread, "Freeze: freeze failed", JSTaggedValue::Exception()); 352 } 353 354 // 5.Return O. 355 return obj.GetTaggedValue(); 356} 357 358// 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P ) 359JSTaggedValue BuiltinsObject::GetOwnPropertyDescriptor(EcmaRuntimeCallInfo *argv) 360{ 361 ASSERT(argv); 362 JSThread *thread = argv->GetThread(); 363 BUILTINS_API_TRACE(thread, Object, GetOwnPropertyDescriptor); 364 [[maybe_unused]] EcmaHandleScope handleScope(thread); 365 366 // 1.Let obj be ToObject(O). 367 JSHandle<JSTaggedValue> func = GetCallArg(argv, 0); 368 JSHandle<JSObject> handle = JSTaggedValue::ToObject(thread, func); 369 370 // 2.ReturnIfAbrupt(obj). 371 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 372 373 // 3.Let key be ToPropertyKey(P). 374 JSHandle<JSTaggedValue> prop = GetCallArg(argv, 1); 375 JSHandle<JSTaggedValue> key = JSTaggedValue::ToPropertyKey(thread, prop); 376 377 // 4.ReturnIfAbrupt(key). 378 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 379 380 // 5.Let desc be obj.[[GetOwnProperty]](key). 381 PropertyDescriptor desc(thread); 382 JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(handle), key, desc); 383 384 // 6.ReturnIfAbrupt(desc). 385 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 386 387 // 7.Return FromPropertyDescriptor(desc). 388 JSHandle<JSTaggedValue> res = JSObject::FromPropertyDescriptor(thread, desc); 389 return res.GetTaggedValue(); 390} 391 392JSTaggedValue BuiltinsObject::GetOwnPropertyDescriptors(EcmaRuntimeCallInfo *argv) 393{ 394 ASSERT(argv); 395 JSThread *thread = argv->GetThread(); 396 BUILTINS_API_TRACE(thread, Object, GetOwnPropertyDescriptors); 397 [[maybe_unused]] EcmaHandleScope handleScope(thread); 398 399 // 1.Let obj be ToObject(O). 400 JSHandle<JSTaggedValue> func = GetCallArg(argv, 0); 401 JSHandle<JSObject> handle = JSTaggedValue::ToObject(thread, func); 402 403 // 2.ReturnIfAbrupt(obj). 404 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 405 406 // 3. Let ownKeys be ? obj.[[OwnPropertyKeys]](). 407 JSHandle<TaggedArray> ownKeys = 408 JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>(handle)); 409 410 // 4.ReturnIfAbrupt(ownKeys). 411 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 412 413 // 5.Let descriptors be OrdinaryObjectCreate(%Object.prototype%). 414 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 415 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 416 JSHandle<JSFunction> constructor(env->GetObjectFunction()); 417 JSHandle<JSObject> descriptors = factory->NewJSObjectByConstructor(constructor); 418 419 // 6.For each element key of ownKeys, do 420 // a. Let desc be ? obj.[[GetOwnProperty]](key). 421 // b. Let descriptor be FromPropertyDescriptor(desc). 422 // c. If descriptor is not undefined, perform ! CreateDataPropertyOrThrow(descriptors, key, descriptor). 423 uint32_t length = ownKeys->GetLength(); 424 JSMutableHandle<JSTaggedValue> handleKey(thread, JSTaggedValue::Undefined()); 425 for (uint32_t i = 0; i < length; ++i) { 426 handleKey.Update(ownKeys->Get(i)); 427 PropertyDescriptor desc(thread); 428 JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(handle), handleKey, desc); 429 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 430 JSHandle<JSTaggedValue> descriptor = JSObject::FromPropertyDescriptor(thread, desc); 431 if (!descriptor->IsUndefined()) { 432 JSObject::CreateDataPropertyOrThrow(thread, descriptors, handleKey, descriptor); 433 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 434 } 435 } 436 437 // 7.Return descriptors. 438 return descriptors.GetTaggedValue(); 439} 440 441// Runtime Semantics 442JSTaggedValue BuiltinsObject::GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &object, 443 const KeyType &type) 444{ 445 BUILTINS_API_TRACE(thread, Object, GetOwnPropertyKeys); 446 // 1.Let obj be ToObject(O). 447 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 448 JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, object); 449 450 // 2.ReturnIfAbrupt(obj). 451 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 452 453 // 3.Let keys be obj.[[OwnPropertyKeys]](). 454 JSHandle<TaggedArray> handleKeys = JSTaggedValue::GetOwnPropertyKeys(thread, JSHandle<JSTaggedValue>::Cast(obj)); 455 456 // 4.ReturnIfAbrupt(keys). 457 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 458 459 // 5.Let nameList be a new empty List. 460 // new an empty array and append 461 uint32_t length = handleKeys->GetLength(); 462 JSHandle<TaggedArray> nameList = factory->NewTaggedArray(length); 463 464 // 6.Repeat for each element nextKey of keys in List order, 465 uint32_t copyLength = 0; 466 switch (type) { 467 case KeyType::STRING_TYPE: { 468 for (uint32_t i = 0; i < length; i++) { 469 JSTaggedValue key = handleKeys->Get(i); 470 if (key.IsString()) { 471 nameList->Set(thread, copyLength, key); 472 copyLength++; 473 } 474 } 475 break; 476 } 477 case KeyType::SYMBOL_TYPE: { 478 for (uint32_t i = 0; i < length; i++) { 479 JSTaggedValue key = handleKeys->Get(i); 480 if (key.IsSymbol()) { 481 nameList->Set(thread, copyLength, key); 482 copyLength++; 483 } 484 } 485 break; 486 } 487 default: 488 break; 489 } 490 491 // 7.Return CreateArrayFromList(nameList). 492 JSHandle<TaggedArray> resultList = factory->CopyArray(nameList, length, copyLength); 493 JSHandle<JSArray> resultArray = JSArray::CreateArrayFromList(thread, resultList); 494 return resultArray.GetTaggedValue(); 495} 496 497// 19.1.2.7 Object.getOwnPropertyNames ( O ) 498JSTaggedValue BuiltinsObject::GetOwnPropertyNames(EcmaRuntimeCallInfo *argv) 499{ 500 ASSERT(argv); 501 JSThread *thread = argv->GetThread(); 502 BUILTINS_API_TRACE(thread, Object, GetOwnPropertyNames); 503 [[maybe_unused]] EcmaHandleScope handleScope(thread); 504 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 505 KeyType type = KeyType::STRING_TYPE; 506 507 // 1.Return GetOwnPropertyKeys(O, String). 508 return GetOwnPropertyKeys(thread, obj, type); 509} 510 511// 19.1.2.8 Object.getOwnPropertySymbols ( O ) 512JSTaggedValue BuiltinsObject::GetOwnPropertySymbols(EcmaRuntimeCallInfo *argv) 513{ 514 ASSERT(argv); 515 JSThread *thread = argv->GetThread(); 516 BUILTINS_API_TRACE(thread, Object, GetOwnPropertySymbols); 517 [[maybe_unused]] EcmaHandleScope handleScope(thread); 518 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 519 KeyType type = KeyType::SYMBOL_TYPE; 520 521 // 1.Return GetOwnPropertyKeys(O, Symbol). 522 return GetOwnPropertyKeys(thread, obj, type); 523} 524 525// 19.1.2.9 Object.getPrototypeOf ( O ) 526JSTaggedValue BuiltinsObject::GetPrototypeOf(EcmaRuntimeCallInfo *argv) 527{ 528 ASSERT(argv); 529 JSThread *thread = argv->GetThread(); 530 BUILTINS_API_TRACE(thread, Object, GetPrototypeOf); 531 [[maybe_unused]] EcmaHandleScope handleScope(thread); 532 533 // 1.Let obj be ToObject(O). 534 JSHandle<JSTaggedValue> func = GetCallArg(argv, 0); 535 536 JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, func); 537 538 // 2.ReturnIfAbrupt(obj). 539 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 540 541 // 3.Return obj.[[GetPrototypeOf]](). 542 return JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(obj)); 543} 544 545// 19.1.2.10 Object.is ( value1, value2 ) 546JSTaggedValue BuiltinsObject::Is(EcmaRuntimeCallInfo *argv) 547{ 548 ASSERT(argv); 549 BUILTINS_API_TRACE(argv->GetThread(), Object, Is); 550 551 // 1.Return SameValue(value1, value2). 552 bool result = JSTaggedValue::SameValue(GetCallArg(argv, 0), GetCallArg(argv, 1)); 553 return GetTaggedBoolean(result); 554} 555 556// 19.1.2.11 Object.isExtensible ( O ) 557JSTaggedValue BuiltinsObject::IsExtensible(EcmaRuntimeCallInfo *argv) 558{ 559 ASSERT(argv); 560 JSThread *thread = argv->GetThread(); 561 BUILTINS_API_TRACE(thread, Object, IsExtensible); 562 // 1.If Type(O) is not Object, return false. 563 JSTaggedValue obj = GetCallArg(argv, 0).GetTaggedValue(); 564 if (!obj.IsHeapObject()) { 565 return GetTaggedBoolean(false); 566 } 567 [[maybe_unused]] EcmaHandleScope handleScope(thread); 568 // 2.Return IsExtensible(O). 569 return GetTaggedBoolean(obj.IsExtensible(thread)); 570} 571 572// 19.1.2.12 Object.isFrozen ( O ) 573JSTaggedValue BuiltinsObject::IsFrozen(EcmaRuntimeCallInfo *argv) 574{ 575 ASSERT(argv); 576 BUILTINS_API_TRACE(argv->GetThread(), Object, IsFrozen); 577 // 1.If Type(O) is not Object, return true. 578 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 579 if (!obj->IsECMAObject()) { 580 return GetTaggedBoolean(true); 581 } 582 583 JSThread *thread = argv->GetThread(); 584 [[maybe_unused]] EcmaHandleScope handleScope(thread); 585 586 // 2.Return TestIntegrityLevel(O, "frozen"). 587 bool status = JSObject::TestIntegrityLevel(thread, JSHandle<JSObject>(obj), IntegrityLevel::FROZEN); 588 return GetTaggedBoolean(status); 589} 590 591// 19.1.2.13 Object.isSealed ( O ) 592JSTaggedValue BuiltinsObject::IsSealed(EcmaRuntimeCallInfo *argv) 593{ 594 ASSERT(argv); 595 BUILTINS_API_TRACE(argv->GetThread(), Object, IsSealed); 596 // 1.If Type(O) is not Object, return true. 597 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 598 if (!obj->IsECMAObject()) { 599 return GetTaggedBoolean(true); 600 } 601 602 JSThread *thread = argv->GetThread(); 603 [[maybe_unused]] EcmaHandleScope handleScope(thread); 604 605 // 2.Return TestIntegrityLevel(O, "sealed"). 606 bool status = JSObject::TestIntegrityLevel(thread, JSHandle<JSObject>(obj), IntegrityLevel::SEALED); 607 return GetTaggedBoolean(status); 608} 609 610// 19.1.2.14 Object.keys(O) 611JSTaggedValue BuiltinsObject::Keys(EcmaRuntimeCallInfo *argv) 612{ 613 ASSERT(argv); 614 JSThread *thread = argv->GetThread(); 615 BUILTINS_API_TRACE(thread, Object, Keys); 616 [[maybe_unused]] EcmaHandleScope handleScope(thread); 617 618 // 1. Let obj be ToObject(O). 619 JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 620 621 JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, msg); 622 623 // 2. ReturnIfAbrupt(obj). 624 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 625 626 // 3. Let nameList be EnumerableOwnNames(obj). 627 JSHandle<TaggedArray> nameList = JSObject::EnumerableOwnNames(thread, obj); 628 629 // 4. ReturnIfAbrupt(nameList). 630 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 631 632 // 5. Return CreateArrayFromList(nameList). 633 JSHandle<JSArray> result = JSArray::CreateArrayFromList(thread, nameList); 634 return result.GetTaggedValue(); 635} 636 637// 20.1.2.22 Object.values(O) 638JSTaggedValue BuiltinsObject::Values(EcmaRuntimeCallInfo *argv) 639{ 640 ASSERT(argv); 641 JSThread *thread = argv->GetThread(); 642 BUILTINS_API_TRACE(thread, Object, Values); 643 [[maybe_unused]] EcmaHandleScope handleScope(thread); 644 645 // 1. Let obj be ToObject(O). 646 JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 647 JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, msg); 648 649 // 2. ReturnIfAbrupt(obj). 650 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 651 652 // 3. Let nameList be ? EnumerableOwnPropertyNames(obj, value). 653 JSHandle<TaggedArray> nameList = JSObject::EnumerableOwnPropertyNames(thread, obj, PropertyKind::VALUE); 654 655 // 4. ReturnIfAbrupt(nameList). 656 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 657 658 // 5. Return CreateArrayFromList(nameList). 659 JSHandle<JSArray> result = JSArray::CreateArrayFromList(thread, nameList); 660 return result.GetTaggedValue(); 661} 662 663// 19.1.2.15 Object.preventExtensions(O) 664JSTaggedValue BuiltinsObject::PreventExtensions(EcmaRuntimeCallInfo *argv) 665{ 666 ASSERT(argv); 667 JSThread *thread = argv->GetThread(); 668 BUILTINS_API_TRACE(thread, Object, PreventExtensions); 669 // 1. If Type(O) is not Object, return O. 670 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 671 if (!obj->IsECMAObject()) { 672 return obj.GetTaggedValue(); 673 } 674 [[maybe_unused]] EcmaHandleScope handleScope(thread); 675 // 2. Let status be O.[[PreventExtensions]](). 676 bool status = JSTaggedValue::PreventExtensions(thread, obj); 677 678 // 3. ReturnIfAbrupt(status). 679 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 680 681 // 4. If status is false, throw a TypeError exception. 682 if (!status) { 683 // throw a TypeError exception. 684 THROW_TYPE_ERROR_AND_RETURN(thread, "PreventExtensions: preventExtensions failed", 685 JSTaggedValue::Exception()); 686 } 687 688 // 5. Return O. 689 return obj.GetTaggedValue(); 690} 691// 19.1.2.16 Object.prototype 692 693// 19.1.2.17 Object.seal(O) 694JSTaggedValue BuiltinsObject::Seal(EcmaRuntimeCallInfo *argv) 695{ 696 ASSERT(argv); 697 JSThread *thread = argv->GetThread(); 698 BUILTINS_API_TRACE(thread, Object, Seal); 699 700 // 1. If Type(O) is not Object, return O. 701 JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 702 if (!msg->IsECMAObject()) { 703 return msg.GetTaggedValue(); 704 } 705 706 [[maybe_unused]] EcmaHandleScope handleScope(thread); 707 708 // 2. Let status be SetIntegrityLevel(O, "sealed"). 709 JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, msg); 710 bool status = JSObject::SetIntegrityLevel(thread, object, IntegrityLevel::SEALED); 711 712 // 3. ReturnIfAbrupt(status). 713 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 714 715 // 4. If status is false, throw a TypeError exception. 716 if (!status) { 717 // throw a TypeError exception. 718 THROW_TYPE_ERROR_AND_RETURN(thread, "Seal: seal failed", JSTaggedValue::Exception()); 719 } 720 721 // 5. Return O. 722 return object.GetTaggedValue(); 723} 724 725// 19.1.2.18 Object.setPrototypeOf(O, proto) 726JSTaggedValue BuiltinsObject::SetPrototypeOf(EcmaRuntimeCallInfo *argv) 727{ 728 ASSERT(argv); 729 JSThread *thread = argv->GetThread(); 730 BUILTINS_API_TRACE(thread, Object, SetPrototypeOf); 731 [[maybe_unused]] EcmaHandleScope handleScope(thread); 732 // 1. Let O be RequireObjectCoercible(O). 733 JSHandle<JSTaggedValue> object = JSTaggedValue::RequireObjectCoercible(thread, GetCallArg(argv, 0)); 734 735 // 2. ReturnIfAbrupt(O). 736 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 737 738 // 3. If Type(proto) is neither Object nor Null, throw a TypeError exception. 739 JSHandle<JSTaggedValue> proto = GetCallArg(argv, 1); 740 if (!proto->IsNull() && !proto->IsECMAObject()) { 741 // throw a TypeError exception. 742 THROW_TYPE_ERROR_AND_RETURN(thread, "SetPrototypeOf: proto is neither Object nor Null", 743 JSTaggedValue::Exception()); 744 } 745 746 // 4. If Type(O) is not Object, return O. 747 if (!object->IsECMAObject()) { 748 return object.GetTaggedValue(); 749 } 750 751 // 5. Let status be O.[[SetPrototypeOf]](proto). 752 bool status = JSTaggedValue::SetPrototype(thread, object, proto); 753 754 // 6. ReturnIfAbrupt(status). 755 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 756 757 // 7. If status is false, throw a TypeError exception. 758 if (!status) { 759 // throw a TypeError exception. 760 THROW_TYPE_ERROR_AND_RETURN(thread, "SetPrototypeOf: prototype set failed", JSTaggedValue::Exception()); 761 } 762 763 // 8. Return O. 764 return object.GetTaggedValue(); 765} 766 767// 19.1.3.1 Object.prototype.constructor 768 769// 19.1.3.2 Object.prototype.hasOwnProperty(V) 770JSTaggedValue BuiltinsObject::HasOwnProperty(EcmaRuntimeCallInfo *argv) 771{ 772 ASSERT(argv); 773 JSThread *thread = argv->GetThread(); 774 BUILTINS_API_TRACE(thread, Object, HasOwnProperty); 775 [[maybe_unused]] EcmaHandleScope handleScope(thread); 776 JSHandle<JSTaggedValue> thisValue = GetThis(argv); 777 JSHandle<JSTaggedValue> prop = GetCallArg(argv, 0); 778 return HasOwnPropertyInternal(thread, thisValue, prop); 779} 780 781JSTaggedValue BuiltinsObject::HasOwnPropertyInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue, 782 JSHandle<JSTaggedValue> prop) 783{ 784 [[maybe_unused]] EcmaHandleScope handleScope(thread); 785 std::pair<JSTaggedValue, bool> result = ObjectFastOperator::HasOwnProperty(thread, thisValue.GetTaggedValue(), 786 prop.GetTaggedValue()); 787 if (!result.first.IsHole()) { 788 return GetTaggedBoolean(true); 789 } else if (result.second) { 790 return GetTaggedBoolean(false); 791 } 792 793 // 1. Let P be ToPropertyKey(V). 794 JSHandle<JSTaggedValue> property = JSTaggedValue::ToPropertyKey(thread, prop); 795 796 // 2. ReturnIfAbrupt(P). 797 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 798 799 // 3. Let O be ToObject(this value). 800 JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, thisValue); 801 802 // 4. ReturnIfAbrupt(O). 803 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 804 805 // 5. Return HasOwnProperty(O, P). 806 bool res = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(object), property); 807 return GetTaggedBoolean(res); 808} 809 810// 19.1.3.3 Object.prototype.isPrototypeOf(V) 811JSTaggedValue BuiltinsObject::IsPrototypeOf(EcmaRuntimeCallInfo *argv) 812{ 813 ASSERT(argv); 814 JSThread *thread = argv->GetThread(); 815 BUILTINS_API_TRACE(thread, Object, IsPrototypeOf); 816 // 1. If Type(V) is not Object, return false. 817 JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 818 if (!msg->IsECMAObject()) { 819 return GetTaggedBoolean(false); 820 } 821 [[maybe_unused]] EcmaHandleScope handleScope(thread); 822 // 2. Let O be ToObject(this value). 823 JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, GetThis(argv)); 824 // 3. ReturnIfAbrupt(O). 825 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 826 827 // 4. Repeat 828 // a. Let V be V.[[GetPrototypeOf]](). 829 // b. If V is null, return false 830 // c. If SameValue(O, V) is true, return true. 831 JSMutableHandle<JSTaggedValue> msgValueHandle(thread, msg.GetTaggedValue()); 832 while (!msgValueHandle->IsNull()) { 833 msgValueHandle.Update(JSTaggedValue::GetPrototype(thread, msgValueHandle)); 834 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 835 836 if (JSTaggedValue::SameValue(object.GetTaggedValue(), msgValueHandle.GetTaggedValue())) { 837 return GetTaggedBoolean(true); 838 } 839 } 840 return GetTaggedBoolean(false); 841} 842 843// 19.1.3.4 Object.prototype.propertyIsEnumerable(V) 844JSTaggedValue BuiltinsObject::PropertyIsEnumerable(EcmaRuntimeCallInfo *argv) 845{ 846 ASSERT(argv); 847 // 1. Let P be ToPropertyKey(V). 848 JSThread *thread = argv->GetThread(); 849 BUILTINS_API_TRACE(thread, Object, PropertyIsEnumerable); 850 [[maybe_unused]] EcmaHandleScope handleScope(thread); 851 JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 852 JSHandle<JSTaggedValue> property = JSTaggedValue::ToPropertyKey(thread, msg); 853 854 // 2. ReturnIfAbrupt(P). 855 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 856 857 // 3. Let O be ToObject(this value). 858 JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, GetThis(argv)); 859 // 4. ReturnIfAbrupt(O). 860 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 861 862 // 5. Let desc be O.[[GetOwnProperty]](P). 863 PropertyDescriptor desc(thread); 864 JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(object), property, desc); 865 866 // 6. ReturnIfAbrupt(desc). 867 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 868 869 // 7. If desc is undefined, return false. 870 if (desc.IsEmpty()) { 871 return GetTaggedBoolean(false); 872 } 873 874 // 8. Return the value of desc.[[Enumerable]]. 875 return GetTaggedBoolean(desc.IsEnumerable()); 876} 877 878// 19.1.3.5 Object.prototype.toLocaleString([reserved1[, reserved2]]) 879JSTaggedValue BuiltinsObject::ToLocaleString(EcmaRuntimeCallInfo *argv) 880{ 881 ASSERT(argv); 882 JSThread *thread = argv->GetThread(); 883 BUILTINS_API_TRACE(thread, Object, ToLocaleString); 884 [[maybe_unused]] EcmaHandleScope handleScope(thread); 885 // 1. Let O be the this value. 886 JSHandle<JSTaggedValue> object = GetThis(argv); 887 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 888 889 // 2. Return Invoke(O, "toString"). 890 JSHandle<JSTaggedValue> calleeKey = thread->GlobalConstants()->GetHandledToStringString(); 891 const uint32_t argsLength = argv->GetArgsNumber(); 892 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 893 EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, object, undefined, argsLength); 894 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 895 info->SetCallArg(argsLength, 0, argv, 0); 896 return JSFunction::Invoke(info, calleeKey); 897} 898 899JSTaggedValue BuiltinsObject::GetBuiltinObjectToString(JSThread *thread, const JSHandle<JSObject> &object) 900{ 901 BUILTINS_API_TRACE(thread, Object, GetBuiltinObjectToString); 902 // 4. Let isArray be IsArray(O). 903 bool isArray = object.GetTaggedValue().IsArray(thread); 904 // 5. ReturnIfAbrupt(isArray). 905 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 906 907 if (isArray) { 908 // 6. If isArray is true, return "[object Array]". 909 return thread->GlobalConstants()->GetArrayToString(); 910 } else if (object->IsJSPrimitiveRef()) { 911 // 7. Else, if O is an exotic String object, return "[object String]". 912 JSPrimitiveRef *primitiveRef = JSPrimitiveRef::Cast(*object); 913 if (primitiveRef->IsString()) { 914 return thread->GlobalConstants()->GetStringToString(); 915 } else if (primitiveRef->IsBoolean()) { 916 // 11. Else, if O has a [[BooleanData]] internal slot, return "[object Boolean]". 917 return thread->GlobalConstants()->GetBooleanToString(); 918 } else if (primitiveRef->IsNumber()) { 919 // 12. Else, if O has a [[NumberData]] internal slot, return "[object Number]". 920 return thread->GlobalConstants()->GetNumberToString(); 921 } 922 } else if (object->IsArguments()) { 923 // if O has a [[ArgumentsData]] internal slot, return "[object Arguments]". 924 return thread->GlobalConstants()->GetArgumentsToString(); 925 } else if (object->IsCallable()) { 926 // if O has a [[CallableData]] internal slot, return "[object Function]". 927 return thread->GlobalConstants()->GetFunctionToString(); 928 } else if (object->IsJSError()) { 929 // if O has a [[ErrorData]] internal slot, return "[object Error]". 930 return thread->GlobalConstants()->GetErrorToString(); 931 } else if (object->IsDate()) { 932 // if O has a [[DateData]] internal slot, return "[object Date]". 933 return thread->GlobalConstants()->GetDateToString(); 934 } else if (object->IsJSRegExp()) { 935 // if O has a [[RegExpData]] internal slot, return "[object JSRegExp]". 936 return thread->GlobalConstants()->GetRegExpToString(); 937 } 938 // 15. Else, return "[Object Object]". 939 return thread->GlobalConstants()->GetObjectToString(); 940} 941 942// 19.1.3.6 Object.prototype.toString() 943JSTaggedValue BuiltinsObject::ToString(EcmaRuntimeCallInfo *argv) 944{ 945 ASSERT(argv); 946 JSThread *thread = argv->GetThread(); 947 BUILTINS_API_TRACE(thread, Object, ToString); 948 [[maybe_unused]] EcmaHandleScope handleScope(thread); 949 // 1. If the this value is undefined, return "[object Undefined]". 950 951 JSHandle<JSTaggedValue> msg = GetThis(argv); 952 if (msg->IsUndefined()) { 953 return thread->GlobalConstants()->GetUndefinedToString(); 954 } 955 // 2. If the this value is null, return "[object Null]". 956 if (msg->IsNull()) { 957 return thread->GlobalConstants()->GetNullToString(); 958 } 959 960 // 3. Let O be ToObject(this value). 961 JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, GetThis(argv)); 962 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 963 964 // 16. Let tag be Get (O, @@toStringTag). 965 auto ecmaVm = thread->GetEcmaVM(); 966 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv(); 967 auto factory = ecmaVm->GetFactory(); 968 969 JSHandle<JSTaggedValue> tag = JSTaggedValue::GetProperty(thread, msg, env->GetToStringTagSymbol()).GetValue(); 970 971 // 17. ReturnIfAbrupt(tag). 972 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 973 974 // 18. If Type(tag) is not String, return builtin object to string. 975 if (!tag->IsString()) { 976 return GetBuiltinObjectToString(thread, object); 977 } 978 979 // 19. Return the String that is the result of concatenating "[object ", tag, and "]". 980 JSHandle<EcmaString> leftString(factory->NewFromASCII("[object ")); 981 JSHandle<EcmaString> rightString(factory->NewFromASCII("]")); 982 983 JSHandle<EcmaString> newLeftStringHandle = 984 factory->ConcatFromString(leftString, JSTaggedValue::ToString(thread, tag)); 985 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 986 auto result = factory->ConcatFromString(newLeftStringHandle, rightString); 987 return result.GetTaggedValue(); 988} 989 990// 19.1.3.7 Object.prototype.valueOf() 991JSTaggedValue BuiltinsObject::ValueOf(EcmaRuntimeCallInfo *argv) 992{ 993 ASSERT(argv); 994 JSThread *thread = argv->GetThread(); 995 BUILTINS_API_TRACE(thread, Object, ValueOf); 996 [[maybe_unused]] EcmaHandleScope handleScope(thread); 997 998 // 1. Return ToObject(this value). 999 JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, GetThis(argv)); 1000 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1001 return object.GetTaggedValue(); 1002} 1003// B.2.2.1 Object.prototype.__proto__ 1004JSTaggedValue BuiltinsObject::ProtoGetter(EcmaRuntimeCallInfo *argv) 1005{ 1006 ASSERT(argv); 1007 JSThread *thread = argv->GetThread(); 1008 BUILTINS_API_TRACE(thread, Object, ProtoGetter); 1009 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1010 1011 // 1.Let obj be ToObject(this value). 1012 JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, GetThis(argv)); 1013 1014 // 2.ReturnIfAbrupt(obj). 1015 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1016 1017 // 3.Return obj.[[GetPrototypeOf]](). 1018 return JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(obj)); 1019} 1020 1021JSTaggedValue BuiltinsObject::ProtoSetter(EcmaRuntimeCallInfo *argv) 1022{ 1023 ASSERT(argv); 1024 JSThread *thread = argv->GetThread(); 1025 BUILTINS_API_TRACE(thread, Object, ProtoSetter); 1026 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1027 // 1. Let O be RequireObjectCoercible(this value). 1028 JSHandle<JSTaggedValue> obj = JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv)); 1029 1030 // 2. ReturnIfAbrupt(O). 1031 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1032 1033 // 3. If Type(proto) is neither Object nor Null, return undefined.. 1034 JSHandle<JSTaggedValue> proto = GetCallArg(argv, 0); 1035 if (!proto->IsNull() && !proto->IsECMAObject()) { 1036 return JSTaggedValue::Undefined(); 1037 } 1038 1039 // 4. If Type(O) is not Object, return undefined. 1040 if (!obj->IsECMAObject()) { 1041 return JSTaggedValue::Undefined(); 1042 } 1043 1044 // 5. Let status be O.[[SetPrototypeOf]](proto). 1045 bool status = JSTaggedValue::SetPrototype(thread, obj, proto, true); 1046 1047 // 6. ReturnIfAbrupt(status). 1048 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1049 1050 // 7. If status is false, throw a TypeError exception. 1051 if (!status) { 1052 // throw a TypeError exception. 1053 THROW_TYPE_ERROR_AND_RETURN(thread, "ProtoSetter: proto set failed", JSTaggedValue::Exception()); 1054 } 1055 1056 // 8. Return O. 1057 return JSTaggedValue::Undefined(); 1058} 1059 1060JSTaggedValue BuiltinsObject::CreateRealm(EcmaRuntimeCallInfo *argv) 1061{ 1062 ASSERT(argv); 1063 JSThread *thread = argv->GetThread(); 1064 BUILTINS_API_TRACE(thread, Object, CreateRealm); 1065 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1066 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 1067 JSHandle<JSRealm> realm = factory->NewJSRealm(); 1068 return realm.GetTaggedValue(); 1069} 1070 1071JSTaggedValue BuiltinsObject::Entries(EcmaRuntimeCallInfo *argv) 1072{ 1073 ASSERT(argv); 1074 JSThread *thread = argv->GetThread(); 1075 BUILTINS_API_TRACE(thread, Object, ToString); 1076 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1077 1078 // 1. Let obj be ? ToObject(O). 1079 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 1080 if (obj->IsJSUint8Array() || obj->IsJSUint16Array()) { 1081 THROW_RANGE_ERROR_AND_RETURN(thread, "Object entries is not supported IsJSUint8Array or IsJSUint16Array", 1082 JSTaggedValue::Exception()); 1083 } 1084 JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, obj); 1085 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1086 // 2. Let nameList be ? EnumerableOwnPropertyNames(obj, key+value). 1087 JSHandle<TaggedArray> nameList = JSObject::EnumerableOwnPropertyNames(thread, object, PropertyKind::KEY_VALUE); 1088 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1089 // 3. Return CreateArrayFromList(nameList). 1090 return JSArray::CreateArrayFromList(thread, nameList).GetTaggedValue(); 1091} 1092 1093JSTaggedValue BuiltinsObject::FromEntries(EcmaRuntimeCallInfo *argv) 1094{ 1095 ASSERT(argv); 1096 JSThread *thread = argv->GetThread(); 1097 BUILTINS_API_TRACE(thread, Object, FromEntries); 1098 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1099 1100 JSHandle<JSTaggedValue> iterable = GetCallArg(argv, 0); 1101 // 1. Perform ? RequireObjectCoercible(iterable). 1102 if (iterable->IsUndefined() || iterable->IsNull()) { 1103 THROW_TYPE_ERROR_AND_RETURN(thread, "iterable is undefined or null", JSTaggedValue::Exception()); 1104 } 1105 1106 // 2. Let obj be ! OrdinaryObjectCreate(%Object.prototype%). 1107 // 3. Assert: obj is an extensible ordinary object with no own properties. 1108 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 1109 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 1110 JSHandle<JSFunction> constructor(env->GetObjectFunction()); 1111 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(constructor); 1112 1113 // 4. Let stepsDefine be the algorithm steps defined in CreateDataPropertyOnObject Functions. 1114 // 5. Let lengthDefine be the number of non-optional parameters of the function definition in 1115 // CreateDataPropertyOnObject Functions. 1116 // 6. Let adder be ! CreateBuiltinFunction(stepsDefine, lengthDefine, "", « »). 1117 JSHandle<Method> method(thread, 1118 thread->GetEcmaVM()->GetMethodByIndex(MethodIndex::BUILTINS_OBJECT_CREATE_DATA_PROPERTY_ON_OBJECT_FUNCTIONS)); 1119 JSHandle<JSFunction> addrFunc = factory->NewJSFunction(env, method); 1120 1121 JSHandle<JSTaggedValue> adder(thread, addrFunc.GetTaggedValue()); 1122 1123 // 7. Return ? AddEntriesFromIterable(obj, iterable, adder). 1124 return BuiltinsMap::AddEntriesFromIterable(thread, obj, iterable, adder, factory); 1125} 1126 1127JSTaggedValue BuiltinsObject::CreateDataPropertyOnObjectFunctions(EcmaRuntimeCallInfo *argv) 1128{ 1129 ASSERT(argv); 1130 JSThread *thread = argv->GetThread(); 1131 BUILTINS_API_TRACE(thread, Object, CreateDataPropertyOnObjectFunctions); 1132 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1133 1134 // 1. Let O be the this value. 1135 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1136 JSHandle<JSObject> thisObjHandle = JSHandle<JSObject>::Cast(thisHandle); 1137 1138 // 2. Assert: Type(O) is Object. 1139 // 3. Assert: O is an extensible ordinary object. 1140 ASSERT(thisHandle->IsHeapObject()); 1141 1142 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0); 1143 JSHandle<JSTaggedValue> value = GetCallArg(argv, 1); 1144 1145 // 4. Let propertyKey be ? ToPropertyKey(key). 1146 JSHandle<JSTaggedValue> propertyKey = JSTaggedValue::ToPropertyKey(thread, key); 1147 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1148 1149 // 5. Perform ! CreateDataPropertyOrThrow(O, propertyKey, value). 1150 JSObject::CreateDataPropertyOrThrow(thread, thisObjHandle, propertyKey, value); 1151 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1152 1153 // 6. Return undefined. 1154 return JSTaggedValue::Undefined(); 1155} 1156 1157JSTaggedValue BuiltinsObject::HasOwn(EcmaRuntimeCallInfo *argv) 1158{ 1159 ASSERT(argv); 1160 JSThread *thread = argv->GetThread(); 1161 BUILTINS_API_TRACE(thread, Object, HasOwn); 1162 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1163 1164 // 1. Let obj be ? ToObject(O). 1165 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0); 1166 JSHandle<JSObject> object = JSTaggedValue::ToObject(thread, obj); 1167 1168 // 2.ReturnIfAbrupt(obj). 1169 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1170 1171 // 3.Let key be ToPropertyKey(P). 1172 JSHandle<JSTaggedValue> prop = GetCallArg(argv, 1); 1173 JSHandle<JSTaggedValue> key = JSTaggedValue::ToPropertyKey(thread, prop); 1174 1175 // 4. ReturnIfAbrupt(4). 1176 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1177 1178 // 5. Return HasOwnProperty(O, P). 1179 bool res = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(object), key); 1180 return GetTaggedBoolean(res); 1181} 1182} // namespace panda::ecmascript::builtins 1183