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