1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/object_operator.h" 17 18#include "ecmascript/global_dictionary-inl.h" 19#include "ecmascript/js_primitive_ref.h" 20#include "ecmascript/object_fast_operator-inl.h" 21#include "ecmascript/property_detector-inl.h" 22 23namespace panda::ecmascript { 24void ObjectOperator::HandleKey(const JSHandle<JSTaggedValue> &key) 25{ 26 if (key->IsInt()) { 27 int32_t keyInt = key->GetInt(); 28 if (keyInt >= 0) { 29 elementIndex_ = static_cast<uint32_t>(keyInt); 30 return; 31 } 32 key_ = JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread_, JSTaggedValue(keyInt))); 33 return; 34 } 35 36 if (key->IsString()) { 37 keyFromStringType_ = true; 38 uint32_t index = 0; 39 if (JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index)) { 40 ASSERT(index < JSObject::MAX_ELEMENT_INDEX); 41 elementIndex_ = index; 42 return; 43 } 44 if (EcmaStringAccessor(key->GetTaggedObject()).IsInternString()) { 45 key_ = key; 46 return; 47 } 48 key_ = JSHandle<JSTaggedValue>(thread_, thread_->GetEcmaVM()->GetFactory()->InternString(key)); 49 return; 50 } 51 52 if (key->IsDouble()) { 53 double number = key->GetDouble(); 54 if (number >= 0 && number < JSObject::MAX_ELEMENT_INDEX) { 55 auto integer = static_cast<uint32_t>(number); 56 if (integer == number) { 57 elementIndex_ = static_cast<uint32_t>(number); 58 return; 59 } 60 } 61 key_ = JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread_, key.GetTaggedValue())); 62 if (!EcmaStringAccessor(key_.GetTaggedValue()).IsInternString()) { 63 key_ = JSHandle<JSTaggedValue>(thread_, thread_->GetEcmaVM()->GetFactory()->InternString(key_)); 64 } 65 return; 66 } 67 68 if (key->IsSymbol()) { 69 key_ = key; 70 return; 71 } 72 73 JSHandle<JSTaggedValue> keyHandle(thread_, JSTaggedValue::ToPrimitive(thread_, key, PREFER_STRING)); 74 RETURN_IF_ABRUPT_COMPLETION(thread_); 75 if (key->IsSymbol()) { 76 key_ = keyHandle; 77 return; 78 } 79 key_ = JSHandle<JSTaggedValue>(thread_, 80 thread_->GetEcmaVM()->GetFactory()->InternString( 81 JSHandle<JSTaggedValue>::Cast(JSTaggedValue::ToString(thread_, keyHandle)))); 82} 83 84void ObjectOperator::UpdateHolder() 85{ 86 if (holder_->IsString() && (GetThroughElement() || GetStringLength())) { 87 JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined(); 88 holder_.Update(JSPrimitiveRef::StringCreate(thread_, holder_, undefined).GetTaggedValue()); 89 } else { 90 if (holder_->IsString() || holder_->IsNumber()) { 91 SetIsOnPrototype(true); 92 } 93 holder_.Update(JSTaggedValue::ToPrototypeOrObj(thread_, holder_).GetTaggedValue()); 94 } 95} 96 97void ObjectOperator::UpdateIsTSHClass() 98{ 99 if (!holder_->IsECMAObject()) { 100 SetIsTSHClass(false); 101 return; 102 } 103 auto hclass = JSHandle<JSObject>::Cast(holder_)->GetClass(); 104 if (hclass->IsTS()) { 105 SetIsTSHClass(true); 106 } 107} 108 109void ObjectOperator::StartLookUp(OperatorType type) 110{ 111 UpdateHolder(); 112 113 if (type == OperatorType::OWN) { 114 LookupPropertyInHolder(); 115 } else { 116 LookupProperty(); 117 } 118} 119 120void ObjectOperator::StartGlobalLookUp(OperatorType type) 121{ 122 UpdateHolder(); 123 124 if (type == OperatorType::OWN) { 125 GlobalLookupPropertyInHolder(); 126 } else { 127 GlobalLookupProperty(); 128 } 129} 130 131ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &key, OperatorType type) 132 : thread_(thread), 133 holder_(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject()), 134 receiver_(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject()) 135{ 136 HandleKey(key); 137 StartGlobalLookUp(type); 138} 139 140ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSObject> &holder, const JSHandle<JSTaggedValue> &key, 141 OperatorType type) 142 : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, holder.GetTaggedValue()) 143{ 144 HandleKey(key); 145 StartLookUp(type); 146} 147 148ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder, 149 const JSHandle<JSTaggedValue> &key, OperatorType type) 150 : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, holder.GetTaggedValue()) 151{ 152 HandleKey(key); 153 StartLookUp(type); 154} 155 156ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder, uint32_t index, 157 OperatorType type) 158 : thread_(thread), 159 holder_(thread, holder.GetTaggedValue()), 160 receiver_(thread, holder.GetTaggedValue()), 161 elementIndex_(index) 162{ 163 StartLookUp(type); 164} 165 166ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder, 167 const JSHandle<JSTaggedValue> &receiver, const JSHandle<JSTaggedValue> &key, 168 OperatorType type) 169 : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, receiver.GetTaggedValue()) 170{ 171 SetHasReceiver(true); 172 HandleKey(key); 173 StartLookUp(type); 174} 175 176// op for fast path 177ObjectOperator::ObjectOperator(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name, 178 OperatorType type) 179 : thread_(thread), holder_(thread, receiver), receiver_(thread, receiver), key_(thread, name) 180{ 181 ASSERT(name.IsStringOrSymbol()); 182 StartLookUp(type); 183} 184JSHandle<JSTaggedValue> ObjectOperator::FastGetValue() 185{ 186 ASSERT(IsFound() && !value_.IsEmpty()); 187 if (value_->IsPropertyBox()) { 188 value_.Update(PropertyBox::Cast(value_->GetTaggedObject())->GetValue()); 189 } 190 if (!IsAccessorDescriptor()) { 191 return value_; 192 } 193 AccessorData *accessor = AccessorData::Cast(value_->GetTaggedObject()); 194 ASSERT(!accessor->IsInternal()); 195 // 8. Return Call(getter, Receiver). 196 return JSHandle<JSTaggedValue>(thread_, JSObject::CallGetter(thread_, accessor, receiver_)); 197} 198ObjectOperator::ObjectOperator(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name, 199 const PropertyAttributes &attr) 200 : thread_(thread), receiver_(thread, receiver), key_(thread, name) 201{ 202 SetAttr(attr); 203} 204void ObjectOperator::FastAdd(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name, 205 const JSHandle<JSTaggedValue> &value, const PropertyAttributes &attr) 206{ 207 ObjectOperator op(thread, receiver, name, attr); 208 op.AddPropertyInternal(value); 209} 210 211// static 212void ObjectOperator::UpdateDetectorOnSetPrototype(const JSThread *thread, JSTaggedValue receiver) 213{ 214 // skip env prepare 215 if (!thread->IsReadyToUpdateDetector()) { 216 return; 217 } 218 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 219 JSHClass *hclass = receiver.GetTaggedObject()->GetClass(); 220 JSType type = hclass->GetObjectType(); 221 switch (type) { 222 case JSType::JS_REG_EXP: { 223 if (PropertyDetector::IsRegExpReplaceDetectorValid(env)) { 224 PropertyDetector::InvalidateRegExpReplaceDetector(env); 225 } 226 if (PropertyDetector::IsRegExpFlagsDetectorValid(env)) { 227 PropertyDetector::InvalidateRegExpFlagsDetector(env); 228 } 229 return; 230 } 231 case JSType::JS_MAP: { 232 if (PropertyDetector::IsMapIteratorDetectorValid(env)) { 233 PropertyDetector::InvalidateMapIteratorDetector(env); 234 } 235 return; 236 } 237 case JSType::JS_SET: { 238 if (PropertyDetector::IsSetIteratorDetectorValid(env)) { 239 PropertyDetector::InvalidateSetIteratorDetector(env); 240 } 241 return; 242 } 243 case JSType::JS_PRIMITIVE_REF: { 244 if (JSPrimitiveRef::Cast(receiver.GetTaggedObject())->IsString() && 245 PropertyDetector::IsStringIteratorDetectorValid(env)) { 246 PropertyDetector::InvalidateStringIteratorDetector(env); 247 } 248 return; 249 } 250 case JSType::JS_ARRAY: { 251 if (PropertyDetector::IsArrayIteratorDetectorValid(env)) { 252 PropertyDetector::InvalidateArrayIteratorDetector(env); 253 } 254 return; 255 } 256 case JSType::JS_INT8_ARRAY: 257 case JSType::JS_UINT8_ARRAY: 258 case JSType::JS_UINT8_CLAMPED_ARRAY: 259 case JSType::JS_INT16_ARRAY: 260 case JSType::JS_UINT16_ARRAY: 261 case JSType::JS_INT32_ARRAY: 262 case JSType::JS_UINT32_ARRAY: 263 case JSType::JS_FLOAT32_ARRAY: 264 case JSType::JS_FLOAT64_ARRAY: 265 case JSType::JS_BIGINT64_ARRAY: 266 case JSType::JS_BIGUINT64_ARRAY: { 267 if (PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) { 268 PropertyDetector::InvalidateTypedArrayIteratorDetector(env); 269 } 270 if (PropertyDetector::IsTypedArraySpeciesProtectDetectorValid(env)) { 271 PropertyDetector::InvalidateTypedArraySpeciesProtectDetector(env); 272 } 273 return; 274 } 275 default: 276 break; 277 } 278 279 if (hclass->IsPrototype() && 280 (receiver == env->GetTaggedInt8ArrayFunctionPrototype() || 281 receiver == env->GetTaggedUint8ArrayFunctionPrototype() || 282 receiver == env->GetTaggedUint8ClampedArrayFunctionPrototype() || 283 receiver == env->GetTaggedInt16ArrayFunctionPrototype() || 284 receiver == env->GetTaggedUint16ArrayFunctionPrototype() || 285 receiver == env->GetTaggedInt32ArrayFunctionPrototype() || 286 receiver == env->GetTaggedUint32ArrayFunctionPrototype() || 287 receiver == env->GetTaggedFloat32ArrayFunctionPrototype() || 288 receiver == env->GetTaggedFloat64ArrayFunctionPrototype() || 289 receiver == env->GetTaggedBigInt64ArrayFunctionPrototype() || 290 receiver == env->GetTaggedBigUint64ArrayFunctionPrototype()) && 291 PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) { 292 PropertyDetector::InvalidateTypedArrayIteratorDetector(env); 293 return; 294 } 295 if ((PropertyDetector::IsNumberStringNotRegexpLikeDetectorValid(env) && 296 JSObject::Cast(receiver)->GetJSHClass()->IsPrototype() && receiver.IsJSPrimitive())) { 297 PropertyDetector::InvalidateNumberStringNotRegexpLikeDetector(env); 298 return; 299 } 300} 301 302void ObjectOperator::UpdateDetector() 303{ 304 if (IsElement()) { 305 return; 306 } 307 ObjectOperator::UpdateDetector(thread_, holder_.GetTaggedValue(), key_.GetTaggedValue()); 308} 309 310// static 311void ObjectOperator::UpdateDetector(const JSThread *thread, JSTaggedValue receiver, JSTaggedValue key) 312{ 313 // skip env prepare 314 if (!thread->IsReadyToUpdateDetector()) { 315 return; 316 } 317 bool maybeDetector = IsDetectorName(thread, key); 318 if (!maybeDetector) { 319 return; 320 } 321 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 322 auto globalConst = thread->GlobalConstants(); 323 if (key == env->GetTaggedReplaceSymbol() && 324 (receiver.IsJSRegExp() || receiver == env->GetTaggedRegExpPrototype())) { 325 if (!PropertyDetector::IsRegExpReplaceDetectorValid(env)) { 326 return; 327 } 328 PropertyDetector::InvalidateRegExpReplaceDetector(env); 329 } else if (key == env->GetTaggedIteratorSymbol()) { 330 if (receiver.IsJSMap() || receiver == env->GetTaggedMapPrototype()) { 331 if (!PropertyDetector::IsMapIteratorDetectorValid(env)) { 332 return; 333 } 334 PropertyDetector::InvalidateMapIteratorDetector(env); 335 } else if (receiver.IsJSSet() || receiver == env->GetTaggedSetPrototype()) { 336 if (!PropertyDetector::IsSetIteratorDetectorValid(env)) { 337 return; 338 } 339 PropertyDetector::InvalidateSetIteratorDetector(env); 340 } else if ((receiver.IsJSPrimitiveRef() && JSPrimitiveRef::Cast(receiver.GetTaggedObject())->IsString()) || 341 receiver == env->GetTaggedStringPrototype()) { 342 if (!PropertyDetector::IsStringIteratorDetectorValid(env)) { 343 return; 344 } 345 PropertyDetector::InvalidateStringIteratorDetector(env); 346 } else if (receiver.IsJSArray() || receiver == env->GetTaggedArrayPrototype()) { 347 if (!PropertyDetector::IsArrayIteratorDetectorValid(env)) { 348 return; 349 } 350 PropertyDetector::InvalidateArrayIteratorDetector(env); 351 } else if (receiver.IsTypedArray() || 352 receiver == env->GetTaggedArrayPrototype() || 353 receiver == env->GetTaggedInt8ArrayFunctionPrototype() || 354 receiver == env->GetTaggedUint8ArrayFunctionPrototype() || 355 receiver == env->GetTaggedUint8ClampedArrayFunctionPrototype() || 356 receiver == env->GetTaggedInt16ArrayFunctionPrototype() || 357 receiver == env->GetTaggedUint16ArrayFunctionPrototype() || 358 receiver == env->GetTaggedInt32ArrayFunctionPrototype() || 359 receiver == env->GetTaggedUint32ArrayFunctionPrototype() || 360 receiver == env->GetTaggedFloat32ArrayFunctionPrototype() || 361 receiver == env->GetTaggedFloat64ArrayFunctionPrototype() || 362 receiver == env->GetTaggedBigInt64ArrayFunctionPrototype() || 363 receiver == env->GetTaggedBigUint64ArrayFunctionPrototype()) { 364 if (!PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) { 365 return; 366 } 367 PropertyDetector::InvalidateTypedArrayIteratorDetector(env); 368 } 369 } else if (key == env->GetTaggedSpeciesSymbol()) { 370 if (receiver == env->GetTypedArrayFunction().GetTaggedValue()) { 371 if (!PropertyDetector::IsTypedArraySpeciesProtectDetectorValid(env)) { 372 return; 373 } 374 PropertyDetector::InvalidateTypedArraySpeciesProtectDetector(env); 375 } 376 if (receiver == env->GetRegExpFunction().GetTaggedValue()) { 377 if (!PropertyDetector::IsRegExpSpeciesDetectorValid(env)) { 378 return; 379 } 380 PropertyDetector::InvalidateRegExpSpeciesDetector(env); 381 } 382 } else if ((key == env->GetTaggedReplaceSymbol()) || 383 (key == env->GetTaggedSplitSymbol()) || 384 (key == env->GetTaggedMatchAllSymbol())) { 385 if (!PropertyDetector::IsNumberStringNotRegexpLikeDetectorValid(env)) { 386 return; 387 } 388 // check String.prototype or Number.prototype or Object.prototype 389 if ((JSObject::Cast(receiver)->GetJSHClass()->IsPrototype() && 390 (receiver.IsJSPrimitive() || receiver == env->GetTaggedObjectFunctionPrototype()))) { 391 PropertyDetector::InvalidateNumberStringNotRegexpLikeDetector(env); 392 } 393 } else if (key == globalConst->GetHandledFlagsString().GetTaggedValue() && 394 (receiver.IsJSRegExp() || receiver == env->GetTaggedRegExpPrototype())) { 395 if (!PropertyDetector::IsRegExpFlagsDetectorValid(env)) { 396 return; 397 } 398 PropertyDetector::InvalidateRegExpFlagsDetector(env); 399 } 400} 401 402// static 403bool ObjectOperator::IsDetectorName(const JSThread *thread, JSTaggedValue key) 404{ 405 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 406 uintptr_t start = GlobalEnv::GetFirstDetectorSymbolAddr(*env); 407 uintptr_t end = GlobalEnv::GetLastDetectorSymbolAddr(*env); 408 uintptr_t addr = key.GetRawData(); 409 if ((start <= addr) && (addr <= end)) { 410 return true; 411 } 412 if (key == thread->GlobalConstants()->GetHandledFlagsString().GetTaggedValue()) { 413 return true; 414 } 415 return false; 416} 417 418SharedFieldType ObjectOperator::GetSharedFieldType() const 419{ 420 return JSObject::Cast(holder_->GetTaggedObject())->GetJSHClass()->IsDictionaryMode() 421 ? attributes_.GetDictSharedFieldType() 422 : attributes_.GetSharedFieldType(); 423} 424 425void ObjectOperator::ToPropertyDescriptor(PropertyDescriptor &desc) const 426{ 427 DISALLOW_GARBAGE_COLLECTION; 428 if (!IsFound()) { 429 return; 430 } 431 432 if (!IsAccessorDescriptor()) { 433 desc.SetWritable(IsWritable()); 434 JSTaggedValue val = GetValue(); 435 desc.SetValue(JSHandle<JSTaggedValue>(thread_, val)); 436 desc.SetSharedFieldType(GetSharedFieldType()); 437 } else { 438 auto result = GetValue(); 439 bool isPropertyBox = result.IsPropertyBox(); 440 if (isPropertyBox) { 441 result = PropertyBox::Cast(result.GetTaggedObject())->GetValue(); 442 } 443 AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject()); 444 445 if (UNLIKELY(accessor->IsInternal())) { 446 desc.SetWritable(IsWritable()); 447 auto val = accessor->CallInternalGet(thread_, JSHandle<JSObject>::Cast(GetHolder())); 448 JSMutableHandle<JSTaggedValue> value(thread_, val); 449 if (isPropertyBox) { 450 JSHandle<PropertyBox> cell(value_); 451 cell->SetValue(thread_, val); 452 value.Update(cell); 453 } 454 desc.SetValue(value); 455 } else { 456 desc.SetGetter(JSHandle<JSTaggedValue>(thread_, accessor->GetGetter())); 457 desc.SetSetter(JSHandle<JSTaggedValue>(thread_, accessor->GetSetter())); 458 } 459 } 460 461 desc.SetEnumerable(IsEnumerable()); 462 desc.SetConfigurable(IsConfigurable()); 463} 464 465void ObjectOperator::GlobalLookupProperty() 466{ 467 GlobalLookupPropertyInHolder(); 468 if (IsFound()) { 469 return; 470 } 471 JSTaggedValue proto = JSTaggedValue::GetPrototype(thread_, holder_); 472 RETURN_IF_ABRUPT_COMPLETION(thread_); 473 if (!proto.IsHeapObject()) { 474 return; 475 } 476 holder_.Update(proto); 477 if (holder_->IsJSProxy()) { 478 return; 479 } 480 SetIsOnPrototype(true); 481 LookupProperty(); 482} 483 484void ObjectOperator::LookupProperty() 485{ 486 while (true) { 487 if (holder_->IsJSProxy()) { 488 return; 489 } 490 UpdateIsTSHClass(); 491 LookupPropertyInHolder(); 492 if (IsFound()) { 493 return; 494 } 495 496 JSTaggedValue proto = JSTaggedValue::GetPrototype(thread_, holder_); 497 RETURN_IF_ABRUPT_COMPLETION(thread_); 498 if (!proto.IsHeapObject()) { 499 return; 500 } 501 502 holder_.Update(proto); 503 SetIsOnPrototype(true); 504 } 505} 506 507void ObjectOperator::LookupGlobal(const JSHandle<JSObject> &obj) 508{ 509 ASSERT(obj->IsJSGlobalObject()); 510 if (IsElement()) { 511 LookupElementInlinedProps(obj); 512 return; 513 } 514 TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject()); 515 if (array->GetLength() == 0) { 516 return; 517 } 518 GlobalDictionary *dict = GlobalDictionary::Cast(array); 519 int entry = dict->FindEntry(key_.GetTaggedValue()); 520 if (entry == -1) { 521 return; 522 } 523 JSTaggedValue value(dict->GetBox(entry)); 524 auto attr = dict->GetAttributes(entry).GetValue(); 525 SetFound(entry, value, attr, true); 526} 527 528void ObjectOperator::LookupPropertyInlinedProps(const JSHandle<JSObject> &obj) 529{ 530 if (IsElement()) { 531 LookupElementInlinedProps(obj); 532 return; 533 } 534 535 if (!obj.GetTaggedValue().IsJSObject()) { 536 return; 537 } 538 539 if (obj->IsJSGlobalObject()) { 540 DISALLOW_GARBAGE_COLLECTION; 541 TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject()); 542 if (array->GetLength() == 0) { 543 return; 544 } 545 546 GlobalDictionary *dict = GlobalDictionary::Cast(array); 547 int entry = dict->FindEntry(key_.GetTaggedValue()); 548 if (entry == -1) { 549 return; 550 } 551 552 JSTaggedValue value(dict->GetBox(entry)); 553 auto attr = dict->GetAttributes(entry).GetValue(); 554 SetFound(entry, value, attr, !IsFoundDict()); 555 return; 556 } 557 558 TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject()); 559 if (!array->IsDictionaryMode()) { 560 JSHClass *jshclass = obj->GetJSHClass(); 561 int entry = JSHClass::FindPropertyEntry(thread_, jshclass, key_.GetTaggedValue()); 562 if (entry == -1) { 563 return; 564 } 565 JSTaggedValue attrs = jshclass->GetLayout(); 566 LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject()); 567 PropertyAttributes attr(layoutInfo->GetAttr(entry)); 568 ASSERT(entry == static_cast<int>(attr.GetOffset())); 569 JSTaggedValue value; 570 if (attr.IsInlinedProps()) { 571 value = obj->GetPropertyInlinedPropsWithRep(entry, attr); 572 if (value.IsHole()) { 573 if (receiverHoleEntry_ == -1 && receiver_ == holder_) { 574 receiverHoleEntry_ = entry; 575 } 576 return; 577 } 578 } else { 579 entry -= static_cast<int>(jshclass->GetInlinedProperties()); 580 value = array->Get(entry); 581 } 582 583 SetFound(entry, value, attr.GetValue(), !IsFoundDict()); 584 return; 585 } 586 SetFoundDict(true); 587 NameDictionary *dict = NameDictionary::Cast(array); 588 int entry = dict->FindEntry(key_.GetTaggedValue()); 589 if (entry == -1) { 590 return; 591 } 592 593 JSTaggedValue value = dict->GetValue(entry); 594 auto attr = dict->GetAttributes(entry).GetValue(); 595 SetFound(entry, value, attr, false); 596} 597 598void ObjectOperator::TransitionForAttributeChanged(const JSHandle<JSObject> &receiver, PropertyAttributes attr) 599{ 600 if (IsElement()) { 601 uint32_t index = GetIndex(); 602 if (!receiver->GetJSHClass()->IsDictionaryElement()) { 603 JSObject::ElementsToDictionary(thread_, receiver); 604 RETURN_IF_ABRUPT_COMPLETION(thread_); 605 auto dict = NumberDictionary::Cast(receiver->GetElements().GetTaggedObject()); 606 index = static_cast<uint32_t>(dict->FindEntry(JSTaggedValue(index))); 607 PropertyAttributes origin = dict->GetAttributes(index); 608 attr.SetDictionaryOrder(origin.GetDictionaryOrder()); 609 dict->SetAttributes(thread_, index, attr); 610 } else { 611 auto dict = NumberDictionary::Cast(receiver->GetElements().GetTaggedObject()); 612 dict->SetAttributes(thread_, index, attr); 613 } 614 // update found result 615 UpdateFound(index, attr.GetValue(), false, true); 616 } else if (receiver->IsJSGlobalObject()) { 617 uint32_t index = GetIndex(); 618 JSHandle<GlobalDictionary> dictHandle(thread_, receiver->GetProperties()); 619 dictHandle->SetAttributes(thread_, index, attr); 620 GlobalDictionary::InvalidatePropertyBox(thread_, dictHandle, index); 621 } else { 622 uint32_t index = GetIndex(); 623 if (!receiver->GetJSHClass()->IsDictionaryMode()) { 624 JSHandle<NameDictionary> dict(JSObject::TransitionToDictionary(thread_, receiver)); 625 RETURN_IF_ABRUPT_COMPLETION(thread_); 626 index = static_cast<uint32_t>(dict->FindEntry(key_.GetTaggedValue())); 627 PropertyAttributes origin = dict->GetAttributes(index); 628 attr.SetDictSharedFieldType(attr.GetSharedFieldType()); 629 attr.SetDictionaryOrder(origin.GetDictionaryOrder()); 630 dict->SetAttributes(thread_, index, attr); 631 } else { 632 auto dict = NameDictionary::Cast(receiver->GetProperties().GetTaggedObject()); 633 dict->SetAttributes(thread_, index, attr); 634 } 635 // update found result 636 UpdateFound(index, attr.GetValue(), false, true); 637 } 638} 639 640bool ObjectOperator::UpdateValueAndDetails(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value, 641 PropertyAttributes attr, bool attrChanged) 642{ 643 auto valueAccessor = GetValue(); 644 if (valueAccessor.IsPropertyBox()) { 645 valueAccessor = PropertyBox::Cast(valueAccessor.GetTaggedObject())->GetValue(); 646 } 647 bool isInternalAccessor = IsAccessorDescriptor() 648 && AccessorData::Cast(valueAccessor.GetTaggedObject())->IsInternal(); 649 if (!attrChanged) { 650 return UpdateDataValue(receiver, value, isInternalAccessor); 651 } 652 if (attr.IsWritable()) { 653 TransitionForAttributeChanged(receiver, attr); 654 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false); 655 return UpdateDataValue(receiver, value, isInternalAccessor); 656 } 657 bool res = UpdateDataValue(receiver, value, isInternalAccessor); 658 if (res) { 659 TransitionForAttributeChanged(receiver, attr); 660 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false); 661 } 662 return res; 663} 664 665bool ObjectOperator::UpdateDataValue(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value, 666 bool isInternalAccessor, bool mayThrow) 667{ 668 if (IsElement()) { 669 TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject()); 670 if (!elements->IsDictionaryMode()) { 671 if (receiver.GetTaggedValue().IsJSCOWArray()) { 672 JSArray::CheckAndCopyArray(thread_, JSHandle<JSArray>(receiver)); 673 } else if (receiver->IsTypedArray()) { 674 JSTaggedValue holder = receiver.GetTaggedValue(); 675 JSType jsType = holder.GetTaggedObject()->GetClass()->GetObjectType(); 676 JSTaggedValue typedArrayProperty = JSTypedArray::FastSetPropertyByIndex(thread_, 677 receiver.GetTaggedValue(), GetIndex(), value.GetTaggedValue(), jsType); 678 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false); 679 if (typedArrayProperty.IsHole()) { 680 return false; 681 } 682 return true; 683 } 684 ElementsKind oldKind = receiver->GetClass()->GetElementsKind(); 685 if (JSHClass::TransitToElementsKind(thread_, receiver, value)) { 686 SetIsTransition(true); 687 ElementsKind newKind = receiver->GetClass()->GetElementsKind(); 688 // newKind != currentKind, we need to convert the whole array to the newKind. 689 Elements::MigrateArrayWithKind(thread_, receiver, oldKind, newKind); 690 } 691 ElementAccessor::Set(thread_, receiver, GetIndex(), value, false); 692 return true; 693 } 694 695 NumberDictionary *dict = NumberDictionary::Cast(elements); 696 dict->UpdateValue(thread_, GetIndex(), value.GetTaggedValue()); 697 return true; 698 } 699 700 if (receiver->IsJSGlobalObject()) { 701 // need update cell type ? 702 auto *dict = GlobalDictionary::Cast(receiver->GetProperties().GetTaggedObject()); 703 if (isInternalAccessor && !value->IsAccessor()) { 704 PropertyAttributes attr = dict->GetAttributes(GetIndex()); 705 attr.SetIsAccessor(false); 706 dict->SetAttributes(thread_, GetIndex(), attr); 707 } 708 PropertyBox *cell = dict->GetBox(GetIndex()); 709 cell->SetValue(thread_, value.GetTaggedValue()); 710 return true; 711 } 712 713 if (isInternalAccessor) { 714 auto accessor = AccessorData::Cast(GetValue().GetTaggedObject()); 715 if (accessor->HasSetter()) { 716 bool res = accessor->CallInternalSet(thread_, JSHandle<JSObject>(receiver), value, mayThrow); 717 if (receiver->GetJSHClass()->IsDictionaryMode()) { 718 SetIsInlinedProps(false); 719 SetFastMode(false); 720 } 721 return res; 722 } 723 } 724 725 JSMutableHandle<TaggedArray> properties(thread_, TaggedArray::Cast(receiver->GetProperties().GetTaggedObject())); 726 if (!properties->IsDictionaryMode()) { 727 PropertyAttributes attr = GetAttr(); 728 uint32_t offset = index_; 729 if (!attr.IsInlinedProps()) { 730 auto *hclass = receiver_->GetTaggedObject()->GetClass(); 731 offset += hclass->GetInlinedProperties(); 732 } 733 attr.SetOffset(offset); 734 JSHandle<JSObject> objHandle(receiver_); 735 ElementsKind oldKind = objHandle->GetJSHClass()->GetElementsKind(); 736 auto actualValue = 737 JSHClass::ConvertOrTransitionWithRep(thread_, objHandle, key_, value, attr); 738 JSObject::TryMigrateToGenericKindForJSObject(thread_, objHandle, oldKind); 739 if (actualValue.isTransition) { 740 SetIsTransition(true); 741 } 742 attributes_.SetRepresentation(attr.GetRepresentation()); 743 744 if (attr.IsInlinedProps()) { 745 receiver->SetPropertyInlinedPropsWithRep(thread_, GetIndex(), actualValue.value); 746 } else { 747 if (receiver.GetTaggedValue().IsJSCOWArray()) { 748 JSArray::CheckAndCopyArray(thread_, JSHandle<JSArray>(receiver)); 749 properties.Update(JSHandle<JSArray>(receiver)->GetProperties()); 750 } 751 if (actualValue.isTagged) { 752 properties->Set<true>(thread_, GetIndex(), value.GetTaggedValue()); 753 } else { 754 properties->Set<false>(thread_, GetIndex(), actualValue.value); 755 } 756 } 757 } else { 758 properties.GetObject<NameDictionary>()->UpdateValue(thread_, GetIndex(), value.GetTaggedValue()); 759 } 760 return true; 761} 762 763bool ObjectOperator::WriteDataProperty(const JSHandle<JSObject> &receiver, const PropertyDescriptor &desc) 764{ 765 PropertyAttributes attr = GetAttr(); 766 bool attrChanged = false; 767 768 // composed new attribute from desc 769 if (desc.HasConfigurable() && attr.IsConfigurable() != desc.IsConfigurable()) { 770 attr.SetConfigurable(desc.IsConfigurable()); 771 attrChanged = true; 772 } 773 if (desc.HasEnumerable() && attr.IsEnumerable() != desc.IsEnumerable()) { 774 attr.SetEnumerable(desc.IsEnumerable()); 775 attrChanged = true; 776 } 777 778 if (!desc.IsAccessorDescriptor()) { 779 if (desc.HasWritable() && attr.IsWritable() != desc.IsWritable()) { 780 attr.SetWritable(desc.IsWritable()); 781 attrChanged = true; 782 } 783 if (!desc.HasValue()) { 784 if (attrChanged) { 785 TransitionForAttributeChanged(receiver, attr); 786 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false); 787 } 788 return true; 789 } 790 791 if (IsAccessorDescriptor()) { 792 TaggedObject *obj = GetValue().GetTaggedObject(); 793 if (receiver->IsJSGlobalObject()) { 794 JSTaggedValue val = GetValue(); 795 if (val.IsPropertyBox()) { 796 PropertyBox *cell = PropertyBox::Cast(val.GetTaggedObject()); 797 obj = cell->GetValue().GetTaggedObject(); 798 } 799 } 800 auto accessor = AccessorData::Cast(obj); 801 if (!accessor->IsInternal() || !accessor->HasSetter()) { 802 attr.SetIsAccessor(false); 803 attrChanged = true; 804 } 805 } 806 807 return UpdateValueAndDetails(receiver, desc.GetValue(), attr, attrChanged); 808 } else { 809 if (IsAccessorDescriptor() && !IsElement()) { 810 TaggedArray *properties = TaggedArray::Cast(receiver->GetProperties().GetTaggedObject()); 811 if (attrChanged && !properties->IsDictionaryMode()) { 812 // as some accessorData is in globalEnv, we need to new accessorData. 813 JSHandle<AccessorData> accessor = thread_->GetEcmaVM()->GetFactory()->NewAccessorData(); 814 815 if (desc.HasGetter()) { 816 accessor->SetGetter(thread_, desc.GetGetter().GetTaggedValue()); 817 } else { 818 accessor->SetGetter(thread_, JSHandle<AccessorData>::Cast(value_)->GetGetter()); 819 } 820 if (desc.HasSetter()) { 821 accessor->SetSetter(thread_, desc.GetSetter().GetTaggedValue()); 822 } else { 823 accessor->SetSetter(thread_, JSHandle<AccessorData>::Cast(value_)->GetSetter()); 824 } 825 826 JSHandle<NameDictionary> dict(JSObject::TransitionToDictionary(thread_, receiver)); 827 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false); 828 int entry = dict->FindEntry(key_.GetTaggedValue()); 829 ASSERT(entry != -1); 830 dict->UpdateValueAndAttributes(thread_, entry, accessor.GetTaggedValue(), attr); 831 return true; 832 } 833 } 834 835 auto valueAccessor = GetValue(); 836 if (valueAccessor.IsPropertyBox()) { 837 valueAccessor = PropertyBox::Cast(valueAccessor.GetTaggedObject())->GetValue(); 838 } 839 JSHandle<AccessorData> accessor = 840 (IsAccessorDescriptor() && !JSHandle<AccessorData>(thread_, valueAccessor)->IsInternal()) ? 841 JSHandle<AccessorData>(thread_, valueAccessor) : 842 thread_->GetEcmaVM()->GetFactory()->NewAccessorData(); 843 if (desc.HasGetter()) { 844 accessor->SetGetter(thread_, desc.GetGetter().GetTaggedValue()); 845 } 846 847 if (desc.HasSetter()) { 848 accessor->SetSetter(thread_, desc.GetSetter().GetTaggedValue()); 849 } 850 851 if (!IsAccessorDescriptor()) { 852 attr.SetIsAccessor(true); 853 attrChanged = true; 854 } 855 856 JSHandle<JSTaggedValue> value = JSHandle<JSTaggedValue>::Cast(accessor); 857 bool success = UpdateValueAndDetails(receiver, value, attr, attrChanged); 858 if (success) { 859 JSHandle<JSObject> obj(receiver); 860 if (obj->GetJSHClass()->IsPrototype()) { 861 JSHandle<ProtoChangeMarker> markerHandle = thread_->GetEcmaVM()->GetFactory()->NewProtoChangeMarker(); 862 obj->GetJSHClass()->SetProtoChangeMarker(thread_, markerHandle.GetTaggedValue()); 863 } 864 JSHClass::NotifyAccessorChanged(thread_, JSHandle<JSHClass>(thread_, obj->GetJSHClass())); 865 } 866 return success; 867 } 868} 869 870void ObjectOperator::DeletePropertyInHolder() 871{ 872 if (IsElement()) { 873 return DeleteElementInHolder(); 874 } 875 ObjectOperator::UpdateDetector(thread_, holder_.GetTaggedValue(), key_.GetTaggedValue()); 876 JSObject::DeletePropertyInternal(thread_, JSHandle<JSObject>(holder_), key_, GetIndex()); 877} 878 879bool ObjectOperator::AddProperty(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value, 880 PropertyAttributes attr) 881{ 882 if (IsElement()) { 883 ElementsKind oldKind = receiver->GetClass()->GetElementsKind(); 884 uint32_t oldLen = receiver.GetTaggedValue().IsJSArray() ? 885 JSArray::Cast(*receiver)->GetArrayLength() : 0; 886 bool ret = JSObject::AddElementInternal(thread_, receiver, elementIndex_, value, attr); 887 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false); 888 ElementsKind newKind = receiver->GetClass()->GetElementsKind(); 889 uint32_t newLen = receiver.GetTaggedValue().IsJSArray() ? 890 JSArray::Cast(*receiver)->GetArrayLength() : 0; 891 SetElementOutOfBounds(newLen > oldLen); 892 bool isTransited = false; 893 if (receiver.GetTaggedValue().IsJSArray() && (newKind != oldKind)) { 894 isTransited = true; 895 } 896 bool isDict = receiver->GetJSHClass()->IsDictionaryElement(); 897 SetFound(elementIndex_, value.GetTaggedValue(), attr.GetValue(), !isDict, isTransited); 898 return ret; 899 } 900 901 ResetStateForAddProperty(); 902 receiver_.Update(receiver.GetTaggedValue()); 903 SetAttr(attr.GetValue()); 904 AddPropertyInternal(value); 905 return true; 906} 907 908void ObjectOperator::WriteElement(const JSHandle<JSObject> &receiver, JSHandle<JSTaggedValue> value) const 909{ 910 ASSERT(IsElement() && GetIndex() < JSObject::MAX_ELEMENT_INDEX); 911 912 if (!ElementAccessor::IsDictionaryMode(receiver)) { 913 ElementAccessor::Set(thread_, receiver, index_, value, true); 914 return; 915 } 916 917 TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject()); 918 NumberDictionary *dictionary = NumberDictionary::Cast(elements); 919 dictionary->UpdateValue(thread_, GetIndex(), value.GetTaggedValue()); 920} 921 922void ObjectOperator::DeleteElementInHolder() const 923{ 924 JSHandle<JSObject> obj(holder_); 925 if (obj->IsJSSArray()) { 926 auto arrayHandler = JSHandle<JSSharedArray>::Cast(obj); 927 JSSharedArray::DeleteInElementMode(thread_, arrayHandler); 928 return; 929 } 930 JSHandle<JSTaggedValue> holeHandle(thread_, JSTaggedValue::Hole()); 931 if (!ElementAccessor::IsDictionaryMode(obj)) { 932 ElementAccessor::Set(thread_, obj, index_, holeHandle, true, ElementsKind::HOLE); 933 JSObject::ElementsToDictionary(thread_, JSHandle<JSObject>(holder_)); 934 RETURN_IF_ABRUPT_COMPLETION(thread_); 935 } else { 936 TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject()); 937 JSHandle<NumberDictionary> dictHandle(thread_, elements); 938 JSHandle<NumberDictionary> newDict = NumberDictionary::Remove(thread_, dictHandle, GetIndex()); 939 obj->SetElements(thread_, newDict); 940 } 941} 942 943void ObjectOperator::SetFound(uint32_t index, JSTaggedValue value, uint64_t attr, bool mode, bool transition) 944{ 945 SetIndex(index); 946 SetValue(value); 947 SetFastMode(mode); 948 SetIsTransition(transition); 949 SetAttr(attr); 950} 951 952void ObjectOperator::UpdateFound(uint32_t index, uint64_t attr, bool mode, bool transition) 953{ 954 SetIndex(index); 955 SetFastMode(mode); 956 SetIsTransition(transition); 957 SetAttr(attr); 958} 959 960void ObjectOperator::ResetState() 961{ 962 // index may used by element 963 SetIndex(NOT_FOUND_INDEX); 964 SetValue(JSTaggedValue::Undefined()); 965 SetFastMode(false); 966 SetAttr(0); 967 SetIsOnPrototype(false); 968 SetHasReceiver(false); 969 SetIsTSHClass(false); 970} 971 972void ObjectOperator::ResetStateForAddProperty() 973{ 974 bool isOnPrototype = IsOnPrototype(); 975 ResetState(); 976 SetIsOnPrototype(isOnPrototype); 977} 978 979void ObjectOperator::LookupElementInlinedProps(const JSHandle<JSObject> &obj) 980{ 981 // if is js string, do special. 982 if (obj->IsJSPrimitiveRef() && JSPrimitiveRef::Cast(obj.GetTaggedValue().GetTaggedObject())->IsString()) { 983 PropertyDescriptor desc(thread_); 984 bool status = JSPrimitiveRef::StringGetIndexProperty(thread_, obj, elementIndex_, &desc); 985 if (status) { 986 PropertyAttributes attr(desc); 987 SetFound(elementIndex_, desc.GetValue().GetTaggedValue(), attr.GetValue(), !IsFoundDict()); 988 return; 989 } 990 } 991 { 992 DISALLOW_GARBAGE_COLLECTION; 993 if (obj->IsTypedArray()) { 994 JSTaggedValue val = JSTypedArray::FastElementGet(thread_, 995 JSHandle<JSTaggedValue>::Cast(obj), elementIndex_).GetValue().GetTaggedValue(); 996 RETURN_IF_ABRUPT_COMPLETION(thread_); 997 if (!val.IsHole()) { 998 SetFound(elementIndex_, val, PropertyAttributes::GetDefaultAttributes(), !IsFoundDict()); 999 } 1000 return; 1001 } 1002 TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject()); 1003 if (elements->GetLength() == 0) { 1004 return; // Empty Array 1005 } 1006 1007 if (!elements->IsDictionaryMode()) { 1008 if (elements->GetLength() <= elementIndex_) { 1009 return; 1010 } 1011 1012 JSTaggedValue value = ElementAccessor::Get(obj, elementIndex_); 1013 if (value.IsHole()) { 1014 return; 1015 } 1016 SetFound(elementIndex_, value, PropertyAttributes::GetDefaultAttributes(), !IsFoundDict()); 1017 } else { 1018 SetFoundDict(true); 1019 NumberDictionary *dictionary = NumberDictionary::Cast(obj->GetElements().GetTaggedObject()); 1020 JSTaggedValue key(static_cast<int>(elementIndex_)); 1021 int entry = dictionary->FindEntry(key); 1022 if (entry == -1) { 1023 return; 1024 } 1025 1026 auto attr = dictionary->GetAttributes(entry).GetValue(); 1027 SetFound(entry, dictionary->GetValue(entry), attr, false); 1028 } 1029 } 1030} 1031 1032void ObjectOperator::AddPropertyInternal(const JSHandle<JSTaggedValue> &value) 1033{ 1034 ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory(); 1035 JSHandle<JSObject> obj(GetReceiver()); 1036 PropertyAttributes attr = GetAttr(); 1037 if (obj->IsJSGlobalObject()) { 1038 JSMutableHandle<GlobalDictionary> dict(thread_, obj->GetProperties()); 1039 if (dict->GetLength() == 0) { 1040 dict.Update(GlobalDictionary::Create(thread_)); 1041 } 1042 1043 // Add PropertyBox to global dictionary 1044 JSHandle<PropertyBox> cellHandle = factory->NewPropertyBox(key_); 1045 cellHandle->SetValue(thread_, value.GetTaggedValue()); 1046 PropertyBoxType cellType = value->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT; 1047 attr.SetBoxType(cellType); 1048 1049 JSHandle<GlobalDictionary> properties = 1050 GlobalDictionary::PutIfAbsent(thread_, dict, key_, JSHandle<JSTaggedValue>(cellHandle), attr); 1051 obj->SetProperties(thread_, properties); 1052 // index and fastMode is not essential for global obj; 1053 SetFound(0, cellHandle.GetTaggedValue(), attr.GetValue(), true); 1054 return; 1055 } 1056 1057 // The property has already existed whose value is hole, initialized by speculative hclass. 1058 // Not need AddProperty,just SetProperty 1059 if (receiverHoleEntry_ != -1) { 1060 attr.SetOffset(receiverHoleEntry_); 1061 JSHandle<JSObject> objHandle(receiver_); 1062 ElementsKind oldKind = objHandle->GetJSHClass()->GetElementsKind(); 1063 auto actualValue = 1064 JSHClass::ConvertOrTransitionWithRep(thread_, objHandle, key_, value, attr); 1065 JSObject::TryMigrateToGenericKindForJSObject(thread_, objHandle, oldKind); 1066 if (actualValue.isTransition) { 1067 SetIsTransition(true); 1068 } 1069 attributes_.SetRepresentation(attr.GetRepresentation()); 1070 auto *hclass = receiver_->GetTaggedObject()->GetClass(); 1071 if (actualValue.isTagged) { 1072 JSObject::Cast(receiver_.GetTaggedValue())->SetProperty<true>(thread_, hclass, 1073 attr, value.GetTaggedValue()); 1074 } else { 1075 JSObject::Cast(receiver_.GetTaggedValue())->SetProperty<false>(thread_, hclass, attr, actualValue.value); 1076 } 1077 uint32_t index = attr.IsInlinedProps() ? attr.GetOffset() : 1078 attr.GetOffset() - obj->GetJSHClass()->GetInlinedProperties(); 1079 SetIsTSHClass(true); 1080 SetIsOnPrototype(false); 1081 SetFound(index, value.GetTaggedValue(), attr.GetValue(), true); 1082 return; 1083 } 1084 1085 attr = ObjectFastOperator::AddPropertyByName(thread_, obj, key_, value, attr); 1086 RETURN_IF_ABRUPT_COMPLETION(thread_); 1087 if (obj->GetJSHClass()->IsDictionaryMode()) { 1088 SetFound(0, value.GetTaggedValue(), attr.GetValue(), false); 1089 } else { 1090 uint32_t index = attr.IsInlinedProps() ? attr.GetOffset() : 1091 attr.GetOffset() - obj->GetJSHClass()->GetInlinedProperties(); 1092 SetFound(index, value.GetTaggedValue(), attr.GetValue(), true, true); 1093 } 1094} 1095 1096void ObjectOperator::DefineSetter(const JSHandle<JSTaggedValue> &value) 1097{ 1098 ASSERT(IsAccessorDescriptor()); 1099 JSHandle<AccessorData> accessor = JSHandle<AccessorData>::Cast(value_); 1100 accessor->SetSetter(thread_, value.GetTaggedValue()); 1101 UpdateDataValue(JSHandle<JSObject>::Cast(receiver_), JSHandle<JSTaggedValue>::Cast(accessor), false); 1102} 1103 1104void ObjectOperator::DefineGetter(const JSHandle<JSTaggedValue> &value) 1105{ 1106 ASSERT(IsAccessorDescriptor()); 1107 JSHandle<AccessorData> accessor = JSHandle<AccessorData>::Cast(value_); 1108 accessor->SetGetter(thread_, value.GetTaggedValue()); 1109 UpdateDataValue(JSHandle<JSObject>::Cast(receiver_), JSHandle<JSTaggedValue>::Cast(accessor), false); 1110} 1111} // namespace panda::ecmascript 1112