14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 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#include "ecmascript/object_operator.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/global_dictionary-inl.h"
194514f5e3Sopenharmony_ci#include "ecmascript/js_primitive_ref.h"
204514f5e3Sopenharmony_ci#include "ecmascript/object_fast_operator-inl.h"
214514f5e3Sopenharmony_ci#include "ecmascript/property_detector-inl.h"
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_cinamespace panda::ecmascript {
244514f5e3Sopenharmony_civoid ObjectOperator::HandleKey(const JSHandle<JSTaggedValue> &key)
254514f5e3Sopenharmony_ci{
264514f5e3Sopenharmony_ci    if (key->IsInt()) {
274514f5e3Sopenharmony_ci        int32_t keyInt = key->GetInt();
284514f5e3Sopenharmony_ci        if (keyInt >= 0) {
294514f5e3Sopenharmony_ci            elementIndex_ = static_cast<uint32_t>(keyInt);
304514f5e3Sopenharmony_ci            return;
314514f5e3Sopenharmony_ci        }
324514f5e3Sopenharmony_ci        key_ = JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread_, JSTaggedValue(keyInt)));
334514f5e3Sopenharmony_ci        return;
344514f5e3Sopenharmony_ci    }
354514f5e3Sopenharmony_ci
364514f5e3Sopenharmony_ci    if (key->IsString()) {
374514f5e3Sopenharmony_ci        keyFromStringType_ = true;
384514f5e3Sopenharmony_ci        uint32_t index = 0;
394514f5e3Sopenharmony_ci        if (JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index)) {
404514f5e3Sopenharmony_ci            ASSERT(index < JSObject::MAX_ELEMENT_INDEX);
414514f5e3Sopenharmony_ci            elementIndex_ = index;
424514f5e3Sopenharmony_ci            return;
434514f5e3Sopenharmony_ci        }
444514f5e3Sopenharmony_ci        if (EcmaStringAccessor(key->GetTaggedObject()).IsInternString()) {
454514f5e3Sopenharmony_ci            key_ = key;
464514f5e3Sopenharmony_ci            return;
474514f5e3Sopenharmony_ci        }
484514f5e3Sopenharmony_ci        key_ = JSHandle<JSTaggedValue>(thread_, thread_->GetEcmaVM()->GetFactory()->InternString(key));
494514f5e3Sopenharmony_ci        return;
504514f5e3Sopenharmony_ci    }
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ci    if (key->IsDouble()) {
534514f5e3Sopenharmony_ci        double number = key->GetDouble();
544514f5e3Sopenharmony_ci        if (number >= 0 && number < JSObject::MAX_ELEMENT_INDEX) {
554514f5e3Sopenharmony_ci            auto integer = static_cast<uint32_t>(number);
564514f5e3Sopenharmony_ci            if (integer == number) {
574514f5e3Sopenharmony_ci                elementIndex_ = static_cast<uint32_t>(number);
584514f5e3Sopenharmony_ci                return;
594514f5e3Sopenharmony_ci            }
604514f5e3Sopenharmony_ci        }
614514f5e3Sopenharmony_ci        key_ = JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread_, key.GetTaggedValue()));
624514f5e3Sopenharmony_ci        if (!EcmaStringAccessor(key_.GetTaggedValue()).IsInternString()) {
634514f5e3Sopenharmony_ci                key_ = JSHandle<JSTaggedValue>(thread_, thread_->GetEcmaVM()->GetFactory()->InternString(key_));
644514f5e3Sopenharmony_ci        }
654514f5e3Sopenharmony_ci        return;
664514f5e3Sopenharmony_ci    }
674514f5e3Sopenharmony_ci
684514f5e3Sopenharmony_ci    if (key->IsSymbol()) {
694514f5e3Sopenharmony_ci        key_ = key;
704514f5e3Sopenharmony_ci        return;
714514f5e3Sopenharmony_ci    }
724514f5e3Sopenharmony_ci
734514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> keyHandle(thread_, JSTaggedValue::ToPrimitive(thread_, key, PREFER_STRING));
744514f5e3Sopenharmony_ci    RETURN_IF_ABRUPT_COMPLETION(thread_);
754514f5e3Sopenharmony_ci    if (key->IsSymbol()) {
764514f5e3Sopenharmony_ci        key_ = keyHandle;
774514f5e3Sopenharmony_ci        return;
784514f5e3Sopenharmony_ci    }
794514f5e3Sopenharmony_ci    key_ = JSHandle<JSTaggedValue>(thread_,
804514f5e3Sopenharmony_ci                                   thread_->GetEcmaVM()->GetFactory()->InternString(
814514f5e3Sopenharmony_ci                                       JSHandle<JSTaggedValue>::Cast(JSTaggedValue::ToString(thread_, keyHandle))));
824514f5e3Sopenharmony_ci}
834514f5e3Sopenharmony_ci
844514f5e3Sopenharmony_civoid ObjectOperator::UpdateHolder()
854514f5e3Sopenharmony_ci{
864514f5e3Sopenharmony_ci    if (holder_->IsString() && (GetThroughElement() || GetStringLength())) {
874514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
884514f5e3Sopenharmony_ci        holder_.Update(JSPrimitiveRef::StringCreate(thread_, holder_, undefined).GetTaggedValue());
894514f5e3Sopenharmony_ci    } else {
904514f5e3Sopenharmony_ci        if (holder_->IsString() || holder_->IsNumber()) {
914514f5e3Sopenharmony_ci            SetIsOnPrototype(true);
924514f5e3Sopenharmony_ci        }
934514f5e3Sopenharmony_ci        holder_.Update(JSTaggedValue::ToPrototypeOrObj(thread_, holder_).GetTaggedValue());
944514f5e3Sopenharmony_ci    }
954514f5e3Sopenharmony_ci}
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_civoid ObjectOperator::UpdateIsTSHClass()
984514f5e3Sopenharmony_ci{
994514f5e3Sopenharmony_ci    if (!holder_->IsECMAObject()) {
1004514f5e3Sopenharmony_ci        SetIsTSHClass(false);
1014514f5e3Sopenharmony_ci        return;
1024514f5e3Sopenharmony_ci    }
1034514f5e3Sopenharmony_ci    auto hclass = JSHandle<JSObject>::Cast(holder_)->GetClass();
1044514f5e3Sopenharmony_ci    if (hclass->IsTS()) {
1054514f5e3Sopenharmony_ci        SetIsTSHClass(true);
1064514f5e3Sopenharmony_ci    }
1074514f5e3Sopenharmony_ci}
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_civoid ObjectOperator::StartLookUp(OperatorType type)
1104514f5e3Sopenharmony_ci{
1114514f5e3Sopenharmony_ci    UpdateHolder();
1124514f5e3Sopenharmony_ci
1134514f5e3Sopenharmony_ci    if (type == OperatorType::OWN) {
1144514f5e3Sopenharmony_ci        LookupPropertyInHolder();
1154514f5e3Sopenharmony_ci    } else {
1164514f5e3Sopenharmony_ci        LookupProperty();
1174514f5e3Sopenharmony_ci    }
1184514f5e3Sopenharmony_ci}
1194514f5e3Sopenharmony_ci
1204514f5e3Sopenharmony_civoid ObjectOperator::StartGlobalLookUp(OperatorType type)
1214514f5e3Sopenharmony_ci{
1224514f5e3Sopenharmony_ci    UpdateHolder();
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ci    if (type == OperatorType::OWN) {
1254514f5e3Sopenharmony_ci        GlobalLookupPropertyInHolder();
1264514f5e3Sopenharmony_ci    } else {
1274514f5e3Sopenharmony_ci        GlobalLookupProperty();
1284514f5e3Sopenharmony_ci    }
1294514f5e3Sopenharmony_ci}
1304514f5e3Sopenharmony_ci
1314514f5e3Sopenharmony_ciObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &key, OperatorType type)
1324514f5e3Sopenharmony_ci    : thread_(thread),
1334514f5e3Sopenharmony_ci      holder_(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject()),
1344514f5e3Sopenharmony_ci      receiver_(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject())
1354514f5e3Sopenharmony_ci{
1364514f5e3Sopenharmony_ci    HandleKey(key);
1374514f5e3Sopenharmony_ci    StartGlobalLookUp(type);
1384514f5e3Sopenharmony_ci}
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_ciObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSObject> &holder, const JSHandle<JSTaggedValue> &key,
1414514f5e3Sopenharmony_ci                               OperatorType type)
1424514f5e3Sopenharmony_ci    : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, holder.GetTaggedValue())
1434514f5e3Sopenharmony_ci{
1444514f5e3Sopenharmony_ci    HandleKey(key);
1454514f5e3Sopenharmony_ci    StartLookUp(type);
1464514f5e3Sopenharmony_ci}
1474514f5e3Sopenharmony_ci
1484514f5e3Sopenharmony_ciObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder,
1494514f5e3Sopenharmony_ci                               const JSHandle<JSTaggedValue> &key, OperatorType type)
1504514f5e3Sopenharmony_ci    : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, holder.GetTaggedValue())
1514514f5e3Sopenharmony_ci{
1524514f5e3Sopenharmony_ci    HandleKey(key);
1534514f5e3Sopenharmony_ci    StartLookUp(type);
1544514f5e3Sopenharmony_ci}
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_ciObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder, uint32_t index,
1574514f5e3Sopenharmony_ci                               OperatorType type)
1584514f5e3Sopenharmony_ci    : thread_(thread),
1594514f5e3Sopenharmony_ci      holder_(thread, holder.GetTaggedValue()),
1604514f5e3Sopenharmony_ci      receiver_(thread, holder.GetTaggedValue()),
1614514f5e3Sopenharmony_ci      elementIndex_(index)
1624514f5e3Sopenharmony_ci{
1634514f5e3Sopenharmony_ci    StartLookUp(type);
1644514f5e3Sopenharmony_ci}
1654514f5e3Sopenharmony_ci
1664514f5e3Sopenharmony_ciObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder,
1674514f5e3Sopenharmony_ci                               const JSHandle<JSTaggedValue> &receiver, const JSHandle<JSTaggedValue> &key,
1684514f5e3Sopenharmony_ci                               OperatorType type)
1694514f5e3Sopenharmony_ci    : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, receiver.GetTaggedValue())
1704514f5e3Sopenharmony_ci{
1714514f5e3Sopenharmony_ci    SetHasReceiver(true);
1724514f5e3Sopenharmony_ci    HandleKey(key);
1734514f5e3Sopenharmony_ci    StartLookUp(type);
1744514f5e3Sopenharmony_ci}
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_ci// op for fast path
1774514f5e3Sopenharmony_ciObjectOperator::ObjectOperator(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name,
1784514f5e3Sopenharmony_ci                               OperatorType type)
1794514f5e3Sopenharmony_ci    : thread_(thread), holder_(thread, receiver), receiver_(thread, receiver), key_(thread, name)
1804514f5e3Sopenharmony_ci{
1814514f5e3Sopenharmony_ci    ASSERT(name.IsStringOrSymbol());
1824514f5e3Sopenharmony_ci    StartLookUp(type);
1834514f5e3Sopenharmony_ci}
1844514f5e3Sopenharmony_ciJSHandle<JSTaggedValue> ObjectOperator::FastGetValue()
1854514f5e3Sopenharmony_ci{
1864514f5e3Sopenharmony_ci    ASSERT(IsFound() && !value_.IsEmpty());
1874514f5e3Sopenharmony_ci    if (value_->IsPropertyBox()) {
1884514f5e3Sopenharmony_ci        value_.Update(PropertyBox::Cast(value_->GetTaggedObject())->GetValue());
1894514f5e3Sopenharmony_ci    }
1904514f5e3Sopenharmony_ci    if (!IsAccessorDescriptor()) {
1914514f5e3Sopenharmony_ci        return value_;
1924514f5e3Sopenharmony_ci    }
1934514f5e3Sopenharmony_ci    AccessorData *accessor = AccessorData::Cast(value_->GetTaggedObject());
1944514f5e3Sopenharmony_ci    ASSERT(!accessor->IsInternal());
1954514f5e3Sopenharmony_ci    // 8. Return Call(getter, Receiver).
1964514f5e3Sopenharmony_ci    return JSHandle<JSTaggedValue>(thread_, JSObject::CallGetter(thread_, accessor, receiver_));
1974514f5e3Sopenharmony_ci}
1984514f5e3Sopenharmony_ciObjectOperator::ObjectOperator(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name,
1994514f5e3Sopenharmony_ci                               const PropertyAttributes &attr)
2004514f5e3Sopenharmony_ci    : thread_(thread), receiver_(thread, receiver), key_(thread, name)
2014514f5e3Sopenharmony_ci{
2024514f5e3Sopenharmony_ci    SetAttr(attr);
2034514f5e3Sopenharmony_ci}
2044514f5e3Sopenharmony_civoid ObjectOperator::FastAdd(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name,
2054514f5e3Sopenharmony_ci                             const JSHandle<JSTaggedValue> &value, const PropertyAttributes &attr)
2064514f5e3Sopenharmony_ci{
2074514f5e3Sopenharmony_ci    ObjectOperator op(thread, receiver, name, attr);
2084514f5e3Sopenharmony_ci    op.AddPropertyInternal(value);
2094514f5e3Sopenharmony_ci}
2104514f5e3Sopenharmony_ci
2114514f5e3Sopenharmony_ci// static
2124514f5e3Sopenharmony_civoid ObjectOperator::UpdateDetectorOnSetPrototype(const JSThread *thread, JSTaggedValue receiver)
2134514f5e3Sopenharmony_ci{
2144514f5e3Sopenharmony_ci    // skip env prepare
2154514f5e3Sopenharmony_ci    if (!thread->IsReadyToUpdateDetector()) {
2164514f5e3Sopenharmony_ci        return;
2174514f5e3Sopenharmony_ci    }
2184514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
2194514f5e3Sopenharmony_ci    JSHClass *hclass = receiver.GetTaggedObject()->GetClass();
2204514f5e3Sopenharmony_ci    JSType type = hclass->GetObjectType();
2214514f5e3Sopenharmony_ci    switch (type) {
2224514f5e3Sopenharmony_ci        case JSType::JS_REG_EXP: {
2234514f5e3Sopenharmony_ci            if (PropertyDetector::IsRegExpReplaceDetectorValid(env)) {
2244514f5e3Sopenharmony_ci                PropertyDetector::InvalidateRegExpReplaceDetector(env);
2254514f5e3Sopenharmony_ci            }
2264514f5e3Sopenharmony_ci            if (PropertyDetector::IsRegExpFlagsDetectorValid(env)) {
2274514f5e3Sopenharmony_ci                PropertyDetector::InvalidateRegExpFlagsDetector(env);
2284514f5e3Sopenharmony_ci            }
2294514f5e3Sopenharmony_ci            return;
2304514f5e3Sopenharmony_ci        }
2314514f5e3Sopenharmony_ci        case JSType::JS_MAP: {
2324514f5e3Sopenharmony_ci            if (PropertyDetector::IsMapIteratorDetectorValid(env)) {
2334514f5e3Sopenharmony_ci                PropertyDetector::InvalidateMapIteratorDetector(env);
2344514f5e3Sopenharmony_ci            }
2354514f5e3Sopenharmony_ci            return;
2364514f5e3Sopenharmony_ci        }
2374514f5e3Sopenharmony_ci        case JSType::JS_SET: {
2384514f5e3Sopenharmony_ci            if (PropertyDetector::IsSetIteratorDetectorValid(env)) {
2394514f5e3Sopenharmony_ci                PropertyDetector::InvalidateSetIteratorDetector(env);
2404514f5e3Sopenharmony_ci            }
2414514f5e3Sopenharmony_ci            return;
2424514f5e3Sopenharmony_ci        }
2434514f5e3Sopenharmony_ci        case JSType::JS_PRIMITIVE_REF: {
2444514f5e3Sopenharmony_ci            if (JSPrimitiveRef::Cast(receiver.GetTaggedObject())->IsString() &&
2454514f5e3Sopenharmony_ci                PropertyDetector::IsStringIteratorDetectorValid(env)) {
2464514f5e3Sopenharmony_ci                PropertyDetector::InvalidateStringIteratorDetector(env);
2474514f5e3Sopenharmony_ci            }
2484514f5e3Sopenharmony_ci            return;
2494514f5e3Sopenharmony_ci        }
2504514f5e3Sopenharmony_ci        case JSType::JS_ARRAY: {
2514514f5e3Sopenharmony_ci            if (PropertyDetector::IsArrayIteratorDetectorValid(env)) {
2524514f5e3Sopenharmony_ci                PropertyDetector::InvalidateArrayIteratorDetector(env);
2534514f5e3Sopenharmony_ci            }
2544514f5e3Sopenharmony_ci            return;
2554514f5e3Sopenharmony_ci        }
2564514f5e3Sopenharmony_ci        case JSType::JS_INT8_ARRAY:
2574514f5e3Sopenharmony_ci        case JSType::JS_UINT8_ARRAY:
2584514f5e3Sopenharmony_ci        case JSType::JS_UINT8_CLAMPED_ARRAY:
2594514f5e3Sopenharmony_ci        case JSType::JS_INT16_ARRAY:
2604514f5e3Sopenharmony_ci        case JSType::JS_UINT16_ARRAY:
2614514f5e3Sopenharmony_ci        case JSType::JS_INT32_ARRAY:
2624514f5e3Sopenharmony_ci        case JSType::JS_UINT32_ARRAY:
2634514f5e3Sopenharmony_ci        case JSType::JS_FLOAT32_ARRAY:
2644514f5e3Sopenharmony_ci        case JSType::JS_FLOAT64_ARRAY:
2654514f5e3Sopenharmony_ci        case JSType::JS_BIGINT64_ARRAY:
2664514f5e3Sopenharmony_ci        case JSType::JS_BIGUINT64_ARRAY: {
2674514f5e3Sopenharmony_ci            if (PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
2684514f5e3Sopenharmony_ci                PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
2694514f5e3Sopenharmony_ci            }
2704514f5e3Sopenharmony_ci            if (PropertyDetector::IsTypedArraySpeciesProtectDetectorValid(env)) {
2714514f5e3Sopenharmony_ci                PropertyDetector::InvalidateTypedArraySpeciesProtectDetector(env);
2724514f5e3Sopenharmony_ci            }
2734514f5e3Sopenharmony_ci            return;
2744514f5e3Sopenharmony_ci        }
2754514f5e3Sopenharmony_ci        default:
2764514f5e3Sopenharmony_ci            break;
2774514f5e3Sopenharmony_ci    }
2784514f5e3Sopenharmony_ci
2794514f5e3Sopenharmony_ci    if (hclass->IsPrototype() &&
2804514f5e3Sopenharmony_ci        (receiver == env->GetTaggedInt8ArrayFunctionPrototype() ||
2814514f5e3Sopenharmony_ci         receiver == env->GetTaggedUint8ArrayFunctionPrototype() ||
2824514f5e3Sopenharmony_ci         receiver == env->GetTaggedUint8ClampedArrayFunctionPrototype() ||
2834514f5e3Sopenharmony_ci         receiver == env->GetTaggedInt16ArrayFunctionPrototype() ||
2844514f5e3Sopenharmony_ci         receiver == env->GetTaggedUint16ArrayFunctionPrototype() ||
2854514f5e3Sopenharmony_ci         receiver == env->GetTaggedInt32ArrayFunctionPrototype() ||
2864514f5e3Sopenharmony_ci         receiver == env->GetTaggedUint32ArrayFunctionPrototype() ||
2874514f5e3Sopenharmony_ci         receiver == env->GetTaggedFloat32ArrayFunctionPrototype() ||
2884514f5e3Sopenharmony_ci         receiver == env->GetTaggedFloat64ArrayFunctionPrototype() ||
2894514f5e3Sopenharmony_ci         receiver == env->GetTaggedBigInt64ArrayFunctionPrototype() ||
2904514f5e3Sopenharmony_ci         receiver == env->GetTaggedBigUint64ArrayFunctionPrototype()) &&
2914514f5e3Sopenharmony_ci         PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
2924514f5e3Sopenharmony_ci        PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
2934514f5e3Sopenharmony_ci        return;
2944514f5e3Sopenharmony_ci    }
2954514f5e3Sopenharmony_ci    if ((PropertyDetector::IsNumberStringNotRegexpLikeDetectorValid(env) &&
2964514f5e3Sopenharmony_ci        JSObject::Cast(receiver)->GetJSHClass()->IsPrototype() && receiver.IsJSPrimitive())) {
2974514f5e3Sopenharmony_ci        PropertyDetector::InvalidateNumberStringNotRegexpLikeDetector(env);
2984514f5e3Sopenharmony_ci        return;
2994514f5e3Sopenharmony_ci    }
3004514f5e3Sopenharmony_ci}
3014514f5e3Sopenharmony_ci
3024514f5e3Sopenharmony_civoid ObjectOperator::UpdateDetector()
3034514f5e3Sopenharmony_ci{
3044514f5e3Sopenharmony_ci    if (IsElement()) {
3054514f5e3Sopenharmony_ci        return;
3064514f5e3Sopenharmony_ci    }
3074514f5e3Sopenharmony_ci    ObjectOperator::UpdateDetector(thread_, holder_.GetTaggedValue(), key_.GetTaggedValue());
3084514f5e3Sopenharmony_ci}
3094514f5e3Sopenharmony_ci
3104514f5e3Sopenharmony_ci// static
3114514f5e3Sopenharmony_civoid ObjectOperator::UpdateDetector(const JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
3124514f5e3Sopenharmony_ci{
3134514f5e3Sopenharmony_ci    // skip env prepare
3144514f5e3Sopenharmony_ci    if (!thread->IsReadyToUpdateDetector()) {
3154514f5e3Sopenharmony_ci        return;
3164514f5e3Sopenharmony_ci    }
3174514f5e3Sopenharmony_ci    bool maybeDetector = IsDetectorName(thread, key);
3184514f5e3Sopenharmony_ci    if (!maybeDetector) {
3194514f5e3Sopenharmony_ci        return;
3204514f5e3Sopenharmony_ci    }
3214514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
3224514f5e3Sopenharmony_ci    auto globalConst = thread->GlobalConstants();
3234514f5e3Sopenharmony_ci    if (key == env->GetTaggedReplaceSymbol() &&
3244514f5e3Sopenharmony_ci        (receiver.IsJSRegExp() || receiver == env->GetTaggedRegExpPrototype())) {
3254514f5e3Sopenharmony_ci        if (!PropertyDetector::IsRegExpReplaceDetectorValid(env)) {
3264514f5e3Sopenharmony_ci            return;
3274514f5e3Sopenharmony_ci        }
3284514f5e3Sopenharmony_ci        PropertyDetector::InvalidateRegExpReplaceDetector(env);
3294514f5e3Sopenharmony_ci    } else if (key == env->GetTaggedIteratorSymbol()) {
3304514f5e3Sopenharmony_ci        if (receiver.IsJSMap() || receiver == env->GetTaggedMapPrototype()) {
3314514f5e3Sopenharmony_ci            if (!PropertyDetector::IsMapIteratorDetectorValid(env)) {
3324514f5e3Sopenharmony_ci                return;
3334514f5e3Sopenharmony_ci            }
3344514f5e3Sopenharmony_ci            PropertyDetector::InvalidateMapIteratorDetector(env);
3354514f5e3Sopenharmony_ci        } else if (receiver.IsJSSet() || receiver == env->GetTaggedSetPrototype()) {
3364514f5e3Sopenharmony_ci            if (!PropertyDetector::IsSetIteratorDetectorValid(env)) {
3374514f5e3Sopenharmony_ci                return;
3384514f5e3Sopenharmony_ci            }
3394514f5e3Sopenharmony_ci            PropertyDetector::InvalidateSetIteratorDetector(env);
3404514f5e3Sopenharmony_ci        } else if ((receiver.IsJSPrimitiveRef() && JSPrimitiveRef::Cast(receiver.GetTaggedObject())->IsString()) ||
3414514f5e3Sopenharmony_ci                   receiver == env->GetTaggedStringPrototype()) {
3424514f5e3Sopenharmony_ci            if (!PropertyDetector::IsStringIteratorDetectorValid(env)) {
3434514f5e3Sopenharmony_ci                return;
3444514f5e3Sopenharmony_ci            }
3454514f5e3Sopenharmony_ci            PropertyDetector::InvalidateStringIteratorDetector(env);
3464514f5e3Sopenharmony_ci        } else if (receiver.IsJSArray() || receiver == env->GetTaggedArrayPrototype()) {
3474514f5e3Sopenharmony_ci            if (!PropertyDetector::IsArrayIteratorDetectorValid(env)) {
3484514f5e3Sopenharmony_ci                return;
3494514f5e3Sopenharmony_ci            }
3504514f5e3Sopenharmony_ci            PropertyDetector::InvalidateArrayIteratorDetector(env);
3514514f5e3Sopenharmony_ci        } else if (receiver.IsTypedArray() ||
3524514f5e3Sopenharmony_ci                   receiver == env->GetTaggedArrayPrototype() ||
3534514f5e3Sopenharmony_ci                   receiver == env->GetTaggedInt8ArrayFunctionPrototype() ||
3544514f5e3Sopenharmony_ci                   receiver == env->GetTaggedUint8ArrayFunctionPrototype() ||
3554514f5e3Sopenharmony_ci                   receiver == env->GetTaggedUint8ClampedArrayFunctionPrototype() ||
3564514f5e3Sopenharmony_ci                   receiver == env->GetTaggedInt16ArrayFunctionPrototype() ||
3574514f5e3Sopenharmony_ci                   receiver == env->GetTaggedUint16ArrayFunctionPrototype() ||
3584514f5e3Sopenharmony_ci                   receiver == env->GetTaggedInt32ArrayFunctionPrototype() ||
3594514f5e3Sopenharmony_ci                   receiver == env->GetTaggedUint32ArrayFunctionPrototype() ||
3604514f5e3Sopenharmony_ci                   receiver == env->GetTaggedFloat32ArrayFunctionPrototype() ||
3614514f5e3Sopenharmony_ci                   receiver == env->GetTaggedFloat64ArrayFunctionPrototype() ||
3624514f5e3Sopenharmony_ci                   receiver == env->GetTaggedBigInt64ArrayFunctionPrototype() ||
3634514f5e3Sopenharmony_ci                   receiver == env->GetTaggedBigUint64ArrayFunctionPrototype()) {
3644514f5e3Sopenharmony_ci            if (!PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
3654514f5e3Sopenharmony_ci                return;
3664514f5e3Sopenharmony_ci            }
3674514f5e3Sopenharmony_ci            PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
3684514f5e3Sopenharmony_ci        }
3694514f5e3Sopenharmony_ci    } else if (key == env->GetTaggedSpeciesSymbol()) {
3704514f5e3Sopenharmony_ci        if (receiver == env->GetTypedArrayFunction().GetTaggedValue()) {
3714514f5e3Sopenharmony_ci            if (!PropertyDetector::IsTypedArraySpeciesProtectDetectorValid(env)) {
3724514f5e3Sopenharmony_ci                return;
3734514f5e3Sopenharmony_ci            }
3744514f5e3Sopenharmony_ci            PropertyDetector::InvalidateTypedArraySpeciesProtectDetector(env);
3754514f5e3Sopenharmony_ci        }
3764514f5e3Sopenharmony_ci        if (receiver == env->GetRegExpFunction().GetTaggedValue()) {
3774514f5e3Sopenharmony_ci            if (!PropertyDetector::IsRegExpSpeciesDetectorValid(env)) {
3784514f5e3Sopenharmony_ci                return;
3794514f5e3Sopenharmony_ci            }
3804514f5e3Sopenharmony_ci            PropertyDetector::InvalidateRegExpSpeciesDetector(env);
3814514f5e3Sopenharmony_ci        }
3824514f5e3Sopenharmony_ci    } else if ((key == env->GetTaggedReplaceSymbol()) ||
3834514f5e3Sopenharmony_ci        (key == env->GetTaggedSplitSymbol()) ||
3844514f5e3Sopenharmony_ci        (key == env->GetTaggedMatchAllSymbol())) {
3854514f5e3Sopenharmony_ci        if (!PropertyDetector::IsNumberStringNotRegexpLikeDetectorValid(env)) {
3864514f5e3Sopenharmony_ci            return;
3874514f5e3Sopenharmony_ci        }
3884514f5e3Sopenharmony_ci        // check String.prototype or Number.prototype or Object.prototype
3894514f5e3Sopenharmony_ci        if ((JSObject::Cast(receiver)->GetJSHClass()->IsPrototype() &&
3904514f5e3Sopenharmony_ci            (receiver.IsJSPrimitive() || receiver == env->GetTaggedObjectFunctionPrototype()))) {
3914514f5e3Sopenharmony_ci            PropertyDetector::InvalidateNumberStringNotRegexpLikeDetector(env);
3924514f5e3Sopenharmony_ci        }
3934514f5e3Sopenharmony_ci    } else if (key == globalConst->GetHandledFlagsString().GetTaggedValue() &&
3944514f5e3Sopenharmony_ci        (receiver.IsJSRegExp() || receiver == env->GetTaggedRegExpPrototype())) {
3954514f5e3Sopenharmony_ci        if (!PropertyDetector::IsRegExpFlagsDetectorValid(env)) {
3964514f5e3Sopenharmony_ci            return;
3974514f5e3Sopenharmony_ci        }
3984514f5e3Sopenharmony_ci        PropertyDetector::InvalidateRegExpFlagsDetector(env);
3994514f5e3Sopenharmony_ci    }
4004514f5e3Sopenharmony_ci}
4014514f5e3Sopenharmony_ci
4024514f5e3Sopenharmony_ci// static
4034514f5e3Sopenharmony_cibool ObjectOperator::IsDetectorName(const JSThread *thread, JSTaggedValue key)
4044514f5e3Sopenharmony_ci{
4054514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
4064514f5e3Sopenharmony_ci    uintptr_t start = GlobalEnv::GetFirstDetectorSymbolAddr(*env);
4074514f5e3Sopenharmony_ci    uintptr_t end = GlobalEnv::GetLastDetectorSymbolAddr(*env);
4084514f5e3Sopenharmony_ci    uintptr_t addr = key.GetRawData();
4094514f5e3Sopenharmony_ci    if ((start <= addr) && (addr <= end)) {
4104514f5e3Sopenharmony_ci        return true;
4114514f5e3Sopenharmony_ci    }
4124514f5e3Sopenharmony_ci    if (key == thread->GlobalConstants()->GetHandledFlagsString().GetTaggedValue()) {
4134514f5e3Sopenharmony_ci        return true;
4144514f5e3Sopenharmony_ci    }
4154514f5e3Sopenharmony_ci    return false;
4164514f5e3Sopenharmony_ci}
4174514f5e3Sopenharmony_ci
4184514f5e3Sopenharmony_ciSharedFieldType ObjectOperator::GetSharedFieldType() const
4194514f5e3Sopenharmony_ci{
4204514f5e3Sopenharmony_ci    return JSObject::Cast(holder_->GetTaggedObject())->GetJSHClass()->IsDictionaryMode()
4214514f5e3Sopenharmony_ci                              ? attributes_.GetDictSharedFieldType()
4224514f5e3Sopenharmony_ci                              : attributes_.GetSharedFieldType();
4234514f5e3Sopenharmony_ci}
4244514f5e3Sopenharmony_ci
4254514f5e3Sopenharmony_civoid ObjectOperator::ToPropertyDescriptor(PropertyDescriptor &desc) const
4264514f5e3Sopenharmony_ci{
4274514f5e3Sopenharmony_ci    DISALLOW_GARBAGE_COLLECTION;
4284514f5e3Sopenharmony_ci    if (!IsFound()) {
4294514f5e3Sopenharmony_ci        return;
4304514f5e3Sopenharmony_ci    }
4314514f5e3Sopenharmony_ci
4324514f5e3Sopenharmony_ci    if (!IsAccessorDescriptor()) {
4334514f5e3Sopenharmony_ci        desc.SetWritable(IsWritable());
4344514f5e3Sopenharmony_ci        JSTaggedValue val = GetValue();
4354514f5e3Sopenharmony_ci        desc.SetValue(JSHandle<JSTaggedValue>(thread_, val));
4364514f5e3Sopenharmony_ci        desc.SetSharedFieldType(GetSharedFieldType());
4374514f5e3Sopenharmony_ci    } else {
4384514f5e3Sopenharmony_ci        auto result = GetValue();
4394514f5e3Sopenharmony_ci        bool isPropertyBox = result.IsPropertyBox();
4404514f5e3Sopenharmony_ci        if (isPropertyBox) {
4414514f5e3Sopenharmony_ci            result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
4424514f5e3Sopenharmony_ci        }
4434514f5e3Sopenharmony_ci        AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject());
4444514f5e3Sopenharmony_ci
4454514f5e3Sopenharmony_ci        if (UNLIKELY(accessor->IsInternal())) {
4464514f5e3Sopenharmony_ci            desc.SetWritable(IsWritable());
4474514f5e3Sopenharmony_ci            auto val = accessor->CallInternalGet(thread_, JSHandle<JSObject>::Cast(GetHolder()));
4484514f5e3Sopenharmony_ci            JSMutableHandle<JSTaggedValue> value(thread_, val);
4494514f5e3Sopenharmony_ci            if (isPropertyBox) {
4504514f5e3Sopenharmony_ci                JSHandle<PropertyBox> cell(value_);
4514514f5e3Sopenharmony_ci                cell->SetValue(thread_, val);
4524514f5e3Sopenharmony_ci                value.Update(cell);
4534514f5e3Sopenharmony_ci            }
4544514f5e3Sopenharmony_ci            desc.SetValue(value);
4554514f5e3Sopenharmony_ci        } else {
4564514f5e3Sopenharmony_ci            desc.SetGetter(JSHandle<JSTaggedValue>(thread_, accessor->GetGetter()));
4574514f5e3Sopenharmony_ci            desc.SetSetter(JSHandle<JSTaggedValue>(thread_, accessor->GetSetter()));
4584514f5e3Sopenharmony_ci        }
4594514f5e3Sopenharmony_ci    }
4604514f5e3Sopenharmony_ci
4614514f5e3Sopenharmony_ci    desc.SetEnumerable(IsEnumerable());
4624514f5e3Sopenharmony_ci    desc.SetConfigurable(IsConfigurable());
4634514f5e3Sopenharmony_ci}
4644514f5e3Sopenharmony_ci
4654514f5e3Sopenharmony_civoid ObjectOperator::GlobalLookupProperty()
4664514f5e3Sopenharmony_ci{
4674514f5e3Sopenharmony_ci    GlobalLookupPropertyInHolder();
4684514f5e3Sopenharmony_ci    if (IsFound()) {
4694514f5e3Sopenharmony_ci        return;
4704514f5e3Sopenharmony_ci    }
4714514f5e3Sopenharmony_ci    JSTaggedValue proto = JSTaggedValue::GetPrototype(thread_, holder_);
4724514f5e3Sopenharmony_ci    RETURN_IF_ABRUPT_COMPLETION(thread_);
4734514f5e3Sopenharmony_ci    if (!proto.IsHeapObject()) {
4744514f5e3Sopenharmony_ci        return;
4754514f5e3Sopenharmony_ci    }
4764514f5e3Sopenharmony_ci    holder_.Update(proto);
4774514f5e3Sopenharmony_ci    if (holder_->IsJSProxy()) {
4784514f5e3Sopenharmony_ci        return;
4794514f5e3Sopenharmony_ci    }
4804514f5e3Sopenharmony_ci    SetIsOnPrototype(true);
4814514f5e3Sopenharmony_ci    LookupProperty();
4824514f5e3Sopenharmony_ci}
4834514f5e3Sopenharmony_ci
4844514f5e3Sopenharmony_civoid ObjectOperator::LookupProperty()
4854514f5e3Sopenharmony_ci{
4864514f5e3Sopenharmony_ci    while (true) {
4874514f5e3Sopenharmony_ci        if (holder_->IsJSProxy()) {
4884514f5e3Sopenharmony_ci            return;
4894514f5e3Sopenharmony_ci        }
4904514f5e3Sopenharmony_ci        UpdateIsTSHClass();
4914514f5e3Sopenharmony_ci        LookupPropertyInHolder();
4924514f5e3Sopenharmony_ci        if (IsFound()) {
4934514f5e3Sopenharmony_ci            return;
4944514f5e3Sopenharmony_ci        }
4954514f5e3Sopenharmony_ci
4964514f5e3Sopenharmony_ci        JSTaggedValue proto = JSTaggedValue::GetPrototype(thread_, holder_);
4974514f5e3Sopenharmony_ci        RETURN_IF_ABRUPT_COMPLETION(thread_);
4984514f5e3Sopenharmony_ci        if (!proto.IsHeapObject()) {
4994514f5e3Sopenharmony_ci            return;
5004514f5e3Sopenharmony_ci        }
5014514f5e3Sopenharmony_ci
5024514f5e3Sopenharmony_ci        holder_.Update(proto);
5034514f5e3Sopenharmony_ci        SetIsOnPrototype(true);
5044514f5e3Sopenharmony_ci    }
5054514f5e3Sopenharmony_ci}
5064514f5e3Sopenharmony_ci
5074514f5e3Sopenharmony_civoid ObjectOperator::LookupGlobal(const JSHandle<JSObject> &obj)
5084514f5e3Sopenharmony_ci{
5094514f5e3Sopenharmony_ci    ASSERT(obj->IsJSGlobalObject());
5104514f5e3Sopenharmony_ci    if (IsElement()) {
5114514f5e3Sopenharmony_ci        LookupElementInlinedProps(obj);
5124514f5e3Sopenharmony_ci        return;
5134514f5e3Sopenharmony_ci    }
5144514f5e3Sopenharmony_ci    TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
5154514f5e3Sopenharmony_ci    if (array->GetLength() == 0) {
5164514f5e3Sopenharmony_ci        return;
5174514f5e3Sopenharmony_ci    }
5184514f5e3Sopenharmony_ci    GlobalDictionary *dict = GlobalDictionary::Cast(array);
5194514f5e3Sopenharmony_ci    int entry = dict->FindEntry(key_.GetTaggedValue());
5204514f5e3Sopenharmony_ci    if (entry == -1) {
5214514f5e3Sopenharmony_ci        return;
5224514f5e3Sopenharmony_ci    }
5234514f5e3Sopenharmony_ci    JSTaggedValue value(dict->GetBox(entry));
5244514f5e3Sopenharmony_ci    auto attr = dict->GetAttributes(entry).GetValue();
5254514f5e3Sopenharmony_ci    SetFound(entry, value, attr, true);
5264514f5e3Sopenharmony_ci}
5274514f5e3Sopenharmony_ci
5284514f5e3Sopenharmony_civoid ObjectOperator::LookupPropertyInlinedProps(const JSHandle<JSObject> &obj)
5294514f5e3Sopenharmony_ci{
5304514f5e3Sopenharmony_ci    if (IsElement()) {
5314514f5e3Sopenharmony_ci        LookupElementInlinedProps(obj);
5324514f5e3Sopenharmony_ci        return;
5334514f5e3Sopenharmony_ci    }
5344514f5e3Sopenharmony_ci
5354514f5e3Sopenharmony_ci    if (!obj.GetTaggedValue().IsJSObject()) {
5364514f5e3Sopenharmony_ci        return;
5374514f5e3Sopenharmony_ci    }
5384514f5e3Sopenharmony_ci
5394514f5e3Sopenharmony_ci    if (obj->IsJSGlobalObject()) {
5404514f5e3Sopenharmony_ci        DISALLOW_GARBAGE_COLLECTION;
5414514f5e3Sopenharmony_ci        TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
5424514f5e3Sopenharmony_ci        if (array->GetLength() == 0) {
5434514f5e3Sopenharmony_ci            return;
5444514f5e3Sopenharmony_ci        }
5454514f5e3Sopenharmony_ci
5464514f5e3Sopenharmony_ci        GlobalDictionary *dict = GlobalDictionary::Cast(array);
5474514f5e3Sopenharmony_ci        int entry = dict->FindEntry(key_.GetTaggedValue());
5484514f5e3Sopenharmony_ci        if (entry == -1) {
5494514f5e3Sopenharmony_ci            return;
5504514f5e3Sopenharmony_ci        }
5514514f5e3Sopenharmony_ci
5524514f5e3Sopenharmony_ci        JSTaggedValue value(dict->GetBox(entry));
5534514f5e3Sopenharmony_ci        auto attr = dict->GetAttributes(entry).GetValue();
5544514f5e3Sopenharmony_ci        SetFound(entry, value, attr, !IsFoundDict());
5554514f5e3Sopenharmony_ci        return;
5564514f5e3Sopenharmony_ci    }
5574514f5e3Sopenharmony_ci
5584514f5e3Sopenharmony_ci    TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
5594514f5e3Sopenharmony_ci    if (!array->IsDictionaryMode()) {
5604514f5e3Sopenharmony_ci        JSHClass *jshclass = obj->GetJSHClass();
5614514f5e3Sopenharmony_ci        int entry = JSHClass::FindPropertyEntry(thread_, jshclass, key_.GetTaggedValue());
5624514f5e3Sopenharmony_ci        if (entry == -1) {
5634514f5e3Sopenharmony_ci            return;
5644514f5e3Sopenharmony_ci        }
5654514f5e3Sopenharmony_ci        JSTaggedValue attrs = jshclass->GetLayout();
5664514f5e3Sopenharmony_ci        LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject());
5674514f5e3Sopenharmony_ci        PropertyAttributes attr(layoutInfo->GetAttr(entry));
5684514f5e3Sopenharmony_ci        ASSERT(entry == static_cast<int>(attr.GetOffset()));
5694514f5e3Sopenharmony_ci        JSTaggedValue value;
5704514f5e3Sopenharmony_ci        if (attr.IsInlinedProps()) {
5714514f5e3Sopenharmony_ci            value = obj->GetPropertyInlinedPropsWithRep(entry, attr);
5724514f5e3Sopenharmony_ci            if (value.IsHole()) {
5734514f5e3Sopenharmony_ci                if (receiverHoleEntry_ == -1 && receiver_ == holder_) {
5744514f5e3Sopenharmony_ci                    receiverHoleEntry_ = entry;
5754514f5e3Sopenharmony_ci                }
5764514f5e3Sopenharmony_ci                return;
5774514f5e3Sopenharmony_ci            }
5784514f5e3Sopenharmony_ci        } else {
5794514f5e3Sopenharmony_ci            entry -= static_cast<int>(jshclass->GetInlinedProperties());
5804514f5e3Sopenharmony_ci            value = array->Get(entry);
5814514f5e3Sopenharmony_ci        }
5824514f5e3Sopenharmony_ci
5834514f5e3Sopenharmony_ci        SetFound(entry, value, attr.GetValue(), !IsFoundDict());
5844514f5e3Sopenharmony_ci        return;
5854514f5e3Sopenharmony_ci    }
5864514f5e3Sopenharmony_ci    SetFoundDict(true);
5874514f5e3Sopenharmony_ci    NameDictionary *dict = NameDictionary::Cast(array);
5884514f5e3Sopenharmony_ci    int entry = dict->FindEntry(key_.GetTaggedValue());
5894514f5e3Sopenharmony_ci    if (entry == -1) {
5904514f5e3Sopenharmony_ci        return;
5914514f5e3Sopenharmony_ci    }
5924514f5e3Sopenharmony_ci
5934514f5e3Sopenharmony_ci    JSTaggedValue value = dict->GetValue(entry);
5944514f5e3Sopenharmony_ci    auto attr = dict->GetAttributes(entry).GetValue();
5954514f5e3Sopenharmony_ci    SetFound(entry, value, attr, false);
5964514f5e3Sopenharmony_ci}
5974514f5e3Sopenharmony_ci
5984514f5e3Sopenharmony_civoid ObjectOperator::TransitionForAttributeChanged(const JSHandle<JSObject> &receiver, PropertyAttributes attr)
5994514f5e3Sopenharmony_ci{
6004514f5e3Sopenharmony_ci    if (IsElement()) {
6014514f5e3Sopenharmony_ci        uint32_t index = GetIndex();
6024514f5e3Sopenharmony_ci        if (!receiver->GetJSHClass()->IsDictionaryElement()) {
6034514f5e3Sopenharmony_ci            JSObject::ElementsToDictionary(thread_, receiver);
6044514f5e3Sopenharmony_ci            RETURN_IF_ABRUPT_COMPLETION(thread_);
6054514f5e3Sopenharmony_ci            auto dict = NumberDictionary::Cast(receiver->GetElements().GetTaggedObject());
6064514f5e3Sopenharmony_ci            index = static_cast<uint32_t>(dict->FindEntry(JSTaggedValue(index)));
6074514f5e3Sopenharmony_ci            PropertyAttributes origin = dict->GetAttributes(index);
6084514f5e3Sopenharmony_ci            attr.SetDictionaryOrder(origin.GetDictionaryOrder());
6094514f5e3Sopenharmony_ci            dict->SetAttributes(thread_, index, attr);
6104514f5e3Sopenharmony_ci        } else {
6114514f5e3Sopenharmony_ci            auto dict = NumberDictionary::Cast(receiver->GetElements().GetTaggedObject());
6124514f5e3Sopenharmony_ci            dict->SetAttributes(thread_, index, attr);
6134514f5e3Sopenharmony_ci        }
6144514f5e3Sopenharmony_ci        // update found result
6154514f5e3Sopenharmony_ci        UpdateFound(index, attr.GetValue(), false, true);
6164514f5e3Sopenharmony_ci    } else if (receiver->IsJSGlobalObject()) {
6174514f5e3Sopenharmony_ci        uint32_t index = GetIndex();
6184514f5e3Sopenharmony_ci        JSHandle<GlobalDictionary> dictHandle(thread_, receiver->GetProperties());
6194514f5e3Sopenharmony_ci        dictHandle->SetAttributes(thread_, index, attr);
6204514f5e3Sopenharmony_ci        GlobalDictionary::InvalidatePropertyBox(thread_, dictHandle, index);
6214514f5e3Sopenharmony_ci    } else {
6224514f5e3Sopenharmony_ci        uint32_t index = GetIndex();
6234514f5e3Sopenharmony_ci        if (!receiver->GetJSHClass()->IsDictionaryMode()) {
6244514f5e3Sopenharmony_ci            JSHandle<NameDictionary> dict(JSObject::TransitionToDictionary(thread_, receiver));
6254514f5e3Sopenharmony_ci            RETURN_IF_ABRUPT_COMPLETION(thread_);
6264514f5e3Sopenharmony_ci            index = static_cast<uint32_t>(dict->FindEntry(key_.GetTaggedValue()));
6274514f5e3Sopenharmony_ci            PropertyAttributes origin = dict->GetAttributes(index);
6284514f5e3Sopenharmony_ci            attr.SetDictSharedFieldType(attr.GetSharedFieldType());
6294514f5e3Sopenharmony_ci            attr.SetDictionaryOrder(origin.GetDictionaryOrder());
6304514f5e3Sopenharmony_ci            dict->SetAttributes(thread_, index, attr);
6314514f5e3Sopenharmony_ci        } else {
6324514f5e3Sopenharmony_ci            auto dict = NameDictionary::Cast(receiver->GetProperties().GetTaggedObject());
6334514f5e3Sopenharmony_ci            dict->SetAttributes(thread_, index, attr);
6344514f5e3Sopenharmony_ci        }
6354514f5e3Sopenharmony_ci        // update found result
6364514f5e3Sopenharmony_ci        UpdateFound(index, attr.GetValue(), false, true);
6374514f5e3Sopenharmony_ci    }
6384514f5e3Sopenharmony_ci}
6394514f5e3Sopenharmony_ci
6404514f5e3Sopenharmony_cibool ObjectOperator::UpdateValueAndDetails(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value,
6414514f5e3Sopenharmony_ci                                           PropertyAttributes attr, bool attrChanged)
6424514f5e3Sopenharmony_ci{
6434514f5e3Sopenharmony_ci    auto valueAccessor = GetValue();
6444514f5e3Sopenharmony_ci    if (valueAccessor.IsPropertyBox()) {
6454514f5e3Sopenharmony_ci        valueAccessor = PropertyBox::Cast(valueAccessor.GetTaggedObject())->GetValue();
6464514f5e3Sopenharmony_ci    }
6474514f5e3Sopenharmony_ci    bool isInternalAccessor = IsAccessorDescriptor()
6484514f5e3Sopenharmony_ci        && AccessorData::Cast(valueAccessor.GetTaggedObject())->IsInternal();
6494514f5e3Sopenharmony_ci    if (!attrChanged) {
6504514f5e3Sopenharmony_ci        return UpdateDataValue(receiver, value, isInternalAccessor);
6514514f5e3Sopenharmony_ci    }
6524514f5e3Sopenharmony_ci    if (attr.IsWritable()) {
6534514f5e3Sopenharmony_ci        TransitionForAttributeChanged(receiver, attr);
6544514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
6554514f5e3Sopenharmony_ci        return UpdateDataValue(receiver, value, isInternalAccessor);
6564514f5e3Sopenharmony_ci    }
6574514f5e3Sopenharmony_ci    bool res = UpdateDataValue(receiver, value, isInternalAccessor);
6584514f5e3Sopenharmony_ci    if (res) {
6594514f5e3Sopenharmony_ci        TransitionForAttributeChanged(receiver, attr);
6604514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
6614514f5e3Sopenharmony_ci    }
6624514f5e3Sopenharmony_ci    return res;
6634514f5e3Sopenharmony_ci}
6644514f5e3Sopenharmony_ci
6654514f5e3Sopenharmony_cibool ObjectOperator::UpdateDataValue(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value,
6664514f5e3Sopenharmony_ci                                     bool isInternalAccessor, bool mayThrow)
6674514f5e3Sopenharmony_ci{
6684514f5e3Sopenharmony_ci    if (IsElement()) {
6694514f5e3Sopenharmony_ci        TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject());
6704514f5e3Sopenharmony_ci        if (!elements->IsDictionaryMode()) {
6714514f5e3Sopenharmony_ci            if (receiver.GetTaggedValue().IsJSCOWArray()) {
6724514f5e3Sopenharmony_ci                JSArray::CheckAndCopyArray(thread_, JSHandle<JSArray>(receiver));
6734514f5e3Sopenharmony_ci            } else if (receiver->IsTypedArray()) {
6744514f5e3Sopenharmony_ci                JSTaggedValue holder = receiver.GetTaggedValue();
6754514f5e3Sopenharmony_ci                JSType jsType = holder.GetTaggedObject()->GetClass()->GetObjectType();
6764514f5e3Sopenharmony_ci                JSTaggedValue typedArrayProperty = JSTypedArray::FastSetPropertyByIndex(thread_,
6774514f5e3Sopenharmony_ci                    receiver.GetTaggedValue(), GetIndex(), value.GetTaggedValue(), jsType);
6784514f5e3Sopenharmony_ci                RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
6794514f5e3Sopenharmony_ci                if (typedArrayProperty.IsHole()) {
6804514f5e3Sopenharmony_ci                    return false;
6814514f5e3Sopenharmony_ci                }
6824514f5e3Sopenharmony_ci                return true;
6834514f5e3Sopenharmony_ci            }
6844514f5e3Sopenharmony_ci            ElementsKind oldKind = receiver->GetClass()->GetElementsKind();
6854514f5e3Sopenharmony_ci            if (JSHClass::TransitToElementsKind(thread_, receiver, value)) {
6864514f5e3Sopenharmony_ci                SetIsTransition(true);
6874514f5e3Sopenharmony_ci                ElementsKind newKind = receiver->GetClass()->GetElementsKind();
6884514f5e3Sopenharmony_ci                // newKind != currentKind, we need to convert the whole array to the newKind.
6894514f5e3Sopenharmony_ci                Elements::MigrateArrayWithKind(thread_, receiver, oldKind, newKind);
6904514f5e3Sopenharmony_ci            }
6914514f5e3Sopenharmony_ci            ElementAccessor::Set(thread_, receiver, GetIndex(), value, false);
6924514f5e3Sopenharmony_ci            return true;
6934514f5e3Sopenharmony_ci        }
6944514f5e3Sopenharmony_ci
6954514f5e3Sopenharmony_ci        NumberDictionary *dict = NumberDictionary::Cast(elements);
6964514f5e3Sopenharmony_ci        dict->UpdateValue(thread_, GetIndex(), value.GetTaggedValue());
6974514f5e3Sopenharmony_ci        return true;
6984514f5e3Sopenharmony_ci    }
6994514f5e3Sopenharmony_ci
7004514f5e3Sopenharmony_ci    if (receiver->IsJSGlobalObject()) {
7014514f5e3Sopenharmony_ci        // need update cell type ?
7024514f5e3Sopenharmony_ci        auto *dict = GlobalDictionary::Cast(receiver->GetProperties().GetTaggedObject());
7034514f5e3Sopenharmony_ci        if (isInternalAccessor && !value->IsAccessor()) {
7044514f5e3Sopenharmony_ci            PropertyAttributes attr = dict->GetAttributes(GetIndex());
7054514f5e3Sopenharmony_ci            attr.SetIsAccessor(false);
7064514f5e3Sopenharmony_ci            dict->SetAttributes(thread_, GetIndex(), attr);
7074514f5e3Sopenharmony_ci        }
7084514f5e3Sopenharmony_ci        PropertyBox *cell = dict->GetBox(GetIndex());
7094514f5e3Sopenharmony_ci        cell->SetValue(thread_, value.GetTaggedValue());
7104514f5e3Sopenharmony_ci        return true;
7114514f5e3Sopenharmony_ci    }
7124514f5e3Sopenharmony_ci
7134514f5e3Sopenharmony_ci    if (isInternalAccessor) {
7144514f5e3Sopenharmony_ci        auto accessor = AccessorData::Cast(GetValue().GetTaggedObject());
7154514f5e3Sopenharmony_ci        if (accessor->HasSetter()) {
7164514f5e3Sopenharmony_ci            bool res = accessor->CallInternalSet(thread_, JSHandle<JSObject>(receiver), value, mayThrow);
7174514f5e3Sopenharmony_ci            if (receiver->GetJSHClass()->IsDictionaryMode()) {
7184514f5e3Sopenharmony_ci                SetIsInlinedProps(false);
7194514f5e3Sopenharmony_ci                SetFastMode(false);
7204514f5e3Sopenharmony_ci            }
7214514f5e3Sopenharmony_ci            return res;
7224514f5e3Sopenharmony_ci        }
7234514f5e3Sopenharmony_ci    }
7244514f5e3Sopenharmony_ci
7254514f5e3Sopenharmony_ci    JSMutableHandle<TaggedArray> properties(thread_, TaggedArray::Cast(receiver->GetProperties().GetTaggedObject()));
7264514f5e3Sopenharmony_ci    if (!properties->IsDictionaryMode()) {
7274514f5e3Sopenharmony_ci        PropertyAttributes attr = GetAttr();
7284514f5e3Sopenharmony_ci        uint32_t offset = index_;
7294514f5e3Sopenharmony_ci        if (!attr.IsInlinedProps()) {
7304514f5e3Sopenharmony_ci            auto *hclass = receiver_->GetTaggedObject()->GetClass();
7314514f5e3Sopenharmony_ci            offset += hclass->GetInlinedProperties();
7324514f5e3Sopenharmony_ci        }
7334514f5e3Sopenharmony_ci        attr.SetOffset(offset);
7344514f5e3Sopenharmony_ci        JSHandle<JSObject> objHandle(receiver_);
7354514f5e3Sopenharmony_ci        ElementsKind oldKind = objHandle->GetJSHClass()->GetElementsKind();
7364514f5e3Sopenharmony_ci        auto actualValue =
7374514f5e3Sopenharmony_ci            JSHClass::ConvertOrTransitionWithRep(thread_, objHandle, key_, value, attr);
7384514f5e3Sopenharmony_ci        JSObject::TryMigrateToGenericKindForJSObject(thread_, objHandle, oldKind);
7394514f5e3Sopenharmony_ci        if (actualValue.isTransition) {
7404514f5e3Sopenharmony_ci            SetIsTransition(true);
7414514f5e3Sopenharmony_ci        }
7424514f5e3Sopenharmony_ci        attributes_.SetRepresentation(attr.GetRepresentation());
7434514f5e3Sopenharmony_ci
7444514f5e3Sopenharmony_ci        if (attr.IsInlinedProps()) {
7454514f5e3Sopenharmony_ci            receiver->SetPropertyInlinedPropsWithRep(thread_, GetIndex(), actualValue.value);
7464514f5e3Sopenharmony_ci        } else {
7474514f5e3Sopenharmony_ci            if (receiver.GetTaggedValue().IsJSCOWArray()) {
7484514f5e3Sopenharmony_ci                JSArray::CheckAndCopyArray(thread_, JSHandle<JSArray>(receiver));
7494514f5e3Sopenharmony_ci                properties.Update(JSHandle<JSArray>(receiver)->GetProperties());
7504514f5e3Sopenharmony_ci            }
7514514f5e3Sopenharmony_ci            if (actualValue.isTagged) {
7524514f5e3Sopenharmony_ci                properties->Set<true>(thread_, GetIndex(), value.GetTaggedValue());
7534514f5e3Sopenharmony_ci            } else {
7544514f5e3Sopenharmony_ci                properties->Set<false>(thread_, GetIndex(), actualValue.value);
7554514f5e3Sopenharmony_ci            }
7564514f5e3Sopenharmony_ci        }
7574514f5e3Sopenharmony_ci    } else {
7584514f5e3Sopenharmony_ci        properties.GetObject<NameDictionary>()->UpdateValue(thread_, GetIndex(), value.GetTaggedValue());
7594514f5e3Sopenharmony_ci    }
7604514f5e3Sopenharmony_ci    return true;
7614514f5e3Sopenharmony_ci}
7624514f5e3Sopenharmony_ci
7634514f5e3Sopenharmony_cibool ObjectOperator::WriteDataProperty(const JSHandle<JSObject> &receiver, const PropertyDescriptor &desc)
7644514f5e3Sopenharmony_ci{
7654514f5e3Sopenharmony_ci    PropertyAttributes attr = GetAttr();
7664514f5e3Sopenharmony_ci    bool attrChanged = false;
7674514f5e3Sopenharmony_ci
7684514f5e3Sopenharmony_ci    // composed new attribute from desc
7694514f5e3Sopenharmony_ci    if (desc.HasConfigurable() && attr.IsConfigurable() != desc.IsConfigurable()) {
7704514f5e3Sopenharmony_ci        attr.SetConfigurable(desc.IsConfigurable());
7714514f5e3Sopenharmony_ci        attrChanged = true;
7724514f5e3Sopenharmony_ci    }
7734514f5e3Sopenharmony_ci    if (desc.HasEnumerable() && attr.IsEnumerable() != desc.IsEnumerable()) {
7744514f5e3Sopenharmony_ci        attr.SetEnumerable(desc.IsEnumerable());
7754514f5e3Sopenharmony_ci        attrChanged = true;
7764514f5e3Sopenharmony_ci    }
7774514f5e3Sopenharmony_ci
7784514f5e3Sopenharmony_ci    if (!desc.IsAccessorDescriptor()) {
7794514f5e3Sopenharmony_ci        if (desc.HasWritable() && attr.IsWritable() != desc.IsWritable()) {
7804514f5e3Sopenharmony_ci            attr.SetWritable(desc.IsWritable());
7814514f5e3Sopenharmony_ci            attrChanged = true;
7824514f5e3Sopenharmony_ci        }
7834514f5e3Sopenharmony_ci        if (!desc.HasValue()) {
7844514f5e3Sopenharmony_ci            if (attrChanged) {
7854514f5e3Sopenharmony_ci                TransitionForAttributeChanged(receiver, attr);
7864514f5e3Sopenharmony_ci                RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
7874514f5e3Sopenharmony_ci            }
7884514f5e3Sopenharmony_ci            return true;
7894514f5e3Sopenharmony_ci        }
7904514f5e3Sopenharmony_ci
7914514f5e3Sopenharmony_ci        if (IsAccessorDescriptor()) {
7924514f5e3Sopenharmony_ci            TaggedObject *obj = GetValue().GetTaggedObject();
7934514f5e3Sopenharmony_ci            if (receiver->IsJSGlobalObject()) {
7944514f5e3Sopenharmony_ci                JSTaggedValue val = GetValue();
7954514f5e3Sopenharmony_ci                if (val.IsPropertyBox()) {
7964514f5e3Sopenharmony_ci                    PropertyBox *cell = PropertyBox::Cast(val.GetTaggedObject());
7974514f5e3Sopenharmony_ci                    obj = cell->GetValue().GetTaggedObject();
7984514f5e3Sopenharmony_ci                }
7994514f5e3Sopenharmony_ci            }
8004514f5e3Sopenharmony_ci            auto accessor = AccessorData::Cast(obj);
8014514f5e3Sopenharmony_ci            if (!accessor->IsInternal() || !accessor->HasSetter()) {
8024514f5e3Sopenharmony_ci                attr.SetIsAccessor(false);
8034514f5e3Sopenharmony_ci                attrChanged = true;
8044514f5e3Sopenharmony_ci            }
8054514f5e3Sopenharmony_ci        }
8064514f5e3Sopenharmony_ci
8074514f5e3Sopenharmony_ci        return UpdateValueAndDetails(receiver, desc.GetValue(), attr, attrChanged);
8084514f5e3Sopenharmony_ci    } else {
8094514f5e3Sopenharmony_ci        if (IsAccessorDescriptor() && !IsElement()) {
8104514f5e3Sopenharmony_ci            TaggedArray *properties = TaggedArray::Cast(receiver->GetProperties().GetTaggedObject());
8114514f5e3Sopenharmony_ci            if (attrChanged && !properties->IsDictionaryMode()) {
8124514f5e3Sopenharmony_ci                // as some accessorData is in globalEnv, we need to new accessorData.
8134514f5e3Sopenharmony_ci                JSHandle<AccessorData> accessor = thread_->GetEcmaVM()->GetFactory()->NewAccessorData();
8144514f5e3Sopenharmony_ci
8154514f5e3Sopenharmony_ci                if (desc.HasGetter()) {
8164514f5e3Sopenharmony_ci                    accessor->SetGetter(thread_, desc.GetGetter().GetTaggedValue());
8174514f5e3Sopenharmony_ci                } else {
8184514f5e3Sopenharmony_ci                    accessor->SetGetter(thread_, JSHandle<AccessorData>::Cast(value_)->GetGetter());
8194514f5e3Sopenharmony_ci                }
8204514f5e3Sopenharmony_ci                if (desc.HasSetter()) {
8214514f5e3Sopenharmony_ci                    accessor->SetSetter(thread_, desc.GetSetter().GetTaggedValue());
8224514f5e3Sopenharmony_ci                } else {
8234514f5e3Sopenharmony_ci                    accessor->SetSetter(thread_, JSHandle<AccessorData>::Cast(value_)->GetSetter());
8244514f5e3Sopenharmony_ci                }
8254514f5e3Sopenharmony_ci
8264514f5e3Sopenharmony_ci                JSHandle<NameDictionary> dict(JSObject::TransitionToDictionary(thread_, receiver));
8274514f5e3Sopenharmony_ci                RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
8284514f5e3Sopenharmony_ci                int entry = dict->FindEntry(key_.GetTaggedValue());
8294514f5e3Sopenharmony_ci                ASSERT(entry != -1);
8304514f5e3Sopenharmony_ci                dict->UpdateValueAndAttributes(thread_, entry, accessor.GetTaggedValue(), attr);
8314514f5e3Sopenharmony_ci                return true;
8324514f5e3Sopenharmony_ci            }
8334514f5e3Sopenharmony_ci        }
8344514f5e3Sopenharmony_ci
8354514f5e3Sopenharmony_ci        auto valueAccessor = GetValue();
8364514f5e3Sopenharmony_ci        if (valueAccessor.IsPropertyBox()) {
8374514f5e3Sopenharmony_ci            valueAccessor = PropertyBox::Cast(valueAccessor.GetTaggedObject())->GetValue();
8384514f5e3Sopenharmony_ci        }
8394514f5e3Sopenharmony_ci        JSHandle<AccessorData> accessor =
8404514f5e3Sopenharmony_ci            (IsAccessorDescriptor() && !JSHandle<AccessorData>(thread_, valueAccessor)->IsInternal()) ?
8414514f5e3Sopenharmony_ci            JSHandle<AccessorData>(thread_, valueAccessor) :
8424514f5e3Sopenharmony_ci            thread_->GetEcmaVM()->GetFactory()->NewAccessorData();
8434514f5e3Sopenharmony_ci        if (desc.HasGetter()) {
8444514f5e3Sopenharmony_ci            accessor->SetGetter(thread_, desc.GetGetter().GetTaggedValue());
8454514f5e3Sopenharmony_ci        }
8464514f5e3Sopenharmony_ci
8474514f5e3Sopenharmony_ci        if (desc.HasSetter()) {
8484514f5e3Sopenharmony_ci            accessor->SetSetter(thread_, desc.GetSetter().GetTaggedValue());
8494514f5e3Sopenharmony_ci        }
8504514f5e3Sopenharmony_ci
8514514f5e3Sopenharmony_ci        if (!IsAccessorDescriptor()) {
8524514f5e3Sopenharmony_ci            attr.SetIsAccessor(true);
8534514f5e3Sopenharmony_ci            attrChanged = true;
8544514f5e3Sopenharmony_ci        }
8554514f5e3Sopenharmony_ci
8564514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> value = JSHandle<JSTaggedValue>::Cast(accessor);
8574514f5e3Sopenharmony_ci        bool success = UpdateValueAndDetails(receiver, value, attr, attrChanged);
8584514f5e3Sopenharmony_ci        if (success) {
8594514f5e3Sopenharmony_ci            JSHandle<JSObject> obj(receiver);
8604514f5e3Sopenharmony_ci            if (obj->GetJSHClass()->IsPrototype()) {
8614514f5e3Sopenharmony_ci                JSHandle<ProtoChangeMarker> markerHandle = thread_->GetEcmaVM()->GetFactory()->NewProtoChangeMarker();
8624514f5e3Sopenharmony_ci                obj->GetJSHClass()->SetProtoChangeMarker(thread_, markerHandle.GetTaggedValue());
8634514f5e3Sopenharmony_ci            }
8644514f5e3Sopenharmony_ci            JSHClass::NotifyAccessorChanged(thread_, JSHandle<JSHClass>(thread_, obj->GetJSHClass()));
8654514f5e3Sopenharmony_ci        }
8664514f5e3Sopenharmony_ci        return success;
8674514f5e3Sopenharmony_ci    }
8684514f5e3Sopenharmony_ci}
8694514f5e3Sopenharmony_ci
8704514f5e3Sopenharmony_civoid ObjectOperator::DeletePropertyInHolder()
8714514f5e3Sopenharmony_ci{
8724514f5e3Sopenharmony_ci    if (IsElement()) {
8734514f5e3Sopenharmony_ci        return DeleteElementInHolder();
8744514f5e3Sopenharmony_ci    }
8754514f5e3Sopenharmony_ci    ObjectOperator::UpdateDetector(thread_, holder_.GetTaggedValue(), key_.GetTaggedValue());
8764514f5e3Sopenharmony_ci    JSObject::DeletePropertyInternal(thread_, JSHandle<JSObject>(holder_), key_, GetIndex());
8774514f5e3Sopenharmony_ci}
8784514f5e3Sopenharmony_ci
8794514f5e3Sopenharmony_cibool ObjectOperator::AddProperty(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value,
8804514f5e3Sopenharmony_ci                                 PropertyAttributes attr)
8814514f5e3Sopenharmony_ci{
8824514f5e3Sopenharmony_ci    if (IsElement()) {
8834514f5e3Sopenharmony_ci        ElementsKind oldKind = receiver->GetClass()->GetElementsKind();
8844514f5e3Sopenharmony_ci        uint32_t oldLen = receiver.GetTaggedValue().IsJSArray() ?
8854514f5e3Sopenharmony_ci            JSArray::Cast(*receiver)->GetArrayLength() : 0;
8864514f5e3Sopenharmony_ci        bool ret = JSObject::AddElementInternal(thread_, receiver, elementIndex_, value, attr);
8874514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
8884514f5e3Sopenharmony_ci        ElementsKind newKind = receiver->GetClass()->GetElementsKind();
8894514f5e3Sopenharmony_ci        uint32_t newLen = receiver.GetTaggedValue().IsJSArray() ?
8904514f5e3Sopenharmony_ci            JSArray::Cast(*receiver)->GetArrayLength() : 0;
8914514f5e3Sopenharmony_ci        SetElementOutOfBounds(newLen > oldLen);
8924514f5e3Sopenharmony_ci        bool isTransited = false;
8934514f5e3Sopenharmony_ci        if (receiver.GetTaggedValue().IsJSArray() && (newKind != oldKind)) {
8944514f5e3Sopenharmony_ci            isTransited = true;
8954514f5e3Sopenharmony_ci        }
8964514f5e3Sopenharmony_ci        bool isDict = receiver->GetJSHClass()->IsDictionaryElement();
8974514f5e3Sopenharmony_ci        SetFound(elementIndex_, value.GetTaggedValue(), attr.GetValue(), !isDict, isTransited);
8984514f5e3Sopenharmony_ci        return ret;
8994514f5e3Sopenharmony_ci    }
9004514f5e3Sopenharmony_ci
9014514f5e3Sopenharmony_ci    ResetStateForAddProperty();
9024514f5e3Sopenharmony_ci    receiver_.Update(receiver.GetTaggedValue());
9034514f5e3Sopenharmony_ci    SetAttr(attr.GetValue());
9044514f5e3Sopenharmony_ci    AddPropertyInternal(value);
9054514f5e3Sopenharmony_ci    return true;
9064514f5e3Sopenharmony_ci}
9074514f5e3Sopenharmony_ci
9084514f5e3Sopenharmony_civoid ObjectOperator::WriteElement(const JSHandle<JSObject> &receiver, JSHandle<JSTaggedValue> value) const
9094514f5e3Sopenharmony_ci{
9104514f5e3Sopenharmony_ci    ASSERT(IsElement() && GetIndex() < JSObject::MAX_ELEMENT_INDEX);
9114514f5e3Sopenharmony_ci
9124514f5e3Sopenharmony_ci    if (!ElementAccessor::IsDictionaryMode(receiver)) {
9134514f5e3Sopenharmony_ci        ElementAccessor::Set(thread_, receiver, index_, value, true);
9144514f5e3Sopenharmony_ci        return;
9154514f5e3Sopenharmony_ci    }
9164514f5e3Sopenharmony_ci
9174514f5e3Sopenharmony_ci    TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject());
9184514f5e3Sopenharmony_ci    NumberDictionary *dictionary = NumberDictionary::Cast(elements);
9194514f5e3Sopenharmony_ci    dictionary->UpdateValue(thread_, GetIndex(), value.GetTaggedValue());
9204514f5e3Sopenharmony_ci}
9214514f5e3Sopenharmony_ci
9224514f5e3Sopenharmony_civoid ObjectOperator::DeleteElementInHolder() const
9234514f5e3Sopenharmony_ci{
9244514f5e3Sopenharmony_ci    JSHandle<JSObject> obj(holder_);
9254514f5e3Sopenharmony_ci    if (obj->IsJSSArray()) {
9264514f5e3Sopenharmony_ci        auto arrayHandler = JSHandle<JSSharedArray>::Cast(obj);
9274514f5e3Sopenharmony_ci        JSSharedArray::DeleteInElementMode(thread_, arrayHandler);
9284514f5e3Sopenharmony_ci        return;
9294514f5e3Sopenharmony_ci    }
9304514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> holeHandle(thread_, JSTaggedValue::Hole());
9314514f5e3Sopenharmony_ci    if (!ElementAccessor::IsDictionaryMode(obj)) {
9324514f5e3Sopenharmony_ci        ElementAccessor::Set(thread_, obj, index_, holeHandle, true, ElementsKind::HOLE);
9334514f5e3Sopenharmony_ci        JSObject::ElementsToDictionary(thread_, JSHandle<JSObject>(holder_));
9344514f5e3Sopenharmony_ci        RETURN_IF_ABRUPT_COMPLETION(thread_);
9354514f5e3Sopenharmony_ci    } else {
9364514f5e3Sopenharmony_ci        TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject());
9374514f5e3Sopenharmony_ci        JSHandle<NumberDictionary> dictHandle(thread_, elements);
9384514f5e3Sopenharmony_ci        JSHandle<NumberDictionary> newDict = NumberDictionary::Remove(thread_, dictHandle, GetIndex());
9394514f5e3Sopenharmony_ci        obj->SetElements(thread_, newDict);
9404514f5e3Sopenharmony_ci    }
9414514f5e3Sopenharmony_ci}
9424514f5e3Sopenharmony_ci
9434514f5e3Sopenharmony_civoid ObjectOperator::SetFound(uint32_t index, JSTaggedValue value, uint64_t attr, bool mode, bool transition)
9444514f5e3Sopenharmony_ci{
9454514f5e3Sopenharmony_ci    SetIndex(index);
9464514f5e3Sopenharmony_ci    SetValue(value);
9474514f5e3Sopenharmony_ci    SetFastMode(mode);
9484514f5e3Sopenharmony_ci    SetIsTransition(transition);
9494514f5e3Sopenharmony_ci    SetAttr(attr);
9504514f5e3Sopenharmony_ci}
9514514f5e3Sopenharmony_ci
9524514f5e3Sopenharmony_civoid ObjectOperator::UpdateFound(uint32_t index, uint64_t attr, bool mode, bool transition)
9534514f5e3Sopenharmony_ci{
9544514f5e3Sopenharmony_ci    SetIndex(index);
9554514f5e3Sopenharmony_ci    SetFastMode(mode);
9564514f5e3Sopenharmony_ci    SetIsTransition(transition);
9574514f5e3Sopenharmony_ci    SetAttr(attr);
9584514f5e3Sopenharmony_ci}
9594514f5e3Sopenharmony_ci
9604514f5e3Sopenharmony_civoid ObjectOperator::ResetState()
9614514f5e3Sopenharmony_ci{
9624514f5e3Sopenharmony_ci    // index may used by element
9634514f5e3Sopenharmony_ci    SetIndex(NOT_FOUND_INDEX);
9644514f5e3Sopenharmony_ci    SetValue(JSTaggedValue::Undefined());
9654514f5e3Sopenharmony_ci    SetFastMode(false);
9664514f5e3Sopenharmony_ci    SetAttr(0);
9674514f5e3Sopenharmony_ci    SetIsOnPrototype(false);
9684514f5e3Sopenharmony_ci    SetHasReceiver(false);
9694514f5e3Sopenharmony_ci    SetIsTSHClass(false);
9704514f5e3Sopenharmony_ci}
9714514f5e3Sopenharmony_ci
9724514f5e3Sopenharmony_civoid ObjectOperator::ResetStateForAddProperty()
9734514f5e3Sopenharmony_ci{
9744514f5e3Sopenharmony_ci    bool isOnPrototype = IsOnPrototype();
9754514f5e3Sopenharmony_ci    ResetState();
9764514f5e3Sopenharmony_ci    SetIsOnPrototype(isOnPrototype);
9774514f5e3Sopenharmony_ci}
9784514f5e3Sopenharmony_ci
9794514f5e3Sopenharmony_civoid ObjectOperator::LookupElementInlinedProps(const JSHandle<JSObject> &obj)
9804514f5e3Sopenharmony_ci{
9814514f5e3Sopenharmony_ci    // if is js string, do special.
9824514f5e3Sopenharmony_ci    if (obj->IsJSPrimitiveRef() && JSPrimitiveRef::Cast(obj.GetTaggedValue().GetTaggedObject())->IsString()) {
9834514f5e3Sopenharmony_ci        PropertyDescriptor desc(thread_);
9844514f5e3Sopenharmony_ci        bool status = JSPrimitiveRef::StringGetIndexProperty(thread_, obj, elementIndex_, &desc);
9854514f5e3Sopenharmony_ci        if (status) {
9864514f5e3Sopenharmony_ci            PropertyAttributes attr(desc);
9874514f5e3Sopenharmony_ci            SetFound(elementIndex_, desc.GetValue().GetTaggedValue(), attr.GetValue(), !IsFoundDict());
9884514f5e3Sopenharmony_ci            return;
9894514f5e3Sopenharmony_ci        }
9904514f5e3Sopenharmony_ci    }
9914514f5e3Sopenharmony_ci    {
9924514f5e3Sopenharmony_ci        DISALLOW_GARBAGE_COLLECTION;
9934514f5e3Sopenharmony_ci        if (obj->IsTypedArray()) {
9944514f5e3Sopenharmony_ci            JSTaggedValue val = JSTypedArray::FastElementGet(thread_,
9954514f5e3Sopenharmony_ci                JSHandle<JSTaggedValue>::Cast(obj), elementIndex_).GetValue().GetTaggedValue();
9964514f5e3Sopenharmony_ci            RETURN_IF_ABRUPT_COMPLETION(thread_);
9974514f5e3Sopenharmony_ci            if (!val.IsHole()) {
9984514f5e3Sopenharmony_ci                SetFound(elementIndex_, val, PropertyAttributes::GetDefaultAttributes(), !IsFoundDict());
9994514f5e3Sopenharmony_ci            }
10004514f5e3Sopenharmony_ci            return;
10014514f5e3Sopenharmony_ci        }
10024514f5e3Sopenharmony_ci        TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject());
10034514f5e3Sopenharmony_ci        if (elements->GetLength() == 0) {
10044514f5e3Sopenharmony_ci            return;  // Empty Array
10054514f5e3Sopenharmony_ci        }
10064514f5e3Sopenharmony_ci
10074514f5e3Sopenharmony_ci        if (!elements->IsDictionaryMode()) {
10084514f5e3Sopenharmony_ci            if (elements->GetLength() <= elementIndex_) {
10094514f5e3Sopenharmony_ci                return;
10104514f5e3Sopenharmony_ci            }
10114514f5e3Sopenharmony_ci
10124514f5e3Sopenharmony_ci            JSTaggedValue value = ElementAccessor::Get(obj, elementIndex_);
10134514f5e3Sopenharmony_ci            if (value.IsHole()) {
10144514f5e3Sopenharmony_ci                return;
10154514f5e3Sopenharmony_ci            }
10164514f5e3Sopenharmony_ci            SetFound(elementIndex_, value, PropertyAttributes::GetDefaultAttributes(), !IsFoundDict());
10174514f5e3Sopenharmony_ci        } else {
10184514f5e3Sopenharmony_ci            SetFoundDict(true);
10194514f5e3Sopenharmony_ci            NumberDictionary *dictionary = NumberDictionary::Cast(obj->GetElements().GetTaggedObject());
10204514f5e3Sopenharmony_ci            JSTaggedValue key(static_cast<int>(elementIndex_));
10214514f5e3Sopenharmony_ci            int entry = dictionary->FindEntry(key);
10224514f5e3Sopenharmony_ci            if (entry == -1) {
10234514f5e3Sopenharmony_ci                return;
10244514f5e3Sopenharmony_ci            }
10254514f5e3Sopenharmony_ci
10264514f5e3Sopenharmony_ci            auto attr = dictionary->GetAttributes(entry).GetValue();
10274514f5e3Sopenharmony_ci            SetFound(entry, dictionary->GetValue(entry), attr, false);
10284514f5e3Sopenharmony_ci        }
10294514f5e3Sopenharmony_ci    }
10304514f5e3Sopenharmony_ci}
10314514f5e3Sopenharmony_ci
10324514f5e3Sopenharmony_civoid ObjectOperator::AddPropertyInternal(const JSHandle<JSTaggedValue> &value)
10334514f5e3Sopenharmony_ci{
10344514f5e3Sopenharmony_ci    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
10354514f5e3Sopenharmony_ci    JSHandle<JSObject> obj(GetReceiver());
10364514f5e3Sopenharmony_ci    PropertyAttributes attr = GetAttr();
10374514f5e3Sopenharmony_ci    if (obj->IsJSGlobalObject()) {
10384514f5e3Sopenharmony_ci        JSMutableHandle<GlobalDictionary> dict(thread_, obj->GetProperties());
10394514f5e3Sopenharmony_ci        if (dict->GetLength() == 0) {
10404514f5e3Sopenharmony_ci            dict.Update(GlobalDictionary::Create(thread_));
10414514f5e3Sopenharmony_ci        }
10424514f5e3Sopenharmony_ci
10434514f5e3Sopenharmony_ci        // Add PropertyBox to global dictionary
10444514f5e3Sopenharmony_ci        JSHandle<PropertyBox> cellHandle = factory->NewPropertyBox(key_);
10454514f5e3Sopenharmony_ci        cellHandle->SetValue(thread_, value.GetTaggedValue());
10464514f5e3Sopenharmony_ci        PropertyBoxType cellType = value->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT;
10474514f5e3Sopenharmony_ci        attr.SetBoxType(cellType);
10484514f5e3Sopenharmony_ci
10494514f5e3Sopenharmony_ci        JSHandle<GlobalDictionary> properties =
10504514f5e3Sopenharmony_ci            GlobalDictionary::PutIfAbsent(thread_, dict, key_, JSHandle<JSTaggedValue>(cellHandle), attr);
10514514f5e3Sopenharmony_ci        obj->SetProperties(thread_, properties);
10524514f5e3Sopenharmony_ci        // index and fastMode is not essential for global obj;
10534514f5e3Sopenharmony_ci        SetFound(0, cellHandle.GetTaggedValue(), attr.GetValue(), true);
10544514f5e3Sopenharmony_ci        return;
10554514f5e3Sopenharmony_ci    }
10564514f5e3Sopenharmony_ci
10574514f5e3Sopenharmony_ci    // The property has already existed whose value is hole, initialized by speculative hclass.
10584514f5e3Sopenharmony_ci    // Not need AddProperty,just SetProperty
10594514f5e3Sopenharmony_ci    if (receiverHoleEntry_ != -1) {
10604514f5e3Sopenharmony_ci        attr.SetOffset(receiverHoleEntry_);
10614514f5e3Sopenharmony_ci        JSHandle<JSObject> objHandle(receiver_);
10624514f5e3Sopenharmony_ci        ElementsKind oldKind = objHandle->GetJSHClass()->GetElementsKind();
10634514f5e3Sopenharmony_ci        auto actualValue =
10644514f5e3Sopenharmony_ci            JSHClass::ConvertOrTransitionWithRep(thread_, objHandle, key_, value, attr);
10654514f5e3Sopenharmony_ci        JSObject::TryMigrateToGenericKindForJSObject(thread_, objHandle, oldKind);
10664514f5e3Sopenharmony_ci        if (actualValue.isTransition) {
10674514f5e3Sopenharmony_ci            SetIsTransition(true);
10684514f5e3Sopenharmony_ci        }
10694514f5e3Sopenharmony_ci        attributes_.SetRepresentation(attr.GetRepresentation());
10704514f5e3Sopenharmony_ci        auto *hclass = receiver_->GetTaggedObject()->GetClass();
10714514f5e3Sopenharmony_ci        if (actualValue.isTagged) {
10724514f5e3Sopenharmony_ci            JSObject::Cast(receiver_.GetTaggedValue())->SetProperty<true>(thread_, hclass,
10734514f5e3Sopenharmony_ci                                                                          attr, value.GetTaggedValue());
10744514f5e3Sopenharmony_ci        } else {
10754514f5e3Sopenharmony_ci            JSObject::Cast(receiver_.GetTaggedValue())->SetProperty<false>(thread_, hclass, attr, actualValue.value);
10764514f5e3Sopenharmony_ci        }
10774514f5e3Sopenharmony_ci        uint32_t index = attr.IsInlinedProps() ? attr.GetOffset() :
10784514f5e3Sopenharmony_ci                attr.GetOffset() - obj->GetJSHClass()->GetInlinedProperties();
10794514f5e3Sopenharmony_ci        SetIsTSHClass(true);
10804514f5e3Sopenharmony_ci        SetIsOnPrototype(false);
10814514f5e3Sopenharmony_ci        SetFound(index, value.GetTaggedValue(), attr.GetValue(), true);
10824514f5e3Sopenharmony_ci        return;
10834514f5e3Sopenharmony_ci    }
10844514f5e3Sopenharmony_ci
10854514f5e3Sopenharmony_ci    attr = ObjectFastOperator::AddPropertyByName(thread_, obj, key_, value, attr);
10864514f5e3Sopenharmony_ci    RETURN_IF_ABRUPT_COMPLETION(thread_);
10874514f5e3Sopenharmony_ci    if (obj->GetJSHClass()->IsDictionaryMode()) {
10884514f5e3Sopenharmony_ci        SetFound(0, value.GetTaggedValue(), attr.GetValue(), false);
10894514f5e3Sopenharmony_ci    } else {
10904514f5e3Sopenharmony_ci        uint32_t index = attr.IsInlinedProps() ? attr.GetOffset() :
10914514f5e3Sopenharmony_ci                attr.GetOffset() - obj->GetJSHClass()->GetInlinedProperties();
10924514f5e3Sopenharmony_ci        SetFound(index, value.GetTaggedValue(), attr.GetValue(), true, true);
10934514f5e3Sopenharmony_ci    }
10944514f5e3Sopenharmony_ci}
10954514f5e3Sopenharmony_ci
10964514f5e3Sopenharmony_civoid ObjectOperator::DefineSetter(const JSHandle<JSTaggedValue> &value)
10974514f5e3Sopenharmony_ci{
10984514f5e3Sopenharmony_ci    ASSERT(IsAccessorDescriptor());
10994514f5e3Sopenharmony_ci    JSHandle<AccessorData> accessor = JSHandle<AccessorData>::Cast(value_);
11004514f5e3Sopenharmony_ci    accessor->SetSetter(thread_, value.GetTaggedValue());
11014514f5e3Sopenharmony_ci    UpdateDataValue(JSHandle<JSObject>::Cast(receiver_), JSHandle<JSTaggedValue>::Cast(accessor), false);
11024514f5e3Sopenharmony_ci}
11034514f5e3Sopenharmony_ci
11044514f5e3Sopenharmony_civoid ObjectOperator::DefineGetter(const JSHandle<JSTaggedValue> &value)
11054514f5e3Sopenharmony_ci{
11064514f5e3Sopenharmony_ci    ASSERT(IsAccessorDescriptor());
11074514f5e3Sopenharmony_ci    JSHandle<AccessorData> accessor = JSHandle<AccessorData>::Cast(value_);
11084514f5e3Sopenharmony_ci    accessor->SetGetter(thread_, value.GetTaggedValue());
11094514f5e3Sopenharmony_ci    UpdateDataValue(JSHandle<JSObject>::Cast(receiver_), JSHandle<JSTaggedValue>::Cast(accessor), false);
11104514f5e3Sopenharmony_ci}
11114514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
1112