• 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_INL_H
17 #define ECMASCRIPT_JSOBJECT_INL_H
18 
19 #include "ecmascript/js_object.h"
20 
21 #include "ecmascript/element_accessor-inl.h"
22 #include "ecmascript/js_array.h"
23 #include "ecmascript/js_hclass-inl.h"
24 #include "ecmascript/js_tagged_value-inl.h"
25 #include "ecmascript/js_typed_array.h"
26 #include "ecmascript/tagged_array-inl.h"
27 #include "ecmascript/tagged_queue.h"
28 #include "ecmascript/tagged_dictionary.h"
29 
30 namespace panda::ecmascript {
SetCallable(bool flag)31 inline void ECMAObject::SetCallable(bool flag)
32 {
33     GetClass()->SetCallable(flag);
34 }
35 
IsCallable()36 inline bool ECMAObject::IsCallable() const
37 {
38     return GetClass()->IsCallable();
39 }
40 
41 // JSObject
IsExtensible()42 inline bool JSObject::IsExtensible() const
43 {
44     return GetJSHClass()->IsExtensible();
45 }
46 
FillElementsWithHoles(const JSThread * thread,uint32_t start,uint32_t end)47 inline void JSObject::FillElementsWithHoles(const JSThread *thread, uint32_t start, uint32_t end)
48 {
49     if (start >= end) {
50         return;
51     }
52 
53     JSHandle<JSObject> thisObj(thread, this);
54     for (uint32_t i = start; i < end; i++) {
55         ElementAccessor::Set(thread, thisObj, i, JSTaggedValue::Hole(), false);
56     }
57 }
58 
GetJSHClass()59 inline JSHClass *JSObject::GetJSHClass() const
60 {
61     return GetClass();
62 }
63 
GetNonInlinedFastPropsCapacity()64 inline uint32_t JSObject::GetNonInlinedFastPropsCapacity() const
65 {
66     uint32_t inlineProps = GetJSHClass()->GetInlinedProperties();
67     if (inlineProps < JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS) {
68         return PropertyAttributes::MAX_FAST_PROPS_CAPACITY - JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS;
69     }
70     return PropertyAttributes::MAX_FAST_PROPS_CAPACITY - inlineProps;
71 }
72 
IsJSGlobalObject()73 inline bool JSObject::IsJSGlobalObject() const
74 {
75     return GetJSHClass()->IsJSGlobalObject();
76 }
77 
IsConstructor()78 inline bool JSObject::IsConstructor() const
79 {
80     return GetJSHClass()->IsConstructor();
81 }
82 
IsECMAObject()83 inline bool JSObject::IsECMAObject() const
84 {
85     return GetJSHClass()->IsECMAObject();
86 }
87 
IsJSError()88 inline bool JSObject::IsJSError() const
89 {
90     return GetJSHClass()->IsJSError();
91 }
92 
IsArguments()93 inline bool JSObject::IsArguments() const
94 {
95     return GetJSHClass()->IsArguments();
96 }
97 
IsDate()98 inline bool JSObject::IsDate() const
99 {
100     return GetJSHClass()->IsDate();
101 }
102 
IsJSArray()103 inline bool JSObject::IsJSArray() const
104 {
105     return GetJSHClass()->IsJSArray();
106 }
107 
IsJSMap()108 inline bool JSObject::IsJSMap() const
109 {
110     return GetJSHClass()->IsJSMap();
111 }
112 
IsJSSet()113 inline bool JSObject::IsJSSet() const
114 {
115     return GetJSHClass()->IsJSSet();
116 }
117 
IsJSRegExp()118 inline bool JSObject::IsJSRegExp() const
119 {
120     return GetJSHClass()->IsJSRegExp();
121 }
122 
IsJSFunction()123 inline bool JSObject::IsJSFunction() const
124 {
125     return GetJSHClass()->IsJSFunction();
126 }
127 
IsBoundFunction()128 inline bool JSObject::IsBoundFunction() const
129 {
130     return GetJSHClass()->IsJsBoundFunction();
131 }
132 
IsJSIntlBoundFunction()133 inline bool JSObject::IsJSIntlBoundFunction() const
134 {
135     return GetJSHClass()->IsJSIntlBoundFunction();
136 }
137 
IsProxyRevocFunction()138 inline bool JSObject::IsProxyRevocFunction() const
139 {
140     return GetJSHClass()->IsJSProxyRevocFunction();
141 }
142 
IsAccessorData()143 inline bool JSObject::IsAccessorData() const
144 {
145     return GetJSHClass()->IsAccessorData();
146 }
147 
IsJSGlobalEnv()148 inline bool JSObject::IsJSGlobalEnv() const
149 {
150     return GetJSHClass()->IsJsGlobalEnv();
151 }
152 
IsJSProxy()153 inline bool JSObject::IsJSProxy() const
154 {
155     return GetJSHClass()->IsJSProxy();
156 }
157 
IsGeneratorObject()158 inline bool JSObject::IsGeneratorObject() const
159 {
160     return GetJSHClass()->IsGeneratorObject();
161 }
162 
IsAsyncGeneratorObject()163 inline bool JSObject::IsAsyncGeneratorObject() const
164 {
165     return GetJSHClass()->IsAsyncGeneratorObject();
166 }
167 
IsForinIterator()168 inline bool JSObject::IsForinIterator() const
169 {
170     return GetJSHClass()->IsForinIterator();
171 }
172 
IsJSSetIterator()173 inline bool JSObject::IsJSSetIterator() const
174 {
175     return GetJSHClass()->IsJSSetIterator();
176 }
177 
IsJSRegExpIterator()178 inline bool JSObject::IsJSRegExpIterator() const
179 {
180     return GetJSHClass()->IsJSRegExpIterator();
181 }
182 
IsJSMapIterator()183 inline bool JSObject::IsJSMapIterator() const
184 {
185     return GetJSHClass()->IsJSMapIterator();
186 }
187 
IsJSArrayIterator()188 inline bool JSObject::IsJSArrayIterator() const
189 {
190     return GetJSHClass()->IsJSArrayIterator();
191 }
192 
IsJSAPIArrayListIterator()193 inline bool JSObject::IsJSAPIArrayListIterator() const
194 {
195     return GetJSHClass()->IsJSAPIArrayListIterator();
196 }
197 
IsJSAPIStackIterator()198 inline bool JSObject::IsJSAPIStackIterator() const
199 {
200     return GetJSHClass()->IsJSAPIStackIterator();
201 }
202 
IsJSAPIVectorIterator()203 inline bool JSObject::IsJSAPIVectorIterator() const
204 {
205     return GetJSHClass()->IsJSAPIVectorIterator();
206 }
207 
IsJSAPILinkedListIterator()208 inline bool JSObject::IsJSAPILinkedListIterator() const
209 {
210     return GetJSHClass()->IsJSAPILinkedListIterator();
211 }
212 
IsJSAPIListIterator()213 inline bool JSObject::IsJSAPIListIterator() const
214 {
215     return GetJSHClass()->IsJSAPIListIterator();
216 }
217 
IsJSPrimitiveRef()218 inline bool JSObject::IsJSPrimitiveRef() const
219 {
220     return GetJSHClass()->IsJsPrimitiveRef();
221 }
222 
IsElementDict()223 inline bool JSObject::IsElementDict() const
224 {
225     return TaggedArray::Cast(GetElements().GetTaggedObject())->IsDictionaryMode();
226 }
227 
IsPropertiesDict()228 inline bool JSObject::IsPropertiesDict() const
229 {
230     return TaggedArray::Cast(GetProperties().GetTaggedObject())->IsDictionaryMode();
231 }
232 
IsTypedArray()233 inline bool JSObject::IsTypedArray() const
234 {
235     return GetJSHClass()->IsTypedArray();
236 }
237 
ConvertValueWithRep(PropertyAttributes attr,JSTaggedValue value)238 std::pair<bool, JSTaggedValue> JSObject::ConvertValueWithRep(PropertyAttributes attr, JSTaggedValue value)
239 {
240     if (attr.IsDoubleRep()) {
241         if (value.IsInt()) {
242             double doubleValue = value.GetInt();
243             return std::pair(true, JSTaggedValue(bit_cast<JSTaggedType>(doubleValue)));
244         } else if (value.IsDouble()) {
245             return std::pair(true, JSTaggedValue(bit_cast<JSTaggedType>(value.GetDouble())));
246         } else {
247             return std::pair(false, value);
248         }
249     } else if (attr.IsIntRep()) {
250         if (value.IsInt()) {
251             int intValue = value.GetInt();
252             return std::pair(true, JSTaggedValue(static_cast<JSTaggedType>(intValue)));
253         } else {
254             return std::pair(false, value);
255         }
256     }
257     return std::pair(true, value);
258 }
259 
SetPropertyInlinedPropsWithRep(const JSThread * thread,uint32_t index,JSTaggedValue value)260 void JSObject::SetPropertyInlinedPropsWithRep(const JSThread *thread, uint32_t index, JSTaggedValue value)
261 {
262     auto layout = LayoutInfo::Cast(GetJSHClass()->GetLayout().GetTaggedObject());
263     auto attr = layout->GetAttr(index);
264     if (attr.IsTaggedRep()) {
265         SetPropertyInlinedProps<true>(thread, index, value);
266     } else {
267         SetPropertyInlinedProps<false>(thread, index, value);
268     }
269 }
270 
271 template <bool needBarrier>
SetPropertyInlinedProps(const JSThread * thread,uint32_t index,JSTaggedValue value)272 void JSObject::SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value)
273 {
274     SetPropertyInlinedProps<needBarrier>(thread, GetJSHClass(), index, value);
275 }
276 
GetPropertyInlinedPropsWithRep(uint32_t index,PropertyAttributes attr)277 JSTaggedValue JSObject::GetPropertyInlinedPropsWithRep(uint32_t index, PropertyAttributes attr) const
278 {
279     return GetPropertyInlinedPropsWithRep(GetJSHClass(), index, attr);
280 }
281 
GetPropertyInlinedPropsWithRep(const JSHClass * hclass,uint32_t index,PropertyAttributes attr)282 JSTaggedValue JSObject::GetPropertyInlinedPropsWithRep(const JSHClass *hclass, uint32_t index,
283                                                        PropertyAttributes attr) const
284 {
285     auto value = GetPropertyInlinedProps(hclass, index);
286     if (attr.IsDoubleRep()) {
287         value = JSTaggedValue(bit_cast<double>(value.GetRawData()));
288     } else if (attr.IsIntRep()) {
289         value = JSTaggedValue(static_cast<int32_t>(value.GetRawData()));
290     }
291     return value;
292 }
293 
GetPropertyInlinedProps(uint32_t index)294 JSTaggedValue JSObject::GetPropertyInlinedProps(uint32_t index) const
295 {
296     return GetPropertyInlinedProps(GetJSHClass(), index);
297 }
298 
299 template <bool needBarrier>
SetPropertyInlinedProps(const JSThread * thread,const JSHClass * hclass,uint32_t index,JSTaggedValue value)300 void JSObject::SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index,
301                                        JSTaggedValue value)
302 {
303     uint32_t offset = hclass->GetInlinedPropertiesOffset(index);
304     if (needBarrier) {
305         SET_VALUE_WITH_BARRIER(thread, this, offset, value);
306     } else {
307         SET_VALUE_PRIMITIVE(this, offset, value);
308     }
309 }
310 
GetPropertyInlinedProps(const JSHClass * hclass,uint32_t index)311 JSTaggedValue JSObject::GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const
312 {
313     uint32_t offset = hclass->GetInlinedPropertiesOffset(index);
314     return JSTaggedValue(GET_VALUE(this, offset));
315 }
316 
GetProperty(const JSHClass * hclass,PropertyAttributes attr)317 JSTaggedValue JSObject::GetProperty(const JSHClass *hclass, PropertyAttributes attr) const
318 {
319     if (attr.IsInlinedProps()) {
320         return GetPropertyInlinedPropsWithRep(hclass, attr.GetOffset(), attr);
321     }
322     TaggedArray *array = TaggedArray::Cast(GetProperties().GetTaggedObject());
323     return array->Get(attr.GetOffset() - hclass->GetInlinedProperties());
324 }
325 
326 template <bool needBarrier>
SetProperty(const JSThread * thread,const JSHClass * hclass,PropertyAttributes attr,JSTaggedValue value)327 void JSObject::SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr, JSTaggedValue value)
328 {
329     if (attr.IsInlinedProps()) {
330         SetPropertyInlinedProps<needBarrier>(thread, hclass, attr.GetOffset(), value);
331     } else {
332         TaggedArray *array = TaggedArray::Cast(GetProperties().GetTaggedObject());
333         array->Set<needBarrier>(thread, attr.GetOffset() - hclass->GetInlinedProperties(), value);
334     }
335 }
336 
ShouldTransToDict(uint32_t capacity,uint32_t index)337 inline bool JSObject::ShouldTransToDict(uint32_t capacity, uint32_t index)
338 {
339     if (index < capacity) {
340         return false;
341     }
342 
343     if (index - capacity > MAX_GAP) {
344         return true;
345     }
346 
347     if (index >= static_cast<uint32_t>(INT32_MAX)) {
348         return true;
349     }
350 
351     if (capacity >= MIN_GAP) {
352         return index > capacity * FAST_ELEMENTS_FACTOR;
353     }
354 
355     return false;
356 }
357 
ShouldTransToFastElements(JSHandle<NumberDictionary> dictionary,uint32_t capacity,uint32_t index)358 inline bool JSObject::ShouldTransToFastElements(JSHandle<NumberDictionary> dictionary,
359                                                 uint32_t capacity, uint32_t index)
360 {
361     if (index >= static_cast<uint32_t>(INT32_MAX)) {
362         return false;
363     }
364     uint32_t dictionarySize = static_cast<uint32_t>(dictionary->GetLength());
365     // Turn fast if only saves 50% space.
366     if (dictionarySize * SHOULD_TRANS_TO_FAST_ELEMENTS_FACTOR >= capacity) {
367         return true;
368     }
369     return false;
370 }
371 
ComputeElementCapacity(uint32_t oldCapacity,bool isNew)372 inline uint32_t JSObject::ComputeElementCapacity(uint32_t oldCapacity, bool isNew)
373 {
374     uint32_t newCapacity = isNew ? oldCapacity : (oldCapacity + (oldCapacity >> 1U));
375     return newCapacity > MIN_ELEMENTS_LENGTH ? newCapacity : MIN_ELEMENTS_LENGTH;
376 }
377 
ComputeElementCapacityHighGrowth(uint32_t oldCapacity)378 inline uint32_t JSObject::ComputeElementCapacityHighGrowth(uint32_t oldCapacity)
379 {
380     uint32_t newCapacity = oldCapacity * 2;
381     return newCapacity > MIN_ELEMENTS_LENGTH ? newCapacity : MIN_ELEMENTS_LENGTH;
382 }
383 
ComputeElementCapacityWithHint(uint32_t oldCapacity,uint32_t hint)384 inline uint32_t JSObject::ComputeElementCapacityWithHint(uint32_t oldCapacity, uint32_t hint)
385 {
386     uint32_t newCapacity = 0;
387     if ((oldCapacity >= hint) || (hint < MIN_ELEMENTS_HINT_LENGTH) || (hint >= MAX_ELEMENTS_HINT_LENGTH)) {
388         return newCapacity;
389     }
390     if ((hint / oldCapacity) <= ELEMENTS_HINT_FACTOR) {
391         newCapacity = hint;
392     }
393     return newCapacity;
394 }
395 
ComputeNonInlinedFastPropsCapacity(JSThread * thread,uint32_t oldCapacity,uint32_t maxNonInlinedFastPropsCapacity)396 inline uint32_t JSObject::ComputeNonInlinedFastPropsCapacity(JSThread *thread, uint32_t oldCapacity,
397                                                              uint32_t maxNonInlinedFastPropsCapacity)
398 {
399     uint32_t newCapacity = oldCapacity + thread->GetPropertiesGrowStep();
400     return newCapacity > maxNonInlinedFastPropsCapacity ? maxNonInlinedFastPropsCapacity : newCapacity;
401 }
402 
403 // static
404 template<ElementTypes types>
CreateListFromArrayLike(JSThread * thread,const JSHandle<JSTaggedValue> & obj)405 JSHandle<JSTaggedValue> JSObject::CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
406 {
407     // 3. If Type(obj) is not Object, throw a TypeError exception.
408     if (!obj->IsECMAObject()) {
409         THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike must accept object",
410                                     JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
411     }
412     // 4. Let len be ToLength(Get(obj, "length")).
413     JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();
414 
415     JSHandle<JSTaggedValue> value = GetProperty(thread, obj, lengthKeyHandle).GetValue();
416     JSTaggedNumber number = JSTaggedValue::ToLength(thread, value);
417     // 5. ReturnIfAbrupt(len).
418     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
419     if (number.GetNumber() > MAX_ELEMENT_INDEX) {
420         THROW_TYPE_ERROR_AND_RETURN(thread, "len is bigger than 2^32 - 1",
421                                     JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
422     }
423 
424     uint32_t len = number.ToUint32();
425     // 6. Let list be an empty List.
426     JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len);
427 
428     if (obj->IsTypedArray()) {
429         JSTypedArray::FastCopyElementToArray(thread, obj, array);
430         // c. ReturnIfAbrupt(next).
431         RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
432         return JSHandle<JSTaggedValue>(array);
433     }
434     // 8. Repeat while index < len
435     for (uint32_t i = 0; i < len; i++) {
436         JSTaggedValue next = JSTaggedValue::GetProperty(thread, obj, i).GetValue().GetTaggedValue();
437         // c. ReturnIfAbrupt(next).
438         RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
439 
440         if constexpr (types == ElementTypes::STRING_AND_SYMBOL) {
441             if (!next.IsString() && !next.IsSymbol()) {
442                 THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike: not an element of elementTypes",
443                                             JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
444             }
445         }
446 
447         array->Set(thread, i, next);
448     }
449     return JSHandle<JSTaggedValue>(array);
450 }
451 
ShouldGetValueFromBox(ObjectOperator * op)452 inline JSTaggedValue JSObject::ShouldGetValueFromBox(ObjectOperator *op)
453 {
454     JSTaggedValue result = op->GetValue();
455     if (result.IsPropertyBox()) {
456         result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
457     }
458     return result;
459 }
460 
CheckHClassHit(const JSHandle<JSObject> & obj,const JSHandle<JSHClass> & cls)461 inline bool JSObject::CheckHClassHit(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &cls)
462 {
463     return obj->GetJSHClass() == *cls;
464 }
465 
SetValuesOrEntries(JSThread * thread,const JSHandle<TaggedArray> & prop,uint32_t index,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value,PropertyKind kind)466 inline uint32_t JSObject::SetValuesOrEntries(JSThread *thread, const JSHandle<TaggedArray> &prop, uint32_t index,
467                                              const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
468                                              PropertyKind kind)
469 {
470     if (kind == PropertyKind::VALUE) {
471         prop->Set(thread, index++, value);
472         return index;
473     }
474     JSHandle<TaggedArray> keyValue = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(2);  // 2: key-value pair
475     keyValue->Set(thread, 0, key);
476     keyValue->Set(thread, 1, value);
477     JSHandle<JSArray> entry = JSArray::CreateArrayFromList(thread, keyValue);
478     prop->Set(thread, index++, entry.GetTaggedValue());
479     return index;
480 }
481 
SetEnumCacheKind(JSThread * thread,TaggedArray * array,EnumCacheKind kind)482 inline void JSObject::SetEnumCacheKind(JSThread *thread, TaggedArray *array, EnumCacheKind kind)
483 {
484     array->Set(thread, EnumCache::ENUM_CACHE_KIND_OFFSET, JSTaggedValue(static_cast<uint8_t>(kind)));
485 }
486 
GetEnumCacheKind(JSThread * thread,TaggedArray * array)487 inline EnumCacheKind JSObject::GetEnumCacheKind(JSThread *thread, TaggedArray *array)
488 {
489     return static_cast<EnumCacheKind>(array->Get(thread, EnumCache::ENUM_CACHE_KIND_OFFSET).GetInt());
490 }
491 
GetEnumCacheKind(JSThread * thread,JSTaggedValue enumCache)492 inline EnumCacheKind JSObject::GetEnumCacheKind(JSThread *thread, JSTaggedValue enumCache)
493 {
494     if (enumCache.IsUndefinedOrNull()) {
495         return EnumCacheKind::NONE;
496     }
497     JSTaggedValue emptyArray = thread->GlobalConstants()->GetEmptyArray();
498     if (enumCache == emptyArray) {
499         return EnumCacheKind::SIMPLE;
500     }
501     TaggedArray *array = TaggedArray::Cast(enumCache.GetTaggedObject());
502     return JSObject::GetEnumCacheKind(thread, array);
503 }
504 
GetPrototype(JSTaggedValue obj)505 inline JSTaggedValue JSObject::GetPrototype(JSTaggedValue obj)
506 {
507     JSHClass *hclass = obj.GetTaggedObject()->GetClass();
508     return hclass->GetPrototype();
509 }
510 
IsDepulicateKeys(JSThread * thread,JSHandle<TaggedArray> keys,int32_t lastLength,JSHandle<TaggedQueue> shadowQueue,JSHandle<JSTaggedValue> key)511 inline bool JSObject::IsDepulicateKeys(JSThread *thread, JSHandle<TaggedArray> keys, int32_t lastLength,
512                                        JSHandle<TaggedQueue> shadowQueue, JSHandle<JSTaggedValue> key)
513 {
514     if (lastLength < 0) {
515         return false;
516     }
517     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
518     for (int32_t i = EnumCache::ENUM_CACHE_HEADER_SIZE; i < lastLength; i++) {
519         value.Update(keys->Get(i));
520         bool has = JSTaggedValue::Equal(thread, value, key);
521         if (has) {
522             return true;
523         }
524     }
525 
526     uint32_t shadowSize = shadowQueue->Size();
527     for (uint32_t i = 0; i < shadowSize; i++) {
528         value.Update(shadowQueue->Get(i));
529         bool has = JSTaggedValue::Equal(thread, value, key);
530         if (has) {
531             return true;
532         }
533     }
534     return false;
535 }
536 
ClearHasDeleteProperty(JSHandle<JSTaggedValue> object)537 inline void JSObject::ClearHasDeleteProperty(JSHandle<JSTaggedValue> object)
538 {
539     object->GetTaggedObject()->GetClass()->SetHasDeleteProperty(false);
540 }
541 
GetOwnEnumerableNamesInFastMode(JSThread * thread,const JSHandle<JSObject> & obj,uint32_t * copyLengthOfKeys,uint32_t * copyLengthOfElements)542 inline std::pair<JSHandle<TaggedArray>, JSHandle<TaggedArray>> JSObject::GetOwnEnumerableNamesInFastMode(
543     JSThread *thread, const JSHandle<JSObject> &obj, uint32_t *copyLengthOfKeys, uint32_t *copyLengthOfElements)
544 {
545     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
546     std::pair<uint32_t, uint32_t> numOfKeys = obj->GetNumberOfEnumKeys();
547     uint32_t numOfEnumKeys = numOfKeys.first;
548     uint32_t numOfElements = obj->GetNumberOfElements();
549     JSHandle<TaggedArray> elementArray = numOfElements > 0 ? JSObject::GetEnumElementKeys(
550         thread, obj, 0, numOfElements, copyLengthOfElements) : factory->EmptyArray();
551     JSHandle<TaggedArray> keyArray = numOfEnumKeys > 0 ? JSObject::GetAllEnumKeys(
552         thread, obj, numOfEnumKeys, copyLengthOfKeys) : factory->EmptyArray();
553     return std::make_pair(keyArray, elementArray);
554 }
555 
556 }  //  namespace panda::ecmascript
557 #endif  // ECMASCRIPT_JSOBJECT_INL_H
558