• 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/ic/property_box.h"
22 #include "ecmascript/js_handle.h"
23 #include "ecmascript/js_hclass.h"
24 #include "ecmascript/js_native_pointer.h"
25 #include "ecmascript/js_tagged_value.h"
26 #include "ecmascript/mem/slots.h"
27 #include "ecmascript/mem/visitor.h"
28 #include "ecmascript/method.h"
29 #include "ecmascript/object_operator.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 // Integrity level for objects
43 enum IntegrityLevel { SEALED, FROZEN };
44 
45 enum PositionKind { UNKNOWN = 0, INDEXED_PROPERTY = 1, INLINE_NAMED_PROPERTY = 2, OUT_NAMED_PROPERTY = 3 };
46 enum PropertyKind { KEY = 0, VALUE, KEY_VALUE };
47 
48 // ecma6.0 6.2.4 The Property Descriptor Specification Type
49 class PropertyDescriptor final {
50 public:
51     explicit PropertyDescriptor() = delete;
52 
53     ~PropertyDescriptor() = default;
54     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyDescriptor);
55     DEFAULT_COPY_SEMANTIC(PropertyDescriptor);
56 
PropertyDescriptor(const JSThread * thread)57     explicit PropertyDescriptor(const JSThread *thread) : thread_(thread) {}
58 
PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v)59     explicit PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v) : thread_(thread), value_(v) {}
60 
PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v,bool w,bool e,bool c)61     explicit PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v, bool w, bool e, bool c)
62         : thread_(thread),
63           writable_(w),
64           enumerable_(e),
65           configurable_(c),
66           hasWritable_(true),
67           hasEnumerable_(true),
68           hasConfigurable_(true),
69           value_(v)
70     {
71     }
72 
PropertyDescriptor(const JSThread * thread,bool w,bool e,bool c)73     explicit PropertyDescriptor(const JSThread *thread, bool w, bool e, bool c)
74         : PropertyDescriptor(thread, JSHandle<JSTaggedValue>(), w, e, c)
75     {
76     }
77 
GetValue()78     inline JSHandle<JSTaggedValue> GetValue() const
79     {
80         if (value_.IsEmpty()) {
81             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined());
82         }
83         return value_;
84     }
85 
SetValue(JSHandle<JSTaggedValue> value)86     inline void SetValue(JSHandle<JSTaggedValue> value)
87     {
88         value_ = value;
89     }
90 
IsWritable()91     inline bool IsWritable() const
92     {
93         return writable_;
94     }
95 
SetWritable(bool flag)96     inline void SetWritable(bool flag)
97     {
98         writable_ = flag;
99         hasWritable_ = true;
100     }
101 
IsEnumerable()102     inline bool IsEnumerable() const
103     {
104         return enumerable_;
105     }
106 
SetEnumerable(bool flag)107     inline void SetEnumerable(bool flag)
108     {
109         enumerable_ = flag;
110         hasEnumerable_ = true;
111     }
112 
IsConfigurable()113     inline bool IsConfigurable() const
114     {
115         return configurable_;
116     }
117 
SetConfigurable(bool flag)118     inline void SetConfigurable(bool flag)
119     {
120         configurable_ = flag;
121         hasConfigurable_ = true;
122     }
123 
HasValue()124     inline bool HasValue() const
125     {
126         return !value_.IsEmpty();
127     }
128 
HasWritable()129     inline bool HasWritable() const
130     {
131         return hasWritable_;
132     }
133 
HasConfigurable()134     inline bool HasConfigurable() const
135     {
136         return hasConfigurable_;
137     }
138 
HasEnumerable()139     inline bool HasEnumerable() const
140     {
141         return hasEnumerable_;
142     }
143 
HasGetter()144     inline bool HasGetter() const
145     {
146         return !getter_.IsEmpty();
147     }
148 
HasSetter()149     inline bool HasSetter() const
150     {
151         return !setter_.IsEmpty();
152     }
153 
GetGetter()154     inline JSHandle<JSTaggedValue> GetGetter() const
155     {
156         if (getter_->IsNull()) {
157             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined());
158         }
159         return getter_;
160     }
161 
GetSetter()162     inline JSHandle<JSTaggedValue> GetSetter() const
163     {
164         if (setter_->IsNull()) {
165             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined());
166         }
167         return setter_;
168     }
169 
SetGetter(JSHandle<JSTaggedValue> value)170     inline void SetGetter(JSHandle<JSTaggedValue> value)
171     {
172         getter_ = value;
173     }
174 
SetSetter(JSHandle<JSTaggedValue> value)175     inline void SetSetter(JSHandle<JSTaggedValue> value)
176     {
177         setter_ = value;
178     }
179 
180     // 6.2.4.1
IsAccessorDescriptor()181     inline bool IsAccessorDescriptor() const
182     {
183         // 2. If both Desc.[[Get]] and Desc.[[Set]] are absent, return false.
184         return !(getter_.IsEmpty() && setter_.IsEmpty());
185     }
186 
IsDataDescriptor()187     inline bool IsDataDescriptor() const
188     {
189         // 2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, return false.
190         return !(value_.IsEmpty() && !hasWritable_);
191     }
192 
IsGenericDescriptor()193     inline bool IsGenericDescriptor() const
194     {
195         // 2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both false, return true
196         return !IsAccessorDescriptor() && !IsDataDescriptor();
197     }
198 
IsEmpty()199     inline bool IsEmpty() const
200     {
201         return !hasWritable_ && !hasEnumerable_ && !hasConfigurable_ && !HasValue() && !HasGetter() && !HasSetter();
202     }
203 
204     static void CompletePropertyDescriptor(const JSThread *thread, PropertyDescriptor &desc);
205 
206 private:
207     const JSThread *thread_{nullptr};
208 
209     bool writable_ {false};
210     bool enumerable_ {false};
211     bool configurable_ {false};
212     bool hasWritable_ {false};
213     bool hasEnumerable_ {false};
214     bool hasConfigurable_ {false};
215 
216     JSHandle<JSTaggedValue> value_ {};
217     JSHandle<JSTaggedValue> getter_ {};
218     JSHandle<JSTaggedValue> setter_ {};
219 };
220 
221 enum class ElementTypes { ALLTYPES, STRING_AND_SYMBOL };
222 
223 class PropertyMetaData {
224 public:
225     using IsFoundField = BitField<bool, 0, 1>;
226     using IsInlinedPropsField = IsFoundField::NextFlag;
227     using RepresentationField = IsInlinedPropsField::NextField<Representation, 3>;
228     using OffsetField = RepresentationField::NextField<uint32_t, PropertyAttributes::OFFSET_BITFIELD_NUM>;
229 
PropertyMetaData(uint32_t metaData)230     explicit PropertyMetaData(uint32_t metaData) : metaData_(metaData) {}
231 
232     ~PropertyMetaData() = default;
233     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyMetaData);
234     DEFAULT_COPY_SEMANTIC(PropertyMetaData);
235 
PropertyMetaData(bool isFound)236     explicit PropertyMetaData(bool isFound)
237     {
238         SetFound(isFound);
239     }
240 
IsFound()241     inline bool IsFound() const
242     {
243         return IsFoundField::Get(metaData_);
244     }
245 
SetFound(bool flag)246     inline void SetFound(bool flag)
247     {
248         IsFoundField::Set(flag, &metaData_);
249     }
250 
GetIsInlinedProps()251     inline bool GetIsInlinedProps() const
252     {
253         return IsInlinedPropsField::Get(metaData_);
254     }
255 
SetIsInlinedProps(bool flag)256     inline void SetIsInlinedProps(bool flag)
257     {
258         IsInlinedPropsField::Set(flag, &metaData_);
259     }
260 
GetRepresentation()261     inline Representation GetRepresentation() const
262     {
263         return RepresentationField::Get(metaData_);
264     }
265 
SetRepresentation(Representation representation)266     inline void SetRepresentation(Representation representation)
267     {
268         RepresentationField::Set<uint32_t>(representation, &metaData_);
269     }
270 
SetOffset(uint32_t offset)271     inline void SetOffset(uint32_t offset)
272     {
273         OffsetField::Set<uint32_t>(offset, &metaData_);
274     }
275 
GetOffset()276     inline uint32_t GetOffset() const
277     {
278         return OffsetField::Get(metaData_);
279     }
280 
281 private:
282     uint32_t metaData_{0};
283 };
284 
285 class OperationResult {
286 public:
OperationResult(const JSThread * thread,JSTaggedValue value,PropertyMetaData metaData)287     explicit OperationResult(const JSThread *thread, JSTaggedValue value, PropertyMetaData metaData)
288         : metaData_(metaData)
289     {
290         thread_ = thread;
291         value_ = JSHandle<JSTaggedValue>(thread_, value);
292     }
293 
294     ~OperationResult() = default;
295     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(OperationResult);
296     DEFAULT_COPY_SEMANTIC(OperationResult);
297 
GetValue()298     JSHandle<JSTaggedValue> GetValue() const
299     {
300         if (value_->IsPropertyBox()) {
301             return JSHandle<JSTaggedValue>(thread_,
302                                            PropertyBox::Cast(value_.GetTaggedValue().GetTaggedObject())->GetValue());
303         }
304         return value_;
305     }
306 
GetRawValue()307     JSHandle<JSTaggedValue> GetRawValue() const
308     {
309         return value_;
310     }
311 
GetPropertyMetaData()312     const PropertyMetaData &GetPropertyMetaData() const
313     {
314         return metaData_;
315     }
316 
317 private:
318     const JSThread *thread_ {nullptr};
319     JSHandle<JSTaggedValue> value_ {};
320     PropertyMetaData metaData_{0U};
321 };
322 
323 class ECMAObject : public TaggedObject {
324 public:
325     static constexpr int HASH_INDEX = 0;
326     static constexpr int FUNCTION_EXTRA_INDEX = 1;
327     static constexpr int RESOLVED_MAX_SIZE = 2;
328 
329     CAST_CHECK(ECMAObject, IsECMAObject);
330 
331     void SetCallable(bool flag);
332     bool IsCallable() const;
333     Method *GetCallTarget() const;
334 
335     static constexpr size_t HASH_OFFSET = TaggedObjectSize();
336     static constexpr size_t SIZE = HASH_OFFSET + sizeof(JSTaggedType);
337 
338     void SetHash(int32_t hash);
339     int32_t GetHash() const;
340     bool HasHash() const;
341 
InitializeHash()342     void InitializeHash()
343     {
344         Barriers::SetPrimitive<JSTaggedType>(this, ECMAObject::HASH_OFFSET, JSTaggedValue(0).GetRawData());
345     }
346 
347     void* GetNativePointerField(int32_t index) const;
348     void SetNativePointerField(int32_t index, void *nativePointer,
349         const DeleteEntryPoint &callBack, void *data, size_t nativeBindingsize = 0);
350     int32_t GetNativePointerFieldCount() const;
351     void SetNativePointerFieldCount(int32_t count);
352 
353     DECL_VISIT_OBJECT(HASH_OFFSET, SIZE);
354 
VisitObjects(const EcmaObjectRangeVisitor & visitor)355     void VisitObjects(const EcmaObjectRangeVisitor &visitor)
356     {
357         // no field in this object
358         VisitRangeSlot(visitor);
359     }
360 };
361 
362 class JSObject : public ECMAObject {
363 public:
364     static constexpr int MIN_ELEMENTS_LENGTH = 3;
365     static constexpr int MIN_PROPERTIES_LENGTH = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS;
366     static constexpr int PROPERTIES_GROW_SIZE = 4;
367     static constexpr int FAST_ELEMENTS_FACTOR = 3;
368     static constexpr int MIN_GAP = 256;
369     static constexpr int MAX_GAP = 1_KB;
370     static constexpr uint32_t MAX_ELEMENT_INDEX = std::numeric_limits<uint32_t>::max();
371 
372     CAST_CHECK(JSObject, IsECMAObject);
373 
374     // ecma6.0 6.2.4.4
375     static JSHandle<JSTaggedValue> FromPropertyDescriptor(JSThread *thread, const PropertyDescriptor &desc);
376 
377     // ecma6.0 6.2.4.5 ToPropertyDescriptor ( Obj )
378     static void ToPropertyDescriptor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, PropertyDescriptor &desc);
379     static bool ToPropertyDescriptorFast(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
380                                          PropertyDescriptor &desc);
381 
382     // ecma6 7.3 Operations on Objects
383     static JSHandle<JSTaggedValue> GetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
384                                              const JSHandle<JSTaggedValue> &key);
385 
386     static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
387                                    const JSHandle<JSTaggedValue> &value);
388 
389     static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index,
390                                    const JSHandle<JSTaggedValue> &value);
391 
392     static bool CreateMethodProperty(JSThread *thread, const JSHandle<JSObject> &obj,
393                                      const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value);
394 
395     static bool CreateDataPropertyOrThrow(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, uint32_t index,
399                                           const JSHandle<JSTaggedValue> &value);
400 
401     static JSHandle<TaggedArray> EnumerableOwnNames(JSThread *thread, const JSHandle<JSObject> &obj);
402 
403     // 7.3.23 EnumerableOwnPropertyNames ( O, kind )
404     static JSHandle<TaggedArray> EnumerableOwnPropertyNames(JSThread *thread, const JSHandle<JSObject> &obj,
405                                                             PropertyKind kind);
406     static void EnumerableOwnPropertyNamesHelper(JSThread *thread, const JSHandle<JSObject> &obj,
407         const JSHandle<TaggedArray> &arr, JSHandle<TaggedArray> &properties,
408         uint32_t &index, bool &fastMode, 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     // ecma6 9.1
423     // [[GetPrototypeOf]]
424     static JSTaggedValue GetPrototype(const JSHandle<JSObject> &obj);
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 &current);
459 
460     static bool ValidateAndApplyPropertyDescriptor(ObjectOperator *op, bool extensible, const PropertyDescriptor &desc,
461                                                    const PropertyDescriptor &current);
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 IsAsyncGeneratorObject() const;
542     bool IsForinIterator() const;
543     bool IsJSSetIterator() const;
544     bool IsJSRegExpIterator() const;
545     bool IsJSMapIterator() const;
546     bool IsJSArrayIterator() const;
547     bool IsJSAPIArrayListIterator() const;
548     bool IsJSAPIStackIterator() const;
549     bool IsJSAPIVectorIterator() const;
550     bool IsJSAPILinkedListIterator() const;
551     bool IsJSAPIListIterator() const;
552     bool IsJSPrimitiveRef() const;
553     bool IsElementDict() const;
554     bool IsPropertiesDict() const;
555     bool IsTypedArray() const;
556 
557     static void DefinePropertyByLiteral(JSThread *thread, const JSHandle<JSObject> &obj,
558                                         const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
559                                         bool useForClass = false);
560     static void DefineSetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
561                              const JSHandle<JSTaggedValue> &value);
562     static void DefineGetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
563                              const JSHandle<JSTaggedValue> &value);
564     static JSHandle<JSObject> CreateObjectFromProperties(const JSThread *thread,
565                                                          const JSHandle<TaggedArray> &properties);
566     static void GetAllKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset,
567                            const JSHandle<TaggedArray> &keyArray);
568     static void GetAllKeys(const JSHandle<JSObject> &obj, std::vector<JSTaggedValue> &keyVector);
569     static void GetAllElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
570                                   const JSHandle<TaggedArray> &keyArray);
571     static void GetALLElementKeysIntoVector(const JSThread *thread, const JSHandle<JSObject> &obj,
572                                             std::vector<JSTaggedValue> &keyVector);
573     uint32_t GetNumberOfKeys();
574     uint32_t GetNumberOfElements();
575 
576     static JSHandle<TaggedArray> GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
577                                                     uint32_t numOfElements, uint32_t *keys);
578     static JSHandle<TaggedArray> GetAllEnumKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset,
579                                                 uint32_t numOfKeys, uint32_t *keys);
580 
581     static void AddAccessor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
582                             const JSHandle<AccessorData> &value, PropertyAttributes attr);
583 
584     static constexpr size_t PROPERTIES_OFFSET = ECMAObject::SIZE;
585 
586     ACCESSORS(Properties, PROPERTIES_OFFSET, ELEMENTS_OFFSET);
587     ACCESSORS(Elements, ELEMENTS_OFFSET, SIZE);
588 
589     DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, PROPERTIES_OFFSET, SIZE)
590 
591     DECL_DUMP()
592 
593     static JSHandle<NameDictionary> TransitionToDictionary(const JSThread *thread, const JSHandle<JSObject> &receiver);
594 
595     inline void SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value);
596     inline void SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index,
597                                         JSTaggedValue value);
598     inline JSTaggedValue GetPropertyInlinedProps(uint32_t index) const;
599     inline JSTaggedValue GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const;
600     inline JSTaggedValue GetProperty(const JSHClass *hclass, PropertyAttributes attr) const;
601     inline void SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr,
602                             JSTaggedValue value);
603 
604     static bool IsArrayLengthWritable(JSThread *thread, const JSHandle<JSObject> &receiver);
605     bool UpdatePropertyInDictionary(const JSThread *thread, JSTaggedValue key, JSTaggedValue value);
606     static bool ShouldTransToDict(uint32_t capacity, uint32_t index);
607     static JSHandle<TaggedArray> GrowElementsCapacity(const JSThread *thread, const JSHandle<JSObject> &obj,
608                                                       uint32_t capacity);
609 
610     static JSHandle<JSTaggedValue> IterableToList(JSThread *thread, const JSHandle<JSTaggedValue> &items,
611                                                   JSTaggedValue method = JSTaggedValue::Undefined());
612 
613 protected:
614     static void ElementsToDictionary(const JSThread *thread, JSHandle<JSObject> obj);
615 
616 private:
617     friend class ObjectOperator;
618     friend class LoadICRuntime;
619     friend class StoreICRuntime;
620     friend class ObjectFastOperator;
621     friend class ICRuntimeStub;
622     friend class RuntimeStubs;
623 
624     static bool AddElementInternal(
625         JSThread *thread, const JSHandle<JSObject> &receiver, uint32_t index, const JSHandle<JSTaggedValue> &value,
626         PropertyAttributes attr = PropertyAttributes(PropertyAttributes::GetDefaultAttributes()));
627 
628     static JSTaggedValue GetProperty(JSThread *thread, ObjectOperator *op);
629     static bool SetProperty(ObjectOperator *op, const JSHandle<JSTaggedValue> &value, bool mayThrow);
630     static void DeletePropertyInternal(JSThread *thread, const JSHandle<JSObject> &obj,
631                                        const JSHandle<JSTaggedValue> &key, uint32_t index);
632     int FindProperty(const JSHandle<JSTaggedValue> &key);
633 
634     static uint32_t ComputeElementCapacity(uint32_t oldCapacity);
635     static uint32_t ComputePropertyCapacity(uint32_t oldCapacity);
636 
637     static JSTaggedValue ShouldGetValueFromBox(ObjectOperator *op);
638     static std::pair<JSHandle<TaggedArray>, JSHandle<TaggedArray>> GetOwnEnumerableNamesInFastMode(
639         JSThread *thread, const JSHandle<JSObject> &obj, uint32_t *copyLengthOfKeys, uint32_t *copyLengthOfElements);
640     static bool CheckHClassHit(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &cls);
641     static uint32_t SetValuesOrEntries(JSThread *thread, const JSHandle<TaggedArray> &prop, uint32_t index,
642                                        const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
643                                        PropertyKind kind);
644 };
645 }  // namespace ecmascript
646 }  // namespace panda
647 
648 #endif
649