• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 "ecmascript/ecma_macros.h"
20 #include "ecmascript/ecma_vm.h"
21 #include "ecmascript/filter_helper.h"
22 #include "ecmascript/ic/property_box.h"
23 #include "ecmascript/js_handle.h"
24 #include "ecmascript/js_hclass.h"
25 #include "ecmascript/js_tagged_value.h"
26 #include "ecmascript/mem/layout_visitor.h"
27 #include "ecmascript/mem/slots.h"
28 #include "ecmascript/mem/visitor.h"
29 #include "ecmascript/method.h"
30 #include "ecmascript/property_attributes.h"
31 #include "ecmascript/tagged_array.h"
32 
33 namespace panda {
34 namespace ecmascript {
35 class ObjectOperator;
36 class JSFunction;
37 class AccessorData;
38 class JSArray;
39 class JSForInIterator;
40 class LexicalEnv;
41 class GlobalEnv;
42 class TaggedQueue;
43 class NumberDictionary;
44 
45 namespace builtins {
46     class BuiltinsArkTools;
47 }
48 
49 using EnumCacheKind = EnumCache::EnumCacheKind;
50 using SCheckMode = JSShared::SCheckMode;
51 
52 // Integrity level for objects
53 enum IntegrityLevel { SEALED, FROZEN };
54 
55 enum PositionKind { UNKNOWN = 0, INDEXED_PROPERTY = 1, INLINE_NAMED_PROPERTY = 2, OUT_NAMED_PROPERTY = 3 };
56 enum PropertyKind { KEY = 0, VALUE, KEY_VALUE };
57 
58 // ecma6.0 6.2.4 The Property Descriptor Specification Type
59 class PropertyDescriptor final {
60 public:
61     PropertyDescriptor() = delete;
62 
63     ~PropertyDescriptor() = default;
64     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyDescriptor);
65     DEFAULT_COPY_SEMANTIC(PropertyDescriptor);
66 
PropertyDescriptor(const JSThread * thread)67     explicit PropertyDescriptor(const JSThread *thread) : thread_(thread) {}
68 
PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v)69     PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v) : thread_(thread), value_(v) {}
70 
PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v,bool w,bool e,bool c)71     PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v, bool w, bool e, bool c)
72         : thread_(thread),
73           writable_(w),
74           enumerable_(e),
75           configurable_(c),
76           hasWritable_(true),
77           hasEnumerable_(true),
78           hasConfigurable_(true),
79           value_(v)
80     {
81     }
82 
PropertyDescriptor(const JSThread * thread,bool w,bool e,bool c)83     PropertyDescriptor(const JSThread *thread, bool w, bool e, bool c)
84         : PropertyDescriptor(thread, JSHandle<JSTaggedValue>(), w, e, c)
85     {
86     }
87 
GetValue()88     inline JSHandle<JSTaggedValue> GetValue() const
89     {
90         if (value_.IsEmpty()) {
91             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined());
92         }
93         return value_;
94     }
95 
GetKey()96     inline JSHandle<JSTaggedValue> GetKey() const
97     {
98         if (key_.IsEmpty()) {
99             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined());
100         }
101         return key_;
102     }
103 
SetValue(JSHandle<JSTaggedValue> value)104     inline void SetValue(JSHandle<JSTaggedValue> value)
105     {
106         value_ = value;
107     }
108 
SetKey(JSHandle<JSTaggedValue> key)109     inline void SetKey(JSHandle<JSTaggedValue> key)
110     {
111         key_ = key;
112     }
113 
SetSharedFieldType(SharedFieldType fieldType)114     inline void SetSharedFieldType(SharedFieldType fieldType)
115     {
116         fieldType_ = fieldType;
117     }
118 
GetSharedFieldType()119     inline SharedFieldType GetSharedFieldType() const
120     {
121         return fieldType_;
122     }
123 
IsWritable()124     inline bool IsWritable() const
125     {
126         return writable_;
127     }
128 
SetWritable(bool flag)129     inline void SetWritable(bool flag)
130     {
131         writable_ = flag;
132         hasWritable_ = true;
133     }
134 
IsEnumerable()135     inline bool IsEnumerable() const
136     {
137         return enumerable_;
138     }
139 
SetEnumerable(bool flag)140     inline void SetEnumerable(bool flag)
141     {
142         enumerable_ = flag;
143         hasEnumerable_ = true;
144     }
145 
IsConfigurable()146     inline bool IsConfigurable() const
147     {
148         return configurable_;
149     }
150 
SetConfigurable(bool flag)151     inline void SetConfigurable(bool flag)
152     {
153         configurable_ = flag;
154         hasConfigurable_ = true;
155     }
156 
HasValue()157     inline bool HasValue() const
158     {
159         return !value_.IsEmpty();
160     }
161 
HasWritable()162     inline bool HasWritable() const
163     {
164         return hasWritable_;
165     }
166 
HasConfigurable()167     inline bool HasConfigurable() const
168     {
169         return hasConfigurable_;
170     }
171 
HasEnumerable()172     inline bool HasEnumerable() const
173     {
174         return hasEnumerable_;
175     }
176 
HasGetter()177     inline bool HasGetter() const
178     {
179         return !getter_.IsEmpty();
180     }
181 
HasSetter()182     inline bool HasSetter() const
183     {
184         return !setter_.IsEmpty();
185     }
186 
GetGetter()187     inline JSHandle<JSTaggedValue> GetGetter() const
188     {
189         if (getter_->IsNull()) {
190             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined());
191         }
192         return getter_;
193     }
194 
GetSetter()195     inline JSHandle<JSTaggedValue> GetSetter() const
196     {
197         if (setter_->IsNull()) {
198             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined());
199         }
200         return setter_;
201     }
202 
SetGetter(JSHandle<JSTaggedValue> value)203     inline void SetGetter(JSHandle<JSTaggedValue> value)
204     {
205         getter_ = value;
206     }
207 
SetSetter(JSHandle<JSTaggedValue> value)208     inline void SetSetter(JSHandle<JSTaggedValue> value)
209     {
210         setter_ = value;
211     }
212 
213     // 6.2.4.1
IsAccessorDescriptor()214     inline bool IsAccessorDescriptor() const
215     {
216         // 2. If both Desc.[[Get]] and Desc.[[Set]] are absent, return false.
217         return !(getter_.IsEmpty() && setter_.IsEmpty());
218     }
219 
IsDataDescriptor()220     inline bool IsDataDescriptor() const
221     {
222         // 2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, return false.
223         return !(value_.IsEmpty() && !hasWritable_);
224     }
225 
IsGenericDescriptor()226     inline bool IsGenericDescriptor() const
227     {
228         // 2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both false, return true
229         return !IsAccessorDescriptor() && !IsDataDescriptor();
230     }
231 
IsEmpty()232     inline bool IsEmpty() const
233     {
234         return !hasWritable_ && !hasEnumerable_ && !hasConfigurable_ && !HasValue() && !HasGetter() && !HasSetter();
235     }
236 
237     static void CompletePropertyDescriptor(const JSThread *thread, PropertyDescriptor &desc);
238 
239 private:
240     const JSThread *thread_{nullptr};
241 
242     bool writable_ {false};
243     bool enumerable_ {false};
244     bool configurable_ {false};
245     bool hasWritable_ {false};
246     bool hasEnumerable_ {false};
247     bool hasConfigurable_ {false};
248     SharedFieldType fieldType_ {SharedFieldType::NONE};
249 
250     JSHandle<JSTaggedValue> value_ {};
251     JSHandle<JSTaggedValue> getter_ {};
252     JSHandle<JSTaggedValue> setter_ {};
253     JSHandle<JSTaggedValue> key_ {};
254 };
255 
256 enum class ElementTypes { ALLTYPES, STRING_AND_SYMBOL };
257 
258 class PropertyMetaData {
259 public:
260     using IsFoundField = BitField<bool, 0, 1>;
261     using IsInlinedPropsField = IsFoundField::NextFlag;
262     // 3: The bit field that represents the "Representation" of the property
263     using RepresentationField = IsInlinedPropsField::NextField<Representation, 3>;
264     using OffsetField = RepresentationField::NextField<uint32_t, PropertyAttributes::MAX_FAST_PROPS_CAPACITY_LOG2>;
265 
PropertyMetaData(uint32_t metaData)266     explicit PropertyMetaData(uint32_t metaData) : metaData_(metaData) {}
267 
268     ~PropertyMetaData() = default;
269     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyMetaData);
270     DEFAULT_COPY_SEMANTIC(PropertyMetaData);
271 
PropertyMetaData(bool isFound)272     explicit PropertyMetaData(bool isFound)
273     {
274         SetFound(isFound);
275     }
276 
IsFound()277     inline bool IsFound() const
278     {
279         return IsFoundField::Get(metaData_);
280     }
281 
SetFound(bool flag)282     inline void SetFound(bool flag)
283     {
284         IsFoundField::Set(flag, &metaData_);
285     }
286 
GetIsInlinedProps()287     inline bool GetIsInlinedProps() const
288     {
289         return IsInlinedPropsField::Get(metaData_);
290     }
291 
SetIsInlinedProps(bool flag)292     inline void SetIsInlinedProps(bool flag)
293     {
294         IsInlinedPropsField::Set(flag, &metaData_);
295     }
296 
GetRepresentation()297     inline Representation GetRepresentation() const
298     {
299         return RepresentationField::Get(metaData_);
300     }
301 
SetRepresentation(Representation representation)302     inline void SetRepresentation(Representation representation)
303     {
304         RepresentationField::Set<uint32_t>(representation, &metaData_);
305     }
306 
SetOffset(uint32_t offset)307     inline void SetOffset(uint32_t offset)
308     {
309         OffsetField::Set<uint32_t>(offset, &metaData_);
310     }
311 
GetOffset()312     inline uint32_t GetOffset() const
313     {
314         return OffsetField::Get(metaData_);
315     }
316 
317 private:
318     uint32_t metaData_{0};
319 };
320 
321 class OperationResult {
322 public:
OperationResult(const JSThread * thread,JSTaggedValue value,PropertyMetaData metaData)323     OperationResult(const JSThread *thread, JSTaggedValue value, PropertyMetaData metaData)
324         : metaData_(metaData)
325     {
326         thread_ = thread;
327         value_ = JSHandle<JSTaggedValue>(thread_, value);
328     }
329 
330     ~OperationResult() = default;
331     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(OperationResult);
332     DEFAULT_COPY_SEMANTIC(OperationResult);
333 
GetValue()334     JSHandle<JSTaggedValue> GetValue() const
335     {
336         if (value_->IsPropertyBox()) {
337             return JSHandle<JSTaggedValue>(thread_,
338                                            PropertyBox::Cast(value_.GetTaggedValue().GetTaggedObject())->GetValue());
339         }
340         return value_;
341     }
342 
GetRawValue()343     JSHandle<JSTaggedValue> GetRawValue() const
344     {
345         return value_;
346     }
347 
GetPropertyMetaData()348     const PropertyMetaData &GetPropertyMetaData() const
349     {
350         return metaData_;
351     }
352 
353 private:
354     const JSThread *thread_ {nullptr};
355     JSHandle<JSTaggedValue> value_ {};
356     PropertyMetaData metaData_ {0U};
357 };
358 
359 
360 // HashField possible layout:
361 // [ hashValue ] | [extraInfo] | [ hashValue, extraInfo, nativePointer, ... ]
362 // nativePointer number depends on the extraLength of taggedArray
363 class ECMAObject : public TaggedObject {
364 public:
365     static constexpr int HASH_INDEX = 0;
366     static constexpr int FUNCTION_EXTRA_INDEX = 1;
367     static constexpr int RESOLVED_MAX_SIZE = 2;
368 
369     CAST_CHECK(ECMAObject, IsECMAObject);
370 
371     void SetCallable(bool flag);
372     bool IsCallable() const;
373     Method *GetCallTarget() const;
374     void *GetNativePointer() const;
375 
376     static constexpr size_t HASH_OFFSET = TaggedObjectSize();
377     static constexpr size_t SIZE = HASH_OFFSET + sizeof(JSTaggedType);
378 
379     static void SetHash(const JSThread *thread, int32_t hash, const JSHandle<ECMAObject> &obj);
380     int32_t GetHash() const;
381     bool HasHash() const;
382 
InitializeHash()383     void InitializeHash()
384     {
385         Barriers::SetPrimitive<JSTaggedType>(this, ECMAObject::HASH_OFFSET, JSTaggedValue(0).GetRawData());
386     }
387 
388     void* GetNativePointerField(int32_t index) const;
389     static void SetNativePointerField(const JSThread *thread, const JSHandle<JSObject> &obj, int32_t index,
390                                       void *nativePointer, const NativePointerCallback &callBack, void *data,
391                                       size_t nativeBindingsize = 0, Concurrent isConcurrent = Concurrent::NO);
392     int32_t GetNativePointerFieldCount() const;
393     static void SetNativePointerFieldCount(const JSThread *thread, const JSHandle<JSObject> &obj, int32_t count);
394 
395     DECL_VISIT_OBJECT(HASH_OFFSET, SIZE);
396 
397     template <VisitType visitType, class DerivedVisitor>
VisitObjects(EcmaObjectRangeVisitor<DerivedVisitor> & visitor)398     void VisitObjects(EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
399     {
400         // no field in this object
401         VisitRangeSlot<visitType>(visitor);
402     }
403 };
404 
405 class JSObject : public ECMAObject {
406 public:
407     static constexpr int MIN_ELEMENTS_LENGTH = 3;
408     static constexpr int MIN_PROPERTIES_LENGTH = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS;
409     static constexpr int FAST_ELEMENTS_FACTOR = 3;
410     static constexpr int MIN_GAP = 256;
411     static constexpr int MAX_GAP = 1_KB;
412     static constexpr uint32_t MAX_ELEMENT_INDEX = std::numeric_limits<uint32_t>::max();
413     static constexpr int MIN_ELEMENTS_HINT_LENGTH = 1_KB;
414     static constexpr int MAX_ELEMENTS_HINT_LENGTH = 2_MB;
415     static constexpr int ELEMENTS_HINT_FACTOR = 8;
416     static constexpr int SHOULD_TRANS_TO_FAST_ELEMENTS_FACTOR = 2;
417 
418     CAST_CHECK(JSObject, IsECMAObject);
419 
420     // ecma6.0 6.2.4.4
421     static JSHandle<JSTaggedValue> FromPropertyDescriptor(JSThread *thread, const PropertyDescriptor &desc);
422 
423     // ecma6.0 6.2.4.5 ToPropertyDescriptor ( Obj )
424     static void ToPropertyDescriptor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, PropertyDescriptor &desc);
425     static bool ToPropertyDescriptorFast(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
426                                          PropertyDescriptor &desc);
427 
428     static JSHandle<JSTaggedValue> CallFunction(JSThread *thread, const JSHandle<JSTaggedValue> &func);
429 
430     // ecma6 7.3 Operations on Objects
431     static JSHandle<JSTaggedValue> GetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
432                                              const JSHandle<JSTaggedValue> &key);
433 
434     static JSHandle<JSTaggedValue> FastGetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
435                                                  const JSHandle<JSTaggedValue> &key);
436 
437     static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
438                                    const JSHandle<JSTaggedValue> &value, SCheckMode sCheckMode = SCheckMode::CHECK);
439 
440     static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index,
441                                    const JSHandle<JSTaggedValue> &value, SCheckMode sCheckMode = SCheckMode::CHECK);
442 
443     static bool CreateMethodProperty(JSThread *thread, const JSHandle<JSObject> &obj,
444                                      const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value);
445 
446     static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj,
447                                           const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
448                                           SCheckMode sCheckMode = SCheckMode::CHECK);
449 
450     static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index,
451                                           const JSHandle<JSTaggedValue> &value,
452                                           SCheckMode sCheckMode = SCheckMode::CHECK);
453 
454     static JSHandle<TaggedArray> PUBLIC_API EnumerableOwnNames(JSThread *thread, const JSHandle<JSObject> &obj);
455 
456     // 7.3.23 EnumerableOwnPropertyNames ( O, kind )
457     static JSHandle<TaggedArray> EnumerableOwnPropertyNames(JSThread *thread, const JSHandle<JSObject> &obj,
458                                                             PropertyKind kind);
459     static void EnumerableOwnPropertyNamesHelper(JSThread *thread, const JSHandle<JSObject> &obj,
460         const JSHandle<TaggedArray> &arr, JSHandle<TaggedArray> &properties,
461         uint32_t &index, bool &fastMode, PropertyKind kind);
462 
463     static JSHandle<GlobalEnv> GetFunctionRealm(JSThread *thread, const JSHandle<JSTaggedValue> &object);
464 
465     static bool SetIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level);
466 
467     static bool FreezeSharedObject(JSThread *thread, const JSHandle<JSObject> &obj);
468 
469     static bool TestIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level);
470 
471     static JSHandle<JSTaggedValue> SpeciesConstructor(JSThread *thread, const JSHandle<JSObject> &obj,
472                                                       const JSHandle<JSTaggedValue> &defaultConstructor);
473     static JSHandle<JSTaggedValue> SlowSpeciesConstructor(JSThread *thread,
474                                                           const JSHandle<JSTaggedValue> &objConstructor,
475                                                           const JSHandle<JSTaggedValue> &defaultConstructor);
476     // 7.3.17
477     template<ElementTypes types = ElementTypes::ALLTYPES>
478     static JSHandle<JSTaggedValue> CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
479 
480     // ecma6 9.1
481     // [[GetPrototypeOf]]
482     static JSTaggedValue GetPrototype(const JSHandle<JSObject> &obj);
483 
484     static JSTaggedValue GetPrototype(JSTaggedValue obj);
485 
486     // [[SetPrototypeOf]]
487     static bool SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj,
488                              const JSHandle<JSTaggedValue> &proto,
489                              bool isChangeProto = false);
490 
491     // [[IsExtensible]]
492     bool IsExtensible() const;
493 
494     // [[PreventExtensions]]
495     static bool PreventExtensions(JSThread *thread, const JSHandle<JSObject> &obj);
496 
497     // [[GetOwnProperty]] -> Undefined | Property Descriptor
498     static bool GetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
499                                PropertyDescriptor &desc);
500 
501     static bool GlobalGetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc);
502 
503     static bool OrdinaryGetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj,
504                                        const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc);
505 
506     // [[DefineOwnProperty]]
507     static bool DefineOwnProperty(JSThread *thread, ObjectOperator *op,
508                                   const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK);
509 
510     static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
511                                   const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK);
512 
513     static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index,
514                                   const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK);
515 
516     static bool OrdinaryDefineOwnProperty(JSThread *thread, ObjectOperator *op,
517                                           const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK);
518 
519     static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj,
520                                           const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc,
521                                           SCheckMode sCheckMode = SCheckMode::CHECK);
522 
523     static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index,
524                                           const PropertyDescriptor &desc,
525                                           SCheckMode sCheckMode = SCheckMode::CHECK);
526 
527     static bool IsCompatiblePropertyDescriptor(bool extensible, const PropertyDescriptor &desc,
528                                                const PropertyDescriptor &current);
529 
530     static bool ValidateAndApplyPropertyDescriptor(ObjectOperator *op, bool extensible, const PropertyDescriptor &desc,
531                                                    const PropertyDescriptor &current,
532                                                    SCheckMode sCheckMode = SCheckMode::CHECK);
533 
534     static OperationResult PUBLIC_API GetProperty(JSThread *thread, const JSHandle<JSObject> &obj,
535                                                   const JSHandle<JSTaggedValue> &key);
536 
537     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
538                                        const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver);
539 
540     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
541                                        const JSHandle<JSTaggedValue> &key, SCheckMode sCheckMode = SCheckMode::CHECK);
542 
543     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index);
544 
545     static OperationResult GetPropertyFromGlobal(JSThread *thread, const JSHandle<JSTaggedValue> &key);
546 
547     static bool SetProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
548                             JSHandle<JSTaggedValue> value, bool mayThrow = false);
549 
550     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
551                             JSHandle<JSTaggedValue> value, bool mayThrow = false,
552                             SCheckMode checkMode = SCheckMode::CHECK);
553 
554     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
555                             JSHandle<JSTaggedValue> value, const JSHandle<JSTaggedValue> &receiver,
556                             bool mayThrow = false);
557 
558     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index,
559                             JSHandle<JSTaggedValue> value, bool mayThrow = false);
560 
561     static bool GlobalSetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key,
562                                   JSHandle<JSTaggedValue> value, bool mayThrow);
563 
564     // [[HasProperty]]
565     static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key);
566 
567     static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index);
568 
569     // 9.1.10 [[Delete]]
570     static bool DeleteProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
571                                SCheckMode sCheckMode = SCheckMode::CHECK);
572 
573     // [[OwnPropertyKeys]]
574     static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj);
575 
576     static JSHandle<TaggedArray> GetAllPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t filter);
577 
578     static void CollectEnumKeysAlongProtoChain(JSThread *thread, const JSHandle<JSObject> &obj,
579                                                JSHandle<TaggedArray> keyArray, uint32_t *keys,
580                                                JSHandle<TaggedQueue> shadowQueue, int32_t lastLength = -1);
581 
582     static void AppendOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj,
583                                           JSHandle<TaggedArray> keyArray, uint32_t *keys,
584                                           JSHandle<TaggedQueue> shadowQueue);
585 
586     static JSHandle<TaggedArray> GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj);
587 
588     // 9.1.13 ObjectCreate
589     static JSHandle<JSObject> ObjectCreate(JSThread *thread, const JSHandle<JSObject> &proto);
590 
591     // 12.9.4 Runtime Semantics: InstanceofOperator(O, C)
592     static bool InstanceOf(JSThread *thread, const JSHandle<JSTaggedValue> &object,
593                            const JSHandle<JSTaggedValue> &target);
594 
595     static JSTaggedValue TryGetEnumCache(JSThread *thread, JSTaggedValue obj);
596 
597     // 13.7.5.15 EnumerateObjectProperties ( O ); same as [[Enumerate]]
598     static JSHandle<JSForInIterator> EnumerateObjectProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
599     static JSHandle<JSForInIterator> LoadEnumerateProperties(JSThread *thread, const JSHandle<JSTaggedValue> &object);
600 
601     static bool IsRegExp(JSThread *thread, const JSHandle<JSTaggedValue> &argument);
602 
603     static JSTaggedValue CallGetter(JSThread *thread, const AccessorData *accessor,
604                                     const JSHandle<JSTaggedValue> &receiver);
605     static bool PUBLIC_API CallSetter(JSThread *thread, const AccessorData &accessor,
606                                       const JSHandle<JSTaggedValue> &receiver,
607                                       const JSHandle<JSTaggedValue> &value, bool mayThrow = false);
608 
609     static void FillElementsWithHoles(const JSThread *thread, const JSHandle<JSObject> &obj,
610                                       uint32_t start, uint32_t end);
611 
GetJSHClass()612     JSHClass *GetJSHClass() const
613     {
614         return GetClass();
615     }
616     uint32_t GetNonInlinedFastPropsCapacity() const;
617     bool IsJSGlobalObject() const;
618     bool IsConstructor() const;
619     bool IsECMAObject() const;
620     bool IsJSError() const;
621     bool IsArguments() const;
622     bool IsDate() const;
623     bool IsJSArray() const;
624     bool IsJSSArray() const;
625     bool IsJSShared() const;
626     bool IsJSMap() const;
627     bool IsJSSet() const;
628     bool IsJSRegExp() const;
629     bool IsJSFunction() const;
630     bool IsBoundFunction() const;
631     bool IsJSIntlBoundFunction() const;
632     bool IsProxyRevocFunction() const;
633     bool IsAccessorData() const;
634     bool IsJSGlobalEnv() const;
635     bool IsJSProxy() const;
636     bool IsGeneratorObject() const;
637     bool IsAsyncGeneratorObject() const;
638     bool IsForinIterator() const;
639     bool IsJSSetIterator() const;
640     bool IsJSRegExpIterator() const;
641     bool IsJSMapIterator() const;
642     bool IsJSArrayIterator() const;
643     bool IsJSAPIArrayListIterator() const;
644     bool IsJSAPIStackIterator() const;
645     bool IsJSAPIVectorIterator() const;
646     bool IsJSAPIBitVectorIterator() const;
647     bool IsJSAPILinkedListIterator() const;
648     bool IsJSAPIListIterator() const;
649     bool IsJSPrimitiveRef() const;
650     bool IsElementDict() const;
651     bool IsPropertiesDict() const;
652     bool IsTypedArray() const;
653     bool IsSharedTypedArray() const;
654     bool PUBLIC_API ElementsAndPropertiesIsEmpty() const;
655 
656     static PUBLIC_API void DefinePropertyByLiteral(JSThread *thread, const JSHandle<JSObject> &obj,
657                                                    const JSHandle<JSTaggedValue> &key,
658                                                    const JSHandle<JSTaggedValue> &value,
659                                                    bool useForClass = false);
660     static void DefineSetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
661                              const JSHandle<JSTaggedValue> &value);
662     static void DefineGetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
663                              const JSHandle<JSTaggedValue> &value);
664     static PUBLIC_API JSHandle<JSObject> CreateObjectFromProperties(const JSThread *thread,
665                                                                     const JSHandle<TaggedArray> &properties,
666                                                          JSTaggedValue ihc = JSTaggedValue::Undefined());
667     static JSHandle<JSObject> CreateObjectFromProperties(const JSThread *thread,
668                                                          const JSHandle<JSHClass> &hclass,
669                                                          const JSHandle<TaggedArray> &properties,
670                                                          uint32_t propsLen);
671     static JSHandle<JSObject> CreateObjectFromPropertiesByIHClass(const JSThread *thread,
672                                                                   const JSHandle<TaggedArray> &properties,
673                                                                   uint32_t propsLen,
674                                                                   const JSHandle<JSHClass> &ihc);
675     static bool CheckPropertiesForRep(
676         const JSHandle<TaggedArray> &properties, uint32_t propsLen, const JSHandle<JSHClass> &ihc);
677     static void GetAllKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset,
678                            const JSHandle<TaggedArray> &keyArray);
679     static void GetAllKeysForSerialization(const JSHandle<JSObject> &obj, std::vector<JSTaggedValue> &keyVector);
680 
681     static void GetAllKeysByFilter(const JSThread *thread, const JSHandle<JSObject> &obj,
682                                    uint32_t &keyArrayEffectivelength,
683                                    const JSHandle<TaggedArray> &keyArray,
684                                    uint32_t filter);
685     static void GetAllElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
686                                   const JSHandle<TaggedArray> &keyArray);
687     static void GetAllElementKeysByFilter(JSThread *thread,
688                                           const JSHandle<JSObject> &obj,
689                                           const JSHandle<TaggedArray> &keyArray,
690                                           uint32_t &keyArrayEffectiveLength,
691                                           uint32_t filter);
692 
693     static void GetALLElementKeysIntoVector(const JSThread *thread, const JSHandle<JSObject> &obj,
694                                             std::vector<JSTaggedValue> &keyVector);
695     std::pair<uint32_t, uint32_t> GetNumberOfEnumKeys() const;
696     uint32_t GetNumberOfKeys();
697     uint32_t GetNumberOfElements(JSThread *thread);
698 
699     static JSHandle<TaggedArray> GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
700                                                     uint32_t numOfElements, uint32_t *keys);
701     static void CollectEnumElementsAlongProtoChain(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
702                                                    JSHandle<TaggedArray> elementArray, uint32_t *keys,
703                                                    int32_t lastLength = -1);
704     static void GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
705                                    const JSHandle<TaggedArray> &keyArray);
706     static JSHandle<TaggedArray> GetAllEnumKeys(JSThread *thread, const JSHandle<JSObject> &obj,
707                                                 uint32_t numOfKeys, uint32_t *keys);
708     static uint32_t GetAllEnumKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
709                                    const JSHandle<TaggedArray> &keyArray);
710 
711     static void AddAccessor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
712                             const JSHandle<AccessorData> &value, PropertyAttributes attr);
713 
714     static constexpr size_t PROPERTIES_OFFSET = ECMAObject::SIZE;
715 
716     ACCESSORS(Properties, PROPERTIES_OFFSET, ELEMENTS_OFFSET);
717     ACCESSORS(Elements, ELEMENTS_OFFSET, SIZE);
718 
719     DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, PROPERTIES_OFFSET, SIZE)
720 
721     void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR;
Dump()722     void Dump() const DUMP_API_ATTR
723     {
724         Dump(std::cout);
725     }
726     void DumpForSnapshot(std::vector<Reference> &vec) const;
727     static const CString ExtractConstructorAndRecordName(JSThread *thread, TaggedObject *obj, bool noAllocate = false,
728                                                          bool *isCallGetter = nullptr);
729 
730     static JSHandle<NameDictionary> PUBLIC_API TransitionToDictionary(const JSThread *thread,
731                                                                       const JSHandle<JSObject> &receiver);
732 
733     static inline std::pair<bool, JSTaggedValue> ConvertValueWithRep(PropertyAttributes attr, JSTaggedValue value);
734 
735     inline void SetPropertyInlinedPropsWithRep(const JSThread *thread, uint32_t index, JSTaggedValue value);
736     template <size_t objectSize, uint32_t index, bool needBarrier = true>
737     inline void SetPropertyInlinedPropsWithSize(const JSThread* thread, JSTaggedValue value);
738     template <bool needBarrier = true>
739     inline void SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value);
740     template <bool needBarrier = true>
741     inline void SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index,
742                                         JSTaggedValue value);
743     inline JSTaggedValue GetPropertyInlinedPropsWithRep(uint32_t index, PropertyAttributes attr) const;
744     inline JSTaggedValue GetPropertyInlinedPropsWithRep(const JSHClass *hclass, uint32_t index,
745         PropertyAttributes attr) const;
746     template <size_t objectSize, uint32_t index>
747     inline JSTaggedValue GetPropertyInlinedPropsWithSize() const;
748     inline JSTaggedValue GetPropertyInlinedProps(uint32_t index) const;
749     inline JSTaggedValue GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const;
750     inline JSTaggedValue GetProperty(const JSHClass *hclass, PropertyAttributes attr) const;
751     PropertyBox* GetGlobalPropertyBox(JSThread *thread, const std::string& key);
752     template <bool needBarrier = true>
753     inline void SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr,
754                             JSTaggedValue value);
755 
756     static bool IsArrayLengthWritable(JSThread *thread, const JSHandle<JSObject> &receiver);
757     bool UpdatePropertyInDictionary(const JSThread *thread, JSTaggedValue key, JSTaggedValue value);
758     static bool ShouldTransToDict(uint32_t capacity, uint32_t index);
759     static bool ShouldTransToFastElements(JSThread *thread, TaggedArray *elements, uint32_t capacity, uint32_t index);
760     static bool AttributesUnchanged(const JSThread *thread, const JSHandle<JSObject> &obj);
761     static JSHandle<TaggedArray> GrowElementsCapacity(const JSThread *thread, const JSHandle<JSObject> &obj,
762                                                       uint32_t capacity, bool highGrowth = false, bool isNew = false);
763 
764     static bool IsDepulicateKeys(JSThread *thread, JSHandle<TaggedArray> keys, int32_t lastLength,
765                                  JSHandle<TaggedQueue> shadowQueue, JSHandle<JSTaggedValue> key);
766 
767     static void SetEnumCacheKind(JSThread *thread, TaggedArray *array, EnumCacheKind kind);
768     static EnumCacheKind GetEnumCacheKind(JSThread *thread, TaggedArray *array);
769     static EnumCacheKind GetEnumCacheKind(JSThread *thread, JSTaggedValue enumCache);
770 
771     static void ClearHasDeleteProperty(JSHandle<JSTaggedValue> object);
772 
773     static JSHandle<JSTaggedValue> IterableToList(JSThread *thread, const JSHandle<JSTaggedValue> &items,
774                                                   JSTaggedValue method = JSTaggedValue::Undefined());
775 
776     static void TryOptimizeAsFastElements(const JSThread *thread, JSHandle<JSObject> obj);
777     static void OptimizeAsFastProperties(const JSThread *thread, JSHandle<JSObject> obj);
778 
779     static void SetSProperties(JSThread *thread, JSHandle<JSObject> obj, const std::vector<PropertyDescriptor> &descs);
780 
781     static void PUBLIC_API TryMigrateToGenericKindForJSObject(const JSThread *thread, const JSHandle<JSObject> &obj,
782                                                   const ElementsKind oldKind);
783     static void ElementsToDictionary(const JSThread *thread, JSHandle<JSObject> obj);
784 
785 private:
786     friend class ObjectOperator;
787     friend class LoadICRuntime;
788     friend class StoreICRuntime;
789     friend class ObjectFastOperator;
790     friend class ICRuntimeStub;
791     friend class RuntimeStubs;
792     friend class JSSharedArray;
793     friend class builtins::BuiltinsArkTools;
794 
795     static bool HasMutantTaggedArrayElements(const JSHandle<JSObject> &obj);
796     PropertyBox* GetGlobalPropertyBox(JSTaggedValue key);
797     static bool CheckAndUpdateArrayLength(JSThread *thread, const JSHandle<JSObject> &receiver,
798                                           uint32_t index, ElementsKind &kind);
799     static bool PUBLIC_API AddElementInternal(
800         JSThread *thread, const JSHandle<JSObject> &receiver, uint32_t index, const JSHandle<JSTaggedValue> &value,
801         PropertyAttributes attr = PropertyAttributes(PropertyAttributes::GetDefaultAttributes()));
802 
803     static JSTaggedValue GetProperty(JSThread *thread, ObjectOperator *op);
804     static bool SetProperty(ObjectOperator *op, JSHandle<JSTaggedValue> value, bool mayThrow);
805     static bool SetPropertyForData(ObjectOperator *op, const JSHandle<JSTaggedValue> &value, bool *isAccessor);
806     static bool SetPropertyForAccessor(ObjectOperator *op, const JSHandle<JSTaggedValue> &value);
807     static void DeletePropertyInternal(JSThread *thread, const JSHandle<JSObject> &obj,
808                                        const JSHandle<JSTaggedValue> &key, uint32_t index);
809     int FindProperty(const JSHandle<JSTaggedValue> &key);
810 
811     static uint32_t ComputeElementCapacity(uint32_t oldCapacity, bool isNew = false);
812     static uint32_t ComputeElementCapacityHighGrowth(uint32_t oldCapacity);
813     static uint32_t ComputeElementCapacityWithHint(uint32_t oldCapacity, uint32_t hint);
814     static uint32_t ComputeNonInlinedFastPropsCapacity(JSThread *thread, uint32_t oldCapacity,
815                                                        uint32_t maxNonInlinedFastPropsCapacity);
816 
817     static JSTaggedValue ShouldGetValueFromBox(ObjectOperator *op);
818     static std::pair<JSHandle<TaggedArray>, JSHandle<TaggedArray>> GetOwnEnumerableNamesInFastMode(
819         JSThread *thread, const JSHandle<JSObject> &obj, uint32_t *copyLengthOfKeys, uint32_t *copyLengthOfElements);
820     static bool CheckHClassHit(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &cls);
821     static uint32_t SetValuesOrEntries(JSThread *thread, const JSHandle<TaggedArray> &prop, uint32_t index,
822                                        const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
823                                        PropertyKind kind);
824     static bool IsSimpleEnumCacheValid(JSThread *thread, JSTaggedValue receiver);
825     static bool IsEnumCacheWithProtoChainInfoValid(JSThread *thread, JSTaggedValue receiver);
826     static void TrimInlinePropsSpace(const JSThread *thread, const JSHandle<JSObject> &object,
827                                      uint32_t numberInlinedProps);
828     static bool ValidateDataDescriptorWhenConfigurable(ObjectOperator *op, const PropertyDescriptor &desc,
829                                                        const PropertyDescriptor &current, SCheckMode sCheckMode);
830     static bool SetPropertyForDataDescriptor(ObjectOperator *op, JSHandle<JSTaggedValue> value,
831                                              JSHandle<JSTaggedValue> &receiver, bool mayThrow, bool isInternalAccessor);
832     static bool SetPropertyForDataDescriptorProxy(JSThread *thread, ObjectOperator *op,
833                                                   const JSHandle<JSTaggedValue> &value,
834                                                   JSHandle<JSTaggedValue> &receiver);
835 };
836 }  // namespace ecmascript
837 }  // namespace panda
838 
839 #endif
840