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