14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_JSOBJECT_INL_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_JSOBJECT_INL_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/js_object.h"
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_ci#include "ecmascript/element_accessor-inl.h"
224514f5e3Sopenharmony_ci#include "ecmascript/js_array.h"
234514f5e3Sopenharmony_ci#include "ecmascript/js_hclass-inl.h"
244514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value-inl.h"
254514f5e3Sopenharmony_ci#include "ecmascript/js_typed_array.h"
264514f5e3Sopenharmony_ci#include "ecmascript/object_operator.h"
274514f5e3Sopenharmony_ci#include "ecmascript/tagged_array-inl.h"
284514f5e3Sopenharmony_ci#include "ecmascript/tagged_queue.h"
294514f5e3Sopenharmony_ci#include "ecmascript/tagged_dictionary.h"
304514f5e3Sopenharmony_ci
314514f5e3Sopenharmony_cinamespace panda::ecmascript {
324514f5e3Sopenharmony_ciinline void ECMAObject::SetCallable(bool flag)
334514f5e3Sopenharmony_ci{
344514f5e3Sopenharmony_ci    GetClass()->SetCallable(flag);
354514f5e3Sopenharmony_ci}
364514f5e3Sopenharmony_ci
374514f5e3Sopenharmony_ciinline bool ECMAObject::IsCallable() const
384514f5e3Sopenharmony_ci{
394514f5e3Sopenharmony_ci    return GetClass()->IsCallable();
404514f5e3Sopenharmony_ci}
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ci// JSObject
434514f5e3Sopenharmony_ciinline bool JSObject::IsExtensible() const
444514f5e3Sopenharmony_ci{
454514f5e3Sopenharmony_ci    return GetJSHClass()->IsExtensible();
464514f5e3Sopenharmony_ci}
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ciinline void JSObject::FillElementsWithHoles(const JSThread *thread, uint32_t start, uint32_t end)
494514f5e3Sopenharmony_ci{
504514f5e3Sopenharmony_ci    if (start >= end) {
514514f5e3Sopenharmony_ci        return;
524514f5e3Sopenharmony_ci    }
534514f5e3Sopenharmony_ci
544514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> holeHandle(thread, JSTaggedValue::Hole());
554514f5e3Sopenharmony_ci    JSHandle<JSObject> thisObj(thread, this);
564514f5e3Sopenharmony_ci    for (uint32_t i = start; i < end; i++) {
574514f5e3Sopenharmony_ci        ElementAccessor::Set(thread, thisObj, i, holeHandle, false);
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci}
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ciinline uint32_t JSObject::GetNonInlinedFastPropsCapacity() const
624514f5e3Sopenharmony_ci{
634514f5e3Sopenharmony_ci    uint32_t inlineProps = GetJSHClass()->GetInlinedProperties();
644514f5e3Sopenharmony_ci    return PropertyAttributes::MAX_FAST_PROPS_CAPACITY - inlineProps;
654514f5e3Sopenharmony_ci}
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_ciinline bool JSObject::IsJSGlobalObject() const
684514f5e3Sopenharmony_ci{
694514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSGlobalObject();
704514f5e3Sopenharmony_ci}
714514f5e3Sopenharmony_ci
724514f5e3Sopenharmony_ciinline bool JSObject::IsConstructor() const
734514f5e3Sopenharmony_ci{
744514f5e3Sopenharmony_ci    return GetJSHClass()->IsConstructor();
754514f5e3Sopenharmony_ci}
764514f5e3Sopenharmony_ci
774514f5e3Sopenharmony_ciinline bool JSObject::IsECMAObject() const
784514f5e3Sopenharmony_ci{
794514f5e3Sopenharmony_ci    return GetJSHClass()->IsECMAObject();
804514f5e3Sopenharmony_ci}
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ciinline bool JSObject::IsJSError() const
834514f5e3Sopenharmony_ci{
844514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSError();
854514f5e3Sopenharmony_ci}
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ciinline bool JSObject::IsArguments() const
884514f5e3Sopenharmony_ci{
894514f5e3Sopenharmony_ci    return GetJSHClass()->IsArguments();
904514f5e3Sopenharmony_ci}
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ciinline bool JSObject::IsDate() const
934514f5e3Sopenharmony_ci{
944514f5e3Sopenharmony_ci    return GetJSHClass()->IsDate();
954514f5e3Sopenharmony_ci}
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ciinline bool JSObject::IsJSArray() const
984514f5e3Sopenharmony_ci{
994514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSArray();
1004514f5e3Sopenharmony_ci}
1014514f5e3Sopenharmony_ci
1024514f5e3Sopenharmony_ciinline bool JSObject::IsJSSArray() const
1034514f5e3Sopenharmony_ci{
1044514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSSharedArray();
1054514f5e3Sopenharmony_ci}
1064514f5e3Sopenharmony_ci
1074514f5e3Sopenharmony_ciinline bool JSObject::IsJSShared() const
1084514f5e3Sopenharmony_ci{
1094514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSShared();
1104514f5e3Sopenharmony_ci}
1114514f5e3Sopenharmony_ci
1124514f5e3Sopenharmony_ciinline bool JSObject::IsJSMap() const
1134514f5e3Sopenharmony_ci{
1144514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSMap();
1154514f5e3Sopenharmony_ci}
1164514f5e3Sopenharmony_ci
1174514f5e3Sopenharmony_ciinline bool JSObject::IsJSSet() const
1184514f5e3Sopenharmony_ci{
1194514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSSet();
1204514f5e3Sopenharmony_ci}
1214514f5e3Sopenharmony_ci
1224514f5e3Sopenharmony_ciinline bool JSObject::IsJSRegExp() const
1234514f5e3Sopenharmony_ci{
1244514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSRegExp();
1254514f5e3Sopenharmony_ci}
1264514f5e3Sopenharmony_ci
1274514f5e3Sopenharmony_ciinline bool JSObject::IsJSFunction() const
1284514f5e3Sopenharmony_ci{
1294514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSFunction();
1304514f5e3Sopenharmony_ci}
1314514f5e3Sopenharmony_ci
1324514f5e3Sopenharmony_ciinline bool JSObject::IsBoundFunction() const
1334514f5e3Sopenharmony_ci{
1344514f5e3Sopenharmony_ci    return GetJSHClass()->IsJsBoundFunction();
1354514f5e3Sopenharmony_ci}
1364514f5e3Sopenharmony_ci
1374514f5e3Sopenharmony_ciinline bool JSObject::IsJSIntlBoundFunction() const
1384514f5e3Sopenharmony_ci{
1394514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSIntlBoundFunction();
1404514f5e3Sopenharmony_ci}
1414514f5e3Sopenharmony_ci
1424514f5e3Sopenharmony_ciinline bool JSObject::IsProxyRevocFunction() const
1434514f5e3Sopenharmony_ci{
1444514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSProxyRevocFunction();
1454514f5e3Sopenharmony_ci}
1464514f5e3Sopenharmony_ci
1474514f5e3Sopenharmony_ciinline bool JSObject::IsAccessorData() const
1484514f5e3Sopenharmony_ci{
1494514f5e3Sopenharmony_ci    return GetJSHClass()->IsAccessorData();
1504514f5e3Sopenharmony_ci}
1514514f5e3Sopenharmony_ci
1524514f5e3Sopenharmony_ciinline bool JSObject::IsJSGlobalEnv() const
1534514f5e3Sopenharmony_ci{
1544514f5e3Sopenharmony_ci    return GetJSHClass()->IsJsGlobalEnv();
1554514f5e3Sopenharmony_ci}
1564514f5e3Sopenharmony_ci
1574514f5e3Sopenharmony_ciinline bool JSObject::IsJSProxy() const
1584514f5e3Sopenharmony_ci{
1594514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSProxy();
1604514f5e3Sopenharmony_ci}
1614514f5e3Sopenharmony_ci
1624514f5e3Sopenharmony_ciinline bool JSObject::IsGeneratorObject() const
1634514f5e3Sopenharmony_ci{
1644514f5e3Sopenharmony_ci    return GetJSHClass()->IsGeneratorObject();
1654514f5e3Sopenharmony_ci}
1664514f5e3Sopenharmony_ci
1674514f5e3Sopenharmony_ciinline bool JSObject::IsAsyncGeneratorObject() const
1684514f5e3Sopenharmony_ci{
1694514f5e3Sopenharmony_ci    return GetJSHClass()->IsAsyncGeneratorObject();
1704514f5e3Sopenharmony_ci}
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ciinline bool JSObject::IsForinIterator() const
1734514f5e3Sopenharmony_ci{
1744514f5e3Sopenharmony_ci    return GetJSHClass()->IsForinIterator();
1754514f5e3Sopenharmony_ci}
1764514f5e3Sopenharmony_ci
1774514f5e3Sopenharmony_ciinline bool JSObject::IsJSSetIterator() const
1784514f5e3Sopenharmony_ci{
1794514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSSetIterator();
1804514f5e3Sopenharmony_ci}
1814514f5e3Sopenharmony_ci
1824514f5e3Sopenharmony_ciinline bool JSObject::IsJSRegExpIterator() const
1834514f5e3Sopenharmony_ci{
1844514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSRegExpIterator();
1854514f5e3Sopenharmony_ci}
1864514f5e3Sopenharmony_ci
1874514f5e3Sopenharmony_ciinline bool JSObject::IsJSMapIterator() const
1884514f5e3Sopenharmony_ci{
1894514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSMapIterator();
1904514f5e3Sopenharmony_ci}
1914514f5e3Sopenharmony_ci
1924514f5e3Sopenharmony_ciinline bool JSObject::IsJSArrayIterator() const
1934514f5e3Sopenharmony_ci{
1944514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSArrayIterator();
1954514f5e3Sopenharmony_ci}
1964514f5e3Sopenharmony_ci
1974514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIArrayListIterator() const
1984514f5e3Sopenharmony_ci{
1994514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSAPIArrayListIterator();
2004514f5e3Sopenharmony_ci}
2014514f5e3Sopenharmony_ci
2024514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIStackIterator() const
2034514f5e3Sopenharmony_ci{
2044514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSAPIStackIterator();
2054514f5e3Sopenharmony_ci}
2064514f5e3Sopenharmony_ci
2074514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIVectorIterator() const
2084514f5e3Sopenharmony_ci{
2094514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSAPIVectorIterator();
2104514f5e3Sopenharmony_ci}
2114514f5e3Sopenharmony_ci
2124514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIBitVectorIterator() const
2134514f5e3Sopenharmony_ci{
2144514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSAPIBitVectorIterator();
2154514f5e3Sopenharmony_ci}
2164514f5e3Sopenharmony_ci
2174514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPILinkedListIterator() const
2184514f5e3Sopenharmony_ci{
2194514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSAPILinkedListIterator();
2204514f5e3Sopenharmony_ci}
2214514f5e3Sopenharmony_ci
2224514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIListIterator() const
2234514f5e3Sopenharmony_ci{
2244514f5e3Sopenharmony_ci    return GetJSHClass()->IsJSAPIListIterator();
2254514f5e3Sopenharmony_ci}
2264514f5e3Sopenharmony_ci
2274514f5e3Sopenharmony_ciinline bool JSObject::IsJSPrimitiveRef() const
2284514f5e3Sopenharmony_ci{
2294514f5e3Sopenharmony_ci    return GetJSHClass()->IsJsPrimitiveRef();
2304514f5e3Sopenharmony_ci}
2314514f5e3Sopenharmony_ci
2324514f5e3Sopenharmony_ciinline bool JSObject::IsElementDict() const
2334514f5e3Sopenharmony_ci{
2344514f5e3Sopenharmony_ci    return TaggedArray::Cast(GetElements().GetTaggedObject())->IsDictionaryMode();
2354514f5e3Sopenharmony_ci}
2364514f5e3Sopenharmony_ci
2374514f5e3Sopenharmony_ciinline bool JSObject::IsPropertiesDict() const
2384514f5e3Sopenharmony_ci{
2394514f5e3Sopenharmony_ci    return TaggedArray::Cast(GetProperties().GetTaggedObject())->IsDictionaryMode();
2404514f5e3Sopenharmony_ci}
2414514f5e3Sopenharmony_ci
2424514f5e3Sopenharmony_ciinline bool JSObject::IsTypedArray() const
2434514f5e3Sopenharmony_ci{
2444514f5e3Sopenharmony_ci    return GetJSHClass()->IsTypedArray();
2454514f5e3Sopenharmony_ci}
2464514f5e3Sopenharmony_ci
2474514f5e3Sopenharmony_cistd::pair<bool, JSTaggedValue> JSObject::ConvertValueWithRep(PropertyAttributes attr, JSTaggedValue value)
2484514f5e3Sopenharmony_ci{
2494514f5e3Sopenharmony_ci    if (attr.IsDoubleRep()) {
2504514f5e3Sopenharmony_ci        if (value.IsInt()) {
2514514f5e3Sopenharmony_ci            double doubleValue = value.GetInt();
2524514f5e3Sopenharmony_ci            return std::pair(true, JSTaggedValue(bit_cast<JSTaggedType>(doubleValue)));
2534514f5e3Sopenharmony_ci        } else if (value.IsDouble()) {
2544514f5e3Sopenharmony_ci            return std::pair(true, JSTaggedValue(bit_cast<JSTaggedType>(value.GetDouble())));
2554514f5e3Sopenharmony_ci        } else {
2564514f5e3Sopenharmony_ci            return std::pair(false, value);
2574514f5e3Sopenharmony_ci        }
2584514f5e3Sopenharmony_ci    } else if (attr.IsIntRep()) {
2594514f5e3Sopenharmony_ci        if (value.IsInt()) {
2604514f5e3Sopenharmony_ci            int intValue = value.GetInt();
2614514f5e3Sopenharmony_ci            return std::pair(true, JSTaggedValue(static_cast<JSTaggedType>(intValue)));
2624514f5e3Sopenharmony_ci        } else {
2634514f5e3Sopenharmony_ci            return std::pair(false, value);
2644514f5e3Sopenharmony_ci        }
2654514f5e3Sopenharmony_ci    }
2664514f5e3Sopenharmony_ci    return std::pair(true, value);
2674514f5e3Sopenharmony_ci}
2684514f5e3Sopenharmony_ci
2694514f5e3Sopenharmony_civoid JSObject::SetPropertyInlinedPropsWithRep(const JSThread *thread, uint32_t index, JSTaggedValue value)
2704514f5e3Sopenharmony_ci{
2714514f5e3Sopenharmony_ci    auto layout = LayoutInfo::Cast(GetJSHClass()->GetLayout().GetTaggedObject());
2724514f5e3Sopenharmony_ci    auto attr = layout->GetAttr(index);
2734514f5e3Sopenharmony_ci    if (attr.IsTaggedRep()) {
2744514f5e3Sopenharmony_ci        SetPropertyInlinedProps<true>(thread, index, value);
2754514f5e3Sopenharmony_ci    } else {
2764514f5e3Sopenharmony_ci        SetPropertyInlinedProps<false>(thread, index, value);
2774514f5e3Sopenharmony_ci    }
2784514f5e3Sopenharmony_ci}
2794514f5e3Sopenharmony_ci
2804514f5e3Sopenharmony_citemplate <bool needBarrier>
2814514f5e3Sopenharmony_civoid JSObject::SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value)
2824514f5e3Sopenharmony_ci{
2834514f5e3Sopenharmony_ci    SetPropertyInlinedProps<needBarrier>(thread, GetJSHClass(), index, value);
2844514f5e3Sopenharmony_ci}
2854514f5e3Sopenharmony_ci
2864514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetPropertyInlinedPropsWithRep(uint32_t index, PropertyAttributes attr) const
2874514f5e3Sopenharmony_ci{
2884514f5e3Sopenharmony_ci    return GetPropertyInlinedPropsWithRep(GetJSHClass(), index, attr);
2894514f5e3Sopenharmony_ci}
2904514f5e3Sopenharmony_ci
2914514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetPropertyInlinedPropsWithRep(const JSHClass *hclass, uint32_t index,
2924514f5e3Sopenharmony_ci                                                       PropertyAttributes attr) const
2934514f5e3Sopenharmony_ci{
2944514f5e3Sopenharmony_ci    auto value = GetPropertyInlinedProps(hclass, index);
2954514f5e3Sopenharmony_ci    if (attr.IsDoubleRep()) {
2964514f5e3Sopenharmony_ci        value = JSTaggedValue(bit_cast<double>(value.GetRawData()));
2974514f5e3Sopenharmony_ci    } else if (attr.IsIntRep()) {
2984514f5e3Sopenharmony_ci        value = JSTaggedValue(static_cast<int32_t>(value.GetRawData()));
2994514f5e3Sopenharmony_ci    }
3004514f5e3Sopenharmony_ci    return value;
3014514f5e3Sopenharmony_ci}
3024514f5e3Sopenharmony_ci
3034514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetPropertyInlinedProps(uint32_t index) const
3044514f5e3Sopenharmony_ci{
3054514f5e3Sopenharmony_ci    return GetPropertyInlinedProps(GetJSHClass(), index);
3064514f5e3Sopenharmony_ci}
3074514f5e3Sopenharmony_ci
3084514f5e3Sopenharmony_citemplate <bool needBarrier>
3094514f5e3Sopenharmony_civoid JSObject::SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index,
3104514f5e3Sopenharmony_ci                                       JSTaggedValue value)
3114514f5e3Sopenharmony_ci{
3124514f5e3Sopenharmony_ci    uint32_t offset = hclass->GetInlinedPropertiesOffset(index);
3134514f5e3Sopenharmony_ci    ASSERT(hclass->GetObjectSize() > offset);
3144514f5e3Sopenharmony_ci    if constexpr (needBarrier) {
3154514f5e3Sopenharmony_ci        SET_VALUE_WITH_BARRIER(thread, this, offset, value);
3164514f5e3Sopenharmony_ci    } else {
3174514f5e3Sopenharmony_ci        SET_VALUE_PRIMITIVE(this, offset, value);
3184514f5e3Sopenharmony_ci    }
3194514f5e3Sopenharmony_ci}
3204514f5e3Sopenharmony_ci
3214514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const
3224514f5e3Sopenharmony_ci{
3234514f5e3Sopenharmony_ci    uint32_t offset = hclass->GetInlinedPropertiesOffset(index);
3244514f5e3Sopenharmony_ci    return JSTaggedValue(GET_VALUE(this, offset));
3254514f5e3Sopenharmony_ci}
3264514f5e3Sopenharmony_ci
3274514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetProperty(const JSHClass *hclass, PropertyAttributes attr) const
3284514f5e3Sopenharmony_ci{
3294514f5e3Sopenharmony_ci    if (attr.IsInlinedProps()) {
3304514f5e3Sopenharmony_ci        return GetPropertyInlinedPropsWithRep(hclass, attr.GetOffset(), attr);
3314514f5e3Sopenharmony_ci    }
3324514f5e3Sopenharmony_ci    TaggedArray *array = TaggedArray::Cast(GetProperties().GetTaggedObject());
3334514f5e3Sopenharmony_ci    return array->Get(attr.GetOffset() - hclass->GetInlinedProperties());
3344514f5e3Sopenharmony_ci}
3354514f5e3Sopenharmony_ci
3364514f5e3Sopenharmony_citemplate <bool needBarrier>
3374514f5e3Sopenharmony_civoid JSObject::SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr, JSTaggedValue value)
3384514f5e3Sopenharmony_ci{
3394514f5e3Sopenharmony_ci    if (attr.IsInlinedProps()) {
3404514f5e3Sopenharmony_ci        SetPropertyInlinedProps<needBarrier>(thread, hclass, attr.GetOffset(), value);
3414514f5e3Sopenharmony_ci    } else {
3424514f5e3Sopenharmony_ci        TaggedArray *array = TaggedArray::Cast(GetProperties().GetTaggedObject());
3434514f5e3Sopenharmony_ci        array->Set<needBarrier>(thread, attr.GetOffset() - hclass->GetInlinedProperties(), value);
3444514f5e3Sopenharmony_ci    }
3454514f5e3Sopenharmony_ci}
3464514f5e3Sopenharmony_ci
3474514f5e3Sopenharmony_ciinline bool JSObject::ShouldTransToDict(uint32_t capacity, uint32_t index)
3484514f5e3Sopenharmony_ci{
3494514f5e3Sopenharmony_ci    if (index < capacity) {
3504514f5e3Sopenharmony_ci        return false;
3514514f5e3Sopenharmony_ci    }
3524514f5e3Sopenharmony_ci
3534514f5e3Sopenharmony_ci    if (index - capacity > MAX_GAP) {
3544514f5e3Sopenharmony_ci        return true;
3554514f5e3Sopenharmony_ci    }
3564514f5e3Sopenharmony_ci
3574514f5e3Sopenharmony_ci    if (index >= static_cast<uint32_t>(INT32_MAX)) {
3584514f5e3Sopenharmony_ci        return true;
3594514f5e3Sopenharmony_ci    }
3604514f5e3Sopenharmony_ci
3614514f5e3Sopenharmony_ci    if (capacity >= MIN_GAP) {
3624514f5e3Sopenharmony_ci        return index > capacity * FAST_ELEMENTS_FACTOR;
3634514f5e3Sopenharmony_ci    }
3644514f5e3Sopenharmony_ci
3654514f5e3Sopenharmony_ci    return false;
3664514f5e3Sopenharmony_ci}
3674514f5e3Sopenharmony_ci
3684514f5e3Sopenharmony_ciinline bool JSObject::ShouldTransToFastElements(JSThread *thread, TaggedArray *elements,
3694514f5e3Sopenharmony_ci                                                uint32_t capacity, uint32_t index)
3704514f5e3Sopenharmony_ci{
3714514f5e3Sopenharmony_ci    JSHandle<NumberDictionary> dictionary(thread, elements);
3724514f5e3Sopenharmony_ci    if (index >= static_cast<uint32_t>(INT32_MAX)) {
3734514f5e3Sopenharmony_ci        return false;
3744514f5e3Sopenharmony_ci    }
3754514f5e3Sopenharmony_ci    // Turn fast if only saves 50% space.
3764514f5e3Sopenharmony_ci    if (static_cast<uint32_t>(dictionary->GetLength()) * SHOULD_TRANS_TO_FAST_ELEMENTS_FACTOR >= capacity ||
3774514f5e3Sopenharmony_ci        static_cast<uint64_t>(dictionary->NextEnumerationIndex(thread)) >
3784514f5e3Sopenharmony_ci        PropertyAttributes::DictionaryOrderField::MaxValue()) {
3794514f5e3Sopenharmony_ci        return true;
3804514f5e3Sopenharmony_ci    }
3814514f5e3Sopenharmony_ci    return false;
3824514f5e3Sopenharmony_ci}
3834514f5e3Sopenharmony_ci
3844514f5e3Sopenharmony_ciinline uint32_t JSObject::ComputeElementCapacity(uint32_t oldCapacity, bool isNew)
3854514f5e3Sopenharmony_ci{
3864514f5e3Sopenharmony_ci    uint32_t newCapacity = isNew ? oldCapacity : (oldCapacity + (oldCapacity >> 1U));
3874514f5e3Sopenharmony_ci    return newCapacity > MIN_ELEMENTS_LENGTH ? newCapacity : MIN_ELEMENTS_LENGTH;
3884514f5e3Sopenharmony_ci}
3894514f5e3Sopenharmony_ci
3904514f5e3Sopenharmony_ciinline uint32_t JSObject::ComputeElementCapacityHighGrowth(uint32_t oldCapacity)
3914514f5e3Sopenharmony_ci{
3924514f5e3Sopenharmony_ci    uint32_t newCapacity = oldCapacity * 2;
3934514f5e3Sopenharmony_ci    return newCapacity > MIN_ELEMENTS_LENGTH ? newCapacity : MIN_ELEMENTS_LENGTH;
3944514f5e3Sopenharmony_ci}
3954514f5e3Sopenharmony_ci
3964514f5e3Sopenharmony_ciinline uint32_t JSObject::ComputeElementCapacityWithHint(uint32_t oldCapacity, uint32_t hint)
3974514f5e3Sopenharmony_ci{
3984514f5e3Sopenharmony_ci    uint32_t newCapacity = 0;
3994514f5e3Sopenharmony_ci    if ((oldCapacity >= hint) || (hint < MIN_ELEMENTS_HINT_LENGTH) || (hint >= MAX_ELEMENTS_HINT_LENGTH)) {
4004514f5e3Sopenharmony_ci        return newCapacity;
4014514f5e3Sopenharmony_ci    }
4024514f5e3Sopenharmony_ci    if ((hint / oldCapacity) <= ELEMENTS_HINT_FACTOR) {
4034514f5e3Sopenharmony_ci        newCapacity = hint;
4044514f5e3Sopenharmony_ci    }
4054514f5e3Sopenharmony_ci    return newCapacity;
4064514f5e3Sopenharmony_ci}
4074514f5e3Sopenharmony_ci
4084514f5e3Sopenharmony_ciinline uint32_t JSObject::ComputeNonInlinedFastPropsCapacity(JSThread *thread, uint32_t oldCapacity,
4094514f5e3Sopenharmony_ci                                                             uint32_t maxNonInlinedFastPropsCapacity)
4104514f5e3Sopenharmony_ci{
4114514f5e3Sopenharmony_ci    uint32_t newCapacity = oldCapacity + thread->GetPropertiesGrowStep();
4124514f5e3Sopenharmony_ci    return newCapacity > maxNonInlinedFastPropsCapacity ? maxNonInlinedFastPropsCapacity : newCapacity;
4134514f5e3Sopenharmony_ci}
4144514f5e3Sopenharmony_ci
4154514f5e3Sopenharmony_ci// static
4164514f5e3Sopenharmony_citemplate<ElementTypes types>
4174514f5e3Sopenharmony_ciJSHandle<JSTaggedValue> JSObject::CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
4184514f5e3Sopenharmony_ci{
4194514f5e3Sopenharmony_ci    // 3. If Type(obj) is not Object, throw a TypeError exception.
4204514f5e3Sopenharmony_ci    if (!obj->IsECMAObject()) {
4214514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike must accept object",
4224514f5e3Sopenharmony_ci                                    JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
4234514f5e3Sopenharmony_ci    }
4244514f5e3Sopenharmony_ci    if (obj->IsTypedArray()) {
4254514f5e3Sopenharmony_ci        uint32_t len = JSHandle<JSTypedArray>::Cast(obj)->GetArrayLength();
4264514f5e3Sopenharmony_ci        JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len);
4274514f5e3Sopenharmony_ci        JSTypedArray::FastCopyElementToArray(thread, obj, array);
4284514f5e3Sopenharmony_ci        // c. ReturnIfAbrupt(next).
4294514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
4304514f5e3Sopenharmony_ci        return JSHandle<JSTaggedValue>(array);
4314514f5e3Sopenharmony_ci    }
4324514f5e3Sopenharmony_ci    // 4. Let len be ToLength(Get(obj, "length")).
4334514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();
4344514f5e3Sopenharmony_ci
4354514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> value = GetProperty(thread, obj, lengthKeyHandle).GetValue();
4364514f5e3Sopenharmony_ci    JSTaggedNumber number = JSTaggedValue::ToLength(thread, value);
4374514f5e3Sopenharmony_ci    // 5. ReturnIfAbrupt(len).
4384514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
4394514f5e3Sopenharmony_ci    if (number.GetNumber() > MAX_ELEMENT_INDEX) {
4404514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "len is bigger than 2^32 - 1",
4414514f5e3Sopenharmony_ci                                    JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
4424514f5e3Sopenharmony_ci    }
4434514f5e3Sopenharmony_ci
4444514f5e3Sopenharmony_ci    uint32_t len = number.ToUint32();
4454514f5e3Sopenharmony_ci    // 6. Let list be an empty List.
4464514f5e3Sopenharmony_ci    JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len);
4474514f5e3Sopenharmony_ci    // 8. Repeat while index < len
4484514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < len; i++) {
4494514f5e3Sopenharmony_ci        JSTaggedValue next = JSTaggedValue::GetProperty(thread, obj, i).GetValue().GetTaggedValue();
4504514f5e3Sopenharmony_ci        // c. ReturnIfAbrupt(next).
4514514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
4524514f5e3Sopenharmony_ci
4534514f5e3Sopenharmony_ci        if constexpr (types == ElementTypes::STRING_AND_SYMBOL) {
4544514f5e3Sopenharmony_ci            if (!next.IsString() && !next.IsSymbol()) {
4554514f5e3Sopenharmony_ci                THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike: not an element of elementTypes",
4564514f5e3Sopenharmony_ci                                            JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
4574514f5e3Sopenharmony_ci            }
4584514f5e3Sopenharmony_ci        }
4594514f5e3Sopenharmony_ci
4604514f5e3Sopenharmony_ci        array->Set(thread, i, next);
4614514f5e3Sopenharmony_ci    }
4624514f5e3Sopenharmony_ci    return JSHandle<JSTaggedValue>(array);
4634514f5e3Sopenharmony_ci}
4644514f5e3Sopenharmony_ci
4654514f5e3Sopenharmony_ciinline JSTaggedValue JSObject::ShouldGetValueFromBox(ObjectOperator *op)
4664514f5e3Sopenharmony_ci{
4674514f5e3Sopenharmony_ci    JSTaggedValue result = op->GetValue();
4684514f5e3Sopenharmony_ci    if (result.IsPropertyBox()) {
4694514f5e3Sopenharmony_ci        result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
4704514f5e3Sopenharmony_ci    }
4714514f5e3Sopenharmony_ci    return result;
4724514f5e3Sopenharmony_ci}
4734514f5e3Sopenharmony_ci
4744514f5e3Sopenharmony_ciinline bool JSObject::CheckHClassHit(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &cls)
4754514f5e3Sopenharmony_ci{
4764514f5e3Sopenharmony_ci    return obj->GetJSHClass() == *cls;
4774514f5e3Sopenharmony_ci}
4784514f5e3Sopenharmony_ci
4794514f5e3Sopenharmony_ciinline uint32_t JSObject::SetValuesOrEntries(JSThread *thread, const JSHandle<TaggedArray> &prop, uint32_t index,
4804514f5e3Sopenharmony_ci                                             const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
4814514f5e3Sopenharmony_ci                                             PropertyKind kind)
4824514f5e3Sopenharmony_ci{
4834514f5e3Sopenharmony_ci    if (kind == PropertyKind::VALUE) {
4844514f5e3Sopenharmony_ci        prop->Set(thread, index++, value);
4854514f5e3Sopenharmony_ci        return index;
4864514f5e3Sopenharmony_ci    }
4874514f5e3Sopenharmony_ci    JSHandle<TaggedArray> keyValue = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(2);  // 2: key-value pair
4884514f5e3Sopenharmony_ci    keyValue->Set(thread, 0, key);
4894514f5e3Sopenharmony_ci    keyValue->Set(thread, 1, value);
4904514f5e3Sopenharmony_ci    JSHandle<JSArray> entry = JSArray::CreateArrayFromList(thread, keyValue);
4914514f5e3Sopenharmony_ci    prop->Set(thread, index++, entry.GetTaggedValue());
4924514f5e3Sopenharmony_ci    return index;
4934514f5e3Sopenharmony_ci}
4944514f5e3Sopenharmony_ci
4954514f5e3Sopenharmony_ciinline void JSObject::SetEnumCacheKind(JSThread *thread, TaggedArray *array, EnumCacheKind kind)
4964514f5e3Sopenharmony_ci{
4974514f5e3Sopenharmony_ci    array->Set(thread, EnumCache::ENUM_CACHE_KIND_OFFSET, JSTaggedValue(static_cast<uint8_t>(kind)));
4984514f5e3Sopenharmony_ci}
4994514f5e3Sopenharmony_ci
5004514f5e3Sopenharmony_ciinline EnumCacheKind JSObject::GetEnumCacheKind(JSThread *thread, TaggedArray *array)
5014514f5e3Sopenharmony_ci{
5024514f5e3Sopenharmony_ci    return static_cast<EnumCacheKind>(array->Get(thread, EnumCache::ENUM_CACHE_KIND_OFFSET).GetInt());
5034514f5e3Sopenharmony_ci}
5044514f5e3Sopenharmony_ci
5054514f5e3Sopenharmony_ciinline EnumCacheKind JSObject::GetEnumCacheKind(JSThread *thread, JSTaggedValue enumCache)
5064514f5e3Sopenharmony_ci{
5074514f5e3Sopenharmony_ci    if (enumCache.IsUndefinedOrNull()) {
5084514f5e3Sopenharmony_ci        return EnumCacheKind::NONE;
5094514f5e3Sopenharmony_ci    }
5104514f5e3Sopenharmony_ci    JSTaggedValue emptyArray = thread->GlobalConstants()->GetEmptyArray();
5114514f5e3Sopenharmony_ci    if (enumCache == emptyArray) {
5124514f5e3Sopenharmony_ci        return EnumCacheKind::SIMPLE;
5134514f5e3Sopenharmony_ci    }
5144514f5e3Sopenharmony_ci    TaggedArray *array = TaggedArray::Cast(enumCache.GetTaggedObject());
5154514f5e3Sopenharmony_ci    return JSObject::GetEnumCacheKind(thread, array);
5164514f5e3Sopenharmony_ci}
5174514f5e3Sopenharmony_ci
5184514f5e3Sopenharmony_ciinline JSTaggedValue JSObject::GetPrototype(JSTaggedValue obj)
5194514f5e3Sopenharmony_ci{
5204514f5e3Sopenharmony_ci    JSHClass *hclass = obj.GetTaggedObject()->GetClass();
5214514f5e3Sopenharmony_ci    return hclass->GetPrototype();
5224514f5e3Sopenharmony_ci}
5234514f5e3Sopenharmony_ci
5244514f5e3Sopenharmony_ciinline bool JSObject::IsDepulicateKeys(JSThread *thread, JSHandle<TaggedArray> keys, int32_t lastLength,
5254514f5e3Sopenharmony_ci                                       JSHandle<TaggedQueue> shadowQueue, JSHandle<JSTaggedValue> key)
5264514f5e3Sopenharmony_ci{
5274514f5e3Sopenharmony_ci    if (lastLength < 0) {
5284514f5e3Sopenharmony_ci        return false;
5294514f5e3Sopenharmony_ci    }
5304514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
5314514f5e3Sopenharmony_ci    for (int32_t i = EnumCache::ENUM_CACHE_HEADER_SIZE; i < lastLength; i++) {
5324514f5e3Sopenharmony_ci        value.Update(keys->Get(i));
5334514f5e3Sopenharmony_ci        bool has = JSTaggedValue::Equal(thread, value, key);
5344514f5e3Sopenharmony_ci        if (has) {
5354514f5e3Sopenharmony_ci            return true;
5364514f5e3Sopenharmony_ci        }
5374514f5e3Sopenharmony_ci    }
5384514f5e3Sopenharmony_ci
5394514f5e3Sopenharmony_ci    uint32_t shadowSize = shadowQueue->Size();
5404514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < shadowSize; i++) {
5414514f5e3Sopenharmony_ci        value.Update(shadowQueue->Get(i));
5424514f5e3Sopenharmony_ci        bool has = JSTaggedValue::Equal(thread, value, key);
5434514f5e3Sopenharmony_ci        if (has) {
5444514f5e3Sopenharmony_ci            return true;
5454514f5e3Sopenharmony_ci        }
5464514f5e3Sopenharmony_ci    }
5474514f5e3Sopenharmony_ci    return false;
5484514f5e3Sopenharmony_ci}
5494514f5e3Sopenharmony_ci
5504514f5e3Sopenharmony_ciinline void JSObject::ClearHasDeleteProperty(JSHandle<JSTaggedValue> object)
5514514f5e3Sopenharmony_ci{
5524514f5e3Sopenharmony_ci    object->GetTaggedObject()->GetClass()->SetHasDeleteProperty(false);
5534514f5e3Sopenharmony_ci}
5544514f5e3Sopenharmony_ci
5554514f5e3Sopenharmony_ciinline std::pair<JSHandle<TaggedArray>, JSHandle<TaggedArray>> JSObject::GetOwnEnumerableNamesInFastMode(
5564514f5e3Sopenharmony_ci    JSThread *thread, const JSHandle<JSObject> &obj, uint32_t *copyLengthOfKeys, uint32_t *copyLengthOfElements)
5574514f5e3Sopenharmony_ci{
5584514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
5594514f5e3Sopenharmony_ci    std::pair<uint32_t, uint32_t> numOfKeys = obj->GetNumberOfEnumKeys();
5604514f5e3Sopenharmony_ci    uint32_t numOfEnumKeys = numOfKeys.first;
5614514f5e3Sopenharmony_ci    uint32_t numOfElements = obj->GetNumberOfElements();
5624514f5e3Sopenharmony_ci    JSHandle<TaggedArray> elementArray = numOfElements > 0 ? JSObject::GetEnumElementKeys(
5634514f5e3Sopenharmony_ci        thread, obj, 0, numOfElements, copyLengthOfElements) : factory->EmptyArray();
5644514f5e3Sopenharmony_ci    JSHandle<TaggedArray> keyArray = numOfEnumKeys > 0 ? JSObject::GetAllEnumKeys(
5654514f5e3Sopenharmony_ci        thread, obj, numOfEnumKeys, copyLengthOfKeys) : factory->EmptyArray();
5664514f5e3Sopenharmony_ci    return std::make_pair(keyArray, elementArray);
5674514f5e3Sopenharmony_ci}
5684514f5e3Sopenharmony_ci
5694514f5e3Sopenharmony_ciinline bool JSObject::HasMutantTaggedArrayElements(const JSHandle<JSObject> &obj)
5704514f5e3Sopenharmony_ci{
5714514f5e3Sopenharmony_ci    return obj->GetElements().IsMutantTaggedArray();
5724514f5e3Sopenharmony_ci}
5734514f5e3Sopenharmony_ci}  //  namespace panda::ecmascript
5744514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_JSOBJECT_INL_H
575