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 #ifndef ECMASCRIPT_JSOBJECT_H 17 #define ECMASCRIPT_JSOBJECT_H 18 19 #include <vector> 20 21 #include "ecmascript/ecma_macros.h" 22 #include "ecmascript/ecma_runtime_call_info.h" 23 #include "ecmascript/ecma_string.h" 24 #include "ecmascript/ic/property_box.h" 25 #include "ecmascript/js_handle.h" 26 #include "ecmascript/js_hclass.h" 27 #include "ecmascript/js_native_pointer.h" 28 #include "ecmascript/js_tagged_value.h" 29 #include "ecmascript/mem/object_xray.h" 30 #include "ecmascript/mem/slots.h" 31 #include "ecmascript/object_operator.h" 32 #include "ecmascript/property_attributes.h" 33 #include "ecmascript/runtime_trampolines.h" 34 #include "ecmascript/tagged_array.h" 35 36 namespace panda { 37 namespace ecmascript { 38 class ObjectOperator; 39 40 class JSFunction; 41 class AccessorData; 42 class JSArray; 43 44 class JSForInIterator; 45 46 class LexicalEnv; 47 48 // Integrity level for objects 49 enum IntegrityLevel { SEALED, FROZEN }; 50 51 enum PositionKind { UNKNOWN = 0, INDEXED_PROPERTY = 1, INLINE_NAMED_PROPERTY = 2, OUT_NAMED_PROPERTY = 3 }; 52 enum PropertyKind { KEY = 0, VALUE, KEY_VALUE }; 53 54 // ecma6.0 6.2.4 The Property Descriptor Specification Type 55 class PropertyDescriptor final { 56 public: 57 explicit PropertyDescriptor() = delete; 58 59 ~PropertyDescriptor() = default; 60 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyDescriptor); 61 DEFAULT_COPY_SEMANTIC(PropertyDescriptor); 62 PropertyDescriptor(const JSThread * thread)63 explicit PropertyDescriptor(const JSThread *thread) : thread_(thread) {} 64 PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v)65 explicit PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v) : thread_(thread), value_(v) {} 66 PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v,bool w,bool e,bool c)67 explicit PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v, bool w, bool e, bool c) 68 : thread_(thread), 69 writable_(w), 70 enumerable_(e), 71 configurable_(c), 72 hasWritable_(true), 73 hasEnumerable_(true), 74 hasConfigurable_(true), 75 value_(v) 76 { 77 } 78 PropertyDescriptor(const JSThread * thread,bool w,bool e,bool c)79 explicit PropertyDescriptor(const JSThread *thread, bool w, bool e, bool c) 80 : PropertyDescriptor(thread, JSHandle<JSTaggedValue>(), w, e, c) 81 { 82 } 83 GetValue()84 inline JSHandle<JSTaggedValue> GetValue() const 85 { 86 if (value_.IsEmpty()) { 87 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 88 } 89 return value_; 90 } 91 SetValue(JSHandle<JSTaggedValue> value)92 inline void SetValue(JSHandle<JSTaggedValue> value) 93 { 94 value_ = value; 95 } 96 IsWritable()97 inline bool IsWritable() const 98 { 99 return writable_; 100 } 101 SetWritable(bool flag)102 inline void SetWritable(bool flag) 103 { 104 writable_ = flag; 105 hasWritable_ = true; 106 } 107 IsEnumerable()108 inline bool IsEnumerable() const 109 { 110 return enumerable_; 111 } 112 SetEnumerable(bool flag)113 inline void SetEnumerable(bool flag) 114 { 115 enumerable_ = flag; 116 hasEnumerable_ = true; 117 } 118 IsConfigurable()119 inline bool IsConfigurable() const 120 { 121 return configurable_; 122 } 123 SetConfigurable(bool flag)124 inline void SetConfigurable(bool flag) 125 { 126 configurable_ = flag; 127 hasConfigurable_ = true; 128 } 129 HasValue()130 inline bool HasValue() const 131 { 132 return !value_.IsEmpty(); 133 } 134 HasWritable()135 inline bool HasWritable() const 136 { 137 return hasWritable_; 138 } 139 HasConfigurable()140 inline bool HasConfigurable() const 141 { 142 return hasConfigurable_; 143 } 144 HasEnumerable()145 inline bool HasEnumerable() const 146 { 147 return hasEnumerable_; 148 } 149 HasGetter()150 inline bool HasGetter() const 151 { 152 return !getter_.IsEmpty(); 153 } 154 HasSetter()155 inline bool HasSetter() const 156 { 157 return !setter_.IsEmpty(); 158 } 159 GetGetter()160 inline JSHandle<JSTaggedValue> GetGetter() const 161 { 162 if (getter_->IsNull()) { 163 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 164 } 165 return getter_; 166 } 167 GetSetter()168 inline JSHandle<JSTaggedValue> GetSetter() const 169 { 170 if (setter_->IsNull()) { 171 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 172 } 173 return setter_; 174 } 175 SetGetter(JSHandle<JSTaggedValue> value)176 inline void SetGetter(JSHandle<JSTaggedValue> value) 177 { 178 getter_ = value; 179 } 180 SetSetter(JSHandle<JSTaggedValue> value)181 inline void SetSetter(JSHandle<JSTaggedValue> value) 182 { 183 setter_ = value; 184 } 185 186 // 6.2.4.1 IsAccessorDescriptor()187 inline bool IsAccessorDescriptor() const 188 { 189 // 2. If both Desc.[[Get]] and Desc.[[Set]] are absent, return false. 190 return !(getter_.IsEmpty() && setter_.IsEmpty()); 191 } 192 IsDataDescriptor()193 inline bool IsDataDescriptor() const 194 { 195 // 2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, return false. 196 return !(value_.IsEmpty() && !hasWritable_); 197 } 198 IsGenericDescriptor()199 inline bool IsGenericDescriptor() const 200 { 201 // 2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both false, return true 202 return !IsAccessorDescriptor() && !IsDataDescriptor(); 203 } 204 IsEmpty()205 inline bool IsEmpty() const 206 { 207 return !hasWritable_ && !hasEnumerable_ && !hasConfigurable_ && !HasValue() && !HasGetter() && !HasSetter(); 208 } 209 210 static void CompletePropertyDescriptor(const JSThread *thread, PropertyDescriptor &desc); 211 212 private: 213 const JSThread *thread_{nullptr}; 214 215 bool writable_ {false}; 216 bool enumerable_ {false}; 217 bool configurable_ {false}; 218 bool hasWritable_ {false}; 219 bool hasEnumerable_ {false}; 220 bool hasConfigurable_ {false}; 221 222 JSHandle<JSTaggedValue> value_ {}; 223 JSHandle<JSTaggedValue> getter_ {}; 224 JSHandle<JSTaggedValue> setter_ {}; 225 }; 226 227 enum class ElementTypes { ALLTYPES, STRING_AND_SYMBOL }; 228 229 class PropertyMetaData { 230 public: 231 using IsFoundField = BitField<bool, 0, 1>; 232 using IsInlinedPropsField = IsFoundField::NextFlag; 233 using RepresentationField = IsInlinedPropsField::NextField<Representation, 3>; 234 using OffsetField = RepresentationField::NextField<uint32_t, PropertyAttributes::OFFSET_BITFIELD_NUM>; 235 PropertyMetaData(uint32_t metaData)236 explicit PropertyMetaData(uint32_t metaData) : metaData_(metaData) {} 237 238 ~PropertyMetaData() = default; 239 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyMetaData); 240 DEFAULT_COPY_SEMANTIC(PropertyMetaData); 241 PropertyMetaData(bool isFound)242 explicit PropertyMetaData(bool isFound) 243 { 244 SetFound(isFound); 245 } 246 IsFound()247 inline bool IsFound() const 248 { 249 return IsFoundField::Get(metaData_); 250 } 251 SetFound(bool flag)252 inline void SetFound(bool flag) 253 { 254 IsFoundField::Set(flag, &metaData_); 255 } 256 GetIsInlinedProps()257 inline bool GetIsInlinedProps() const 258 { 259 return IsInlinedPropsField::Get(metaData_); 260 } 261 SetIsInlinedProps(bool flag)262 inline void SetIsInlinedProps(bool flag) 263 { 264 IsInlinedPropsField::Set(flag, &metaData_); 265 } 266 GetRepresentation()267 inline Representation GetRepresentation() const 268 { 269 return RepresentationField::Get(metaData_); 270 } 271 SetRepresentation(Representation representation)272 inline void SetRepresentation(Representation representation) 273 { 274 RepresentationField::Set<uint32_t>(representation, &metaData_); 275 } 276 SetOffset(uint32_t offset)277 inline void SetOffset(uint32_t offset) 278 { 279 OffsetField::Set<uint32_t>(offset, &metaData_); 280 } 281 GetOffset()282 inline uint32_t GetOffset() const 283 { 284 return OffsetField::Get(metaData_); 285 } 286 287 private: 288 uint32_t metaData_{0}; 289 }; 290 291 class OperationResult { 292 public: OperationResult(const JSThread * thread,JSTaggedValue value,PropertyMetaData metaData)293 explicit OperationResult(const JSThread *thread, JSTaggedValue value, PropertyMetaData metaData) 294 : metaData_(metaData) 295 { 296 thread_ = thread; 297 value_ = JSHandle<JSTaggedValue>(thread_, value); 298 } 299 300 ~OperationResult() = default; 301 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(OperationResult); 302 DEFAULT_COPY_SEMANTIC(OperationResult); 303 GetValue()304 JSHandle<JSTaggedValue> GetValue() const 305 { 306 if (value_->IsPropertyBox()) { 307 return JSHandle<JSTaggedValue>(thread_, 308 PropertyBox::Cast(value_.GetTaggedValue().GetTaggedObject())->GetValue()); 309 } 310 return value_; 311 } 312 GetRawValue()313 JSHandle<JSTaggedValue> GetRawValue() const 314 { 315 return value_; 316 } 317 GetPropertyMetaData()318 const PropertyMetaData &GetPropertyMetaData() const 319 { 320 return metaData_; 321 } 322 323 private: 324 const JSThread *thread_ {nullptr}; 325 JSHandle<JSTaggedValue> value_ {}; 326 PropertyMetaData metaData_{0U}; 327 }; 328 329 class ECMAObject : public TaggedObject { 330 public: 331 CAST_CHECK(ECMAObject, IsECMAObject); 332 333 void SetBuiltinsCtorMode(); 334 bool IsBuiltinsConstructor() const; 335 void SetCallable(bool flag); 336 bool IsCallable() const; 337 JSMethod *GetCallTarget() const; 338 339 static constexpr size_t HASH_OFFSET = TaggedObjectSize(); 340 static constexpr size_t SIZE = HASH_OFFSET + sizeof(JSTaggedType); 341 342 void SetHash(int32_t hash); 343 int32_t GetHash() const; InitializeHash()344 void InitializeHash() 345 { 346 Barriers::SetDynPrimitive<JSTaggedType>(this, ECMAObject::HASH_OFFSET, JSTaggedValue(0).GetRawData()); 347 } 348 349 void* GetNativePointerField(int32_t index) const; 350 void SetNativePointerField(int32_t index, void *nativePointer, 351 const DeleteEntryPoint &callBack, void *data); 352 int32_t GetNativePointerFieldCount() const; 353 void SetNativePointerFieldCount(int32_t count); 354 355 DECL_VISIT_OBJECT(HASH_OFFSET, SIZE); 356 VisitObjects(const EcmaObjectRangeVisitor & visitor)357 void VisitObjects(const EcmaObjectRangeVisitor &visitor) 358 { 359 // no field in this object 360 VisitRangeSlot(visitor); 361 } 362 }; 363 364 class JSObject : public ECMAObject { 365 public: 366 static constexpr int MIN_ELEMENTS_LENGTH = 3; 367 static constexpr int MIN_PROPERTIES_LENGTH = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS; 368 static constexpr int PROPERTIES_GROW_SIZE = 4; 369 static constexpr int FAST_ELEMENTS_FACTOR = 3; 370 static constexpr int MIN_GAP = 256; 371 static constexpr int MAX_GAP = 1024; 372 static constexpr uint32_t MAX_ELEMENT_INDEX = std::numeric_limits<uint32_t>::max(); 373 374 CAST_CHECK(JSObject, IsECMAObject); 375 CAST_CHECK_TAGGEDVALUE(JSObject, IsECMAObject); 376 377 // ecma6.0 6.2.4.4 378 static JSHandle<JSTaggedValue> FromPropertyDescriptor(JSThread *thread, const PropertyDescriptor &desc); 379 380 // ecma6.0 6.2.4.5 ToPropertyDescriptor ( Obj ) 381 static void ToPropertyDescriptor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, PropertyDescriptor &desc); 382 static bool ToPropertyDescriptorFast(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 383 PropertyDescriptor &desc); 384 385 // ecma6 7.3 Operations on Objects 386 static JSHandle<JSTaggedValue> GetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 387 const JSHandle<JSTaggedValue> &key); 388 389 static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 390 const JSHandle<JSTaggedValue> &value); 391 392 static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 393 const JSHandle<JSTaggedValue> &value); 394 395 static bool CreateMethodProperty(JSThread *thread, const JSHandle<JSObject> &obj, 396 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 397 398 static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, 399 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 400 401 static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 402 const JSHandle<JSTaggedValue> &value); 403 404 static JSHandle<TaggedArray> EnumerableOwnNames(JSThread *thread, const JSHandle<JSObject> &obj); 405 406 // 7.3.23 EnumerableOwnPropertyNames ( O, kind ) 407 static JSHandle<TaggedArray> EnumerableOwnPropertyNames(JSThread *thread, const JSHandle<JSObject> &obj, 408 PropertyKind kind); 409 410 static JSHandle<GlobalEnv> GetFunctionRealm(JSThread *thread, const JSHandle<JSTaggedValue> &object); 411 412 static bool SetIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level); 413 414 static bool TestIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level); 415 416 static JSHandle<JSTaggedValue> SpeciesConstructor(JSThread *thread, const JSHandle<JSObject> &obj, 417 const JSHandle<JSTaggedValue> &defaultConstructort); 418 // 7.3.17 419 template<ElementTypes types = ElementTypes::ALLTYPES> 420 static JSHandle<JSTaggedValue> CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj); 421 422 // emca6 9.1 423 // [[GetPrototypeOf]] 424 JSTaggedValue GetPrototype(JSThread *thread) const; 425 426 // [[SetPrototypeOf]] 427 static bool SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &proto); 428 429 // [[IsExtensible]] 430 bool IsExtensible() const; 431 432 // [[PreventExtensions]] 433 static bool PreventExtensions(JSThread *thread, const JSHandle<JSObject> &obj); 434 435 // [[GetOwnProperty]] -> Undefined | Property Descriptor 436 static bool GetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 437 PropertyDescriptor &desc); 438 439 static bool GlobalGetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc); 440 441 static bool OrdinaryGetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, 442 const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc); 443 444 // [[DefineOwnProperty]] 445 static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 446 const PropertyDescriptor &desc); 447 448 static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 449 const PropertyDescriptor &desc); 450 451 static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, 452 const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc); 453 454 static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 455 const PropertyDescriptor &desc); 456 457 static bool IsCompatiblePropertyDescriptor(bool extensible, const PropertyDescriptor &desc, 458 const PropertyDescriptor ¤t); 459 460 static bool ValidateAndApplyPropertyDescriptor(ObjectOperator *op, bool extensible, const PropertyDescriptor &desc, 461 const PropertyDescriptor ¤t); 462 463 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSObject> &obj, 464 const JSHandle<JSTaggedValue> &key); 465 466 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 467 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver); 468 469 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 470 const JSHandle<JSTaggedValue> &key); 471 472 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index); 473 474 static OperationResult GetPropertyFromGlobal(JSThread *thread, const JSHandle<JSTaggedValue> &key); 475 476 static bool SetProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 477 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 478 479 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 480 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 481 482 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 483 const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &receiver, 484 bool mayThrow = false); 485 486 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index, 487 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 488 489 static bool GlobalSetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, 490 const JSHandle<JSTaggedValue> &value, bool mayThrow); 491 492 // [[HasProperty]] 493 static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key); 494 495 static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index); 496 497 // 9.1.10 [[Delete]] 498 static bool DeleteProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key); 499 500 // [[OwnPropertyKeys]] 501 static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj); 502 503 // 9.1.13 ObjectCreate 504 static JSHandle<JSObject> ObjectCreate(JSThread *thread, const JSHandle<JSObject> &proto); 505 506 // 12.9.4 Runtime Semantics: InstanceofOperator(O, C) 507 static bool InstanceOf(JSThread *thread, const JSHandle<JSTaggedValue> &object, 508 const JSHandle<JSTaggedValue> &target); 509 510 // 13.7.5.15 EnumerateObjectProperties ( O ); same as [[Enumerate]] 511 static JSHandle<JSForInIterator> EnumerateObjectProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj); 512 513 static bool IsRegExp(JSThread *thread, const JSHandle<JSTaggedValue> &argument); 514 515 static JSTaggedValue CallGetter(JSThread *thread, const AccessorData *accessor, 516 const JSHandle<JSTaggedValue> &receiver); 517 static bool CallSetter(JSThread *thread, const AccessorData &accessor, const JSHandle<JSTaggedValue> &receiver, 518 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 519 520 void FillElementsWithHoles(const JSThread *thread, uint32_t start, uint32_t end); 521 522 JSHClass *GetJSHClass() const; 523 bool IsJSGlobalObject() const; 524 bool IsConstructor() const; 525 bool IsECMAObject() const; 526 bool IsJSError() const; 527 bool IsArguments() const; 528 bool IsDate() const; 529 bool IsJSArray() const; 530 bool IsJSMap() const; 531 bool IsJSSet() const; 532 bool IsJSRegExp() const; 533 bool IsJSFunction() const; 534 bool IsBoundFunction() const; 535 bool IsJSIntlBoundFunction() const; 536 bool IsProxyRevocFunction() const; 537 bool IsAccessorData() const; 538 bool IsJSGlobalEnv() const; 539 bool IsJSProxy() const; 540 bool IsGeneratorObject() const; 541 bool IsForinIterator() const; 542 bool IsJSSetIterator() const; 543 bool IsJSMapIterator() const; 544 bool IsJSArrayIterator() const; 545 bool IsJSAPIArrayListIterator() const; 546 bool IsJSPrimitiveRef() const; 547 bool IsElementDict() const; 548 bool IsPropertiesDict() const; 549 bool IsTypedArray() const; 550 551 static void DefinePropertyByLiteral(JSThread *thread, const JSHandle<JSObject> &obj, 552 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value, 553 bool useForClass = false); 554 static void DefineSetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 555 const JSHandle<JSTaggedValue> &value); 556 static void DefineGetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 557 const JSHandle<JSTaggedValue> &value); 558 static JSHandle<JSObject> CreateObjectFromProperties(const JSThread *thread, 559 const JSHandle<TaggedArray> &properties); 560 static void GetAllKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset, 561 const JSHandle<TaggedArray> &keyArray); 562 static void GetAllKeys(const JSThread *thread, const JSHandle<JSObject> &obj, 563 std::vector<JSTaggedValue> &keyVector); 564 static void GetAllElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 565 const JSHandle<TaggedArray> &keyArray); 566 static void GetALLElementKeysIntoVector(const JSThread *thread, const JSHandle<JSObject> &obj, 567 std::vector<JSTaggedValue> &keyVector); 568 uint32_t GetNumberOfKeys(); 569 uint32_t GetNumberOfElements(); 570 571 static JSHandle<TaggedArray> GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 572 uint32_t numOfElements, uint32_t *keys); 573 static JSHandle<TaggedArray> GetAllEnumKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset, 574 uint32_t numOfKeys, uint32_t *keys); 575 576 static void AddAccessor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 577 const JSHandle<AccessorData> &value, PropertyAttributes attr); 578 579 static constexpr size_t PROPERTIES_OFFSET = ECMAObject::SIZE; 580 581 ACCESSORS(Properties, PROPERTIES_OFFSET, ELEMENTS_OFFSET); 582 ACCESSORS(Elements, ELEMENTS_OFFSET, SIZE); 583 584 DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, PROPERTIES_OFFSET, SIZE) 585 586 DECL_DUMP() 587 588 static JSHandle<NameDictionary> TransitionToDictionary(const JSThread *thread, const JSHandle<JSObject> &receiver); 589 590 inline void SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value); 591 inline void SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index, 592 JSTaggedValue value); 593 inline JSTaggedValue GetPropertyInlinedProps(uint32_t index) const; 594 inline JSTaggedValue GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const; 595 inline JSTaggedValue GetProperty(const JSHClass *hclass, PropertyAttributes attr) const; 596 inline void SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr, 597 JSTaggedValue value); 598 599 static bool IsArrayLengthWritable(JSThread *thread, const JSHandle<JSObject> &receiver); 600 bool UpdatePropertyInDictionary(const JSThread *thread, JSTaggedValue key, JSTaggedValue value); 601 static bool ShouldTransToDict(uint32_t capacity, uint32_t index); 602 static JSHandle<TaggedArray> GrowElementsCapacity(const JSThread *thread, const JSHandle<JSObject> &obj, 603 uint32_t capacity); 604 605 protected: 606 static void ElementsToDictionary(const JSThread *thread, JSHandle<JSObject> obj); 607 608 private: 609 friend class ObjectOperator; 610 friend class LoadICRuntime; 611 friend class StoreICRuntime; 612 friend class FastRuntimeStub; 613 friend class ICRuntimeStub; 614 friend class RuntimeTrampolines; 615 616 static bool AddElementInternal( 617 JSThread *thread, const JSHandle<JSObject> &receiver, uint32_t index, const JSHandle<JSTaggedValue> &value, 618 PropertyAttributes attr = PropertyAttributes(PropertyAttributes::GetDefaultAttributes())); 619 620 static JSTaggedValue GetProperty(JSThread *thread, ObjectOperator *op); 621 static bool SetProperty(ObjectOperator *op, const JSHandle<JSTaggedValue> &value, bool mayThrow); 622 static void DeletePropertyInternal(JSThread *thread, const JSHandle<JSObject> &obj, 623 const JSHandle<JSTaggedValue> &key, uint32_t index); 624 int FindProperty(const JSHandle<JSTaggedValue> &key); 625 626 static uint32_t ComputeElementCapacity(uint32_t oldCapacity); 627 static uint32_t ComputePropertyCapacity(uint32_t oldCapacity); 628 629 static JSTaggedValue ShouldGetValueFromBox(ObjectOperator *op); 630 }; 631 } // namespace ecmascript 632 } // namespace panda 633 634 #endif 635