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