11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/objects/js-objects.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/api/api-arguments-inl.h" 81cb0ef41Sopenharmony_ci#include "src/base/optional.h" 91cb0ef41Sopenharmony_ci#include "src/common/globals.h" 101cb0ef41Sopenharmony_ci#include "src/date/date.h" 111cb0ef41Sopenharmony_ci#include "src/execution/arguments.h" 121cb0ef41Sopenharmony_ci#include "src/execution/frames.h" 131cb0ef41Sopenharmony_ci#include "src/execution/isolate.h" 141cb0ef41Sopenharmony_ci#include "src/handles/handles-inl.h" 151cb0ef41Sopenharmony_ci#include "src/handles/maybe-handles.h" 161cb0ef41Sopenharmony_ci#include "src/heap/factory-inl.h" 171cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h" 181cb0ef41Sopenharmony_ci#include "src/heap/memory-chunk.h" 191cb0ef41Sopenharmony_ci#include "src/init/bootstrapper.h" 201cb0ef41Sopenharmony_ci#include "src/logging/counters.h" 211cb0ef41Sopenharmony_ci#include "src/logging/log.h" 221cb0ef41Sopenharmony_ci#include "src/objects/allocation-site-inl.h" 231cb0ef41Sopenharmony_ci#include "src/objects/api-callbacks.h" 241cb0ef41Sopenharmony_ci#include "src/objects/arguments-inl.h" 251cb0ef41Sopenharmony_ci#include "src/objects/dictionary.h" 261cb0ef41Sopenharmony_ci#include "src/objects/elements.h" 271cb0ef41Sopenharmony_ci#include "src/objects/field-type.h" 281cb0ef41Sopenharmony_ci#include "src/objects/fixed-array.h" 291cb0ef41Sopenharmony_ci#include "src/objects/heap-number.h" 301cb0ef41Sopenharmony_ci#include "src/objects/heap-object.h" 311cb0ef41Sopenharmony_ci#include "src/objects/js-array-buffer-inl.h" 321cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h" 331cb0ef41Sopenharmony_ci#include "src/objects/lookup.h" 341cb0ef41Sopenharmony_ci#include "src/objects/map-updater.h" 351cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 361cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT 371cb0ef41Sopenharmony_ci#include "src/objects/js-break-iterator.h" 381cb0ef41Sopenharmony_ci#include "src/objects/js-collator.h" 391cb0ef41Sopenharmony_ci#endif // V8_INTL_SUPPORT 401cb0ef41Sopenharmony_ci#include "src/objects/js-collection.h" 411cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT 421cb0ef41Sopenharmony_ci#include "src/objects/js-date-time-format.h" 431cb0ef41Sopenharmony_ci#include "src/objects/js-display-names.h" 441cb0ef41Sopenharmony_ci#endif // V8_INTL_SUPPORT 451cb0ef41Sopenharmony_ci#include "src/objects/js-generator-inl.h" 461cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT 471cb0ef41Sopenharmony_ci#include "src/objects/js-list-format.h" 481cb0ef41Sopenharmony_ci#include "src/objects/js-locale.h" 491cb0ef41Sopenharmony_ci#include "src/objects/js-number-format.h" 501cb0ef41Sopenharmony_ci#include "src/objects/js-plural-rules.h" 511cb0ef41Sopenharmony_ci#endif // V8_INTL_SUPPORT 521cb0ef41Sopenharmony_ci#include "src/objects/js-promise.h" 531cb0ef41Sopenharmony_ci#include "src/objects/js-regexp-inl.h" 541cb0ef41Sopenharmony_ci#include "src/objects/js-regexp-string-iterator.h" 551cb0ef41Sopenharmony_ci#include "src/objects/js-shadow-realms.h" 561cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT 571cb0ef41Sopenharmony_ci#include "src/objects/js-relative-time-format.h" 581cb0ef41Sopenharmony_ci#include "src/objects/js-segment-iterator.h" 591cb0ef41Sopenharmony_ci#include "src/objects/js-segmenter.h" 601cb0ef41Sopenharmony_ci#include "src/objects/js-segments.h" 611cb0ef41Sopenharmony_ci#endif // V8_INTL_SUPPORT 621cb0ef41Sopenharmony_ci#include "src/objects/js-struct-inl.h" 631cb0ef41Sopenharmony_ci#include "src/objects/js-temporal-objects-inl.h" 641cb0ef41Sopenharmony_ci#include "src/objects/js-weak-refs.h" 651cb0ef41Sopenharmony_ci#include "src/objects/map-inl.h" 661cb0ef41Sopenharmony_ci#include "src/objects/module.h" 671cb0ef41Sopenharmony_ci#include "src/objects/oddball.h" 681cb0ef41Sopenharmony_ci#include "src/objects/property-cell.h" 691cb0ef41Sopenharmony_ci#include "src/objects/property-descriptor.h" 701cb0ef41Sopenharmony_ci#include "src/objects/property.h" 711cb0ef41Sopenharmony_ci#include "src/objects/prototype-info.h" 721cb0ef41Sopenharmony_ci#include "src/objects/prototype.h" 731cb0ef41Sopenharmony_ci#include "src/objects/shared-function-info.h" 741cb0ef41Sopenharmony_ci#include "src/objects/swiss-name-dictionary-inl.h" 751cb0ef41Sopenharmony_ci#include "src/objects/transitions.h" 761cb0ef41Sopenharmony_ci#include "src/strings/string-builder-inl.h" 771cb0ef41Sopenharmony_ci#include "src/strings/string-stream.h" 781cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h" 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 811cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects.h" 821cb0ef41Sopenharmony_ci#include "src/debug/debug-wasm-objects.h" 831cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_cinamespace v8 { 861cb0ef41Sopenharmony_cinamespace internal { 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci// static 891cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::HasProperty(LookupIterator* it) { 901cb0ef41Sopenharmony_ci for (; it->IsFound(); it->Next()) { 911cb0ef41Sopenharmony_ci switch (it->state()) { 921cb0ef41Sopenharmony_ci case LookupIterator::NOT_FOUND: 931cb0ef41Sopenharmony_ci case LookupIterator::TRANSITION: 941cb0ef41Sopenharmony_ci UNREACHABLE(); 951cb0ef41Sopenharmony_ci case LookupIterator::JSPROXY: 961cb0ef41Sopenharmony_ci return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(), 971cb0ef41Sopenharmony_ci it->GetName()); 981cb0ef41Sopenharmony_ci case LookupIterator::INTERCEPTOR: { 991cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> result = 1001cb0ef41Sopenharmony_ci JSObject::GetPropertyAttributesWithInterceptor(it); 1011cb0ef41Sopenharmony_ci if (result.IsNothing()) return Nothing<bool>(); 1021cb0ef41Sopenharmony_ci if (result.FromJust() != ABSENT) return Just(true); 1031cb0ef41Sopenharmony_ci break; 1041cb0ef41Sopenharmony_ci } 1051cb0ef41Sopenharmony_ci case LookupIterator::ACCESS_CHECK: { 1061cb0ef41Sopenharmony_ci if (it->HasAccess()) break; 1071cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> result = 1081cb0ef41Sopenharmony_ci JSObject::GetPropertyAttributesWithFailedAccessCheck(it); 1091cb0ef41Sopenharmony_ci if (result.IsNothing()) return Nothing<bool>(); 1101cb0ef41Sopenharmony_ci return Just(result.FromJust() != ABSENT); 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci case LookupIterator::INTEGER_INDEXED_EXOTIC: 1131cb0ef41Sopenharmony_ci // TypedArray out-of-bounds access. 1141cb0ef41Sopenharmony_ci return Just(false); 1151cb0ef41Sopenharmony_ci case LookupIterator::ACCESSOR: 1161cb0ef41Sopenharmony_ci case LookupIterator::DATA: 1171cb0ef41Sopenharmony_ci return Just(true); 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci return Just(false); 1211cb0ef41Sopenharmony_ci} 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci// static 1241cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::HasOwnProperty(Isolate* isolate, 1251cb0ef41Sopenharmony_ci Handle<JSReceiver> object, 1261cb0ef41Sopenharmony_ci Handle<Name> name) { 1271cb0ef41Sopenharmony_ci if (object->IsJSModuleNamespace()) { 1281cb0ef41Sopenharmony_ci PropertyDescriptor desc; 1291cb0ef41Sopenharmony_ci return JSReceiver::GetOwnPropertyDescriptor(isolate, object, name, &desc); 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci if (object->IsJSObject()) { // Shortcut. 1331cb0ef41Sopenharmony_ci PropertyKey key(isolate, name); 1341cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, key, LookupIterator::OWN); 1351cb0ef41Sopenharmony_ci return HasProperty(&it); 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> attributes = 1391cb0ef41Sopenharmony_ci JSReceiver::GetOwnPropertyAttributes(object, name); 1401cb0ef41Sopenharmony_ci MAYBE_RETURN(attributes, Nothing<bool>()); 1411cb0ef41Sopenharmony_ci return Just(attributes.FromJust() != ABSENT); 1421cb0ef41Sopenharmony_ci} 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ciHandle<Object> JSReceiver::GetDataProperty(LookupIterator* it, 1451cb0ef41Sopenharmony_ci AllocationPolicy allocation_policy) { 1461cb0ef41Sopenharmony_ci for (; it->IsFound(); it->Next()) { 1471cb0ef41Sopenharmony_ci switch (it->state()) { 1481cb0ef41Sopenharmony_ci case LookupIterator::INTERCEPTOR: 1491cb0ef41Sopenharmony_ci case LookupIterator::NOT_FOUND: 1501cb0ef41Sopenharmony_ci case LookupIterator::TRANSITION: 1511cb0ef41Sopenharmony_ci UNREACHABLE(); 1521cb0ef41Sopenharmony_ci case LookupIterator::ACCESS_CHECK: 1531cb0ef41Sopenharmony_ci // Support calling this method without an active context, but refuse 1541cb0ef41Sopenharmony_ci // access to access-checked objects in that case. 1551cb0ef41Sopenharmony_ci if (!it->isolate()->context().is_null() && it->HasAccess()) continue; 1561cb0ef41Sopenharmony_ci V8_FALLTHROUGH; 1571cb0ef41Sopenharmony_ci case LookupIterator::JSPROXY: 1581cb0ef41Sopenharmony_ci it->NotFound(); 1591cb0ef41Sopenharmony_ci return it->isolate()->factory()->undefined_value(); 1601cb0ef41Sopenharmony_ci case LookupIterator::ACCESSOR: 1611cb0ef41Sopenharmony_ci // TODO(verwaest): For now this doesn't call into AccessorInfo, since 1621cb0ef41Sopenharmony_ci // clients don't need it. Update once relevant. 1631cb0ef41Sopenharmony_ci it->NotFound(); 1641cb0ef41Sopenharmony_ci return it->isolate()->factory()->undefined_value(); 1651cb0ef41Sopenharmony_ci case LookupIterator::INTEGER_INDEXED_EXOTIC: 1661cb0ef41Sopenharmony_ci return it->isolate()->factory()->undefined_value(); 1671cb0ef41Sopenharmony_ci case LookupIterator::DATA: 1681cb0ef41Sopenharmony_ci return it->GetDataValue(allocation_policy); 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci return it->isolate()->factory()->undefined_value(); 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci// static 1751cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate, 1761cb0ef41Sopenharmony_ci Handle<JSReceiver> object, 1771cb0ef41Sopenharmony_ci Handle<Object> proto) { 1781cb0ef41Sopenharmony_ci PrototypeIterator iter(isolate, object, kStartAtReceiver); 1791cb0ef41Sopenharmony_ci while (true) { 1801cb0ef41Sopenharmony_ci if (!iter.AdvanceFollowingProxies()) return Nothing<bool>(); 1811cb0ef41Sopenharmony_ci if (iter.IsAtEnd()) return Just(false); 1821cb0ef41Sopenharmony_ci if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) { 1831cb0ef41Sopenharmony_ci return Just(true); 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci} 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci// static 1891cb0ef41Sopenharmony_cibool JSReceiver::CheckPrivateNameStore(LookupIterator* it, bool is_define) { 1901cb0ef41Sopenharmony_ci DCHECK(it->GetName()->IsPrivateName()); 1911cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 1921cb0ef41Sopenharmony_ci Handle<String> name_string( 1931cb0ef41Sopenharmony_ci String::cast(Handle<Symbol>::cast(it->GetName())->description()), 1941cb0ef41Sopenharmony_ci isolate); 1951cb0ef41Sopenharmony_ci bool should_throw = GetShouldThrow(isolate, Nothing<ShouldThrow>()) == 1961cb0ef41Sopenharmony_ci ShouldThrow::kThrowOnError; 1971cb0ef41Sopenharmony_ci for (; it->IsFound(); it->Next()) { 1981cb0ef41Sopenharmony_ci switch (it->state()) { 1991cb0ef41Sopenharmony_ci case LookupIterator::TRANSITION: 2001cb0ef41Sopenharmony_ci case LookupIterator::INTERCEPTOR: 2011cb0ef41Sopenharmony_ci case LookupIterator::JSPROXY: 2021cb0ef41Sopenharmony_ci case LookupIterator::NOT_FOUND: 2031cb0ef41Sopenharmony_ci case LookupIterator::INTEGER_INDEXED_EXOTIC: 2041cb0ef41Sopenharmony_ci case LookupIterator::ACCESSOR: 2051cb0ef41Sopenharmony_ci UNREACHABLE(); 2061cb0ef41Sopenharmony_ci case LookupIterator::ACCESS_CHECK: 2071cb0ef41Sopenharmony_ci if (!it->HasAccess()) { 2081cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck( 2091cb0ef41Sopenharmony_ci Handle<JSObject>::cast(it->GetReceiver())); 2101cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); 2111cb0ef41Sopenharmony_ci return false; 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci break; 2141cb0ef41Sopenharmony_ci case LookupIterator::DATA: 2151cb0ef41Sopenharmony_ci if (is_define && should_throw) { 2161cb0ef41Sopenharmony_ci MessageTemplate message = 2171cb0ef41Sopenharmony_ci it->GetName()->IsPrivateBrand() 2181cb0ef41Sopenharmony_ci ? MessageTemplate::kInvalidPrivateBrandReinitialization 2191cb0ef41Sopenharmony_ci : MessageTemplate::kInvalidPrivateFieldReinitialization; 2201cb0ef41Sopenharmony_ci isolate->Throw(*(isolate->factory()->NewTypeError( 2211cb0ef41Sopenharmony_ci message, name_string, it->GetReceiver()))); 2221cb0ef41Sopenharmony_ci return false; 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci return true; 2251cb0ef41Sopenharmony_ci } 2261cb0ef41Sopenharmony_ci } 2271cb0ef41Sopenharmony_ci DCHECK(!it->IsFound()); 2281cb0ef41Sopenharmony_ci if (!is_define && should_throw) { 2291cb0ef41Sopenharmony_ci isolate->Throw(*(isolate->factory()->NewTypeError( 2301cb0ef41Sopenharmony_ci MessageTemplate::kInvalidPrivateMemberWrite, name_string, 2311cb0ef41Sopenharmony_ci it->GetReceiver()))); 2321cb0ef41Sopenharmony_ci return false; 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci return true; 2351cb0ef41Sopenharmony_ci} 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci// static 2381cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::CheckIfCanDefine(Isolate* isolate, LookupIterator* it, 2391cb0ef41Sopenharmony_ci Handle<Object> value, 2401cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw) { 2411cb0ef41Sopenharmony_ci if (it->IsFound()) { 2421cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it); 2431cb0ef41Sopenharmony_ci MAYBE_RETURN(attributes, Nothing<bool>()); 2441cb0ef41Sopenharmony_ci if ((attributes.FromJust() & DONT_DELETE) != 0) { 2451cb0ef41Sopenharmony_ci RETURN_FAILURE( 2461cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 2471cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName())); 2481cb0ef41Sopenharmony_ci } 2491cb0ef41Sopenharmony_ci } else if (!JSObject::IsExtensible( 2501cb0ef41Sopenharmony_ci Handle<JSObject>::cast(it->GetReceiver()))) { 2511cb0ef41Sopenharmony_ci RETURN_FAILURE( 2521cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 2531cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName())); 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci return Just(true); 2561cb0ef41Sopenharmony_ci} 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_cinamespace { 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_cibool HasExcludedProperty( 2611cb0ef41Sopenharmony_ci const base::ScopedVector<Handle<Object>>* excluded_properties, 2621cb0ef41Sopenharmony_ci Handle<Object> search_element) { 2631cb0ef41Sopenharmony_ci // TODO(gsathya): Change this to be a hashtable. 2641cb0ef41Sopenharmony_ci for (int i = 0; i < excluded_properties->length(); i++) { 2651cb0ef41Sopenharmony_ci if (search_element->SameValue(*excluded_properties->at(i))) { 2661cb0ef41Sopenharmony_ci return true; 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci } 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci return false; 2711cb0ef41Sopenharmony_ci} 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ciV8_WARN_UNUSED_RESULT Maybe<bool> FastAssign( 2741cb0ef41Sopenharmony_ci Handle<JSReceiver> target, Handle<Object> source, 2751cb0ef41Sopenharmony_ci PropertiesEnumerationMode mode, 2761cb0ef41Sopenharmony_ci const base::ScopedVector<Handle<Object>>* excluded_properties, 2771cb0ef41Sopenharmony_ci bool use_set) { 2781cb0ef41Sopenharmony_ci // Non-empty strings are the only non-JSReceivers that need to be handled 2791cb0ef41Sopenharmony_ci // explicitly by Object.assign. 2801cb0ef41Sopenharmony_ci if (!source->IsJSReceiver()) { 2811cb0ef41Sopenharmony_ci return Just(!source->IsString() || String::cast(*source).length() == 0); 2821cb0ef41Sopenharmony_ci } 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci Isolate* isolate = target->GetIsolate(); 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci // If the target is deprecated, the object will be updated on first store. If 2871cb0ef41Sopenharmony_ci // the source for that store equals the target, this will invalidate the 2881cb0ef41Sopenharmony_ci // cached representation of the source. Preventively upgrade the target. 2891cb0ef41Sopenharmony_ci // Do this on each iteration since any property load could cause deprecation. 2901cb0ef41Sopenharmony_ci if (target->map().is_deprecated()) { 2911cb0ef41Sopenharmony_ci JSObject::MigrateInstance(isolate, Handle<JSObject>::cast(target)); 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci Handle<Map> map(JSReceiver::cast(*source).map(), isolate); 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ci if (!map->IsJSObjectMap()) return Just(false); 2971cb0ef41Sopenharmony_ci if (!map->OnlyHasSimpleProperties()) return Just(false); 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci Handle<JSObject> from = Handle<JSObject>::cast(source); 3001cb0ef41Sopenharmony_ci if (from->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) { 3011cb0ef41Sopenharmony_ci return Just(false); 3021cb0ef41Sopenharmony_ci } 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci // We should never try to copy properties from an object itself. 3051cb0ef41Sopenharmony_ci CHECK_IMPLIES(!use_set, !target.is_identical_to(from)); 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci Handle<DescriptorArray> descriptors(map->instance_descriptors(isolate), 3081cb0ef41Sopenharmony_ci isolate); 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci bool stable = true; 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci // Process symbols last and only do that if we found symbols. 3131cb0ef41Sopenharmony_ci bool has_symbol = false; 3141cb0ef41Sopenharmony_ci bool process_symbol_only = false; 3151cb0ef41Sopenharmony_ci while (true) { 3161cb0ef41Sopenharmony_ci for (InternalIndex i : map->IterateOwnDescriptors()) { 3171cb0ef41Sopenharmony_ci HandleScope inner_scope(isolate); 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci Handle<Name> next_key(descriptors->GetKey(i), isolate); 3201cb0ef41Sopenharmony_ci if (mode == PropertiesEnumerationMode::kEnumerationOrder) { 3211cb0ef41Sopenharmony_ci if (next_key->IsSymbol()) { 3221cb0ef41Sopenharmony_ci has_symbol = true; 3231cb0ef41Sopenharmony_ci if (!process_symbol_only) continue; 3241cb0ef41Sopenharmony_ci } else { 3251cb0ef41Sopenharmony_ci if (process_symbol_only) continue; 3261cb0ef41Sopenharmony_ci } 3271cb0ef41Sopenharmony_ci } 3281cb0ef41Sopenharmony_ci Handle<Object> prop_value; 3291cb0ef41Sopenharmony_ci // Directly decode from the descriptor array if |from| did not change 3301cb0ef41Sopenharmony_ci // shape. 3311cb0ef41Sopenharmony_ci if (stable) { 3321cb0ef41Sopenharmony_ci DCHECK_EQ(from->map(), *map); 3331cb0ef41Sopenharmony_ci DCHECK_EQ(*descriptors, map->instance_descriptors(isolate)); 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_ci PropertyDetails details = descriptors->GetDetails(i); 3361cb0ef41Sopenharmony_ci if (!details.IsEnumerable()) continue; 3371cb0ef41Sopenharmony_ci if (details.kind() == PropertyKind::kData) { 3381cb0ef41Sopenharmony_ci if (details.location() == PropertyLocation::kDescriptor) { 3391cb0ef41Sopenharmony_ci prop_value = handle(descriptors->GetStrongValue(i), isolate); 3401cb0ef41Sopenharmony_ci } else { 3411cb0ef41Sopenharmony_ci Representation representation = details.representation(); 3421cb0ef41Sopenharmony_ci FieldIndex index = FieldIndex::ForPropertyIndex( 3431cb0ef41Sopenharmony_ci *map, details.field_index(), representation); 3441cb0ef41Sopenharmony_ci prop_value = 3451cb0ef41Sopenharmony_ci JSObject::FastPropertyAt(isolate, from, representation, index); 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci } else { 3481cb0ef41Sopenharmony_ci LookupIterator it(isolate, from, next_key, 3491cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 3501cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3511cb0ef41Sopenharmony_ci isolate, prop_value, Object::GetProperty(&it), Nothing<bool>()); 3521cb0ef41Sopenharmony_ci stable = from->map() == *map; 3531cb0ef41Sopenharmony_ci descriptors.PatchValue(map->instance_descriptors(isolate)); 3541cb0ef41Sopenharmony_ci } 3551cb0ef41Sopenharmony_ci } else { 3561cb0ef41Sopenharmony_ci // If the map did change, do a slower lookup. We are still guaranteed 3571cb0ef41Sopenharmony_ci // that the object has a simple shape, and that the key is a name. 3581cb0ef41Sopenharmony_ci LookupIterator it(isolate, from, next_key, from, 3591cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 3601cb0ef41Sopenharmony_ci if (!it.IsFound()) continue; 3611cb0ef41Sopenharmony_ci DCHECK(it.state() == LookupIterator::DATA || 3621cb0ef41Sopenharmony_ci it.state() == LookupIterator::ACCESSOR); 3631cb0ef41Sopenharmony_ci if (!it.IsEnumerable()) continue; 3641cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3651cb0ef41Sopenharmony_ci isolate, prop_value, Object::GetProperty(&it), Nothing<bool>()); 3661cb0ef41Sopenharmony_ci } 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci if (use_set) { 3691cb0ef41Sopenharmony_ci // The lookup will walk the prototype chain, so we have to be careful 3701cb0ef41Sopenharmony_ci // to treat any key correctly for any receiver/holder. 3711cb0ef41Sopenharmony_ci PropertyKey key(isolate, next_key); 3721cb0ef41Sopenharmony_ci LookupIterator it(isolate, target, key); 3731cb0ef41Sopenharmony_ci Maybe<bool> result = 3741cb0ef41Sopenharmony_ci Object::SetProperty(&it, prop_value, StoreOrigin::kNamed, 3751cb0ef41Sopenharmony_ci Just(ShouldThrow::kThrowOnError)); 3761cb0ef41Sopenharmony_ci if (result.IsNothing()) return result; 3771cb0ef41Sopenharmony_ci if (stable) { 3781cb0ef41Sopenharmony_ci stable = from->map() == *map; 3791cb0ef41Sopenharmony_ci descriptors.PatchValue(map->instance_descriptors(isolate)); 3801cb0ef41Sopenharmony_ci } 3811cb0ef41Sopenharmony_ci } else { 3821cb0ef41Sopenharmony_ci // No element indexes should get here or the exclusion check may 3831cb0ef41Sopenharmony_ci // yield false negatives for type mismatch. 3841cb0ef41Sopenharmony_ci if (excluded_properties != nullptr && 3851cb0ef41Sopenharmony_ci HasExcludedProperty(excluded_properties, next_key)) { 3861cb0ef41Sopenharmony_ci continue; 3871cb0ef41Sopenharmony_ci } 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue). 3901cb0ef41Sopenharmony_ci // This is an OWN lookup, so constructing a named-mode LookupIterator 3911cb0ef41Sopenharmony_ci // from {next_key} is safe. 3921cb0ef41Sopenharmony_ci LookupIterator it(isolate, target, next_key, LookupIterator::OWN); 3931cb0ef41Sopenharmony_ci CHECK(JSObject::CreateDataProperty(&it, prop_value, Just(kThrowOnError)) 3941cb0ef41Sopenharmony_ci .FromJust()); 3951cb0ef41Sopenharmony_ci } 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci if (mode == PropertiesEnumerationMode::kEnumerationOrder) { 3981cb0ef41Sopenharmony_ci if (process_symbol_only || !has_symbol) { 3991cb0ef41Sopenharmony_ci return Just(true); 4001cb0ef41Sopenharmony_ci } 4011cb0ef41Sopenharmony_ci if (has_symbol) { 4021cb0ef41Sopenharmony_ci process_symbol_only = true; 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci } else { 4051cb0ef41Sopenharmony_ci DCHECK_EQ(mode, PropertiesEnumerationMode::kPropertyAdditionOrder); 4061cb0ef41Sopenharmony_ci return Just(true); 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci } 4091cb0ef41Sopenharmony_ci UNREACHABLE(); 4101cb0ef41Sopenharmony_ci} 4111cb0ef41Sopenharmony_ci} // namespace 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci// static 4141cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::SetOrCopyDataProperties( 4151cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source, 4161cb0ef41Sopenharmony_ci PropertiesEnumerationMode mode, 4171cb0ef41Sopenharmony_ci const base::ScopedVector<Handle<Object>>* excluded_properties, 4181cb0ef41Sopenharmony_ci bool use_set) { 4191cb0ef41Sopenharmony_ci Maybe<bool> fast_assign = 4201cb0ef41Sopenharmony_ci FastAssign(target, source, mode, excluded_properties, use_set); 4211cb0ef41Sopenharmony_ci if (fast_assign.IsNothing()) return Nothing<bool>(); 4221cb0ef41Sopenharmony_ci if (fast_assign.FromJust()) return Just(true); 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked(); 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci // 3b. Let keys be ? from.[[OwnPropertyKeys]](). 4271cb0ef41Sopenharmony_ci Handle<FixedArray> keys; 4281cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4291cb0ef41Sopenharmony_ci isolate, keys, 4301cb0ef41Sopenharmony_ci KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES, 4311cb0ef41Sopenharmony_ci GetKeysConversion::kKeepNumbers), 4321cb0ef41Sopenharmony_ci Nothing<bool>()); 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci if (!from->HasFastProperties() && target->HasFastProperties() && 4351cb0ef41Sopenharmony_ci !target->IsJSGlobalProxy()) { 4361cb0ef41Sopenharmony_ci // JSProxy is always in slow-mode. 4371cb0ef41Sopenharmony_ci DCHECK(!target->IsJSProxy()); 4381cb0ef41Sopenharmony_ci // Convert to slow properties if we're guaranteed to overflow the number of 4391cb0ef41Sopenharmony_ci // descriptors. 4401cb0ef41Sopenharmony_ci int source_length; 4411cb0ef41Sopenharmony_ci if (from->IsJSGlobalObject()) { 4421cb0ef41Sopenharmony_ci source_length = JSGlobalObject::cast(*from) 4431cb0ef41Sopenharmony_ci .global_dictionary(kAcquireLoad) 4441cb0ef41Sopenharmony_ci .NumberOfEnumerableProperties(); 4451cb0ef41Sopenharmony_ci } else if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 4461cb0ef41Sopenharmony_ci source_length = 4471cb0ef41Sopenharmony_ci from->property_dictionary_swiss().NumberOfEnumerableProperties(); 4481cb0ef41Sopenharmony_ci } else { 4491cb0ef41Sopenharmony_ci source_length = 4501cb0ef41Sopenharmony_ci from->property_dictionary().NumberOfEnumerableProperties(); 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci if (source_length > kMaxNumberOfDescriptors) { 4531cb0ef41Sopenharmony_ci JSObject::NormalizeProperties(isolate, Handle<JSObject>::cast(target), 4541cb0ef41Sopenharmony_ci CLEAR_INOBJECT_PROPERTIES, source_length, 4551cb0ef41Sopenharmony_ci "Copying data properties"); 4561cb0ef41Sopenharmony_ci } 4571cb0ef41Sopenharmony_ci } 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci // 4. Repeat for each element nextKey of keys in List order, 4601cb0ef41Sopenharmony_ci for (int i = 0; i < keys->length(); ++i) { 4611cb0ef41Sopenharmony_ci Handle<Object> next_key(keys->get(i), isolate); 4621cb0ef41Sopenharmony_ci if (excluded_properties != nullptr && 4631cb0ef41Sopenharmony_ci HasExcludedProperty(excluded_properties, next_key)) { 4641cb0ef41Sopenharmony_ci continue; 4651cb0ef41Sopenharmony_ci } 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey). 4681cb0ef41Sopenharmony_ci PropertyDescriptor desc; 4691cb0ef41Sopenharmony_ci Maybe<bool> found = 4701cb0ef41Sopenharmony_ci JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc); 4711cb0ef41Sopenharmony_ci if (found.IsNothing()) return Nothing<bool>(); 4721cb0ef41Sopenharmony_ci // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then 4731cb0ef41Sopenharmony_ci if (found.FromJust() && desc.enumerable()) { 4741cb0ef41Sopenharmony_ci // 4a ii 1. Let propValue be ? Get(from, nextKey). 4751cb0ef41Sopenharmony_ci Handle<Object> prop_value; 4761cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4771cb0ef41Sopenharmony_ci isolate, prop_value, 4781cb0ef41Sopenharmony_ci Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>()); 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_ci if (use_set) { 4811cb0ef41Sopenharmony_ci // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true). 4821cb0ef41Sopenharmony_ci Handle<Object> status; 4831cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4841cb0ef41Sopenharmony_ci isolate, status, 4851cb0ef41Sopenharmony_ci Runtime::SetObjectProperty(isolate, target, next_key, prop_value, 4861cb0ef41Sopenharmony_ci StoreOrigin::kMaybeKeyed, 4871cb0ef41Sopenharmony_ci Just(ShouldThrow::kThrowOnError)), 4881cb0ef41Sopenharmony_ci Nothing<bool>()); 4891cb0ef41Sopenharmony_ci } else { 4901cb0ef41Sopenharmony_ci // 4a ii 2. Perform ! CreateDataProperty(target, nextKey, propValue). 4911cb0ef41Sopenharmony_ci PropertyKey key(isolate, next_key); 4921cb0ef41Sopenharmony_ci LookupIterator it(isolate, target, key, LookupIterator::OWN); 4931cb0ef41Sopenharmony_ci CHECK(JSObject::CreateDataProperty(&it, prop_value, Just(kThrowOnError)) 4941cb0ef41Sopenharmony_ci .FromJust()); 4951cb0ef41Sopenharmony_ci } 4961cb0ef41Sopenharmony_ci } 4971cb0ef41Sopenharmony_ci } 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci return Just(true); 5001cb0ef41Sopenharmony_ci} 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_ciString JSReceiver::class_name() { 5031cb0ef41Sopenharmony_ci ReadOnlyRoots roots = GetReadOnlyRoots(); 5041cb0ef41Sopenharmony_ci if (IsFunction()) return roots.Function_string(); 5051cb0ef41Sopenharmony_ci if (IsJSArgumentsObject()) return roots.Arguments_string(); 5061cb0ef41Sopenharmony_ci if (IsJSArray()) return roots.Array_string(); 5071cb0ef41Sopenharmony_ci if (IsJSArrayBuffer()) { 5081cb0ef41Sopenharmony_ci if (JSArrayBuffer::cast(*this).is_shared()) { 5091cb0ef41Sopenharmony_ci return roots.SharedArrayBuffer_string(); 5101cb0ef41Sopenharmony_ci } 5111cb0ef41Sopenharmony_ci return roots.ArrayBuffer_string(); 5121cb0ef41Sopenharmony_ci } 5131cb0ef41Sopenharmony_ci if (IsJSArrayIterator()) return roots.ArrayIterator_string(); 5141cb0ef41Sopenharmony_ci if (IsJSDate()) return roots.Date_string(); 5151cb0ef41Sopenharmony_ci if (IsJSError()) return roots.Error_string(); 5161cb0ef41Sopenharmony_ci if (IsJSGeneratorObject()) return roots.Generator_string(); 5171cb0ef41Sopenharmony_ci if (IsJSMap()) return roots.Map_string(); 5181cb0ef41Sopenharmony_ci if (IsJSMapIterator()) return roots.MapIterator_string(); 5191cb0ef41Sopenharmony_ci if (IsJSProxy()) { 5201cb0ef41Sopenharmony_ci return map().is_callable() ? roots.Function_string() 5211cb0ef41Sopenharmony_ci : roots.Object_string(); 5221cb0ef41Sopenharmony_ci } 5231cb0ef41Sopenharmony_ci if (IsJSRegExp()) return roots.RegExp_string(); 5241cb0ef41Sopenharmony_ci if (IsJSSet()) return roots.Set_string(); 5251cb0ef41Sopenharmony_ci if (IsJSSetIterator()) return roots.SetIterator_string(); 5261cb0ef41Sopenharmony_ci if (IsJSTypedArray()) { 5271cb0ef41Sopenharmony_ci#define SWITCH_KIND(Type, type, TYPE, ctype) \ 5281cb0ef41Sopenharmony_ci if (map().elements_kind() == TYPE##_ELEMENTS) { \ 5291cb0ef41Sopenharmony_ci return roots.Type##Array_string(); \ 5301cb0ef41Sopenharmony_ci } 5311cb0ef41Sopenharmony_ci TYPED_ARRAYS(SWITCH_KIND) 5321cb0ef41Sopenharmony_ci#undef SWITCH_KIND 5331cb0ef41Sopenharmony_ci } 5341cb0ef41Sopenharmony_ci if (IsJSPrimitiveWrapper()) { 5351cb0ef41Sopenharmony_ci Object value = JSPrimitiveWrapper::cast(*this).value(); 5361cb0ef41Sopenharmony_ci if (value.IsBoolean()) return roots.Boolean_string(); 5371cb0ef41Sopenharmony_ci if (value.IsString()) return roots.String_string(); 5381cb0ef41Sopenharmony_ci if (value.IsNumber()) return roots.Number_string(); 5391cb0ef41Sopenharmony_ci if (value.IsBigInt()) return roots.BigInt_string(); 5401cb0ef41Sopenharmony_ci if (value.IsSymbol()) return roots.Symbol_string(); 5411cb0ef41Sopenharmony_ci if (value.IsScript()) return roots.Script_string(); 5421cb0ef41Sopenharmony_ci UNREACHABLE(); 5431cb0ef41Sopenharmony_ci } 5441cb0ef41Sopenharmony_ci if (IsJSWeakMap()) return roots.WeakMap_string(); 5451cb0ef41Sopenharmony_ci if (IsJSWeakSet()) return roots.WeakSet_string(); 5461cb0ef41Sopenharmony_ci if (IsJSGlobalProxy()) return roots.global_string(); 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ci return roots.Object_string(); 5491cb0ef41Sopenharmony_ci} 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_cinamespace { 5521cb0ef41Sopenharmony_cistd::pair<MaybeHandle<JSFunction>, Handle<String>> GetConstructorHelper( 5531cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSReceiver> receiver) { 5541cb0ef41Sopenharmony_ci // If the object was instantiated simply with base == new.target, the 5551cb0ef41Sopenharmony_ci // constructor on the map provides the most accurate name. 5561cb0ef41Sopenharmony_ci // Don't provide the info for prototypes, since their constructors are 5571cb0ef41Sopenharmony_ci // reclaimed and replaced by Object in OptimizeAsPrototype. 5581cb0ef41Sopenharmony_ci if (!receiver->IsJSProxy() && receiver->map().new_target_is_base() && 5591cb0ef41Sopenharmony_ci !receiver->map().is_prototype_map()) { 5601cb0ef41Sopenharmony_ci Handle<Object> maybe_constructor(receiver->map().GetConstructor(), isolate); 5611cb0ef41Sopenharmony_ci if (maybe_constructor->IsJSFunction()) { 5621cb0ef41Sopenharmony_ci Handle<JSFunction> constructor = 5631cb0ef41Sopenharmony_ci Handle<JSFunction>::cast(maybe_constructor); 5641cb0ef41Sopenharmony_ci Handle<String> name = 5651cb0ef41Sopenharmony_ci SharedFunctionInfo::DebugName(handle(constructor->shared(), isolate)); 5661cb0ef41Sopenharmony_ci if (name->length() != 0 && 5671cb0ef41Sopenharmony_ci !name->Equals(ReadOnlyRoots(isolate).Object_string())) { 5681cb0ef41Sopenharmony_ci return std::make_pair(constructor, name); 5691cb0ef41Sopenharmony_ci } 5701cb0ef41Sopenharmony_ci } 5711cb0ef41Sopenharmony_ci } 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci for (PrototypeIterator it(isolate, receiver, kStartAtReceiver); !it.IsAtEnd(); 5741cb0ef41Sopenharmony_ci it.AdvanceIgnoringProxies()) { 5751cb0ef41Sopenharmony_ci auto current = PrototypeIterator::GetCurrent<JSReceiver>(it); 5761cb0ef41Sopenharmony_ci 5771cb0ef41Sopenharmony_ci LookupIterator it_to_string_tag( 5781cb0ef41Sopenharmony_ci isolate, receiver, isolate->factory()->to_string_tag_symbol(), current, 5791cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 5801cb0ef41Sopenharmony_ci auto maybe_to_string_tag = JSReceiver::GetDataProperty( 5811cb0ef41Sopenharmony_ci &it_to_string_tag, AllocationPolicy::kAllocationDisallowed); 5821cb0ef41Sopenharmony_ci if (maybe_to_string_tag->IsString()) { 5831cb0ef41Sopenharmony_ci return std::make_pair(MaybeHandle<JSFunction>(), 5841cb0ef41Sopenharmony_ci Handle<String>::cast(maybe_to_string_tag)); 5851cb0ef41Sopenharmony_ci } 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_ci // Consider the following example: 5881cb0ef41Sopenharmony_ci // 5891cb0ef41Sopenharmony_ci // function A() {} 5901cb0ef41Sopenharmony_ci // function B() {} 5911cb0ef41Sopenharmony_ci // B.prototype = new A(); 5921cb0ef41Sopenharmony_ci // B.prototype.constructor = B; 5931cb0ef41Sopenharmony_ci // 5941cb0ef41Sopenharmony_ci // The constructor name for `B.prototype` must yield "A", so we don't take 5951cb0ef41Sopenharmony_ci // "constructor" into account for the receiver itself, but only starting 5961cb0ef41Sopenharmony_ci // on the prototype chain. 5971cb0ef41Sopenharmony_ci if (!receiver.is_identical_to(current)) { 5981cb0ef41Sopenharmony_ci LookupIterator it_constructor( 5991cb0ef41Sopenharmony_ci isolate, receiver, isolate->factory()->constructor_string(), current, 6001cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 6011cb0ef41Sopenharmony_ci auto maybe_constructor = JSReceiver::GetDataProperty( 6021cb0ef41Sopenharmony_ci &it_constructor, AllocationPolicy::kAllocationDisallowed); 6031cb0ef41Sopenharmony_ci if (maybe_constructor->IsJSFunction()) { 6041cb0ef41Sopenharmony_ci auto constructor = Handle<JSFunction>::cast(maybe_constructor); 6051cb0ef41Sopenharmony_ci auto name = SharedFunctionInfo::DebugName( 6061cb0ef41Sopenharmony_ci handle(constructor->shared(), isolate)); 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ci if (name->length() != 0 && 6091cb0ef41Sopenharmony_ci !name->Equals(ReadOnlyRoots(isolate).Object_string())) { 6101cb0ef41Sopenharmony_ci return std::make_pair(constructor, name); 6111cb0ef41Sopenharmony_ci } 6121cb0ef41Sopenharmony_ci } 6131cb0ef41Sopenharmony_ci } 6141cb0ef41Sopenharmony_ci } 6151cb0ef41Sopenharmony_ci 6161cb0ef41Sopenharmony_ci return std::make_pair(MaybeHandle<JSFunction>(), 6171cb0ef41Sopenharmony_ci handle(receiver->class_name(), isolate)); 6181cb0ef41Sopenharmony_ci} 6191cb0ef41Sopenharmony_ci} // anonymous namespace 6201cb0ef41Sopenharmony_ci 6211cb0ef41Sopenharmony_ci// static 6221cb0ef41Sopenharmony_ciMaybeHandle<JSFunction> JSReceiver::GetConstructor( 6231cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSReceiver> receiver) { 6241cb0ef41Sopenharmony_ci return GetConstructorHelper(isolate, receiver).first; 6251cb0ef41Sopenharmony_ci} 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ci// static 6281cb0ef41Sopenharmony_ciHandle<String> JSReceiver::GetConstructorName(Isolate* isolate, 6291cb0ef41Sopenharmony_ci Handle<JSReceiver> receiver) { 6301cb0ef41Sopenharmony_ci return GetConstructorHelper(isolate, receiver).second; 6311cb0ef41Sopenharmony_ci} 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ciMaybeHandle<NativeContext> JSReceiver::GetCreationContext() { 6341cb0ef41Sopenharmony_ci JSReceiver receiver = *this; 6351cb0ef41Sopenharmony_ci // Externals are JSObjects with null as a constructor. 6361cb0ef41Sopenharmony_ci DCHECK(!receiver.IsJSExternalObject()); 6371cb0ef41Sopenharmony_ci Object constructor = receiver.map().GetConstructor(); 6381cb0ef41Sopenharmony_ci JSFunction function; 6391cb0ef41Sopenharmony_ci if (constructor.IsJSFunction()) { 6401cb0ef41Sopenharmony_ci function = JSFunction::cast(constructor); 6411cb0ef41Sopenharmony_ci } else if (constructor.IsFunctionTemplateInfo()) { 6421cb0ef41Sopenharmony_ci // Remote objects don't have a creation context. 6431cb0ef41Sopenharmony_ci return MaybeHandle<NativeContext>(); 6441cb0ef41Sopenharmony_ci } else if (receiver.IsJSGeneratorObject()) { 6451cb0ef41Sopenharmony_ci function = JSGeneratorObject::cast(receiver).function(); 6461cb0ef41Sopenharmony_ci } else if (receiver.IsJSFunction()) { 6471cb0ef41Sopenharmony_ci function = JSFunction::cast(receiver); 6481cb0ef41Sopenharmony_ci } else { 6491cb0ef41Sopenharmony_ci return MaybeHandle<NativeContext>(); 6501cb0ef41Sopenharmony_ci } 6511cb0ef41Sopenharmony_ci 6521cb0ef41Sopenharmony_ci return function.has_context() 6531cb0ef41Sopenharmony_ci ? Handle<NativeContext>(function.native_context(), 6541cb0ef41Sopenharmony_ci receiver.GetIsolate()) 6551cb0ef41Sopenharmony_ci : MaybeHandle<NativeContext>(); 6561cb0ef41Sopenharmony_ci} 6571cb0ef41Sopenharmony_ci 6581cb0ef41Sopenharmony_ci// static 6591cb0ef41Sopenharmony_ciMaybeHandle<NativeContext> JSReceiver::GetFunctionRealm( 6601cb0ef41Sopenharmony_ci Handle<JSReceiver> receiver) { 6611cb0ef41Sopenharmony_ci Isolate* isolate = receiver->GetIsolate(); 6621cb0ef41Sopenharmony_ci // This is implemented as a loop because it's possible to construct very 6631cb0ef41Sopenharmony_ci // long chains of bound functions or proxies where a recursive implementation 6641cb0ef41Sopenharmony_ci // would run out of stack space. 6651cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 6661cb0ef41Sopenharmony_ci JSReceiver current = *receiver; 6671cb0ef41Sopenharmony_ci do { 6681cb0ef41Sopenharmony_ci DCHECK(current.map().is_constructor()); 6691cb0ef41Sopenharmony_ci if (current.IsJSProxy()) { 6701cb0ef41Sopenharmony_ci JSProxy proxy = JSProxy::cast(current); 6711cb0ef41Sopenharmony_ci if (proxy.IsRevoked()) { 6721cb0ef41Sopenharmony_ci AllowGarbageCollection allow_allocating_errors; 6731cb0ef41Sopenharmony_ci THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyRevoked), 6741cb0ef41Sopenharmony_ci NativeContext); 6751cb0ef41Sopenharmony_ci } 6761cb0ef41Sopenharmony_ci current = JSReceiver::cast(proxy.target()); 6771cb0ef41Sopenharmony_ci continue; 6781cb0ef41Sopenharmony_ci } 6791cb0ef41Sopenharmony_ci if (current.IsJSFunction()) { 6801cb0ef41Sopenharmony_ci JSFunction function = JSFunction::cast(current); 6811cb0ef41Sopenharmony_ci return handle(function.native_context(), isolate); 6821cb0ef41Sopenharmony_ci } 6831cb0ef41Sopenharmony_ci if (current.IsJSBoundFunction()) { 6841cb0ef41Sopenharmony_ci JSBoundFunction function = JSBoundFunction::cast(current); 6851cb0ef41Sopenharmony_ci current = function.bound_target_function(); 6861cb0ef41Sopenharmony_ci continue; 6871cb0ef41Sopenharmony_ci } 6881cb0ef41Sopenharmony_ci if (current.IsJSWrappedFunction()) { 6891cb0ef41Sopenharmony_ci JSWrappedFunction function = JSWrappedFunction::cast(current); 6901cb0ef41Sopenharmony_ci current = function.wrapped_target_function(); 6911cb0ef41Sopenharmony_ci continue; 6921cb0ef41Sopenharmony_ci } 6931cb0ef41Sopenharmony_ci JSObject object = JSObject::cast(current); 6941cb0ef41Sopenharmony_ci DCHECK(!object.IsJSFunction()); 6951cb0ef41Sopenharmony_ci return object.GetCreationContext(); 6961cb0ef41Sopenharmony_ci } while (true); 6971cb0ef41Sopenharmony_ci} 6981cb0ef41Sopenharmony_ci 6991cb0ef41Sopenharmony_ci// static 7001cb0ef41Sopenharmony_ciMaybeHandle<NativeContext> JSReceiver::GetContextForMicrotask( 7011cb0ef41Sopenharmony_ci Handle<JSReceiver> receiver) { 7021cb0ef41Sopenharmony_ci Isolate* isolate = receiver->GetIsolate(); 7031cb0ef41Sopenharmony_ci while (receiver->IsJSBoundFunction() || receiver->IsJSProxy()) { 7041cb0ef41Sopenharmony_ci if (receiver->IsJSBoundFunction()) { 7051cb0ef41Sopenharmony_ci receiver = handle( 7061cb0ef41Sopenharmony_ci Handle<JSBoundFunction>::cast(receiver)->bound_target_function(), 7071cb0ef41Sopenharmony_ci isolate); 7081cb0ef41Sopenharmony_ci } else { 7091cb0ef41Sopenharmony_ci DCHECK(receiver->IsJSProxy()); 7101cb0ef41Sopenharmony_ci Handle<Object> target(Handle<JSProxy>::cast(receiver)->target(), isolate); 7111cb0ef41Sopenharmony_ci if (!target->IsJSReceiver()) return MaybeHandle<NativeContext>(); 7121cb0ef41Sopenharmony_ci receiver = Handle<JSReceiver>::cast(target); 7131cb0ef41Sopenharmony_ci } 7141cb0ef41Sopenharmony_ci } 7151cb0ef41Sopenharmony_ci 7161cb0ef41Sopenharmony_ci if (!receiver->IsJSFunction()) return MaybeHandle<NativeContext>(); 7171cb0ef41Sopenharmony_ci return handle(Handle<JSFunction>::cast(receiver)->native_context(), isolate); 7181cb0ef41Sopenharmony_ci} 7191cb0ef41Sopenharmony_ci 7201cb0ef41Sopenharmony_ciMaybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( 7211cb0ef41Sopenharmony_ci LookupIterator* it) { 7221cb0ef41Sopenharmony_ci for (; it->IsFound(); it->Next()) { 7231cb0ef41Sopenharmony_ci switch (it->state()) { 7241cb0ef41Sopenharmony_ci case LookupIterator::NOT_FOUND: 7251cb0ef41Sopenharmony_ci case LookupIterator::TRANSITION: 7261cb0ef41Sopenharmony_ci UNREACHABLE(); 7271cb0ef41Sopenharmony_ci case LookupIterator::JSPROXY: 7281cb0ef41Sopenharmony_ci return JSProxy::GetPropertyAttributes(it); 7291cb0ef41Sopenharmony_ci case LookupIterator::INTERCEPTOR: { 7301cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> result = 7311cb0ef41Sopenharmony_ci JSObject::GetPropertyAttributesWithInterceptor(it); 7321cb0ef41Sopenharmony_ci if (result.IsNothing()) return result; 7331cb0ef41Sopenharmony_ci if (result.FromJust() != ABSENT) return result; 7341cb0ef41Sopenharmony_ci break; 7351cb0ef41Sopenharmony_ci } 7361cb0ef41Sopenharmony_ci case LookupIterator::ACCESS_CHECK: 7371cb0ef41Sopenharmony_ci if (it->HasAccess()) break; 7381cb0ef41Sopenharmony_ci return JSObject::GetPropertyAttributesWithFailedAccessCheck(it); 7391cb0ef41Sopenharmony_ci case LookupIterator::INTEGER_INDEXED_EXOTIC: 7401cb0ef41Sopenharmony_ci return Just(ABSENT); 7411cb0ef41Sopenharmony_ci case LookupIterator::ACCESSOR: 7421cb0ef41Sopenharmony_ci if (it->GetHolder<Object>()->IsJSModuleNamespace()) { 7431cb0ef41Sopenharmony_ci return JSModuleNamespace::GetPropertyAttributes(it); 7441cb0ef41Sopenharmony_ci } else { 7451cb0ef41Sopenharmony_ci return Just(it->property_attributes()); 7461cb0ef41Sopenharmony_ci } 7471cb0ef41Sopenharmony_ci case LookupIterator::DATA: 7481cb0ef41Sopenharmony_ci return Just(it->property_attributes()); 7491cb0ef41Sopenharmony_ci } 7501cb0ef41Sopenharmony_ci } 7511cb0ef41Sopenharmony_ci return Just(ABSENT); 7521cb0ef41Sopenharmony_ci} 7531cb0ef41Sopenharmony_ci 7541cb0ef41Sopenharmony_cinamespace { 7551cb0ef41Sopenharmony_ci 7561cb0ef41Sopenharmony_ciObject SetHashAndUpdateProperties(HeapObject properties, int hash) { 7571cb0ef41Sopenharmony_ci DCHECK_NE(PropertyArray::kNoHashSentinel, hash); 7581cb0ef41Sopenharmony_ci DCHECK(PropertyArray::HashField::is_valid(hash)); 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ci ReadOnlyRoots roots = properties.GetReadOnlyRoots(); 7611cb0ef41Sopenharmony_ci if (properties == roots.empty_fixed_array() || 7621cb0ef41Sopenharmony_ci properties == roots.empty_property_array() || 7631cb0ef41Sopenharmony_ci properties == roots.empty_property_dictionary() || 7641cb0ef41Sopenharmony_ci properties == roots.empty_swiss_property_dictionary()) { 7651cb0ef41Sopenharmony_ci return Smi::FromInt(hash); 7661cb0ef41Sopenharmony_ci } 7671cb0ef41Sopenharmony_ci 7681cb0ef41Sopenharmony_ci if (properties.IsPropertyArray()) { 7691cb0ef41Sopenharmony_ci PropertyArray::cast(properties).SetHash(hash); 7701cb0ef41Sopenharmony_ci DCHECK_LT(0, PropertyArray::cast(properties).length()); 7711cb0ef41Sopenharmony_ci return properties; 7721cb0ef41Sopenharmony_ci } 7731cb0ef41Sopenharmony_ci 7741cb0ef41Sopenharmony_ci if (properties.IsGlobalDictionary()) { 7751cb0ef41Sopenharmony_ci GlobalDictionary::cast(properties).SetHash(hash); 7761cb0ef41Sopenharmony_ci return properties; 7771cb0ef41Sopenharmony_ci } 7781cb0ef41Sopenharmony_ci 7791cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 7801cb0ef41Sopenharmony_ci DCHECK(properties.IsSwissNameDictionary()); 7811cb0ef41Sopenharmony_ci SwissNameDictionary::cast(properties).SetHash(hash); 7821cb0ef41Sopenharmony_ci } else { 7831cb0ef41Sopenharmony_ci DCHECK(properties.IsNameDictionary()); 7841cb0ef41Sopenharmony_ci NameDictionary::cast(properties).SetHash(hash); 7851cb0ef41Sopenharmony_ci } 7861cb0ef41Sopenharmony_ci return properties; 7871cb0ef41Sopenharmony_ci} 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ciint GetIdentityHashHelper(JSReceiver object) { 7901cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 7911cb0ef41Sopenharmony_ci Object properties = object.raw_properties_or_hash(); 7921cb0ef41Sopenharmony_ci if (properties.IsSmi()) { 7931cb0ef41Sopenharmony_ci return Smi::ToInt(properties); 7941cb0ef41Sopenharmony_ci } 7951cb0ef41Sopenharmony_ci 7961cb0ef41Sopenharmony_ci if (properties.IsPropertyArray()) { 7971cb0ef41Sopenharmony_ci return PropertyArray::cast(properties).Hash(); 7981cb0ef41Sopenharmony_ci } 7991cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL && 8001cb0ef41Sopenharmony_ci properties.IsSwissNameDictionary()) { 8011cb0ef41Sopenharmony_ci return SwissNameDictionary::cast(properties).Hash(); 8021cb0ef41Sopenharmony_ci } 8031cb0ef41Sopenharmony_ci 8041cb0ef41Sopenharmony_ci if (properties.IsNameDictionary()) { 8051cb0ef41Sopenharmony_ci DCHECK(!V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL); 8061cb0ef41Sopenharmony_ci return NameDictionary::cast(properties).Hash(); 8071cb0ef41Sopenharmony_ci } 8081cb0ef41Sopenharmony_ci 8091cb0ef41Sopenharmony_ci if (properties.IsGlobalDictionary()) { 8101cb0ef41Sopenharmony_ci return GlobalDictionary::cast(properties).Hash(); 8111cb0ef41Sopenharmony_ci } 8121cb0ef41Sopenharmony_ci 8131cb0ef41Sopenharmony_ci#ifdef DEBUG 8141cb0ef41Sopenharmony_ci ReadOnlyRoots roots = object.GetReadOnlyRoots(); 8151cb0ef41Sopenharmony_ci DCHECK(properties == roots.empty_fixed_array() || 8161cb0ef41Sopenharmony_ci properties == roots.empty_property_dictionary() || 8171cb0ef41Sopenharmony_ci properties == roots.empty_swiss_property_dictionary()); 8181cb0ef41Sopenharmony_ci#endif 8191cb0ef41Sopenharmony_ci 8201cb0ef41Sopenharmony_ci return PropertyArray::kNoHashSentinel; 8211cb0ef41Sopenharmony_ci} 8221cb0ef41Sopenharmony_ci} // namespace 8231cb0ef41Sopenharmony_ci 8241cb0ef41Sopenharmony_civoid JSReceiver::SetIdentityHash(int hash) { 8251cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 8261cb0ef41Sopenharmony_ci DCHECK_NE(PropertyArray::kNoHashSentinel, hash); 8271cb0ef41Sopenharmony_ci DCHECK(PropertyArray::HashField::is_valid(hash)); 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci HeapObject existing_properties = HeapObject::cast(raw_properties_or_hash()); 8301cb0ef41Sopenharmony_ci Object new_properties = SetHashAndUpdateProperties(existing_properties, hash); 8311cb0ef41Sopenharmony_ci set_raw_properties_or_hash(new_properties, kRelaxedStore); 8321cb0ef41Sopenharmony_ci} 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_civoid JSReceiver::SetProperties(HeapObject properties) { 8351cb0ef41Sopenharmony_ci DCHECK_IMPLIES(properties.IsPropertyArray() && 8361cb0ef41Sopenharmony_ci PropertyArray::cast(properties).length() == 0, 8371cb0ef41Sopenharmony_ci properties == GetReadOnlyRoots().empty_property_array()); 8381cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 8391cb0ef41Sopenharmony_ci int hash = GetIdentityHashHelper(*this); 8401cb0ef41Sopenharmony_ci Object new_properties = properties; 8411cb0ef41Sopenharmony_ci 8421cb0ef41Sopenharmony_ci // TODO(cbruni): Make GetIdentityHashHelper return a bool so that we 8431cb0ef41Sopenharmony_ci // don't have to manually compare against kNoHashSentinel. 8441cb0ef41Sopenharmony_ci if (hash != PropertyArray::kNoHashSentinel) { 8451cb0ef41Sopenharmony_ci new_properties = SetHashAndUpdateProperties(properties, hash); 8461cb0ef41Sopenharmony_ci } 8471cb0ef41Sopenharmony_ci 8481cb0ef41Sopenharmony_ci set_raw_properties_or_hash(new_properties, kRelaxedStore); 8491cb0ef41Sopenharmony_ci} 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ciObject JSReceiver::GetIdentityHash() { 8521cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 8531cb0ef41Sopenharmony_ci 8541cb0ef41Sopenharmony_ci int hash = GetIdentityHashHelper(*this); 8551cb0ef41Sopenharmony_ci if (hash == PropertyArray::kNoHashSentinel) { 8561cb0ef41Sopenharmony_ci return GetReadOnlyRoots().undefined_value(); 8571cb0ef41Sopenharmony_ci } 8581cb0ef41Sopenharmony_ci 8591cb0ef41Sopenharmony_ci return Smi::FromInt(hash); 8601cb0ef41Sopenharmony_ci} 8611cb0ef41Sopenharmony_ci 8621cb0ef41Sopenharmony_ci// static 8631cb0ef41Sopenharmony_ciSmi JSReceiver::CreateIdentityHash(Isolate* isolate, JSReceiver key) { 8641cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 8651cb0ef41Sopenharmony_ci int hash = isolate->GenerateIdentityHash(PropertyArray::HashField::kMax); 8661cb0ef41Sopenharmony_ci DCHECK_NE(PropertyArray::kNoHashSentinel, hash); 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_ci key.SetIdentityHash(hash); 8691cb0ef41Sopenharmony_ci return Smi::FromInt(hash); 8701cb0ef41Sopenharmony_ci} 8711cb0ef41Sopenharmony_ci 8721cb0ef41Sopenharmony_ciSmi JSReceiver::GetOrCreateIdentityHash(Isolate* isolate) { 8731cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 8741cb0ef41Sopenharmony_ci 8751cb0ef41Sopenharmony_ci int hash = GetIdentityHashHelper(*this); 8761cb0ef41Sopenharmony_ci if (hash != PropertyArray::kNoHashSentinel) { 8771cb0ef41Sopenharmony_ci return Smi::FromInt(hash); 8781cb0ef41Sopenharmony_ci } 8791cb0ef41Sopenharmony_ci 8801cb0ef41Sopenharmony_ci return JSReceiver::CreateIdentityHash(isolate, *this); 8811cb0ef41Sopenharmony_ci} 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_civoid JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object, 8841cb0ef41Sopenharmony_ci InternalIndex entry) { 8851cb0ef41Sopenharmony_ci DCHECK(!object->HasFastProperties()); 8861cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 8871cb0ef41Sopenharmony_ci DCHECK(entry.is_found()); 8881cb0ef41Sopenharmony_ci 8891cb0ef41Sopenharmony_ci if (object->IsJSGlobalObject()) { 8901cb0ef41Sopenharmony_ci // If we have a global object, invalidate the cell and remove it from the 8911cb0ef41Sopenharmony_ci // global object's dictionary. 8921cb0ef41Sopenharmony_ci Handle<GlobalDictionary> dictionary( 8931cb0ef41Sopenharmony_ci JSGlobalObject::cast(*object).global_dictionary(kAcquireLoad), isolate); 8941cb0ef41Sopenharmony_ci 8951cb0ef41Sopenharmony_ci Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate); 8961cb0ef41Sopenharmony_ci 8971cb0ef41Sopenharmony_ci Handle<GlobalDictionary> new_dictionary = 8981cb0ef41Sopenharmony_ci GlobalDictionary::DeleteEntry(isolate, dictionary, entry); 8991cb0ef41Sopenharmony_ci JSGlobalObject::cast(*object).set_global_dictionary(*new_dictionary, 9001cb0ef41Sopenharmony_ci kReleaseStore); 9011cb0ef41Sopenharmony_ci 9021cb0ef41Sopenharmony_ci cell->ClearAndInvalidate(ReadOnlyRoots(isolate)); 9031cb0ef41Sopenharmony_ci } else { 9041cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 9051cb0ef41Sopenharmony_ci Handle<SwissNameDictionary> dictionary( 9061cb0ef41Sopenharmony_ci object->property_dictionary_swiss(), isolate); 9071cb0ef41Sopenharmony_ci 9081cb0ef41Sopenharmony_ci dictionary = SwissNameDictionary::DeleteEntry(isolate, dictionary, entry); 9091cb0ef41Sopenharmony_ci object->SetProperties(*dictionary); 9101cb0ef41Sopenharmony_ci } else { 9111cb0ef41Sopenharmony_ci Handle<NameDictionary> dictionary(object->property_dictionary(), isolate); 9121cb0ef41Sopenharmony_ci 9131cb0ef41Sopenharmony_ci dictionary = NameDictionary::DeleteEntry(isolate, dictionary, entry); 9141cb0ef41Sopenharmony_ci object->SetProperties(*dictionary); 9151cb0ef41Sopenharmony_ci } 9161cb0ef41Sopenharmony_ci } 9171cb0ef41Sopenharmony_ci if (object->map().is_prototype_map()) { 9181cb0ef41Sopenharmony_ci // Invalidate prototype validity cell as this may invalidate transitioning 9191cb0ef41Sopenharmony_ci // store IC handlers. 9201cb0ef41Sopenharmony_ci JSObject::InvalidatePrototypeChains(object->map()); 9211cb0ef41Sopenharmony_ci } 9221cb0ef41Sopenharmony_ci} 9231cb0ef41Sopenharmony_ci 9241cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::DeleteProperty(LookupIterator* it, 9251cb0ef41Sopenharmony_ci LanguageMode language_mode) { 9261cb0ef41Sopenharmony_ci it->UpdateProtector(); 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 9291cb0ef41Sopenharmony_ci 9301cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::JSPROXY) { 9311cb0ef41Sopenharmony_ci return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(), 9321cb0ef41Sopenharmony_ci it->GetName(), language_mode); 9331cb0ef41Sopenharmony_ci } 9341cb0ef41Sopenharmony_ci 9351cb0ef41Sopenharmony_ci if (it->GetReceiver()->IsJSProxy()) { 9361cb0ef41Sopenharmony_ci if (it->state() != LookupIterator::NOT_FOUND) { 9371cb0ef41Sopenharmony_ci DCHECK_EQ(LookupIterator::DATA, it->state()); 9381cb0ef41Sopenharmony_ci DCHECK(it->name()->IsPrivate()); 9391cb0ef41Sopenharmony_ci it->Delete(); 9401cb0ef41Sopenharmony_ci } 9411cb0ef41Sopenharmony_ci return Just(true); 9421cb0ef41Sopenharmony_ci } 9431cb0ef41Sopenharmony_ci Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 9441cb0ef41Sopenharmony_ci 9451cb0ef41Sopenharmony_ci for (; it->IsFound(); it->Next()) { 9461cb0ef41Sopenharmony_ci switch (it->state()) { 9471cb0ef41Sopenharmony_ci case LookupIterator::JSPROXY: 9481cb0ef41Sopenharmony_ci case LookupIterator::NOT_FOUND: 9491cb0ef41Sopenharmony_ci case LookupIterator::TRANSITION: 9501cb0ef41Sopenharmony_ci UNREACHABLE(); 9511cb0ef41Sopenharmony_ci case LookupIterator::ACCESS_CHECK: 9521cb0ef41Sopenharmony_ci if (it->HasAccess()) break; 9531cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()); 9541cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 9551cb0ef41Sopenharmony_ci return Just(false); 9561cb0ef41Sopenharmony_ci case LookupIterator::INTERCEPTOR: { 9571cb0ef41Sopenharmony_ci ShouldThrow should_throw = 9581cb0ef41Sopenharmony_ci is_sloppy(language_mode) ? kDontThrow : kThrowOnError; 9591cb0ef41Sopenharmony_ci Maybe<bool> result = 9601cb0ef41Sopenharmony_ci JSObject::DeletePropertyWithInterceptor(it, should_throw); 9611cb0ef41Sopenharmony_ci // An exception was thrown in the interceptor. Propagate. 9621cb0ef41Sopenharmony_ci if (isolate->has_pending_exception()) return Nothing<bool>(); 9631cb0ef41Sopenharmony_ci // Delete with interceptor succeeded. Return result. 9641cb0ef41Sopenharmony_ci // TODO(neis): In strict mode, we should probably throw if the 9651cb0ef41Sopenharmony_ci // interceptor returns false. 9661cb0ef41Sopenharmony_ci if (result.IsJust()) return result; 9671cb0ef41Sopenharmony_ci break; 9681cb0ef41Sopenharmony_ci } 9691cb0ef41Sopenharmony_ci case LookupIterator::INTEGER_INDEXED_EXOTIC: 9701cb0ef41Sopenharmony_ci return Just(true); 9711cb0ef41Sopenharmony_ci case LookupIterator::DATA: 9721cb0ef41Sopenharmony_ci case LookupIterator::ACCESSOR: { 9731cb0ef41Sopenharmony_ci Handle<JSObject> holder = it->GetHolder<JSObject>(); 9741cb0ef41Sopenharmony_ci if (!it->IsConfigurable() || 9751cb0ef41Sopenharmony_ci (holder->IsJSTypedArray() && it->IsElement(*holder))) { 9761cb0ef41Sopenharmony_ci // Fail if the property is not configurable if the property is a 9771cb0ef41Sopenharmony_ci // TypedArray element. 9781cb0ef41Sopenharmony_ci if (is_strict(language_mode)) { 9791cb0ef41Sopenharmony_ci isolate->Throw(*isolate->factory()->NewTypeError( 9801cb0ef41Sopenharmony_ci MessageTemplate::kStrictDeleteProperty, it->GetName(), 9811cb0ef41Sopenharmony_ci receiver)); 9821cb0ef41Sopenharmony_ci return Nothing<bool>(); 9831cb0ef41Sopenharmony_ci } 9841cb0ef41Sopenharmony_ci return Just(false); 9851cb0ef41Sopenharmony_ci } 9861cb0ef41Sopenharmony_ci 9871cb0ef41Sopenharmony_ci it->Delete(); 9881cb0ef41Sopenharmony_ci 9891cb0ef41Sopenharmony_ci return Just(true); 9901cb0ef41Sopenharmony_ci } 9911cb0ef41Sopenharmony_ci } 9921cb0ef41Sopenharmony_ci } 9931cb0ef41Sopenharmony_ci 9941cb0ef41Sopenharmony_ci return Just(true); 9951cb0ef41Sopenharmony_ci} 9961cb0ef41Sopenharmony_ci 9971cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index, 9981cb0ef41Sopenharmony_ci LanguageMode language_mode) { 9991cb0ef41Sopenharmony_ci LookupIterator it(object->GetIsolate(), object, index, object, 10001cb0ef41Sopenharmony_ci LookupIterator::OWN); 10011cb0ef41Sopenharmony_ci return DeleteProperty(&it, language_mode); 10021cb0ef41Sopenharmony_ci} 10031cb0ef41Sopenharmony_ci 10041cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object, 10051cb0ef41Sopenharmony_ci Handle<Name> name, 10061cb0ef41Sopenharmony_ci LanguageMode language_mode) { 10071cb0ef41Sopenharmony_ci LookupIterator it(object->GetIsolate(), object, name, object, 10081cb0ef41Sopenharmony_ci LookupIterator::OWN); 10091cb0ef41Sopenharmony_ci return DeleteProperty(&it, language_mode); 10101cb0ef41Sopenharmony_ci} 10111cb0ef41Sopenharmony_ci 10121cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object, 10131cb0ef41Sopenharmony_ci Handle<Name> name, 10141cb0ef41Sopenharmony_ci LanguageMode language_mode) { 10151cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 10161cb0ef41Sopenharmony_ci PropertyKey key(isolate, name); 10171cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, key, object, LookupIterator::OWN); 10181cb0ef41Sopenharmony_ci return DeleteProperty(&it, language_mode); 10191cb0ef41Sopenharmony_ci} 10201cb0ef41Sopenharmony_ci 10211cb0ef41Sopenharmony_ci// ES6 19.1.2.4 10221cb0ef41Sopenharmony_ci// static 10231cb0ef41Sopenharmony_ciObject JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object, 10241cb0ef41Sopenharmony_ci Handle<Object> key, 10251cb0ef41Sopenharmony_ci Handle<Object> attributes) { 10261cb0ef41Sopenharmony_ci // 1. If Type(O) is not Object, throw a TypeError exception. 10271cb0ef41Sopenharmony_ci if (!object->IsJSReceiver()) { 10281cb0ef41Sopenharmony_ci Handle<String> fun_name = 10291cb0ef41Sopenharmony_ci isolate->factory()->InternalizeUtf8String("Object.defineProperty"); 10301cb0ef41Sopenharmony_ci THROW_NEW_ERROR_RETURN_FAILURE( 10311cb0ef41Sopenharmony_ci isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name)); 10321cb0ef41Sopenharmony_ci } 10331cb0ef41Sopenharmony_ci // 2. Let key be ToPropertyKey(P). 10341cb0ef41Sopenharmony_ci // 3. ReturnIfAbrupt(key). 10351cb0ef41Sopenharmony_ci ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, 10361cb0ef41Sopenharmony_ci Object::ToPropertyKey(isolate, key)); 10371cb0ef41Sopenharmony_ci // 4. Let desc be ToPropertyDescriptor(Attributes). 10381cb0ef41Sopenharmony_ci // 5. ReturnIfAbrupt(desc). 10391cb0ef41Sopenharmony_ci PropertyDescriptor desc; 10401cb0ef41Sopenharmony_ci if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) { 10411cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate).exception(); 10421cb0ef41Sopenharmony_ci } 10431cb0ef41Sopenharmony_ci // 6. Let success be DefinePropertyOrThrow(O,key, desc). 10441cb0ef41Sopenharmony_ci Maybe<bool> success = 10451cb0ef41Sopenharmony_ci DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object), key, &desc, 10461cb0ef41Sopenharmony_ci Just(kThrowOnError)); 10471cb0ef41Sopenharmony_ci // 7. ReturnIfAbrupt(success). 10481cb0ef41Sopenharmony_ci MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception()); 10491cb0ef41Sopenharmony_ci CHECK(success.FromJust()); 10501cb0ef41Sopenharmony_ci // 8. Return O. 10511cb0ef41Sopenharmony_ci return *object; 10521cb0ef41Sopenharmony_ci} 10531cb0ef41Sopenharmony_ci 10541cb0ef41Sopenharmony_ci// ES6 19.1.2.3.1 10551cb0ef41Sopenharmony_ci// static 10561cb0ef41Sopenharmony_ciMaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate, 10571cb0ef41Sopenharmony_ci Handle<Object> object, 10581cb0ef41Sopenharmony_ci Handle<Object> properties) { 10591cb0ef41Sopenharmony_ci // 1. If Type(O) is not Object, throw a TypeError exception. 10601cb0ef41Sopenharmony_ci if (!object->IsJSReceiver()) { 10611cb0ef41Sopenharmony_ci Handle<String> fun_name = 10621cb0ef41Sopenharmony_ci isolate->factory()->InternalizeUtf8String("Object.defineProperties"); 10631cb0ef41Sopenharmony_ci THROW_NEW_ERROR(isolate, 10641cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name), 10651cb0ef41Sopenharmony_ci Object); 10661cb0ef41Sopenharmony_ci } 10671cb0ef41Sopenharmony_ci // 2. Let props be ToObject(Properties). 10681cb0ef41Sopenharmony_ci // 3. ReturnIfAbrupt(props). 10691cb0ef41Sopenharmony_ci Handle<JSReceiver> props; 10701cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION(isolate, props, 10711cb0ef41Sopenharmony_ci Object::ToObject(isolate, properties), Object); 10721cb0ef41Sopenharmony_ci 10731cb0ef41Sopenharmony_ci // 4. Let keys be props.[[OwnPropertyKeys]](). 10741cb0ef41Sopenharmony_ci // 5. ReturnIfAbrupt(keys). 10751cb0ef41Sopenharmony_ci Handle<FixedArray> keys; 10761cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 10771cb0ef41Sopenharmony_ci isolate, keys, 10781cb0ef41Sopenharmony_ci KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly, 10791cb0ef41Sopenharmony_ci ALL_PROPERTIES), 10801cb0ef41Sopenharmony_ci Object); 10811cb0ef41Sopenharmony_ci // 6. Let descriptors be an empty List. 10821cb0ef41Sopenharmony_ci int capacity = keys->length(); 10831cb0ef41Sopenharmony_ci std::vector<PropertyDescriptor> descriptors(capacity); 10841cb0ef41Sopenharmony_ci size_t descriptors_index = 0; 10851cb0ef41Sopenharmony_ci // 7. Repeat for each element nextKey of keys in List order, 10861cb0ef41Sopenharmony_ci for (int i = 0; i < keys->length(); ++i) { 10871cb0ef41Sopenharmony_ci Handle<Object> next_key(keys->get(i), isolate); 10881cb0ef41Sopenharmony_ci // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey). 10891cb0ef41Sopenharmony_ci // 7b. ReturnIfAbrupt(propDesc). 10901cb0ef41Sopenharmony_ci PropertyKey key(isolate, next_key); 10911cb0ef41Sopenharmony_ci LookupIterator it(isolate, props, key, LookupIterator::OWN); 10921cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 10931cb0ef41Sopenharmony_ci if (maybe.IsNothing()) return MaybeHandle<Object>(); 10941cb0ef41Sopenharmony_ci PropertyAttributes attrs = maybe.FromJust(); 10951cb0ef41Sopenharmony_ci // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true: 10961cb0ef41Sopenharmony_ci if (attrs == ABSENT) continue; 10971cb0ef41Sopenharmony_ci if (attrs & DONT_ENUM) continue; 10981cb0ef41Sopenharmony_ci // 7c i. Let descObj be Get(props, nextKey). 10991cb0ef41Sopenharmony_ci // 7c ii. ReturnIfAbrupt(descObj). 11001cb0ef41Sopenharmony_ci Handle<Object> desc_obj; 11011cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it), 11021cb0ef41Sopenharmony_ci Object); 11031cb0ef41Sopenharmony_ci // 7c iii. Let desc be ToPropertyDescriptor(descObj). 11041cb0ef41Sopenharmony_ci bool success = PropertyDescriptor::ToPropertyDescriptor( 11051cb0ef41Sopenharmony_ci isolate, desc_obj, &descriptors[descriptors_index]); 11061cb0ef41Sopenharmony_ci // 7c iv. ReturnIfAbrupt(desc). 11071cb0ef41Sopenharmony_ci if (!success) return MaybeHandle<Object>(); 11081cb0ef41Sopenharmony_ci // 7c v. Append the pair (a two element List) consisting of nextKey and 11091cb0ef41Sopenharmony_ci // desc to the end of descriptors. 11101cb0ef41Sopenharmony_ci descriptors[descriptors_index].set_name(next_key); 11111cb0ef41Sopenharmony_ci descriptors_index++; 11121cb0ef41Sopenharmony_ci } 11131cb0ef41Sopenharmony_ci // 8. For each pair from descriptors in list order, 11141cb0ef41Sopenharmony_ci for (size_t i = 0; i < descriptors_index; ++i) { 11151cb0ef41Sopenharmony_ci PropertyDescriptor* desc = &descriptors[i]; 11161cb0ef41Sopenharmony_ci // 8a. Let P be the first element of pair. 11171cb0ef41Sopenharmony_ci // 8b. Let desc be the second element of pair. 11181cb0ef41Sopenharmony_ci // 8c. Let status be DefinePropertyOrThrow(O, P, desc). 11191cb0ef41Sopenharmony_ci Maybe<bool> status = 11201cb0ef41Sopenharmony_ci DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object), 11211cb0ef41Sopenharmony_ci desc->name(), desc, Just(kThrowOnError)); 11221cb0ef41Sopenharmony_ci // 8d. ReturnIfAbrupt(status). 11231cb0ef41Sopenharmony_ci if (status.IsNothing()) return MaybeHandle<Object>(); 11241cb0ef41Sopenharmony_ci CHECK(status.FromJust()); 11251cb0ef41Sopenharmony_ci } 11261cb0ef41Sopenharmony_ci // 9. Return o. 11271cb0ef41Sopenharmony_ci return object; 11281cb0ef41Sopenharmony_ci} 11291cb0ef41Sopenharmony_ci 11301cb0ef41Sopenharmony_ci// static 11311cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate, 11321cb0ef41Sopenharmony_ci Handle<JSReceiver> object, 11331cb0ef41Sopenharmony_ci Handle<Object> key, 11341cb0ef41Sopenharmony_ci PropertyDescriptor* desc, 11351cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw) { 11361cb0ef41Sopenharmony_ci if (object->IsJSArray()) { 11371cb0ef41Sopenharmony_ci return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object), 11381cb0ef41Sopenharmony_ci key, desc, should_throw); 11391cb0ef41Sopenharmony_ci } 11401cb0ef41Sopenharmony_ci if (object->IsJSProxy()) { 11411cb0ef41Sopenharmony_ci return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object), 11421cb0ef41Sopenharmony_ci key, desc, should_throw); 11431cb0ef41Sopenharmony_ci } 11441cb0ef41Sopenharmony_ci if (object->IsJSTypedArray()) { 11451cb0ef41Sopenharmony_ci return JSTypedArray::DefineOwnProperty( 11461cb0ef41Sopenharmony_ci isolate, Handle<JSTypedArray>::cast(object), key, desc, should_throw); 11471cb0ef41Sopenharmony_ci } 11481cb0ef41Sopenharmony_ci if (object->IsJSModuleNamespace()) { 11491cb0ef41Sopenharmony_ci return JSModuleNamespace::DefineOwnProperty( 11501cb0ef41Sopenharmony_ci isolate, Handle<JSModuleNamespace>::cast(object), key, desc, 11511cb0ef41Sopenharmony_ci should_throw); 11521cb0ef41Sopenharmony_ci } 11531cb0ef41Sopenharmony_ci 11541cb0ef41Sopenharmony_ci // OrdinaryDefineOwnProperty, by virtue of calling 11551cb0ef41Sopenharmony_ci // DefineOwnPropertyIgnoreAttributes, can handle arguments 11561cb0ef41Sopenharmony_ci // (ES#sec-arguments-exotic-objects-defineownproperty-p-desc). 11571cb0ef41Sopenharmony_ci return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key, 11581cb0ef41Sopenharmony_ci desc, should_throw); 11591cb0ef41Sopenharmony_ci} 11601cb0ef41Sopenharmony_ci 11611cb0ef41Sopenharmony_ci// static 11621cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::OrdinaryDefineOwnProperty( 11631cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSObject> object, Handle<Object> key, 11641cb0ef41Sopenharmony_ci PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw) { 11651cb0ef41Sopenharmony_ci DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey. 11661cb0ef41Sopenharmony_ci PropertyKey lookup_key(isolate, key); 11671cb0ef41Sopenharmony_ci return OrdinaryDefineOwnProperty(isolate, object, lookup_key, desc, 11681cb0ef41Sopenharmony_ci should_throw); 11691cb0ef41Sopenharmony_ci} 11701cb0ef41Sopenharmony_ci 11711cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::OrdinaryDefineOwnProperty( 11721cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSObject> object, const PropertyKey& key, 11731cb0ef41Sopenharmony_ci PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw) { 11741cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, key, LookupIterator::OWN); 11751cb0ef41Sopenharmony_ci 11761cb0ef41Sopenharmony_ci // Deal with access checks first. 11771cb0ef41Sopenharmony_ci if (it.state() == LookupIterator::ACCESS_CHECK) { 11781cb0ef41Sopenharmony_ci if (!it.HasAccess()) { 11791cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); 11801cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 11811cb0ef41Sopenharmony_ci return Just(true); 11821cb0ef41Sopenharmony_ci } 11831cb0ef41Sopenharmony_ci it.Next(); 11841cb0ef41Sopenharmony_ci } 11851cb0ef41Sopenharmony_ci 11861cb0ef41Sopenharmony_ci return OrdinaryDefineOwnProperty(&it, desc, should_throw); 11871cb0ef41Sopenharmony_ci} 11881cb0ef41Sopenharmony_ci 11891cb0ef41Sopenharmony_cinamespace { 11901cb0ef41Sopenharmony_ci 11911cb0ef41Sopenharmony_ciMaybeHandle<Object> GetPropertyWithInterceptorInternal( 11921cb0ef41Sopenharmony_ci LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) { 11931cb0ef41Sopenharmony_ci *done = false; 11941cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 11951cb0ef41Sopenharmony_ci // Make sure that the top context does not change when doing callbacks or 11961cb0ef41Sopenharmony_ci // interceptor calls. 11971cb0ef41Sopenharmony_ci AssertNoContextChange ncc(isolate); 11981cb0ef41Sopenharmony_ci 11991cb0ef41Sopenharmony_ci if (interceptor->getter().IsUndefined(isolate)) { 12001cb0ef41Sopenharmony_ci return isolate->factory()->undefined_value(); 12011cb0ef41Sopenharmony_ci } 12021cb0ef41Sopenharmony_ci 12031cb0ef41Sopenharmony_ci Handle<JSObject> holder = it->GetHolder<JSObject>(); 12041cb0ef41Sopenharmony_ci Handle<Object> result; 12051cb0ef41Sopenharmony_ci Handle<Object> receiver = it->GetReceiver(); 12061cb0ef41Sopenharmony_ci if (!receiver->IsJSReceiver()) { 12071cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 12081cb0ef41Sopenharmony_ci isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object); 12091cb0ef41Sopenharmony_ci } 12101cb0ef41Sopenharmony_ci PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, 12111cb0ef41Sopenharmony_ci *holder, Just(kDontThrow)); 12121cb0ef41Sopenharmony_ci 12131cb0ef41Sopenharmony_ci if (it->IsElement(*holder)) { 12141cb0ef41Sopenharmony_ci result = args.CallIndexedGetter(interceptor, it->array_index()); 12151cb0ef41Sopenharmony_ci } else { 12161cb0ef41Sopenharmony_ci result = args.CallNamedGetter(interceptor, it->name()); 12171cb0ef41Sopenharmony_ci } 12181cb0ef41Sopenharmony_ci 12191cb0ef41Sopenharmony_ci RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 12201cb0ef41Sopenharmony_ci if (result.is_null()) return isolate->factory()->undefined_value(); 12211cb0ef41Sopenharmony_ci *done = true; 12221cb0ef41Sopenharmony_ci // Rebox handle before return 12231cb0ef41Sopenharmony_ci return handle(*result, isolate); 12241cb0ef41Sopenharmony_ci} 12251cb0ef41Sopenharmony_ci 12261cb0ef41Sopenharmony_ciMaybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal( 12271cb0ef41Sopenharmony_ci LookupIterator* it, Handle<InterceptorInfo> interceptor) { 12281cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 12291cb0ef41Sopenharmony_ci // Make sure that the top context does not change when doing 12301cb0ef41Sopenharmony_ci // callbacks or interceptor calls. 12311cb0ef41Sopenharmony_ci AssertNoContextChange ncc(isolate); 12321cb0ef41Sopenharmony_ci HandleScope scope(isolate); 12331cb0ef41Sopenharmony_ci 12341cb0ef41Sopenharmony_ci Handle<JSObject> holder = it->GetHolder<JSObject>(); 12351cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!it->IsElement(*holder) && it->name()->IsSymbol(), 12361cb0ef41Sopenharmony_ci interceptor->can_intercept_symbols()); 12371cb0ef41Sopenharmony_ci Handle<Object> receiver = it->GetReceiver(); 12381cb0ef41Sopenharmony_ci if (!receiver->IsJSReceiver()) { 12391cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver, 12401cb0ef41Sopenharmony_ci Object::ConvertReceiver(isolate, receiver), 12411cb0ef41Sopenharmony_ci Nothing<PropertyAttributes>()); 12421cb0ef41Sopenharmony_ci } 12431cb0ef41Sopenharmony_ci PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, 12441cb0ef41Sopenharmony_ci *holder, Just(kDontThrow)); 12451cb0ef41Sopenharmony_ci if (!interceptor->query().IsUndefined(isolate)) { 12461cb0ef41Sopenharmony_ci Handle<Object> result; 12471cb0ef41Sopenharmony_ci if (it->IsElement(*holder)) { 12481cb0ef41Sopenharmony_ci result = args.CallIndexedQuery(interceptor, it->array_index()); 12491cb0ef41Sopenharmony_ci } else { 12501cb0ef41Sopenharmony_ci result = args.CallNamedQuery(interceptor, it->name()); 12511cb0ef41Sopenharmony_ci } 12521cb0ef41Sopenharmony_ci if (!result.is_null()) { 12531cb0ef41Sopenharmony_ci int32_t value; 12541cb0ef41Sopenharmony_ci CHECK(result->ToInt32(&value)); 12551cb0ef41Sopenharmony_ci DCHECK_IMPLIES((value & ~PropertyAttributes::ALL_ATTRIBUTES_MASK) != 0, 12561cb0ef41Sopenharmony_ci value == PropertyAttributes::ABSENT); 12571cb0ef41Sopenharmony_ci return Just(static_cast<PropertyAttributes>(value)); 12581cb0ef41Sopenharmony_ci } 12591cb0ef41Sopenharmony_ci } else if (!interceptor->getter().IsUndefined(isolate)) { 12601cb0ef41Sopenharmony_ci // TODO(verwaest): Use GetPropertyWithInterceptor? 12611cb0ef41Sopenharmony_ci Handle<Object> result; 12621cb0ef41Sopenharmony_ci if (it->IsElement(*holder)) { 12631cb0ef41Sopenharmony_ci result = args.CallIndexedGetter(interceptor, it->array_index()); 12641cb0ef41Sopenharmony_ci } else { 12651cb0ef41Sopenharmony_ci result = args.CallNamedGetter(interceptor, it->name()); 12661cb0ef41Sopenharmony_ci } 12671cb0ef41Sopenharmony_ci if (!result.is_null()) return Just(DONT_ENUM); 12681cb0ef41Sopenharmony_ci } 12691cb0ef41Sopenharmony_ci 12701cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>()); 12711cb0ef41Sopenharmony_ci return Just(ABSENT); 12721cb0ef41Sopenharmony_ci} 12731cb0ef41Sopenharmony_ci 12741cb0ef41Sopenharmony_ciMaybe<bool> SetPropertyWithInterceptorInternal( 12751cb0ef41Sopenharmony_ci LookupIterator* it, Handle<InterceptorInfo> interceptor, 12761cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw, Handle<Object> value) { 12771cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 12781cb0ef41Sopenharmony_ci // Make sure that the top context does not change when doing callbacks or 12791cb0ef41Sopenharmony_ci // interceptor calls. 12801cb0ef41Sopenharmony_ci AssertNoContextChange ncc(isolate); 12811cb0ef41Sopenharmony_ci 12821cb0ef41Sopenharmony_ci if (interceptor->setter().IsUndefined(isolate)) return Just(false); 12831cb0ef41Sopenharmony_ci 12841cb0ef41Sopenharmony_ci Handle<JSObject> holder = it->GetHolder<JSObject>(); 12851cb0ef41Sopenharmony_ci bool result; 12861cb0ef41Sopenharmony_ci Handle<Object> receiver = it->GetReceiver(); 12871cb0ef41Sopenharmony_ci if (!receiver->IsJSReceiver()) { 12881cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver, 12891cb0ef41Sopenharmony_ci Object::ConvertReceiver(isolate, receiver), 12901cb0ef41Sopenharmony_ci Nothing<bool>()); 12911cb0ef41Sopenharmony_ci } 12921cb0ef41Sopenharmony_ci PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, 12931cb0ef41Sopenharmony_ci *holder, should_throw); 12941cb0ef41Sopenharmony_ci 12951cb0ef41Sopenharmony_ci if (it->IsElement(*holder)) { 12961cb0ef41Sopenharmony_ci // TODO(neis): In the future, we may want to actually return the 12971cb0ef41Sopenharmony_ci // interceptor's result, which then should be a boolean. 12981cb0ef41Sopenharmony_ci result = !args.CallIndexedSetter(interceptor, it->array_index(), value) 12991cb0ef41Sopenharmony_ci .is_null(); 13001cb0ef41Sopenharmony_ci } else { 13011cb0ef41Sopenharmony_ci result = !args.CallNamedSetter(interceptor, it->name(), value).is_null(); 13021cb0ef41Sopenharmony_ci } 13031cb0ef41Sopenharmony_ci 13041cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); 13051cb0ef41Sopenharmony_ci return Just(result); 13061cb0ef41Sopenharmony_ci} 13071cb0ef41Sopenharmony_ci 13081cb0ef41Sopenharmony_ciMaybe<bool> DefinePropertyWithInterceptorInternal( 13091cb0ef41Sopenharmony_ci LookupIterator* it, Handle<InterceptorInfo> interceptor, 13101cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw, PropertyDescriptor* desc) { 13111cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 13121cb0ef41Sopenharmony_ci // Make sure that the top context does not change when doing callbacks or 13131cb0ef41Sopenharmony_ci // interceptor calls. 13141cb0ef41Sopenharmony_ci AssertNoContextChange ncc(isolate); 13151cb0ef41Sopenharmony_ci 13161cb0ef41Sopenharmony_ci if (interceptor->definer().IsUndefined(isolate)) return Just(false); 13171cb0ef41Sopenharmony_ci 13181cb0ef41Sopenharmony_ci Handle<JSObject> holder = it->GetHolder<JSObject>(); 13191cb0ef41Sopenharmony_ci bool result; 13201cb0ef41Sopenharmony_ci Handle<Object> receiver = it->GetReceiver(); 13211cb0ef41Sopenharmony_ci if (!receiver->IsJSReceiver()) { 13221cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver, 13231cb0ef41Sopenharmony_ci Object::ConvertReceiver(isolate, receiver), 13241cb0ef41Sopenharmony_ci Nothing<bool>()); 13251cb0ef41Sopenharmony_ci } 13261cb0ef41Sopenharmony_ci PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, 13271cb0ef41Sopenharmony_ci *holder, should_throw); 13281cb0ef41Sopenharmony_ci 13291cb0ef41Sopenharmony_ci std::unique_ptr<v8::PropertyDescriptor> descriptor( 13301cb0ef41Sopenharmony_ci new v8::PropertyDescriptor()); 13311cb0ef41Sopenharmony_ci if (PropertyDescriptor::IsAccessorDescriptor(desc)) { 13321cb0ef41Sopenharmony_ci descriptor.reset(new v8::PropertyDescriptor( 13331cb0ef41Sopenharmony_ci v8::Utils::ToLocal(desc->get()), v8::Utils::ToLocal(desc->set()))); 13341cb0ef41Sopenharmony_ci } else if (PropertyDescriptor::IsDataDescriptor(desc)) { 13351cb0ef41Sopenharmony_ci if (desc->has_writable()) { 13361cb0ef41Sopenharmony_ci descriptor.reset(new v8::PropertyDescriptor( 13371cb0ef41Sopenharmony_ci v8::Utils::ToLocal(desc->value()), desc->writable())); 13381cb0ef41Sopenharmony_ci } else { 13391cb0ef41Sopenharmony_ci descriptor.reset( 13401cb0ef41Sopenharmony_ci new v8::PropertyDescriptor(v8::Utils::ToLocal(desc->value()))); 13411cb0ef41Sopenharmony_ci } 13421cb0ef41Sopenharmony_ci } 13431cb0ef41Sopenharmony_ci if (desc->has_enumerable()) { 13441cb0ef41Sopenharmony_ci descriptor->set_enumerable(desc->enumerable()); 13451cb0ef41Sopenharmony_ci } 13461cb0ef41Sopenharmony_ci if (desc->has_configurable()) { 13471cb0ef41Sopenharmony_ci descriptor->set_configurable(desc->configurable()); 13481cb0ef41Sopenharmony_ci } 13491cb0ef41Sopenharmony_ci 13501cb0ef41Sopenharmony_ci if (it->IsElement(*holder)) { 13511cb0ef41Sopenharmony_ci result = 13521cb0ef41Sopenharmony_ci !args.CallIndexedDefiner(interceptor, it->array_index(), *descriptor) 13531cb0ef41Sopenharmony_ci .is_null(); 13541cb0ef41Sopenharmony_ci } else { 13551cb0ef41Sopenharmony_ci result = 13561cb0ef41Sopenharmony_ci !args.CallNamedDefiner(interceptor, it->name(), *descriptor).is_null(); 13571cb0ef41Sopenharmony_ci } 13581cb0ef41Sopenharmony_ci 13591cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); 13601cb0ef41Sopenharmony_ci return Just(result); 13611cb0ef41Sopenharmony_ci} 13621cb0ef41Sopenharmony_ci 13631cb0ef41Sopenharmony_ci} // namespace 13641cb0ef41Sopenharmony_ci 13651cb0ef41Sopenharmony_ci// ES6 9.1.6.1 13661cb0ef41Sopenharmony_ci// static 13671cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::OrdinaryDefineOwnProperty( 13681cb0ef41Sopenharmony_ci LookupIterator* it, PropertyDescriptor* desc, 13691cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw) { 13701cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 13711cb0ef41Sopenharmony_ci // 1. Let current be O.[[GetOwnProperty]](P). 13721cb0ef41Sopenharmony_ci // 2. ReturnIfAbrupt(current). 13731cb0ef41Sopenharmony_ci PropertyDescriptor current; 13741cb0ef41Sopenharmony_ci MAYBE_RETURN(GetOwnPropertyDescriptor(it, ¤t), Nothing<bool>()); 13751cb0ef41Sopenharmony_ci 13761cb0ef41Sopenharmony_ci it->Restart(); 13771cb0ef41Sopenharmony_ci // Handle interceptor 13781cb0ef41Sopenharmony_ci for (; it->IsFound(); it->Next()) { 13791cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::INTERCEPTOR) { 13801cb0ef41Sopenharmony_ci if (it->HolderIsReceiverOrHiddenPrototype()) { 13811cb0ef41Sopenharmony_ci Maybe<bool> result = DefinePropertyWithInterceptorInternal( 13821cb0ef41Sopenharmony_ci it, it->GetInterceptor(), should_throw, desc); 13831cb0ef41Sopenharmony_ci if (result.IsNothing() || result.FromJust()) { 13841cb0ef41Sopenharmony_ci return result; 13851cb0ef41Sopenharmony_ci } 13861cb0ef41Sopenharmony_ci } 13871cb0ef41Sopenharmony_ci } 13881cb0ef41Sopenharmony_ci } 13891cb0ef41Sopenharmony_ci 13901cb0ef41Sopenharmony_ci // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset 13911cb0ef41Sopenharmony_ci // the iterator every time. Currently, the reasons why we need it are: 13921cb0ef41Sopenharmony_ci // - handle interceptors correctly 13931cb0ef41Sopenharmony_ci // - handle accessors correctly (which might change the holder's map) 13941cb0ef41Sopenharmony_ci it->Restart(); 13951cb0ef41Sopenharmony_ci // 3. Let extensible be the value of the [[Extensible]] internal slot of O. 13961cb0ef41Sopenharmony_ci Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); 13971cb0ef41Sopenharmony_ci bool extensible = JSObject::IsExtensible(object); 13981cb0ef41Sopenharmony_ci 13991cb0ef41Sopenharmony_ci return ValidateAndApplyPropertyDescriptor( 14001cb0ef41Sopenharmony_ci isolate, it, extensible, desc, ¤t, should_throw, Handle<Name>()); 14011cb0ef41Sopenharmony_ci} 14021cb0ef41Sopenharmony_ci 14031cb0ef41Sopenharmony_ci// ES6 9.1.6.2 14041cb0ef41Sopenharmony_ci// static 14051cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::IsCompatiblePropertyDescriptor( 14061cb0ef41Sopenharmony_ci Isolate* isolate, bool extensible, PropertyDescriptor* desc, 14071cb0ef41Sopenharmony_ci PropertyDescriptor* current, Handle<Name> property_name, 14081cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw) { 14091cb0ef41Sopenharmony_ci // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, 14101cb0ef41Sopenharmony_ci // Extensible, Desc, Current). 14111cb0ef41Sopenharmony_ci return ValidateAndApplyPropertyDescriptor( 14121cb0ef41Sopenharmony_ci isolate, nullptr, extensible, desc, current, should_throw, property_name); 14131cb0ef41Sopenharmony_ci} 14141cb0ef41Sopenharmony_ci 14151cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-validateandapplypropertydescriptor 14161cb0ef41Sopenharmony_ci// static 14171cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor( 14181cb0ef41Sopenharmony_ci Isolate* isolate, LookupIterator* it, bool extensible, 14191cb0ef41Sopenharmony_ci PropertyDescriptor* desc, PropertyDescriptor* current, 14201cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw, Handle<Name> property_name) { 14211cb0ef41Sopenharmony_ci // We either need a LookupIterator, or a property name. 14221cb0ef41Sopenharmony_ci DCHECK((it == nullptr) != property_name.is_null()); 14231cb0ef41Sopenharmony_ci Handle<JSObject> object; 14241cb0ef41Sopenharmony_ci if (it != nullptr) object = Handle<JSObject>::cast(it->GetReceiver()); 14251cb0ef41Sopenharmony_ci bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc); 14261cb0ef41Sopenharmony_ci bool desc_is_accessor_descriptor = 14271cb0ef41Sopenharmony_ci PropertyDescriptor::IsAccessorDescriptor(desc); 14281cb0ef41Sopenharmony_ci bool desc_is_generic_descriptor = 14291cb0ef41Sopenharmony_ci PropertyDescriptor::IsGenericDescriptor(desc); 14301cb0ef41Sopenharmony_ci // 1. (Assert) 14311cb0ef41Sopenharmony_ci // 2. If current is undefined, then 14321cb0ef41Sopenharmony_ci if (current->is_empty()) { 14331cb0ef41Sopenharmony_ci // 2a. If extensible is false, return false. 14341cb0ef41Sopenharmony_ci if (!extensible) { 14351cb0ef41Sopenharmony_ci RETURN_FAILURE( 14361cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 14371cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kDefineDisallowed, 14381cb0ef41Sopenharmony_ci it != nullptr ? it->GetName() : property_name)); 14391cb0ef41Sopenharmony_ci } 14401cb0ef41Sopenharmony_ci // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then: 14411cb0ef41Sopenharmony_ci // (This is equivalent to !IsAccessorDescriptor(desc).) 14421cb0ef41Sopenharmony_ci DCHECK_EQ(desc_is_generic_descriptor || desc_is_data_descriptor, 14431cb0ef41Sopenharmony_ci !desc_is_accessor_descriptor); 14441cb0ef41Sopenharmony_ci if (!desc_is_accessor_descriptor) { 14451cb0ef41Sopenharmony_ci // 2c i. If O is not undefined, create an own data property named P of 14461cb0ef41Sopenharmony_ci // object O whose [[Value]], [[Writable]], [[Enumerable]] and 14471cb0ef41Sopenharmony_ci // [[Configurable]] attribute values are described by Desc. If the value 14481cb0ef41Sopenharmony_ci // of an attribute field of Desc is absent, the attribute of the newly 14491cb0ef41Sopenharmony_ci // created property is set to its default value. 14501cb0ef41Sopenharmony_ci if (it != nullptr) { 14511cb0ef41Sopenharmony_ci if (!desc->has_writable()) desc->set_writable(false); 14521cb0ef41Sopenharmony_ci if (!desc->has_enumerable()) desc->set_enumerable(false); 14531cb0ef41Sopenharmony_ci if (!desc->has_configurable()) desc->set_configurable(false); 14541cb0ef41Sopenharmony_ci Handle<Object> value( 14551cb0ef41Sopenharmony_ci desc->has_value() 14561cb0ef41Sopenharmony_ci ? desc->value() 14571cb0ef41Sopenharmony_ci : Handle<Object>::cast(isolate->factory()->undefined_value())); 14581cb0ef41Sopenharmony_ci MaybeHandle<Object> result = 14591cb0ef41Sopenharmony_ci JSObject::DefineOwnPropertyIgnoreAttributes(it, value, 14601cb0ef41Sopenharmony_ci desc->ToAttributes()); 14611cb0ef41Sopenharmony_ci if (result.is_null()) return Nothing<bool>(); 14621cb0ef41Sopenharmony_ci } 14631cb0ef41Sopenharmony_ci } else { 14641cb0ef41Sopenharmony_ci // 2d. Else Desc must be an accessor Property Descriptor, 14651cb0ef41Sopenharmony_ci DCHECK(desc_is_accessor_descriptor); 14661cb0ef41Sopenharmony_ci // 2d i. If O is not undefined, create an own accessor property named P 14671cb0ef41Sopenharmony_ci // of object O whose [[Get]], [[Set]], [[Enumerable]] and 14681cb0ef41Sopenharmony_ci // [[Configurable]] attribute values are described by Desc. If the value 14691cb0ef41Sopenharmony_ci // of an attribute field of Desc is absent, the attribute of the newly 14701cb0ef41Sopenharmony_ci // created property is set to its default value. 14711cb0ef41Sopenharmony_ci if (it != nullptr) { 14721cb0ef41Sopenharmony_ci if (!desc->has_enumerable()) desc->set_enumerable(false); 14731cb0ef41Sopenharmony_ci if (!desc->has_configurable()) desc->set_configurable(false); 14741cb0ef41Sopenharmony_ci Handle<Object> getter( 14751cb0ef41Sopenharmony_ci desc->has_get() 14761cb0ef41Sopenharmony_ci ? desc->get() 14771cb0ef41Sopenharmony_ci : Handle<Object>::cast(isolate->factory()->null_value())); 14781cb0ef41Sopenharmony_ci Handle<Object> setter( 14791cb0ef41Sopenharmony_ci desc->has_set() 14801cb0ef41Sopenharmony_ci ? desc->set() 14811cb0ef41Sopenharmony_ci : Handle<Object>::cast(isolate->factory()->null_value())); 14821cb0ef41Sopenharmony_ci MaybeHandle<Object> result = 14831cb0ef41Sopenharmony_ci JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes()); 14841cb0ef41Sopenharmony_ci if (result.is_null()) return Nothing<bool>(); 14851cb0ef41Sopenharmony_ci } 14861cb0ef41Sopenharmony_ci } 14871cb0ef41Sopenharmony_ci // 2e. Return true. 14881cb0ef41Sopenharmony_ci return Just(true); 14891cb0ef41Sopenharmony_ci } 14901cb0ef41Sopenharmony_ci // 3. If every field in Desc is absent, return true. (This also has a shortcut 14911cb0ef41Sopenharmony_ci // not in the spec: if every field value matches the current value, return.) 14921cb0ef41Sopenharmony_ci if ((!desc->has_enumerable() || 14931cb0ef41Sopenharmony_ci desc->enumerable() == current->enumerable()) && 14941cb0ef41Sopenharmony_ci (!desc->has_configurable() || 14951cb0ef41Sopenharmony_ci desc->configurable() == current->configurable()) && 14961cb0ef41Sopenharmony_ci (!desc->has_value() || 14971cb0ef41Sopenharmony_ci (current->has_value() && current->value()->SameValue(*desc->value()))) && 14981cb0ef41Sopenharmony_ci (!desc->has_writable() || 14991cb0ef41Sopenharmony_ci (current->has_writable() && current->writable() == desc->writable())) && 15001cb0ef41Sopenharmony_ci (!desc->has_get() || 15011cb0ef41Sopenharmony_ci (current->has_get() && current->get()->SameValue(*desc->get()))) && 15021cb0ef41Sopenharmony_ci (!desc->has_set() || 15031cb0ef41Sopenharmony_ci (current->has_set() && current->set()->SameValue(*desc->set())))) { 15041cb0ef41Sopenharmony_ci return Just(true); 15051cb0ef41Sopenharmony_ci } 15061cb0ef41Sopenharmony_ci // 4. If current.[[Configurable]] is false, then 15071cb0ef41Sopenharmony_ci if (!current->configurable()) { 15081cb0ef41Sopenharmony_ci // 4a. If Desc.[[Configurable]] is present and its value is true, return 15091cb0ef41Sopenharmony_ci // false. 15101cb0ef41Sopenharmony_ci if (desc->has_configurable() && desc->configurable()) { 15111cb0ef41Sopenharmony_ci RETURN_FAILURE( 15121cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 15131cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kRedefineDisallowed, 15141cb0ef41Sopenharmony_ci it != nullptr ? it->GetName() : property_name)); 15151cb0ef41Sopenharmony_ci } 15161cb0ef41Sopenharmony_ci // 4b. If Desc.[[Enumerable]] is present and 15171cb0ef41Sopenharmony_ci // ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return 15181cb0ef41Sopenharmony_ci // false. 15191cb0ef41Sopenharmony_ci if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) { 15201cb0ef41Sopenharmony_ci RETURN_FAILURE( 15211cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 15221cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kRedefineDisallowed, 15231cb0ef41Sopenharmony_ci it != nullptr ? it->GetName() : property_name)); 15241cb0ef41Sopenharmony_ci } 15251cb0ef41Sopenharmony_ci } 15261cb0ef41Sopenharmony_ci 15271cb0ef41Sopenharmony_ci bool current_is_data_descriptor = 15281cb0ef41Sopenharmony_ci PropertyDescriptor::IsDataDescriptor(current); 15291cb0ef41Sopenharmony_ci // 5. If ! IsGenericDescriptor(Desc) is true, no further validation is 15301cb0ef41Sopenharmony_ci // required. 15311cb0ef41Sopenharmony_ci if (desc_is_generic_descriptor) { 15321cb0ef41Sopenharmony_ci // Nothing to see here. 15331cb0ef41Sopenharmony_ci 15341cb0ef41Sopenharmony_ci // 6. Else if ! SameValue(!IsDataDescriptor(current), 15351cb0ef41Sopenharmony_ci // !IsDataDescriptor(Desc)) is false, the 15361cb0ef41Sopenharmony_ci } else if (current_is_data_descriptor != desc_is_data_descriptor) { 15371cb0ef41Sopenharmony_ci // 6a. If current.[[Configurable]] is false, return false. 15381cb0ef41Sopenharmony_ci if (!current->configurable()) { 15391cb0ef41Sopenharmony_ci RETURN_FAILURE( 15401cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 15411cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kRedefineDisallowed, 15421cb0ef41Sopenharmony_ci it != nullptr ? it->GetName() : property_name)); 15431cb0ef41Sopenharmony_ci } 15441cb0ef41Sopenharmony_ci // 6b. If IsDataDescriptor(current) is true, then: 15451cb0ef41Sopenharmony_ci if (current_is_data_descriptor) { 15461cb0ef41Sopenharmony_ci // 6b i. If O is not undefined, convert the property named P of object O 15471cb0ef41Sopenharmony_ci // from a data property to an accessor property. Preserve the existing 15481cb0ef41Sopenharmony_ci // values of the converted property's [[Configurable]] and [[Enumerable]] 15491cb0ef41Sopenharmony_ci // attributes and set the rest of the property's attributes to their 15501cb0ef41Sopenharmony_ci // default values. 15511cb0ef41Sopenharmony_ci // --> Folded into step 9 15521cb0ef41Sopenharmony_ci } else { 15531cb0ef41Sopenharmony_ci // 6c i. If O is not undefined, convert the property named P of object O 15541cb0ef41Sopenharmony_ci // from an accessor property to a data property. Preserve the existing 15551cb0ef41Sopenharmony_ci // values of the converted property’s [[Configurable]] and [[Enumerable]] 15561cb0ef41Sopenharmony_ci // attributes and set the rest of the property’s attributes to their 15571cb0ef41Sopenharmony_ci // default values. 15581cb0ef41Sopenharmony_ci // --> Folded into step 9 15591cb0ef41Sopenharmony_ci } 15601cb0ef41Sopenharmony_ci 15611cb0ef41Sopenharmony_ci // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both 15621cb0ef41Sopenharmony_ci // true, then: 15631cb0ef41Sopenharmony_ci } else if (current_is_data_descriptor && desc_is_data_descriptor) { 15641cb0ef41Sopenharmony_ci // 7a. If current.[[Configurable]] is false and current.[[Writable]] is 15651cb0ef41Sopenharmony_ci // false, then 15661cb0ef41Sopenharmony_ci if (!current->configurable() && !current->writable()) { 15671cb0ef41Sopenharmony_ci // 7a i. If Desc.[[Writable]] is present and Desc.[[Writable]] is true, 15681cb0ef41Sopenharmony_ci // return false. 15691cb0ef41Sopenharmony_ci if (desc->has_writable() && desc->writable()) { 15701cb0ef41Sopenharmony_ci RETURN_FAILURE( 15711cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 15721cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kRedefineDisallowed, 15731cb0ef41Sopenharmony_ci it != nullptr ? it->GetName() : property_name)); 15741cb0ef41Sopenharmony_ci } 15751cb0ef41Sopenharmony_ci // 7a ii. If Desc.[[Value]] is present and SameValue(Desc.[[Value]], 15761cb0ef41Sopenharmony_ci // current.[[Value]]) is false, return false. 15771cb0ef41Sopenharmony_ci if (desc->has_value() && !desc->value()->SameValue(*current->value())) { 15781cb0ef41Sopenharmony_ci RETURN_FAILURE( 15791cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 15801cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kRedefineDisallowed, 15811cb0ef41Sopenharmony_ci it != nullptr ? it->GetName() : property_name)); 15821cb0ef41Sopenharmony_ci } 15831cb0ef41Sopenharmony_ci } 15841cb0ef41Sopenharmony_ci } else { 15851cb0ef41Sopenharmony_ci // 8. Else, 15861cb0ef41Sopenharmony_ci // 8a. Assert: ! IsAccessorDescriptor(current) and 15871cb0ef41Sopenharmony_ci // ! IsAccessorDescriptor(Desc) are both true. 15881cb0ef41Sopenharmony_ci DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) && 15891cb0ef41Sopenharmony_ci desc_is_accessor_descriptor); 15901cb0ef41Sopenharmony_ci // 8b. If current.[[Configurable]] is false, then: 15911cb0ef41Sopenharmony_ci if (!current->configurable()) { 15921cb0ef41Sopenharmony_ci // 8a i. If Desc.[[Set]] is present and SameValue(Desc.[[Set]], 15931cb0ef41Sopenharmony_ci // current.[[Set]]) is false, return false. 15941cb0ef41Sopenharmony_ci if (desc->has_set() && !desc->set()->SameValue(*current->set())) { 15951cb0ef41Sopenharmony_ci RETURN_FAILURE( 15961cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 15971cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kRedefineDisallowed, 15981cb0ef41Sopenharmony_ci it != nullptr ? it->GetName() : property_name)); 15991cb0ef41Sopenharmony_ci } 16001cb0ef41Sopenharmony_ci // 8a ii. If Desc.[[Get]] is present and SameValue(Desc.[[Get]], 16011cb0ef41Sopenharmony_ci // current.[[Get]]) is false, return false. 16021cb0ef41Sopenharmony_ci if (desc->has_get() && !desc->get()->SameValue(*current->get())) { 16031cb0ef41Sopenharmony_ci RETURN_FAILURE( 16041cb0ef41Sopenharmony_ci isolate, GetShouldThrow(isolate, should_throw), 16051cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kRedefineDisallowed, 16061cb0ef41Sopenharmony_ci it != nullptr ? it->GetName() : property_name)); 16071cb0ef41Sopenharmony_ci } 16081cb0ef41Sopenharmony_ci } 16091cb0ef41Sopenharmony_ci } 16101cb0ef41Sopenharmony_ci 16111cb0ef41Sopenharmony_ci // 9. If O is not undefined, then: 16121cb0ef41Sopenharmony_ci if (it != nullptr) { 16131cb0ef41Sopenharmony_ci // 9a. For each field of Desc that is present, set the corresponding 16141cb0ef41Sopenharmony_ci // attribute of the property named P of object O to the value of the field. 16151cb0ef41Sopenharmony_ci PropertyAttributes attrs = NONE; 16161cb0ef41Sopenharmony_ci 16171cb0ef41Sopenharmony_ci if (desc->has_enumerable()) { 16181cb0ef41Sopenharmony_ci attrs = static_cast<PropertyAttributes>( 16191cb0ef41Sopenharmony_ci attrs | (desc->enumerable() ? NONE : DONT_ENUM)); 16201cb0ef41Sopenharmony_ci } else { 16211cb0ef41Sopenharmony_ci attrs = static_cast<PropertyAttributes>( 16221cb0ef41Sopenharmony_ci attrs | (current->enumerable() ? NONE : DONT_ENUM)); 16231cb0ef41Sopenharmony_ci } 16241cb0ef41Sopenharmony_ci if (desc->has_configurable()) { 16251cb0ef41Sopenharmony_ci attrs = static_cast<PropertyAttributes>( 16261cb0ef41Sopenharmony_ci attrs | (desc->configurable() ? NONE : DONT_DELETE)); 16271cb0ef41Sopenharmony_ci } else { 16281cb0ef41Sopenharmony_ci attrs = static_cast<PropertyAttributes>( 16291cb0ef41Sopenharmony_ci attrs | (current->configurable() ? NONE : DONT_DELETE)); 16301cb0ef41Sopenharmony_ci } 16311cb0ef41Sopenharmony_ci if (desc_is_data_descriptor || 16321cb0ef41Sopenharmony_ci (desc_is_generic_descriptor && current_is_data_descriptor)) { 16331cb0ef41Sopenharmony_ci if (desc->has_writable()) { 16341cb0ef41Sopenharmony_ci attrs = static_cast<PropertyAttributes>( 16351cb0ef41Sopenharmony_ci attrs | (desc->writable() ? NONE : READ_ONLY)); 16361cb0ef41Sopenharmony_ci } else { 16371cb0ef41Sopenharmony_ci attrs = static_cast<PropertyAttributes>( 16381cb0ef41Sopenharmony_ci attrs | (current->writable() ? NONE : READ_ONLY)); 16391cb0ef41Sopenharmony_ci } 16401cb0ef41Sopenharmony_ci Handle<Object> value( 16411cb0ef41Sopenharmony_ci desc->has_value() ? desc->value() 16421cb0ef41Sopenharmony_ci : current->has_value() 16431cb0ef41Sopenharmony_ci ? current->value() 16441cb0ef41Sopenharmony_ci : Handle<Object>::cast( 16451cb0ef41Sopenharmony_ci isolate->factory()->undefined_value())); 16461cb0ef41Sopenharmony_ci return JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs, 16471cb0ef41Sopenharmony_ci should_throw); 16481cb0ef41Sopenharmony_ci } else { 16491cb0ef41Sopenharmony_ci DCHECK(desc_is_accessor_descriptor || 16501cb0ef41Sopenharmony_ci (desc_is_generic_descriptor && 16511cb0ef41Sopenharmony_ci PropertyDescriptor::IsAccessorDescriptor(current))); 16521cb0ef41Sopenharmony_ci Handle<Object> getter( 16531cb0ef41Sopenharmony_ci desc->has_get() 16541cb0ef41Sopenharmony_ci ? desc->get() 16551cb0ef41Sopenharmony_ci : current->has_get() 16561cb0ef41Sopenharmony_ci ? current->get() 16571cb0ef41Sopenharmony_ci : Handle<Object>::cast(isolate->factory()->null_value())); 16581cb0ef41Sopenharmony_ci Handle<Object> setter( 16591cb0ef41Sopenharmony_ci desc->has_set() 16601cb0ef41Sopenharmony_ci ? desc->set() 16611cb0ef41Sopenharmony_ci : current->has_set() 16621cb0ef41Sopenharmony_ci ? current->set() 16631cb0ef41Sopenharmony_ci : Handle<Object>::cast(isolate->factory()->null_value())); 16641cb0ef41Sopenharmony_ci MaybeHandle<Object> result = 16651cb0ef41Sopenharmony_ci JSObject::DefineAccessor(it, getter, setter, attrs); 16661cb0ef41Sopenharmony_ci if (result.is_null()) return Nothing<bool>(); 16671cb0ef41Sopenharmony_ci } 16681cb0ef41Sopenharmony_ci } 16691cb0ef41Sopenharmony_ci 16701cb0ef41Sopenharmony_ci // 10. Return true. 16711cb0ef41Sopenharmony_ci return Just(true); 16721cb0ef41Sopenharmony_ci} 16731cb0ef41Sopenharmony_ci 16741cb0ef41Sopenharmony_ci// static 16751cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::CreateDataProperty(Isolate* isolate, 16761cb0ef41Sopenharmony_ci Handle<JSReceiver> object, 16771cb0ef41Sopenharmony_ci Handle<Name> key, 16781cb0ef41Sopenharmony_ci Handle<Object> value, 16791cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw) { 16801cb0ef41Sopenharmony_ci PropertyKey lookup_key(isolate, key); 16811cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, lookup_key, LookupIterator::OWN); 16821cb0ef41Sopenharmony_ci return CreateDataProperty(&it, value, should_throw); 16831cb0ef41Sopenharmony_ci} 16841cb0ef41Sopenharmony_ci 16851cb0ef41Sopenharmony_ci// static 16861cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it, 16871cb0ef41Sopenharmony_ci Handle<Object> value, 16881cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw) { 16891cb0ef41Sopenharmony_ci DCHECK(!it->check_prototype_chain()); 16901cb0ef41Sopenharmony_ci Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); 16911cb0ef41Sopenharmony_ci Isolate* isolate = receiver->GetIsolate(); 16921cb0ef41Sopenharmony_ci 16931cb0ef41Sopenharmony_ci if (receiver->IsJSObject()) { 16941cb0ef41Sopenharmony_ci return JSObject::CreateDataProperty(it, value, should_throw); // Shortcut. 16951cb0ef41Sopenharmony_ci } 16961cb0ef41Sopenharmony_ci 16971cb0ef41Sopenharmony_ci PropertyDescriptor new_desc; 16981cb0ef41Sopenharmony_ci new_desc.set_value(value); 16991cb0ef41Sopenharmony_ci new_desc.set_writable(true); 17001cb0ef41Sopenharmony_ci new_desc.set_enumerable(true); 17011cb0ef41Sopenharmony_ci new_desc.set_configurable(true); 17021cb0ef41Sopenharmony_ci 17031cb0ef41Sopenharmony_ci return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(), 17041cb0ef41Sopenharmony_ci &new_desc, should_throw); 17051cb0ef41Sopenharmony_ci} 17061cb0ef41Sopenharmony_ci 17071cb0ef41Sopenharmony_ci// static 17081cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::AddPrivateField(LookupIterator* it, 17091cb0ef41Sopenharmony_ci Handle<Object> value, 17101cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw) { 17111cb0ef41Sopenharmony_ci Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); 17121cb0ef41Sopenharmony_ci Isolate* isolate = receiver->GetIsolate(); 17131cb0ef41Sopenharmony_ci DCHECK(it->GetName()->IsPrivateName()); 17141cb0ef41Sopenharmony_ci Handle<Symbol> symbol = Handle<Symbol>::cast(it->GetName()); 17151cb0ef41Sopenharmony_ci 17161cb0ef41Sopenharmony_ci switch (it->state()) { 17171cb0ef41Sopenharmony_ci case LookupIterator::JSPROXY: { 17181cb0ef41Sopenharmony_ci PropertyDescriptor new_desc; 17191cb0ef41Sopenharmony_ci new_desc.set_value(value); 17201cb0ef41Sopenharmony_ci new_desc.set_writable(true); 17211cb0ef41Sopenharmony_ci new_desc.set_enumerable(true); 17221cb0ef41Sopenharmony_ci new_desc.set_configurable(true); 17231cb0ef41Sopenharmony_ci return JSProxy::SetPrivateSymbol(isolate, Handle<JSProxy>::cast(receiver), 17241cb0ef41Sopenharmony_ci symbol, &new_desc, should_throw); 17251cb0ef41Sopenharmony_ci } 17261cb0ef41Sopenharmony_ci case LookupIterator::DATA: 17271cb0ef41Sopenharmony_ci case LookupIterator::INTERCEPTOR: 17281cb0ef41Sopenharmony_ci case LookupIterator::ACCESSOR: 17291cb0ef41Sopenharmony_ci case LookupIterator::INTEGER_INDEXED_EXOTIC: 17301cb0ef41Sopenharmony_ci UNREACHABLE(); 17311cb0ef41Sopenharmony_ci 17321cb0ef41Sopenharmony_ci case LookupIterator::ACCESS_CHECK: { 17331cb0ef41Sopenharmony_ci if (!it->HasAccess()) { 17341cb0ef41Sopenharmony_ci it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>()); 17351cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); 17361cb0ef41Sopenharmony_ci return Just(true); 17371cb0ef41Sopenharmony_ci } 17381cb0ef41Sopenharmony_ci break; 17391cb0ef41Sopenharmony_ci } 17401cb0ef41Sopenharmony_ci 17411cb0ef41Sopenharmony_ci case LookupIterator::TRANSITION: 17421cb0ef41Sopenharmony_ci case LookupIterator::NOT_FOUND: 17431cb0ef41Sopenharmony_ci break; 17441cb0ef41Sopenharmony_ci } 17451cb0ef41Sopenharmony_ci 17461cb0ef41Sopenharmony_ci return Object::TransitionAndWriteDataProperty(it, value, NONE, should_throw, 17471cb0ef41Sopenharmony_ci StoreOrigin::kMaybeKeyed); 17481cb0ef41Sopenharmony_ci} 17491cb0ef41Sopenharmony_ci 17501cb0ef41Sopenharmony_ci// static 17511cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate, 17521cb0ef41Sopenharmony_ci Handle<JSReceiver> object, 17531cb0ef41Sopenharmony_ci Handle<Object> key, 17541cb0ef41Sopenharmony_ci PropertyDescriptor* desc) { 17551cb0ef41Sopenharmony_ci DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey. 17561cb0ef41Sopenharmony_ci PropertyKey lookup_key(isolate, key); 17571cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, lookup_key, LookupIterator::OWN); 17581cb0ef41Sopenharmony_ci return GetOwnPropertyDescriptor(&it, desc); 17591cb0ef41Sopenharmony_ci} 17601cb0ef41Sopenharmony_ci 17611cb0ef41Sopenharmony_cinamespace { 17621cb0ef41Sopenharmony_ci 17631cb0ef41Sopenharmony_ciMaybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it, 17641cb0ef41Sopenharmony_ci PropertyDescriptor* desc) { 17651cb0ef41Sopenharmony_ci Handle<InterceptorInfo> interceptor; 17661cb0ef41Sopenharmony_ci 17671cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::ACCESS_CHECK) { 17681cb0ef41Sopenharmony_ci if (it->HasAccess()) { 17691cb0ef41Sopenharmony_ci it->Next(); 17701cb0ef41Sopenharmony_ci } else { 17711cb0ef41Sopenharmony_ci interceptor = it->GetInterceptorForFailedAccessCheck(); 17721cb0ef41Sopenharmony_ci if (interceptor.is_null() && 17731cb0ef41Sopenharmony_ci (!JSObject::AllCanRead(it) || 17741cb0ef41Sopenharmony_ci it->state() != LookupIterator::INTERCEPTOR)) { 17751cb0ef41Sopenharmony_ci it->Restart(); 17761cb0ef41Sopenharmony_ci return Just(false); 17771cb0ef41Sopenharmony_ci } 17781cb0ef41Sopenharmony_ci } 17791cb0ef41Sopenharmony_ci } 17801cb0ef41Sopenharmony_ci 17811cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::INTERCEPTOR) { 17821cb0ef41Sopenharmony_ci interceptor = it->GetInterceptor(); 17831cb0ef41Sopenharmony_ci } 17841cb0ef41Sopenharmony_ci if (interceptor.is_null()) return Just(false); 17851cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 17861cb0ef41Sopenharmony_ci if (interceptor->descriptor().IsUndefined(isolate)) return Just(false); 17871cb0ef41Sopenharmony_ci 17881cb0ef41Sopenharmony_ci Handle<Object> result; 17891cb0ef41Sopenharmony_ci Handle<JSObject> holder = it->GetHolder<JSObject>(); 17901cb0ef41Sopenharmony_ci 17911cb0ef41Sopenharmony_ci Handle<Object> receiver = it->GetReceiver(); 17921cb0ef41Sopenharmony_ci if (!receiver->IsJSReceiver()) { 17931cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver, 17941cb0ef41Sopenharmony_ci Object::ConvertReceiver(isolate, receiver), 17951cb0ef41Sopenharmony_ci Nothing<bool>()); 17961cb0ef41Sopenharmony_ci } 17971cb0ef41Sopenharmony_ci 17981cb0ef41Sopenharmony_ci PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, 17991cb0ef41Sopenharmony_ci *holder, Just(kDontThrow)); 18001cb0ef41Sopenharmony_ci if (it->IsElement(*holder)) { 18011cb0ef41Sopenharmony_ci result = args.CallIndexedDescriptor(interceptor, it->array_index()); 18021cb0ef41Sopenharmony_ci } else { 18031cb0ef41Sopenharmony_ci result = args.CallNamedDescriptor(interceptor, it->name()); 18041cb0ef41Sopenharmony_ci } 18051cb0ef41Sopenharmony_ci // An exception was thrown in the interceptor. Propagate. 18061cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 18071cb0ef41Sopenharmony_ci if (!result.is_null()) { 18081cb0ef41Sopenharmony_ci // Request successfully intercepted, try to set the property 18091cb0ef41Sopenharmony_ci // descriptor. 18101cb0ef41Sopenharmony_ci Utils::ApiCheck( 18111cb0ef41Sopenharmony_ci PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc), 18121cb0ef41Sopenharmony_ci it->IsElement(*holder) ? "v8::IndexedPropertyDescriptorCallback" 18131cb0ef41Sopenharmony_ci : "v8::NamedPropertyDescriptorCallback", 18141cb0ef41Sopenharmony_ci "Invalid property descriptor."); 18151cb0ef41Sopenharmony_ci 18161cb0ef41Sopenharmony_ci return Just(true); 18171cb0ef41Sopenharmony_ci } 18181cb0ef41Sopenharmony_ci 18191cb0ef41Sopenharmony_ci it->Next(); 18201cb0ef41Sopenharmony_ci return Just(false); 18211cb0ef41Sopenharmony_ci} 18221cb0ef41Sopenharmony_ci} // namespace 18231cb0ef41Sopenharmony_ci 18241cb0ef41Sopenharmony_ci// ES6 9.1.5.1 18251cb0ef41Sopenharmony_ci// Returns true on success, false if the property didn't exist, nothing if 18261cb0ef41Sopenharmony_ci// an exception was thrown. 18271cb0ef41Sopenharmony_ci// static 18281cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it, 18291cb0ef41Sopenharmony_ci PropertyDescriptor* desc) { 18301cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 18311cb0ef41Sopenharmony_ci // "Virtual" dispatch. 18321cb0ef41Sopenharmony_ci if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) { 18331cb0ef41Sopenharmony_ci return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(), 18341cb0ef41Sopenharmony_ci it->GetName(), desc); 18351cb0ef41Sopenharmony_ci } 18361cb0ef41Sopenharmony_ci 18371cb0ef41Sopenharmony_ci Maybe<bool> intercepted = GetPropertyDescriptorWithInterceptor(it, desc); 18381cb0ef41Sopenharmony_ci MAYBE_RETURN(intercepted, Nothing<bool>()); 18391cb0ef41Sopenharmony_ci if (intercepted.FromJust()) { 18401cb0ef41Sopenharmony_ci return Just(true); 18411cb0ef41Sopenharmony_ci } 18421cb0ef41Sopenharmony_ci 18431cb0ef41Sopenharmony_ci // Request was not intercepted, continue as normal. 18441cb0ef41Sopenharmony_ci // 1. (Assert) 18451cb0ef41Sopenharmony_ci // 2. If O does not have an own property with key P, return undefined. 18461cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it); 18471cb0ef41Sopenharmony_ci MAYBE_RETURN(maybe, Nothing<bool>()); 18481cb0ef41Sopenharmony_ci PropertyAttributes attrs = maybe.FromJust(); 18491cb0ef41Sopenharmony_ci if (attrs == ABSENT) return Just(false); 18501cb0ef41Sopenharmony_ci DCHECK(!isolate->has_pending_exception()); 18511cb0ef41Sopenharmony_ci 18521cb0ef41Sopenharmony_ci // 3. Let D be a newly created Property Descriptor with no fields. 18531cb0ef41Sopenharmony_ci DCHECK(desc->is_empty()); 18541cb0ef41Sopenharmony_ci // 4. Let X be O's own property whose key is P. 18551cb0ef41Sopenharmony_ci // 5. If X is a data property, then 18561cb0ef41Sopenharmony_ci bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR && 18571cb0ef41Sopenharmony_ci it->GetAccessors()->IsAccessorPair(); 18581cb0ef41Sopenharmony_ci if (!is_accessor_pair) { 18591cb0ef41Sopenharmony_ci // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute. 18601cb0ef41Sopenharmony_ci Handle<Object> value; 18611cb0ef41Sopenharmony_ci if (!Object::GetProperty(it).ToHandle(&value)) { 18621cb0ef41Sopenharmony_ci DCHECK(isolate->has_pending_exception()); 18631cb0ef41Sopenharmony_ci return Nothing<bool>(); 18641cb0ef41Sopenharmony_ci } 18651cb0ef41Sopenharmony_ci desc->set_value(value); 18661cb0ef41Sopenharmony_ci // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute 18671cb0ef41Sopenharmony_ci desc->set_writable((attrs & READ_ONLY) == 0); 18681cb0ef41Sopenharmony_ci } else { 18691cb0ef41Sopenharmony_ci // 6. Else X is an accessor property, so 18701cb0ef41Sopenharmony_ci Handle<AccessorPair> accessors = 18711cb0ef41Sopenharmony_ci Handle<AccessorPair>::cast(it->GetAccessors()); 18721cb0ef41Sopenharmony_ci Handle<NativeContext> native_context = 18731cb0ef41Sopenharmony_ci it->GetHolder<JSReceiver>()->GetCreationContext().ToHandleChecked(); 18741cb0ef41Sopenharmony_ci // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute. 18751cb0ef41Sopenharmony_ci desc->set_get(AccessorPair::GetComponent(isolate, native_context, accessors, 18761cb0ef41Sopenharmony_ci ACCESSOR_GETTER)); 18771cb0ef41Sopenharmony_ci // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute. 18781cb0ef41Sopenharmony_ci desc->set_set(AccessorPair::GetComponent(isolate, native_context, accessors, 18791cb0ef41Sopenharmony_ci ACCESSOR_SETTER)); 18801cb0ef41Sopenharmony_ci } 18811cb0ef41Sopenharmony_ci 18821cb0ef41Sopenharmony_ci // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute. 18831cb0ef41Sopenharmony_ci desc->set_enumerable((attrs & DONT_ENUM) == 0); 18841cb0ef41Sopenharmony_ci // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute. 18851cb0ef41Sopenharmony_ci desc->set_configurable((attrs & DONT_DELETE) == 0); 18861cb0ef41Sopenharmony_ci // 9. Return D. 18871cb0ef41Sopenharmony_ci DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) != 18881cb0ef41Sopenharmony_ci PropertyDescriptor::IsDataDescriptor(desc)); 18891cb0ef41Sopenharmony_ci return Just(true); 18901cb0ef41Sopenharmony_ci} 18911cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver, 18921cb0ef41Sopenharmony_ci IntegrityLevel level, 18931cb0ef41Sopenharmony_ci ShouldThrow should_throw) { 18941cb0ef41Sopenharmony_ci DCHECK(level == SEALED || level == FROZEN); 18951cb0ef41Sopenharmony_ci 18961cb0ef41Sopenharmony_ci if (receiver->IsJSObject()) { 18971cb0ef41Sopenharmony_ci Handle<JSObject> object = Handle<JSObject>::cast(receiver); 18981cb0ef41Sopenharmony_ci 18991cb0ef41Sopenharmony_ci if (!object->HasSloppyArgumentsElements() && 19001cb0ef41Sopenharmony_ci !object->IsJSModuleNamespace()) { // Fast path. 19011cb0ef41Sopenharmony_ci // Prevent memory leaks by not adding unnecessary transitions. 19021cb0ef41Sopenharmony_ci Maybe<bool> test = JSObject::TestIntegrityLevel(object, level); 19031cb0ef41Sopenharmony_ci MAYBE_RETURN(test, Nothing<bool>()); 19041cb0ef41Sopenharmony_ci if (test.FromJust()) return test; 19051cb0ef41Sopenharmony_ci 19061cb0ef41Sopenharmony_ci if (level == SEALED) { 19071cb0ef41Sopenharmony_ci return JSObject::PreventExtensionsWithTransition<SEALED>(object, 19081cb0ef41Sopenharmony_ci should_throw); 19091cb0ef41Sopenharmony_ci } else { 19101cb0ef41Sopenharmony_ci return JSObject::PreventExtensionsWithTransition<FROZEN>(object, 19111cb0ef41Sopenharmony_ci should_throw); 19121cb0ef41Sopenharmony_ci } 19131cb0ef41Sopenharmony_ci } 19141cb0ef41Sopenharmony_ci } 19151cb0ef41Sopenharmony_ci 19161cb0ef41Sopenharmony_ci Isolate* isolate = receiver->GetIsolate(); 19171cb0ef41Sopenharmony_ci 19181cb0ef41Sopenharmony_ci MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw), 19191cb0ef41Sopenharmony_ci Nothing<bool>()); 19201cb0ef41Sopenharmony_ci 19211cb0ef41Sopenharmony_ci Handle<FixedArray> keys; 19221cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 19231cb0ef41Sopenharmony_ci isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>()); 19241cb0ef41Sopenharmony_ci 19251cb0ef41Sopenharmony_ci PropertyDescriptor no_conf; 19261cb0ef41Sopenharmony_ci no_conf.set_configurable(false); 19271cb0ef41Sopenharmony_ci 19281cb0ef41Sopenharmony_ci PropertyDescriptor no_conf_no_write; 19291cb0ef41Sopenharmony_ci no_conf_no_write.set_configurable(false); 19301cb0ef41Sopenharmony_ci no_conf_no_write.set_writable(false); 19311cb0ef41Sopenharmony_ci 19321cb0ef41Sopenharmony_ci if (level == SEALED) { 19331cb0ef41Sopenharmony_ci for (int i = 0; i < keys->length(); ++i) { 19341cb0ef41Sopenharmony_ci Handle<Object> key(keys->get(i), isolate); 19351cb0ef41Sopenharmony_ci MAYBE_RETURN(DefineOwnProperty(isolate, receiver, key, &no_conf, 19361cb0ef41Sopenharmony_ci Just(kThrowOnError)), 19371cb0ef41Sopenharmony_ci Nothing<bool>()); 19381cb0ef41Sopenharmony_ci } 19391cb0ef41Sopenharmony_ci return Just(true); 19401cb0ef41Sopenharmony_ci } 19411cb0ef41Sopenharmony_ci 19421cb0ef41Sopenharmony_ci for (int i = 0; i < keys->length(); ++i) { 19431cb0ef41Sopenharmony_ci Handle<Object> key(keys->get(i), isolate); 19441cb0ef41Sopenharmony_ci PropertyDescriptor current_desc; 19451cb0ef41Sopenharmony_ci Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor( 19461cb0ef41Sopenharmony_ci isolate, receiver, key, ¤t_desc); 19471cb0ef41Sopenharmony_ci MAYBE_RETURN(owned, Nothing<bool>()); 19481cb0ef41Sopenharmony_ci if (owned.FromJust()) { 19491cb0ef41Sopenharmony_ci PropertyDescriptor desc = 19501cb0ef41Sopenharmony_ci PropertyDescriptor::IsAccessorDescriptor(¤t_desc) 19511cb0ef41Sopenharmony_ci ? no_conf 19521cb0ef41Sopenharmony_ci : no_conf_no_write; 19531cb0ef41Sopenharmony_ci MAYBE_RETURN( 19541cb0ef41Sopenharmony_ci DefineOwnProperty(isolate, receiver, key, &desc, Just(kThrowOnError)), 19551cb0ef41Sopenharmony_ci Nothing<bool>()); 19561cb0ef41Sopenharmony_ci } 19571cb0ef41Sopenharmony_ci } 19581cb0ef41Sopenharmony_ci return Just(true); 19591cb0ef41Sopenharmony_ci} 19601cb0ef41Sopenharmony_ci 19611cb0ef41Sopenharmony_cinamespace { 19621cb0ef41Sopenharmony_ciMaybe<bool> GenericTestIntegrityLevel(Handle<JSReceiver> receiver, 19631cb0ef41Sopenharmony_ci PropertyAttributes level) { 19641cb0ef41Sopenharmony_ci DCHECK(level == SEALED || level == FROZEN); 19651cb0ef41Sopenharmony_ci 19661cb0ef41Sopenharmony_ci Maybe<bool> extensible = JSReceiver::IsExtensible(receiver); 19671cb0ef41Sopenharmony_ci MAYBE_RETURN(extensible, Nothing<bool>()); 19681cb0ef41Sopenharmony_ci if (extensible.FromJust()) return Just(false); 19691cb0ef41Sopenharmony_ci 19701cb0ef41Sopenharmony_ci Isolate* isolate = receiver->GetIsolate(); 19711cb0ef41Sopenharmony_ci 19721cb0ef41Sopenharmony_ci Handle<FixedArray> keys; 19731cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 19741cb0ef41Sopenharmony_ci isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>()); 19751cb0ef41Sopenharmony_ci 19761cb0ef41Sopenharmony_ci for (int i = 0; i < keys->length(); ++i) { 19771cb0ef41Sopenharmony_ci Handle<Object> key(keys->get(i), isolate); 19781cb0ef41Sopenharmony_ci PropertyDescriptor current_desc; 19791cb0ef41Sopenharmony_ci Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor( 19801cb0ef41Sopenharmony_ci isolate, receiver, key, ¤t_desc); 19811cb0ef41Sopenharmony_ci MAYBE_RETURN(owned, Nothing<bool>()); 19821cb0ef41Sopenharmony_ci if (owned.FromJust()) { 19831cb0ef41Sopenharmony_ci if (current_desc.configurable()) return Just(false); 19841cb0ef41Sopenharmony_ci if (level == FROZEN && 19851cb0ef41Sopenharmony_ci PropertyDescriptor::IsDataDescriptor(¤t_desc) && 19861cb0ef41Sopenharmony_ci current_desc.writable()) { 19871cb0ef41Sopenharmony_ci return Just(false); 19881cb0ef41Sopenharmony_ci } 19891cb0ef41Sopenharmony_ci } 19901cb0ef41Sopenharmony_ci } 19911cb0ef41Sopenharmony_ci return Just(true); 19921cb0ef41Sopenharmony_ci} 19931cb0ef41Sopenharmony_ci 19941cb0ef41Sopenharmony_ci} // namespace 19951cb0ef41Sopenharmony_ci 19961cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> receiver, 19971cb0ef41Sopenharmony_ci IntegrityLevel level) { 19981cb0ef41Sopenharmony_ci if (!receiver->map().IsCustomElementsReceiverMap()) { 19991cb0ef41Sopenharmony_ci return JSObject::TestIntegrityLevel(Handle<JSObject>::cast(receiver), 20001cb0ef41Sopenharmony_ci level); 20011cb0ef41Sopenharmony_ci } 20021cb0ef41Sopenharmony_ci return GenericTestIntegrityLevel(receiver, level); 20031cb0ef41Sopenharmony_ci} 20041cb0ef41Sopenharmony_ci 20051cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object, 20061cb0ef41Sopenharmony_ci ShouldThrow should_throw) { 20071cb0ef41Sopenharmony_ci if (object->IsJSProxy()) { 20081cb0ef41Sopenharmony_ci return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object), 20091cb0ef41Sopenharmony_ci should_throw); 20101cb0ef41Sopenharmony_ci } 20111cb0ef41Sopenharmony_ci DCHECK(object->IsJSObject()); 20121cb0ef41Sopenharmony_ci return JSObject::PreventExtensions(Handle<JSObject>::cast(object), 20131cb0ef41Sopenharmony_ci should_throw); 20141cb0ef41Sopenharmony_ci} 20151cb0ef41Sopenharmony_ci 20161cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) { 20171cb0ef41Sopenharmony_ci if (object->IsJSProxy()) { 20181cb0ef41Sopenharmony_ci return JSProxy::IsExtensible(Handle<JSProxy>::cast(object)); 20191cb0ef41Sopenharmony_ci } 20201cb0ef41Sopenharmony_ci return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object))); 20211cb0ef41Sopenharmony_ci} 20221cb0ef41Sopenharmony_ci 20231cb0ef41Sopenharmony_ci// static 20241cb0ef41Sopenharmony_ciMaybeHandle<Object> JSReceiver::ToPrimitive(Isolate* isolate, 20251cb0ef41Sopenharmony_ci Handle<JSReceiver> receiver, 20261cb0ef41Sopenharmony_ci ToPrimitiveHint hint) { 20271cb0ef41Sopenharmony_ci Handle<Object> exotic_to_prim; 20281cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 20291cb0ef41Sopenharmony_ci isolate, exotic_to_prim, 20301cb0ef41Sopenharmony_ci Object::GetMethod(receiver, isolate->factory()->to_primitive_symbol()), 20311cb0ef41Sopenharmony_ci Object); 20321cb0ef41Sopenharmony_ci if (!exotic_to_prim->IsUndefined(isolate)) { 20331cb0ef41Sopenharmony_ci Handle<Object> hint_string = 20341cb0ef41Sopenharmony_ci isolate->factory()->ToPrimitiveHintString(hint); 20351cb0ef41Sopenharmony_ci Handle<Object> result; 20361cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 20371cb0ef41Sopenharmony_ci isolate, result, 20381cb0ef41Sopenharmony_ci Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string), 20391cb0ef41Sopenharmony_ci Object); 20401cb0ef41Sopenharmony_ci if (result->IsPrimitive()) return result; 20411cb0ef41Sopenharmony_ci THROW_NEW_ERROR(isolate, 20421cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kCannotConvertToPrimitive), 20431cb0ef41Sopenharmony_ci Object); 20441cb0ef41Sopenharmony_ci } 20451cb0ef41Sopenharmony_ci return OrdinaryToPrimitive(isolate, receiver, 20461cb0ef41Sopenharmony_ci (hint == ToPrimitiveHint::kString) 20471cb0ef41Sopenharmony_ci ? OrdinaryToPrimitiveHint::kString 20481cb0ef41Sopenharmony_ci : OrdinaryToPrimitiveHint::kNumber); 20491cb0ef41Sopenharmony_ci} 20501cb0ef41Sopenharmony_ci 20511cb0ef41Sopenharmony_ci// static 20521cb0ef41Sopenharmony_ciMaybeHandle<Object> JSReceiver::OrdinaryToPrimitive( 20531cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSReceiver> receiver, 20541cb0ef41Sopenharmony_ci OrdinaryToPrimitiveHint hint) { 20551cb0ef41Sopenharmony_ci Handle<String> method_names[2]; 20561cb0ef41Sopenharmony_ci switch (hint) { 20571cb0ef41Sopenharmony_ci case OrdinaryToPrimitiveHint::kNumber: 20581cb0ef41Sopenharmony_ci method_names[0] = isolate->factory()->valueOf_string(); 20591cb0ef41Sopenharmony_ci method_names[1] = isolate->factory()->toString_string(); 20601cb0ef41Sopenharmony_ci break; 20611cb0ef41Sopenharmony_ci case OrdinaryToPrimitiveHint::kString: 20621cb0ef41Sopenharmony_ci method_names[0] = isolate->factory()->toString_string(); 20631cb0ef41Sopenharmony_ci method_names[1] = isolate->factory()->valueOf_string(); 20641cb0ef41Sopenharmony_ci break; 20651cb0ef41Sopenharmony_ci } 20661cb0ef41Sopenharmony_ci for (Handle<String> name : method_names) { 20671cb0ef41Sopenharmony_ci Handle<Object> method; 20681cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION(isolate, method, 20691cb0ef41Sopenharmony_ci JSReceiver::GetProperty(isolate, receiver, name), 20701cb0ef41Sopenharmony_ci Object); 20711cb0ef41Sopenharmony_ci if (method->IsCallable()) { 20721cb0ef41Sopenharmony_ci Handle<Object> result; 20731cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 20741cb0ef41Sopenharmony_ci isolate, result, 20751cb0ef41Sopenharmony_ci Execution::Call(isolate, method, receiver, 0, nullptr), Object); 20761cb0ef41Sopenharmony_ci if (result->IsPrimitive()) return result; 20771cb0ef41Sopenharmony_ci } 20781cb0ef41Sopenharmony_ci } 20791cb0ef41Sopenharmony_ci THROW_NEW_ERROR(isolate, 20801cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kCannotConvertToPrimitive), 20811cb0ef41Sopenharmony_ci Object); 20821cb0ef41Sopenharmony_ci} 20831cb0ef41Sopenharmony_ci 20841cb0ef41Sopenharmony_ciV8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries( 20851cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries, 20861cb0ef41Sopenharmony_ci Handle<FixedArray>* result) { 20871cb0ef41Sopenharmony_ci Handle<Map> map(JSReceiver::cast(*receiver).map(), isolate); 20881cb0ef41Sopenharmony_ci 20891cb0ef41Sopenharmony_ci if (!map->IsJSObjectMap()) return Just(false); 20901cb0ef41Sopenharmony_ci if (!map->OnlyHasSimpleProperties()) return Just(false); 20911cb0ef41Sopenharmony_ci 20921cb0ef41Sopenharmony_ci Handle<JSObject> object(JSObject::cast(*receiver), isolate); 20931cb0ef41Sopenharmony_ci Handle<DescriptorArray> descriptors(map->instance_descriptors(isolate), 20941cb0ef41Sopenharmony_ci isolate); 20951cb0ef41Sopenharmony_ci 20961cb0ef41Sopenharmony_ci int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 20971cb0ef41Sopenharmony_ci size_t number_of_own_elements = 20981cb0ef41Sopenharmony_ci object->GetElementsAccessor()->GetCapacity(*object, object->elements()); 20991cb0ef41Sopenharmony_ci 21001cb0ef41Sopenharmony_ci if (number_of_own_elements > 21011cb0ef41Sopenharmony_ci static_cast<size_t>(FixedArray::kMaxLength - number_of_own_descriptors)) { 21021cb0ef41Sopenharmony_ci isolate->Throw(*isolate->factory()->NewRangeError( 21031cb0ef41Sopenharmony_ci MessageTemplate::kInvalidArrayLength)); 21041cb0ef41Sopenharmony_ci return Nothing<bool>(); 21051cb0ef41Sopenharmony_ci } 21061cb0ef41Sopenharmony_ci // The static cast is safe after the range check right above. 21071cb0ef41Sopenharmony_ci Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray( 21081cb0ef41Sopenharmony_ci static_cast<int>(number_of_own_descriptors + number_of_own_elements)); 21091cb0ef41Sopenharmony_ci int count = 0; 21101cb0ef41Sopenharmony_ci 21111cb0ef41Sopenharmony_ci if (object->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) { 21121cb0ef41Sopenharmony_ci MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries( 21131cb0ef41Sopenharmony_ci isolate, object, values_or_entries, get_entries, &count, 21141cb0ef41Sopenharmony_ci ENUMERABLE_STRINGS), 21151cb0ef41Sopenharmony_ci Nothing<bool>()); 21161cb0ef41Sopenharmony_ci } 21171cb0ef41Sopenharmony_ci 21181cb0ef41Sopenharmony_ci // We may have already lost stability, if CollectValuesOrEntries had 21191cb0ef41Sopenharmony_ci // side-effects. 21201cb0ef41Sopenharmony_ci bool stable = *map == object->map(); 21211cb0ef41Sopenharmony_ci if (stable) { 21221cb0ef41Sopenharmony_ci descriptors.PatchValue(map->instance_descriptors(isolate)); 21231cb0ef41Sopenharmony_ci } 21241cb0ef41Sopenharmony_ci 21251cb0ef41Sopenharmony_ci for (InternalIndex index : InternalIndex::Range(number_of_own_descriptors)) { 21261cb0ef41Sopenharmony_ci HandleScope inner_scope(isolate); 21271cb0ef41Sopenharmony_ci 21281cb0ef41Sopenharmony_ci Handle<Name> next_key(descriptors->GetKey(index), isolate); 21291cb0ef41Sopenharmony_ci if (!next_key->IsString()) continue; 21301cb0ef41Sopenharmony_ci Handle<Object> prop_value; 21311cb0ef41Sopenharmony_ci 21321cb0ef41Sopenharmony_ci // Directly decode from the descriptor array if |from| did not change shape. 21331cb0ef41Sopenharmony_ci if (stable) { 21341cb0ef41Sopenharmony_ci DCHECK_EQ(object->map(), *map); 21351cb0ef41Sopenharmony_ci DCHECK_EQ(*descriptors, map->instance_descriptors(isolate)); 21361cb0ef41Sopenharmony_ci 21371cb0ef41Sopenharmony_ci PropertyDetails details = descriptors->GetDetails(index); 21381cb0ef41Sopenharmony_ci if (!details.IsEnumerable()) continue; 21391cb0ef41Sopenharmony_ci if (details.kind() == PropertyKind::kData) { 21401cb0ef41Sopenharmony_ci if (details.location() == PropertyLocation::kDescriptor) { 21411cb0ef41Sopenharmony_ci prop_value = handle(descriptors->GetStrongValue(index), isolate); 21421cb0ef41Sopenharmony_ci } else { 21431cb0ef41Sopenharmony_ci Representation representation = details.representation(); 21441cb0ef41Sopenharmony_ci FieldIndex field_index = FieldIndex::ForPropertyIndex( 21451cb0ef41Sopenharmony_ci *map, details.field_index(), representation); 21461cb0ef41Sopenharmony_ci prop_value = JSObject::FastPropertyAt(isolate, object, representation, 21471cb0ef41Sopenharmony_ci field_index); 21481cb0ef41Sopenharmony_ci } 21491cb0ef41Sopenharmony_ci } else { 21501cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, next_key, 21511cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 21521cb0ef41Sopenharmony_ci DCHECK_EQ(LookupIterator::ACCESSOR, it.state()); 21531cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 21541cb0ef41Sopenharmony_ci isolate, prop_value, Object::GetProperty(&it), Nothing<bool>()); 21551cb0ef41Sopenharmony_ci stable = object->map() == *map; 21561cb0ef41Sopenharmony_ci descriptors.PatchValue(map->instance_descriptors(isolate)); 21571cb0ef41Sopenharmony_ci } 21581cb0ef41Sopenharmony_ci } else { 21591cb0ef41Sopenharmony_ci // If the map did change, do a slower lookup. We are still guaranteed that 21601cb0ef41Sopenharmony_ci // the object has a simple shape, and that the key is a name. 21611cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, next_key, 21621cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 21631cb0ef41Sopenharmony_ci if (!it.IsFound()) continue; 21641cb0ef41Sopenharmony_ci DCHECK(it.state() == LookupIterator::DATA || 21651cb0ef41Sopenharmony_ci it.state() == LookupIterator::ACCESSOR); 21661cb0ef41Sopenharmony_ci if (!it.IsEnumerable()) continue; 21671cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 21681cb0ef41Sopenharmony_ci isolate, prop_value, Object::GetProperty(&it), Nothing<bool>()); 21691cb0ef41Sopenharmony_ci } 21701cb0ef41Sopenharmony_ci 21711cb0ef41Sopenharmony_ci if (get_entries) { 21721cb0ef41Sopenharmony_ci prop_value = MakeEntryPair(isolate, next_key, prop_value); 21731cb0ef41Sopenharmony_ci } 21741cb0ef41Sopenharmony_ci 21751cb0ef41Sopenharmony_ci values_or_entries->set(count, *prop_value); 21761cb0ef41Sopenharmony_ci count++; 21771cb0ef41Sopenharmony_ci } 21781cb0ef41Sopenharmony_ci 21791cb0ef41Sopenharmony_ci DCHECK_LE(count, values_or_entries->length()); 21801cb0ef41Sopenharmony_ci *result = FixedArray::ShrinkOrEmpty(isolate, values_or_entries, count); 21811cb0ef41Sopenharmony_ci return Just(true); 21821cb0ef41Sopenharmony_ci} 21831cb0ef41Sopenharmony_ci 21841cb0ef41Sopenharmony_ciMaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate, 21851cb0ef41Sopenharmony_ci Handle<JSReceiver> object, 21861cb0ef41Sopenharmony_ci PropertyFilter filter, 21871cb0ef41Sopenharmony_ci bool try_fast_path, 21881cb0ef41Sopenharmony_ci bool get_entries) { 21891cb0ef41Sopenharmony_ci Handle<FixedArray> values_or_entries; 21901cb0ef41Sopenharmony_ci if (try_fast_path && filter == ENUMERABLE_STRINGS) { 21911cb0ef41Sopenharmony_ci Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries( 21921cb0ef41Sopenharmony_ci isolate, object, get_entries, &values_or_entries); 21931cb0ef41Sopenharmony_ci if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>(); 21941cb0ef41Sopenharmony_ci if (fast_values_or_entries.FromJust()) return values_or_entries; 21951cb0ef41Sopenharmony_ci } 21961cb0ef41Sopenharmony_ci 21971cb0ef41Sopenharmony_ci PropertyFilter key_filter = 21981cb0ef41Sopenharmony_ci static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE); 21991cb0ef41Sopenharmony_ci 22001cb0ef41Sopenharmony_ci Handle<FixedArray> keys; 22011cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 22021cb0ef41Sopenharmony_ci isolate, keys, 22031cb0ef41Sopenharmony_ci KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, key_filter, 22041cb0ef41Sopenharmony_ci GetKeysConversion::kConvertToString), 22051cb0ef41Sopenharmony_ci MaybeHandle<FixedArray>()); 22061cb0ef41Sopenharmony_ci 22071cb0ef41Sopenharmony_ci values_or_entries = isolate->factory()->NewFixedArray(keys->length()); 22081cb0ef41Sopenharmony_ci int length = 0; 22091cb0ef41Sopenharmony_ci 22101cb0ef41Sopenharmony_ci for (int i = 0; i < keys->length(); ++i) { 22111cb0ef41Sopenharmony_ci Handle<Name> key = 22121cb0ef41Sopenharmony_ci Handle<Name>::cast(handle(keys->get(isolate, i), isolate)); 22131cb0ef41Sopenharmony_ci 22141cb0ef41Sopenharmony_ci if (filter & ONLY_ENUMERABLE) { 22151cb0ef41Sopenharmony_ci PropertyDescriptor descriptor; 22161cb0ef41Sopenharmony_ci Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor( 22171cb0ef41Sopenharmony_ci isolate, object, key, &descriptor); 22181cb0ef41Sopenharmony_ci MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>()); 22191cb0ef41Sopenharmony_ci if (!did_get_descriptor.FromJust() || !descriptor.enumerable()) continue; 22201cb0ef41Sopenharmony_ci } 22211cb0ef41Sopenharmony_ci 22221cb0ef41Sopenharmony_ci Handle<Object> value; 22231cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE( 22241cb0ef41Sopenharmony_ci isolate, value, Object::GetPropertyOrElement(isolate, object, key), 22251cb0ef41Sopenharmony_ci MaybeHandle<FixedArray>()); 22261cb0ef41Sopenharmony_ci 22271cb0ef41Sopenharmony_ci if (get_entries) { 22281cb0ef41Sopenharmony_ci Handle<FixedArray> entry_storage = isolate->factory()->NewFixedArray(2); 22291cb0ef41Sopenharmony_ci entry_storage->set(0, *key); 22301cb0ef41Sopenharmony_ci entry_storage->set(1, *value); 22311cb0ef41Sopenharmony_ci value = isolate->factory()->NewJSArrayWithElements(entry_storage, 22321cb0ef41Sopenharmony_ci PACKED_ELEMENTS, 2); 22331cb0ef41Sopenharmony_ci } 22341cb0ef41Sopenharmony_ci 22351cb0ef41Sopenharmony_ci values_or_entries->set(length, *value); 22361cb0ef41Sopenharmony_ci length++; 22371cb0ef41Sopenharmony_ci } 22381cb0ef41Sopenharmony_ci DCHECK_LE(length, values_or_entries->length()); 22391cb0ef41Sopenharmony_ci return FixedArray::ShrinkOrEmpty(isolate, values_or_entries, length); 22401cb0ef41Sopenharmony_ci} 22411cb0ef41Sopenharmony_ci 22421cb0ef41Sopenharmony_ciMaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver> object, 22431cb0ef41Sopenharmony_ci PropertyFilter filter, 22441cb0ef41Sopenharmony_ci bool try_fast_path) { 22451cb0ef41Sopenharmony_ci return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, 22461cb0ef41Sopenharmony_ci try_fast_path, false); 22471cb0ef41Sopenharmony_ci} 22481cb0ef41Sopenharmony_ci 22491cb0ef41Sopenharmony_ciMaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver> object, 22501cb0ef41Sopenharmony_ci PropertyFilter filter, 22511cb0ef41Sopenharmony_ci bool try_fast_path) { 22521cb0ef41Sopenharmony_ci return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, 22531cb0ef41Sopenharmony_ci try_fast_path, true); 22541cb0ef41Sopenharmony_ci} 22551cb0ef41Sopenharmony_ci 22561cb0ef41Sopenharmony_ciMaybe<bool> JSReceiver::SetPrototype(Isolate* isolate, 22571cb0ef41Sopenharmony_ci Handle<JSReceiver> object, 22581cb0ef41Sopenharmony_ci Handle<Object> value, bool from_javascript, 22591cb0ef41Sopenharmony_ci ShouldThrow should_throw) { 22601cb0ef41Sopenharmony_ci if (object->IsJSProxy()) { 22611cb0ef41Sopenharmony_ci return JSProxy::SetPrototype(isolate, Handle<JSProxy>::cast(object), value, 22621cb0ef41Sopenharmony_ci from_javascript, should_throw); 22631cb0ef41Sopenharmony_ci } 22641cb0ef41Sopenharmony_ci return JSObject::SetPrototype(isolate, Handle<JSObject>::cast(object), value, 22651cb0ef41Sopenharmony_ci from_javascript, should_throw); 22661cb0ef41Sopenharmony_ci} 22671cb0ef41Sopenharmony_ci 22681cb0ef41Sopenharmony_cibool JSReceiver::HasProxyInPrototype(Isolate* isolate) { 22691cb0ef41Sopenharmony_ci for (PrototypeIterator iter(isolate, *this, kStartAtReceiver, 22701cb0ef41Sopenharmony_ci PrototypeIterator::END_AT_NULL); 22711cb0ef41Sopenharmony_ci !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) { 22721cb0ef41Sopenharmony_ci if (iter.GetCurrent().IsJSProxy()) return true; 22731cb0ef41Sopenharmony_ci } 22741cb0ef41Sopenharmony_ci return false; 22751cb0ef41Sopenharmony_ci} 22761cb0ef41Sopenharmony_ci 22771cb0ef41Sopenharmony_cibool JSReceiver::IsCodeLike(Isolate* isolate) const { 22781cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 22791cb0ef41Sopenharmony_ci Object maybe_constructor = map().GetConstructor(); 22801cb0ef41Sopenharmony_ci if (!maybe_constructor.IsJSFunction()) return false; 22811cb0ef41Sopenharmony_ci if (!JSFunction::cast(maybe_constructor).shared().IsApiFunction()) { 22821cb0ef41Sopenharmony_ci return false; 22831cb0ef41Sopenharmony_ci } 22841cb0ef41Sopenharmony_ci Object instance_template = JSFunction::cast(maybe_constructor) 22851cb0ef41Sopenharmony_ci .shared() 22861cb0ef41Sopenharmony_ci .get_api_func_data() 22871cb0ef41Sopenharmony_ci .GetInstanceTemplate(); 22881cb0ef41Sopenharmony_ci if (instance_template.IsUndefined(isolate)) return false; 22891cb0ef41Sopenharmony_ci return ObjectTemplateInfo::cast(instance_template).code_like(); 22901cb0ef41Sopenharmony_ci} 22911cb0ef41Sopenharmony_ci 22921cb0ef41Sopenharmony_ci// static 22931cb0ef41Sopenharmony_ciMaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor, 22941cb0ef41Sopenharmony_ci Handle<JSReceiver> new_target, 22951cb0ef41Sopenharmony_ci Handle<AllocationSite> site) { 22961cb0ef41Sopenharmony_ci // If called through new, new.target can be: 22971cb0ef41Sopenharmony_ci // - a subclass of constructor, 22981cb0ef41Sopenharmony_ci // - a proxy wrapper around constructor, or 22991cb0ef41Sopenharmony_ci // - the constructor itself. 23001cb0ef41Sopenharmony_ci // If called through Reflect.construct, it's guaranteed to be a constructor. 23011cb0ef41Sopenharmony_ci Isolate* const isolate = constructor->GetIsolate(); 23021cb0ef41Sopenharmony_ci DCHECK(constructor->IsConstructor()); 23031cb0ef41Sopenharmony_ci DCHECK(new_target->IsConstructor()); 23041cb0ef41Sopenharmony_ci DCHECK(!constructor->has_initial_map() || 23051cb0ef41Sopenharmony_ci !InstanceTypeChecker::IsJSFunction( 23061cb0ef41Sopenharmony_ci constructor->initial_map().instance_type())); 23071cb0ef41Sopenharmony_ci 23081cb0ef41Sopenharmony_ci Handle<Map> initial_map; 23091cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 23101cb0ef41Sopenharmony_ci isolate, initial_map, 23111cb0ef41Sopenharmony_ci JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject); 23121cb0ef41Sopenharmony_ci int initial_capacity = V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL 23131cb0ef41Sopenharmony_ci ? SwissNameDictionary::kInitialCapacity 23141cb0ef41Sopenharmony_ci : NameDictionary::kInitialCapacity; 23151cb0ef41Sopenharmony_ci Handle<JSObject> result = isolate->factory()->NewFastOrSlowJSObjectFromMap( 23161cb0ef41Sopenharmony_ci initial_map, initial_capacity, AllocationType::kYoung, site); 23171cb0ef41Sopenharmony_ci isolate->counters()->constructed_objects()->Increment(); 23181cb0ef41Sopenharmony_ci isolate->counters()->constructed_objects_runtime()->Increment(); 23191cb0ef41Sopenharmony_ci return result; 23201cb0ef41Sopenharmony_ci} 23211cb0ef41Sopenharmony_ci 23221cb0ef41Sopenharmony_ci// 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] ) 23231cb0ef41Sopenharmony_ci// Notice: This is NOT 19.1.2.2 Object.create ( O, Properties ) 23241cb0ef41Sopenharmony_ciMaybeHandle<JSObject> JSObject::ObjectCreate(Isolate* isolate, 23251cb0ef41Sopenharmony_ci Handle<Object> prototype) { 23261cb0ef41Sopenharmony_ci // Generate the map with the specified {prototype} based on the Object 23271cb0ef41Sopenharmony_ci // function's initial map from the current native context. 23281cb0ef41Sopenharmony_ci // TODO(bmeurer): Use a dedicated cache for Object.create; think about 23291cb0ef41Sopenharmony_ci // slack tracking for Object.create. 23301cb0ef41Sopenharmony_ci Handle<Map> map = 23311cb0ef41Sopenharmony_ci Map::GetObjectCreateMap(isolate, Handle<HeapObject>::cast(prototype)); 23321cb0ef41Sopenharmony_ci 23331cb0ef41Sopenharmony_ci // Actually allocate the object. 23341cb0ef41Sopenharmony_ci return isolate->factory()->NewFastOrSlowJSObjectFromMap(map); 23351cb0ef41Sopenharmony_ci} 23361cb0ef41Sopenharmony_ci 23371cb0ef41Sopenharmony_civoid JSObject::EnsureWritableFastElements(Handle<JSObject> object) { 23381cb0ef41Sopenharmony_ci DCHECK(object->HasSmiOrObjectElements() || 23391cb0ef41Sopenharmony_ci object->HasFastStringWrapperElements() || 23401cb0ef41Sopenharmony_ci object->HasAnyNonextensibleElements()); 23411cb0ef41Sopenharmony_ci FixedArray raw_elems = FixedArray::cast(object->elements()); 23421cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 23431cb0ef41Sopenharmony_ci if (raw_elems.map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) return; 23441cb0ef41Sopenharmony_ci Handle<FixedArray> elems(raw_elems, isolate); 23451cb0ef41Sopenharmony_ci Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( 23461cb0ef41Sopenharmony_ci elems, isolate->factory()->fixed_array_map()); 23471cb0ef41Sopenharmony_ci object->set_elements(*writable_elems); 23481cb0ef41Sopenharmony_ci isolate->counters()->cow_arrays_converted()->Increment(); 23491cb0ef41Sopenharmony_ci} 23501cb0ef41Sopenharmony_ci 23511cb0ef41Sopenharmony_ciint JSObject::GetHeaderSize(InstanceType type, 23521cb0ef41Sopenharmony_ci bool function_has_prototype_slot) { 23531cb0ef41Sopenharmony_ci switch (type) { 23541cb0ef41Sopenharmony_ci case JS_API_OBJECT_TYPE: 23551cb0ef41Sopenharmony_ci case JS_ITERATOR_PROTOTYPE_TYPE: 23561cb0ef41Sopenharmony_ci case JS_MAP_ITERATOR_PROTOTYPE_TYPE: 23571cb0ef41Sopenharmony_ci case JS_OBJECT_PROTOTYPE_TYPE: 23581cb0ef41Sopenharmony_ci case JS_OBJECT_TYPE: 23591cb0ef41Sopenharmony_ci case JS_PROMISE_PROTOTYPE_TYPE: 23601cb0ef41Sopenharmony_ci case JS_REG_EXP_PROTOTYPE_TYPE: 23611cb0ef41Sopenharmony_ci case JS_SET_ITERATOR_PROTOTYPE_TYPE: 23621cb0ef41Sopenharmony_ci case JS_SET_PROTOTYPE_TYPE: 23631cb0ef41Sopenharmony_ci case JS_SPECIAL_API_OBJECT_TYPE: 23641cb0ef41Sopenharmony_ci case JS_STRING_ITERATOR_PROTOTYPE_TYPE: 23651cb0ef41Sopenharmony_ci case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE: 23661cb0ef41Sopenharmony_ci case JS_TYPED_ARRAY_PROTOTYPE_TYPE: 23671cb0ef41Sopenharmony_ci return JSObject::kHeaderSize; 23681cb0ef41Sopenharmony_ci case JS_GENERATOR_OBJECT_TYPE: 23691cb0ef41Sopenharmony_ci return JSGeneratorObject::kHeaderSize; 23701cb0ef41Sopenharmony_ci case JS_ASYNC_FUNCTION_OBJECT_TYPE: 23711cb0ef41Sopenharmony_ci return JSAsyncFunctionObject::kHeaderSize; 23721cb0ef41Sopenharmony_ci case JS_ASYNC_GENERATOR_OBJECT_TYPE: 23731cb0ef41Sopenharmony_ci return JSAsyncGeneratorObject::kHeaderSize; 23741cb0ef41Sopenharmony_ci case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE: 23751cb0ef41Sopenharmony_ci return JSAsyncFromSyncIterator::kHeaderSize; 23761cb0ef41Sopenharmony_ci case JS_GLOBAL_PROXY_TYPE: 23771cb0ef41Sopenharmony_ci return JSGlobalProxy::kHeaderSize; 23781cb0ef41Sopenharmony_ci case JS_GLOBAL_OBJECT_TYPE: 23791cb0ef41Sopenharmony_ci return JSGlobalObject::kHeaderSize; 23801cb0ef41Sopenharmony_ci case JS_BOUND_FUNCTION_TYPE: 23811cb0ef41Sopenharmony_ci return JSBoundFunction::kHeaderSize; 23821cb0ef41Sopenharmony_ci case JS_FUNCTION_TYPE: 23831cb0ef41Sopenharmony_ci case JS_CLASS_CONSTRUCTOR_TYPE: 23841cb0ef41Sopenharmony_ci case JS_PROMISE_CONSTRUCTOR_TYPE: 23851cb0ef41Sopenharmony_ci case JS_REG_EXP_CONSTRUCTOR_TYPE: 23861cb0ef41Sopenharmony_ci case JS_ARRAY_CONSTRUCTOR_TYPE: 23871cb0ef41Sopenharmony_ci#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \ 23881cb0ef41Sopenharmony_ci case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE: 23891cb0ef41Sopenharmony_ci TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH) 23901cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH 23911cb0ef41Sopenharmony_ci return JSFunction::GetHeaderSize(function_has_prototype_slot); 23921cb0ef41Sopenharmony_ci case JS_PRIMITIVE_WRAPPER_TYPE: 23931cb0ef41Sopenharmony_ci return JSPrimitiveWrapper::kHeaderSize; 23941cb0ef41Sopenharmony_ci case JS_DATE_TYPE: 23951cb0ef41Sopenharmony_ci return JSDate::kHeaderSize; 23961cb0ef41Sopenharmony_ci case JS_ARRAY_TYPE: 23971cb0ef41Sopenharmony_ci return JSArray::kHeaderSize; 23981cb0ef41Sopenharmony_ci case JS_ARRAY_BUFFER_TYPE: 23991cb0ef41Sopenharmony_ci return JSArrayBuffer::kHeaderSize; 24001cb0ef41Sopenharmony_ci case JS_ARRAY_ITERATOR_TYPE: 24011cb0ef41Sopenharmony_ci return JSArrayIterator::kHeaderSize; 24021cb0ef41Sopenharmony_ci case JS_TYPED_ARRAY_TYPE: 24031cb0ef41Sopenharmony_ci return JSTypedArray::kHeaderSize; 24041cb0ef41Sopenharmony_ci case JS_DATA_VIEW_TYPE: 24051cb0ef41Sopenharmony_ci return JSDataView::kHeaderSize; 24061cb0ef41Sopenharmony_ci case JS_SET_TYPE: 24071cb0ef41Sopenharmony_ci return JSSet::kHeaderSize; 24081cb0ef41Sopenharmony_ci case JS_MAP_TYPE: 24091cb0ef41Sopenharmony_ci return JSMap::kHeaderSize; 24101cb0ef41Sopenharmony_ci case JS_SET_KEY_VALUE_ITERATOR_TYPE: 24111cb0ef41Sopenharmony_ci case JS_SET_VALUE_ITERATOR_TYPE: 24121cb0ef41Sopenharmony_ci return JSSetIterator::kHeaderSize; 24131cb0ef41Sopenharmony_ci case JS_MAP_KEY_ITERATOR_TYPE: 24141cb0ef41Sopenharmony_ci case JS_MAP_KEY_VALUE_ITERATOR_TYPE: 24151cb0ef41Sopenharmony_ci case JS_MAP_VALUE_ITERATOR_TYPE: 24161cb0ef41Sopenharmony_ci return JSMapIterator::kHeaderSize; 24171cb0ef41Sopenharmony_ci case JS_WEAK_REF_TYPE: 24181cb0ef41Sopenharmony_ci return JSWeakRef::kHeaderSize; 24191cb0ef41Sopenharmony_ci case JS_FINALIZATION_REGISTRY_TYPE: 24201cb0ef41Sopenharmony_ci return JSFinalizationRegistry::kHeaderSize; 24211cb0ef41Sopenharmony_ci case JS_WEAK_MAP_TYPE: 24221cb0ef41Sopenharmony_ci return JSWeakMap::kHeaderSize; 24231cb0ef41Sopenharmony_ci case JS_WEAK_SET_TYPE: 24241cb0ef41Sopenharmony_ci return JSWeakSet::kHeaderSize; 24251cb0ef41Sopenharmony_ci case JS_PROMISE_TYPE: 24261cb0ef41Sopenharmony_ci return JSPromise::kHeaderSize; 24271cb0ef41Sopenharmony_ci case JS_REG_EXP_TYPE: 24281cb0ef41Sopenharmony_ci return JSRegExp::kHeaderSize; 24291cb0ef41Sopenharmony_ci case JS_REG_EXP_STRING_ITERATOR_TYPE: 24301cb0ef41Sopenharmony_ci return JSRegExpStringIterator::kHeaderSize; 24311cb0ef41Sopenharmony_ci case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 24321cb0ef41Sopenharmony_ci return JSObject::kHeaderSize; 24331cb0ef41Sopenharmony_ci case JS_MESSAGE_OBJECT_TYPE: 24341cb0ef41Sopenharmony_ci return JSMessageObject::kHeaderSize; 24351cb0ef41Sopenharmony_ci case JS_ARGUMENTS_OBJECT_TYPE: 24361cb0ef41Sopenharmony_ci return JSObject::kHeaderSize; 24371cb0ef41Sopenharmony_ci case JS_ERROR_TYPE: 24381cb0ef41Sopenharmony_ci return JSObject::kHeaderSize; 24391cb0ef41Sopenharmony_ci case JS_EXTERNAL_OBJECT_TYPE: 24401cb0ef41Sopenharmony_ci return JSExternalObject::kHeaderSize; 24411cb0ef41Sopenharmony_ci case JS_SHADOW_REALM_TYPE: 24421cb0ef41Sopenharmony_ci return JSShadowRealm::kHeaderSize; 24431cb0ef41Sopenharmony_ci case JS_STRING_ITERATOR_TYPE: 24441cb0ef41Sopenharmony_ci return JSStringIterator::kHeaderSize; 24451cb0ef41Sopenharmony_ci case JS_MODULE_NAMESPACE_TYPE: 24461cb0ef41Sopenharmony_ci return JSModuleNamespace::kHeaderSize; 24471cb0ef41Sopenharmony_ci case JS_SHARED_STRUCT_TYPE: 24481cb0ef41Sopenharmony_ci return JSSharedStruct::kHeaderSize; 24491cb0ef41Sopenharmony_ci case JS_TEMPORAL_CALENDAR_TYPE: 24501cb0ef41Sopenharmony_ci return JSTemporalCalendar::kHeaderSize; 24511cb0ef41Sopenharmony_ci case JS_TEMPORAL_DURATION_TYPE: 24521cb0ef41Sopenharmony_ci return JSTemporalDuration::kHeaderSize; 24531cb0ef41Sopenharmony_ci case JS_TEMPORAL_INSTANT_TYPE: 24541cb0ef41Sopenharmony_ci return JSTemporalInstant::kHeaderSize; 24551cb0ef41Sopenharmony_ci case JS_TEMPORAL_PLAIN_DATE_TYPE: 24561cb0ef41Sopenharmony_ci return JSTemporalPlainDate::kHeaderSize; 24571cb0ef41Sopenharmony_ci case JS_TEMPORAL_PLAIN_DATE_TIME_TYPE: 24581cb0ef41Sopenharmony_ci return JSTemporalPlainDateTime::kHeaderSize; 24591cb0ef41Sopenharmony_ci case JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE: 24601cb0ef41Sopenharmony_ci return JSTemporalPlainMonthDay::kHeaderSize; 24611cb0ef41Sopenharmony_ci case JS_TEMPORAL_PLAIN_TIME_TYPE: 24621cb0ef41Sopenharmony_ci return JSTemporalPlainTime::kHeaderSize; 24631cb0ef41Sopenharmony_ci case JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE: 24641cb0ef41Sopenharmony_ci return JSTemporalPlainYearMonth::kHeaderSize; 24651cb0ef41Sopenharmony_ci case JS_TEMPORAL_TIME_ZONE_TYPE: 24661cb0ef41Sopenharmony_ci return JSTemporalTimeZone::kHeaderSize; 24671cb0ef41Sopenharmony_ci case JS_TEMPORAL_ZONED_DATE_TIME_TYPE: 24681cb0ef41Sopenharmony_ci return JSTemporalZonedDateTime::kHeaderSize; 24691cb0ef41Sopenharmony_ci case JS_WRAPPED_FUNCTION_TYPE: 24701cb0ef41Sopenharmony_ci return JSWrappedFunction::kHeaderSize; 24711cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT 24721cb0ef41Sopenharmony_ci case JS_V8_BREAK_ITERATOR_TYPE: 24731cb0ef41Sopenharmony_ci return JSV8BreakIterator::kHeaderSize; 24741cb0ef41Sopenharmony_ci case JS_COLLATOR_TYPE: 24751cb0ef41Sopenharmony_ci return JSCollator::kHeaderSize; 24761cb0ef41Sopenharmony_ci case JS_DATE_TIME_FORMAT_TYPE: 24771cb0ef41Sopenharmony_ci return JSDateTimeFormat::kHeaderSize; 24781cb0ef41Sopenharmony_ci case JS_DISPLAY_NAMES_TYPE: 24791cb0ef41Sopenharmony_ci return JSDisplayNames::kHeaderSize; 24801cb0ef41Sopenharmony_ci case JS_LIST_FORMAT_TYPE: 24811cb0ef41Sopenharmony_ci return JSListFormat::kHeaderSize; 24821cb0ef41Sopenharmony_ci case JS_LOCALE_TYPE: 24831cb0ef41Sopenharmony_ci return JSLocale::kHeaderSize; 24841cb0ef41Sopenharmony_ci case JS_NUMBER_FORMAT_TYPE: 24851cb0ef41Sopenharmony_ci return JSNumberFormat::kHeaderSize; 24861cb0ef41Sopenharmony_ci case JS_PLURAL_RULES_TYPE: 24871cb0ef41Sopenharmony_ci return JSPluralRules::kHeaderSize; 24881cb0ef41Sopenharmony_ci case JS_RELATIVE_TIME_FORMAT_TYPE: 24891cb0ef41Sopenharmony_ci return JSRelativeTimeFormat::kHeaderSize; 24901cb0ef41Sopenharmony_ci case JS_SEGMENT_ITERATOR_TYPE: 24911cb0ef41Sopenharmony_ci return JSSegmentIterator::kHeaderSize; 24921cb0ef41Sopenharmony_ci case JS_SEGMENTER_TYPE: 24931cb0ef41Sopenharmony_ci return JSSegmenter::kHeaderSize; 24941cb0ef41Sopenharmony_ci case JS_SEGMENTS_TYPE: 24951cb0ef41Sopenharmony_ci return JSSegments::kHeaderSize; 24961cb0ef41Sopenharmony_ci#endif // V8_INTL_SUPPORT 24971cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 24981cb0ef41Sopenharmony_ci case WASM_GLOBAL_OBJECT_TYPE: 24991cb0ef41Sopenharmony_ci return WasmGlobalObject::kHeaderSize; 25001cb0ef41Sopenharmony_ci case WASM_INSTANCE_OBJECT_TYPE: 25011cb0ef41Sopenharmony_ci return WasmInstanceObject::kHeaderSize; 25021cb0ef41Sopenharmony_ci case WASM_MEMORY_OBJECT_TYPE: 25031cb0ef41Sopenharmony_ci return WasmMemoryObject::kHeaderSize; 25041cb0ef41Sopenharmony_ci case WASM_MODULE_OBJECT_TYPE: 25051cb0ef41Sopenharmony_ci return WasmModuleObject::kHeaderSize; 25061cb0ef41Sopenharmony_ci case WASM_SUSPENDER_OBJECT_TYPE: 25071cb0ef41Sopenharmony_ci return WasmSuspenderObject::kHeaderSize; 25081cb0ef41Sopenharmony_ci case WASM_TABLE_OBJECT_TYPE: 25091cb0ef41Sopenharmony_ci return WasmTableObject::kHeaderSize; 25101cb0ef41Sopenharmony_ci case WASM_VALUE_OBJECT_TYPE: 25111cb0ef41Sopenharmony_ci return WasmValueObject::kHeaderSize; 25121cb0ef41Sopenharmony_ci case WASM_TAG_OBJECT_TYPE: 25131cb0ef41Sopenharmony_ci return WasmTagObject::kHeaderSize; 25141cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 25151cb0ef41Sopenharmony_ci default: { 25161cb0ef41Sopenharmony_ci // Special type check for API Objects because they are in a large variable 25171cb0ef41Sopenharmony_ci // instance type range. 25181cb0ef41Sopenharmony_ci if (InstanceTypeChecker::IsJSApiObject(type)) { 25191cb0ef41Sopenharmony_ci return JSObject::kHeaderSize; 25201cb0ef41Sopenharmony_ci } 25211cb0ef41Sopenharmony_ci std::stringstream ss; 25221cb0ef41Sopenharmony_ci ss << type; 25231cb0ef41Sopenharmony_ci FATAL("unexpected instance type: %s\n", ss.str().c_str()); 25241cb0ef41Sopenharmony_ci } 25251cb0ef41Sopenharmony_ci } 25261cb0ef41Sopenharmony_ci} 25271cb0ef41Sopenharmony_ci 25281cb0ef41Sopenharmony_ci// static 25291cb0ef41Sopenharmony_cibool JSObject::AllCanRead(LookupIterator* it) { 25301cb0ef41Sopenharmony_ci // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of 25311cb0ef41Sopenharmony_ci // which have already been checked. 25321cb0ef41Sopenharmony_ci DCHECK(it->state() == LookupIterator::ACCESS_CHECK || 25331cb0ef41Sopenharmony_ci it->state() == LookupIterator::INTERCEPTOR); 25341cb0ef41Sopenharmony_ci for (it->Next(); it->IsFound(); it->Next()) { 25351cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::ACCESSOR) { 25361cb0ef41Sopenharmony_ci auto accessors = it->GetAccessors(); 25371cb0ef41Sopenharmony_ci if (accessors->IsAccessorInfo()) { 25381cb0ef41Sopenharmony_ci if (AccessorInfo::cast(*accessors).all_can_read()) return true; 25391cb0ef41Sopenharmony_ci } 25401cb0ef41Sopenharmony_ci } else if (it->state() == LookupIterator::INTERCEPTOR) { 25411cb0ef41Sopenharmony_ci if (it->GetInterceptor()->all_can_read()) return true; 25421cb0ef41Sopenharmony_ci } else if (it->state() == LookupIterator::JSPROXY) { 25431cb0ef41Sopenharmony_ci // Stop lookupiterating. And no, AllCanNotRead. 25441cb0ef41Sopenharmony_ci return false; 25451cb0ef41Sopenharmony_ci } 25461cb0ef41Sopenharmony_ci } 25471cb0ef41Sopenharmony_ci return false; 25481cb0ef41Sopenharmony_ci} 25491cb0ef41Sopenharmony_ci 25501cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck( 25511cb0ef41Sopenharmony_ci LookupIterator* it) { 25521cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 25531cb0ef41Sopenharmony_ci Handle<JSObject> checked = it->GetHolder<JSObject>(); 25541cb0ef41Sopenharmony_ci Handle<InterceptorInfo> interceptor = 25551cb0ef41Sopenharmony_ci it->GetInterceptorForFailedAccessCheck(); 25561cb0ef41Sopenharmony_ci if (interceptor.is_null()) { 25571cb0ef41Sopenharmony_ci while (AllCanRead(it)) { 25581cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::ACCESSOR) { 25591cb0ef41Sopenharmony_ci return Object::GetPropertyWithAccessor(it); 25601cb0ef41Sopenharmony_ci } 25611cb0ef41Sopenharmony_ci DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); 25621cb0ef41Sopenharmony_ci bool done; 25631cb0ef41Sopenharmony_ci Handle<Object> result; 25641cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION(isolate, result, 25651cb0ef41Sopenharmony_ci GetPropertyWithInterceptor(it, &done), Object); 25661cb0ef41Sopenharmony_ci if (done) return result; 25671cb0ef41Sopenharmony_ci } 25681cb0ef41Sopenharmony_ci 25691cb0ef41Sopenharmony_ci } else { 25701cb0ef41Sopenharmony_ci Handle<Object> result; 25711cb0ef41Sopenharmony_ci bool done; 25721cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 25731cb0ef41Sopenharmony_ci isolate, result, 25741cb0ef41Sopenharmony_ci GetPropertyWithInterceptorInternal(it, interceptor, &done), Object); 25751cb0ef41Sopenharmony_ci if (done) return result; 25761cb0ef41Sopenharmony_ci } 25771cb0ef41Sopenharmony_ci 25781cb0ef41Sopenharmony_ci // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns 25791cb0ef41Sopenharmony_ci // undefined. 25801cb0ef41Sopenharmony_ci Handle<Name> name = it->GetName(); 25811cb0ef41Sopenharmony_ci if (name->IsSymbol() && Symbol::cast(*name).is_well_known_symbol()) { 25821cb0ef41Sopenharmony_ci return it->factory()->undefined_value(); 25831cb0ef41Sopenharmony_ci } 25841cb0ef41Sopenharmony_ci 25851cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(checked); 25861cb0ef41Sopenharmony_ci RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 25871cb0ef41Sopenharmony_ci return it->factory()->undefined_value(); 25881cb0ef41Sopenharmony_ci} 25891cb0ef41Sopenharmony_ci 25901cb0ef41Sopenharmony_ciMaybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck( 25911cb0ef41Sopenharmony_ci LookupIterator* it) { 25921cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 25931cb0ef41Sopenharmony_ci Handle<JSObject> checked = it->GetHolder<JSObject>(); 25941cb0ef41Sopenharmony_ci Handle<InterceptorInfo> interceptor = 25951cb0ef41Sopenharmony_ci it->GetInterceptorForFailedAccessCheck(); 25961cb0ef41Sopenharmony_ci if (interceptor.is_null()) { 25971cb0ef41Sopenharmony_ci while (AllCanRead(it)) { 25981cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::ACCESSOR) { 25991cb0ef41Sopenharmony_ci return Just(it->property_attributes()); 26001cb0ef41Sopenharmony_ci } 26011cb0ef41Sopenharmony_ci DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); 26021cb0ef41Sopenharmony_ci auto result = GetPropertyAttributesWithInterceptor(it); 26031cb0ef41Sopenharmony_ci if (isolate->has_scheduled_exception()) break; 26041cb0ef41Sopenharmony_ci if (result.IsJust() && result.FromJust() != ABSENT) return result; 26051cb0ef41Sopenharmony_ci } 26061cb0ef41Sopenharmony_ci } else { 26071cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> result = 26081cb0ef41Sopenharmony_ci GetPropertyAttributesWithInterceptorInternal(it, interceptor); 26091cb0ef41Sopenharmony_ci if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>(); 26101cb0ef41Sopenharmony_ci if (result.FromMaybe(ABSENT) != ABSENT) return result; 26111cb0ef41Sopenharmony_ci } 26121cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(checked); 26131cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>()); 26141cb0ef41Sopenharmony_ci return Just(ABSENT); 26151cb0ef41Sopenharmony_ci} 26161cb0ef41Sopenharmony_ci 26171cb0ef41Sopenharmony_ci// static 26181cb0ef41Sopenharmony_cibool JSObject::AllCanWrite(LookupIterator* it) { 26191cb0ef41Sopenharmony_ci for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) { 26201cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::ACCESSOR) { 26211cb0ef41Sopenharmony_ci Handle<Object> accessors = it->GetAccessors(); 26221cb0ef41Sopenharmony_ci if (accessors->IsAccessorInfo()) { 26231cb0ef41Sopenharmony_ci if (AccessorInfo::cast(*accessors).all_can_write()) return true; 26241cb0ef41Sopenharmony_ci } 26251cb0ef41Sopenharmony_ci } 26261cb0ef41Sopenharmony_ci } 26271cb0ef41Sopenharmony_ci return false; 26281cb0ef41Sopenharmony_ci} 26291cb0ef41Sopenharmony_ci 26301cb0ef41Sopenharmony_ciMaybe<bool> JSObject::SetPropertyWithFailedAccessCheck( 26311cb0ef41Sopenharmony_ci LookupIterator* it, Handle<Object> value, Maybe<ShouldThrow> should_throw) { 26321cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 26331cb0ef41Sopenharmony_ci Handle<JSObject> checked = it->GetHolder<JSObject>(); 26341cb0ef41Sopenharmony_ci Handle<InterceptorInfo> interceptor = 26351cb0ef41Sopenharmony_ci it->GetInterceptorForFailedAccessCheck(); 26361cb0ef41Sopenharmony_ci if (interceptor.is_null()) { 26371cb0ef41Sopenharmony_ci if (AllCanWrite(it)) { 26381cb0ef41Sopenharmony_ci return Object::SetPropertyWithAccessor(it, value, should_throw); 26391cb0ef41Sopenharmony_ci } 26401cb0ef41Sopenharmony_ci } else { 26411cb0ef41Sopenharmony_ci Maybe<bool> result = SetPropertyWithInterceptorInternal( 26421cb0ef41Sopenharmony_ci it, interceptor, should_throw, value); 26431cb0ef41Sopenharmony_ci if (isolate->has_pending_exception()) return Nothing<bool>(); 26441cb0ef41Sopenharmony_ci if (result.IsJust()) return result; 26451cb0ef41Sopenharmony_ci } 26461cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(checked); 26471cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 26481cb0ef41Sopenharmony_ci return Just(true); 26491cb0ef41Sopenharmony_ci} 26501cb0ef41Sopenharmony_ci 26511cb0ef41Sopenharmony_civoid JSObject::SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name, 26521cb0ef41Sopenharmony_ci Handle<Object> value, 26531cb0ef41Sopenharmony_ci PropertyDetails details) { 26541cb0ef41Sopenharmony_ci DCHECK(!object->HasFastProperties()); 26551cb0ef41Sopenharmony_ci DCHECK(name->IsUniqueName()); 26561cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 26571cb0ef41Sopenharmony_ci 26581cb0ef41Sopenharmony_ci uint32_t hash = name->hash(); 26591cb0ef41Sopenharmony_ci 26601cb0ef41Sopenharmony_ci if (object->IsJSGlobalObject()) { 26611cb0ef41Sopenharmony_ci Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(object); 26621cb0ef41Sopenharmony_ci Handle<GlobalDictionary> dictionary( 26631cb0ef41Sopenharmony_ci global_obj->global_dictionary(kAcquireLoad), isolate); 26641cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 26651cb0ef41Sopenharmony_ci InternalIndex entry = dictionary->FindEntry(isolate, roots, name, hash); 26661cb0ef41Sopenharmony_ci 26671cb0ef41Sopenharmony_ci if (entry.is_not_found()) { 26681cb0ef41Sopenharmony_ci DCHECK_IMPLIES(global_obj->map().is_prototype_map(), 26691cb0ef41Sopenharmony_ci Map::IsPrototypeChainInvalidated(global_obj->map())); 26701cb0ef41Sopenharmony_ci auto cell_type = value->IsUndefined(roots) ? PropertyCellType::kUndefined 26711cb0ef41Sopenharmony_ci : PropertyCellType::kConstant; 26721cb0ef41Sopenharmony_ci details = details.set_cell_type(cell_type); 26731cb0ef41Sopenharmony_ci auto cell = isolate->factory()->NewPropertyCell(name, details, value); 26741cb0ef41Sopenharmony_ci dictionary = 26751cb0ef41Sopenharmony_ci GlobalDictionary::Add(isolate, dictionary, name, cell, details); 26761cb0ef41Sopenharmony_ci global_obj->set_global_dictionary(*dictionary, kReleaseStore); 26771cb0ef41Sopenharmony_ci } else { 26781cb0ef41Sopenharmony_ci PropertyCell::PrepareForAndSetValue(isolate, dictionary, entry, value, 26791cb0ef41Sopenharmony_ci details); 26801cb0ef41Sopenharmony_ci DCHECK_EQ(dictionary->CellAt(entry).value(), *value); 26811cb0ef41Sopenharmony_ci } 26821cb0ef41Sopenharmony_ci } else { 26831cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 26841cb0ef41Sopenharmony_ci Handle<SwissNameDictionary> dictionary( 26851cb0ef41Sopenharmony_ci object->property_dictionary_swiss(), isolate); 26861cb0ef41Sopenharmony_ci InternalIndex entry = dictionary->FindEntry(isolate, *name); 26871cb0ef41Sopenharmony_ci if (entry.is_not_found()) { 26881cb0ef41Sopenharmony_ci DCHECK_IMPLIES(object->map().is_prototype_map(), 26891cb0ef41Sopenharmony_ci Map::IsPrototypeChainInvalidated(object->map())); 26901cb0ef41Sopenharmony_ci dictionary = 26911cb0ef41Sopenharmony_ci SwissNameDictionary::Add(isolate, dictionary, name, value, details); 26921cb0ef41Sopenharmony_ci object->SetProperties(*dictionary); 26931cb0ef41Sopenharmony_ci } else { 26941cb0ef41Sopenharmony_ci dictionary->ValueAtPut(entry, *value); 26951cb0ef41Sopenharmony_ci dictionary->DetailsAtPut(entry, details); 26961cb0ef41Sopenharmony_ci } 26971cb0ef41Sopenharmony_ci } else { 26981cb0ef41Sopenharmony_ci Handle<NameDictionary> dictionary(object->property_dictionary(), isolate); 26991cb0ef41Sopenharmony_ci InternalIndex entry = dictionary->FindEntry(isolate, name); 27001cb0ef41Sopenharmony_ci if (entry.is_not_found()) { 27011cb0ef41Sopenharmony_ci DCHECK_IMPLIES(object->map().is_prototype_map(), 27021cb0ef41Sopenharmony_ci Map::IsPrototypeChainInvalidated(object->map())); 27031cb0ef41Sopenharmony_ci dictionary = 27041cb0ef41Sopenharmony_ci NameDictionary::Add(isolate, dictionary, name, value, details); 27051cb0ef41Sopenharmony_ci object->SetProperties(*dictionary); 27061cb0ef41Sopenharmony_ci } else { 27071cb0ef41Sopenharmony_ci PropertyDetails original_details = dictionary->DetailsAt(entry); 27081cb0ef41Sopenharmony_ci int enumeration_index = original_details.dictionary_index(); 27091cb0ef41Sopenharmony_ci DCHECK_GT(enumeration_index, 0); 27101cb0ef41Sopenharmony_ci details = details.set_index(enumeration_index); 27111cb0ef41Sopenharmony_ci dictionary->SetEntry(entry, *name, *value, details); 27121cb0ef41Sopenharmony_ci } 27131cb0ef41Sopenharmony_ci } 27141cb0ef41Sopenharmony_ci } 27151cb0ef41Sopenharmony_ci} 27161cb0ef41Sopenharmony_ci 27171cb0ef41Sopenharmony_civoid JSObject::SetNormalizedElement(Handle<JSObject> object, uint32_t index, 27181cb0ef41Sopenharmony_ci Handle<Object> value, 27191cb0ef41Sopenharmony_ci PropertyDetails details) { 27201cb0ef41Sopenharmony_ci DCHECK_EQ(object->GetElementsKind(), DICTIONARY_ELEMENTS); 27211cb0ef41Sopenharmony_ci 27221cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 27231cb0ef41Sopenharmony_ci 27241cb0ef41Sopenharmony_ci Handle<NumberDictionary> dictionary = 27251cb0ef41Sopenharmony_ci handle(NumberDictionary::cast(object->elements()), isolate); 27261cb0ef41Sopenharmony_ci dictionary = 27271cb0ef41Sopenharmony_ci NumberDictionary::Set(isolate, dictionary, index, value, object, details); 27281cb0ef41Sopenharmony_ci object->set_elements(*dictionary); 27291cb0ef41Sopenharmony_ci} 27301cb0ef41Sopenharmony_ci 27311cb0ef41Sopenharmony_civoid JSObject::JSObjectShortPrint(StringStream* accumulator) { 27321cb0ef41Sopenharmony_ci switch (map().instance_type()) { 27331cb0ef41Sopenharmony_ci case JS_ARRAY_TYPE: { 27341cb0ef41Sopenharmony_ci double length = JSArray::cast(*this).length().IsUndefined() 27351cb0ef41Sopenharmony_ci ? 0 27361cb0ef41Sopenharmony_ci : JSArray::cast(*this).length().Number(); 27371cb0ef41Sopenharmony_ci accumulator->Add("<JSArray[%u]>", static_cast<uint32_t>(length)); 27381cb0ef41Sopenharmony_ci break; 27391cb0ef41Sopenharmony_ci } 27401cb0ef41Sopenharmony_ci case JS_BOUND_FUNCTION_TYPE: { 27411cb0ef41Sopenharmony_ci JSBoundFunction bound_function = JSBoundFunction::cast(*this); 27421cb0ef41Sopenharmony_ci accumulator->Add("<JSBoundFunction"); 27431cb0ef41Sopenharmony_ci accumulator->Add(" (BoundTargetFunction %p)>", 27441cb0ef41Sopenharmony_ci reinterpret_cast<void*>( 27451cb0ef41Sopenharmony_ci bound_function.bound_target_function().ptr())); 27461cb0ef41Sopenharmony_ci break; 27471cb0ef41Sopenharmony_ci } 27481cb0ef41Sopenharmony_ci case JS_WEAK_MAP_TYPE: { 27491cb0ef41Sopenharmony_ci accumulator->Add("<JSWeakMap>"); 27501cb0ef41Sopenharmony_ci break; 27511cb0ef41Sopenharmony_ci } 27521cb0ef41Sopenharmony_ci case JS_WEAK_SET_TYPE: { 27531cb0ef41Sopenharmony_ci accumulator->Add("<JSWeakSet>"); 27541cb0ef41Sopenharmony_ci break; 27551cb0ef41Sopenharmony_ci } 27561cb0ef41Sopenharmony_ci case JS_REG_EXP_TYPE: { 27571cb0ef41Sopenharmony_ci accumulator->Add("<JSRegExp"); 27581cb0ef41Sopenharmony_ci JSRegExp regexp = JSRegExp::cast(*this); 27591cb0ef41Sopenharmony_ci if (regexp.source().IsString()) { 27601cb0ef41Sopenharmony_ci accumulator->Add(" "); 27611cb0ef41Sopenharmony_ci String::cast(regexp.source()).StringShortPrint(accumulator); 27621cb0ef41Sopenharmony_ci } 27631cb0ef41Sopenharmony_ci accumulator->Add(">"); 27641cb0ef41Sopenharmony_ci 27651cb0ef41Sopenharmony_ci break; 27661cb0ef41Sopenharmony_ci } 27671cb0ef41Sopenharmony_ci case JS_PROMISE_CONSTRUCTOR_TYPE: 27681cb0ef41Sopenharmony_ci case JS_REG_EXP_CONSTRUCTOR_TYPE: 27691cb0ef41Sopenharmony_ci case JS_ARRAY_CONSTRUCTOR_TYPE: 27701cb0ef41Sopenharmony_ci#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \ 27711cb0ef41Sopenharmony_ci case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE: 27721cb0ef41Sopenharmony_ci TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH) 27731cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH 27741cb0ef41Sopenharmony_ci case JS_CLASS_CONSTRUCTOR_TYPE: 27751cb0ef41Sopenharmony_ci case JS_FUNCTION_TYPE: { 27761cb0ef41Sopenharmony_ci JSFunction function = JSFunction::cast(*this); 27771cb0ef41Sopenharmony_ci std::unique_ptr<char[]> fun_name = function.shared().DebugNameCStr(); 27781cb0ef41Sopenharmony_ci if (fun_name[0] != '\0') { 27791cb0ef41Sopenharmony_ci accumulator->Add("<JSFunction "); 27801cb0ef41Sopenharmony_ci accumulator->Add(fun_name.get()); 27811cb0ef41Sopenharmony_ci } else { 27821cb0ef41Sopenharmony_ci accumulator->Add("<JSFunction"); 27831cb0ef41Sopenharmony_ci } 27841cb0ef41Sopenharmony_ci if (FLAG_trace_file_names) { 27851cb0ef41Sopenharmony_ci Object source_name = Script::cast(function.shared().script()).name(); 27861cb0ef41Sopenharmony_ci if (source_name.IsString()) { 27871cb0ef41Sopenharmony_ci String str = String::cast(source_name); 27881cb0ef41Sopenharmony_ci if (str.length() > 0) { 27891cb0ef41Sopenharmony_ci accumulator->Add(" <"); 27901cb0ef41Sopenharmony_ci accumulator->Put(str); 27911cb0ef41Sopenharmony_ci accumulator->Add(">"); 27921cb0ef41Sopenharmony_ci } 27931cb0ef41Sopenharmony_ci } 27941cb0ef41Sopenharmony_ci } 27951cb0ef41Sopenharmony_ci accumulator->Add(" (sfi = %p)", 27961cb0ef41Sopenharmony_ci reinterpret_cast<void*>(function.shared().ptr())); 27971cb0ef41Sopenharmony_ci accumulator->Put('>'); 27981cb0ef41Sopenharmony_ci break; 27991cb0ef41Sopenharmony_ci } 28001cb0ef41Sopenharmony_ci case JS_GENERATOR_OBJECT_TYPE: { 28011cb0ef41Sopenharmony_ci accumulator->Add("<JSGenerator>"); 28021cb0ef41Sopenharmony_ci break; 28031cb0ef41Sopenharmony_ci } 28041cb0ef41Sopenharmony_ci case JS_ASYNC_FUNCTION_OBJECT_TYPE: { 28051cb0ef41Sopenharmony_ci accumulator->Add("<JSAsyncFunctionObject>"); 28061cb0ef41Sopenharmony_ci break; 28071cb0ef41Sopenharmony_ci } 28081cb0ef41Sopenharmony_ci case JS_ASYNC_GENERATOR_OBJECT_TYPE: { 28091cb0ef41Sopenharmony_ci accumulator->Add("<JS AsyncGenerator>"); 28101cb0ef41Sopenharmony_ci break; 28111cb0ef41Sopenharmony_ci } 28121cb0ef41Sopenharmony_ci 28131cb0ef41Sopenharmony_ci // All other JSObjects are rather similar to each other (JSObject, 28141cb0ef41Sopenharmony_ci // JSGlobalProxy, JSGlobalObject, JSUndetectable, JSPrimitiveWrapper). 28151cb0ef41Sopenharmony_ci default: { 28161cb0ef41Sopenharmony_ci Map map_of_this = map(); 28171cb0ef41Sopenharmony_ci Heap* heap = GetHeap(); 28181cb0ef41Sopenharmony_ci Object constructor = map_of_this.GetConstructor(); 28191cb0ef41Sopenharmony_ci bool printed = false; 28201cb0ef41Sopenharmony_ci if (constructor.IsHeapObject() && 28211cb0ef41Sopenharmony_ci !heap->Contains(HeapObject::cast(constructor))) { 28221cb0ef41Sopenharmony_ci accumulator->Add("!!!INVALID CONSTRUCTOR!!!"); 28231cb0ef41Sopenharmony_ci } else { 28241cb0ef41Sopenharmony_ci bool is_global_proxy = IsJSGlobalProxy(); 28251cb0ef41Sopenharmony_ci if (constructor.IsJSFunction()) { 28261cb0ef41Sopenharmony_ci if (!heap->Contains(JSFunction::cast(constructor).shared())) { 28271cb0ef41Sopenharmony_ci accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!"); 28281cb0ef41Sopenharmony_ci } else { 28291cb0ef41Sopenharmony_ci String constructor_name = 28301cb0ef41Sopenharmony_ci JSFunction::cast(constructor).shared().Name(); 28311cb0ef41Sopenharmony_ci if (constructor_name.length() > 0) { 28321cb0ef41Sopenharmony_ci accumulator->Add(is_global_proxy ? "<GlobalObject " : "<"); 28331cb0ef41Sopenharmony_ci accumulator->Put(constructor_name); 28341cb0ef41Sopenharmony_ci accumulator->Add(" %smap = %p", 28351cb0ef41Sopenharmony_ci map_of_this.is_deprecated() ? "deprecated-" : "", 28361cb0ef41Sopenharmony_ci map_of_this); 28371cb0ef41Sopenharmony_ci printed = true; 28381cb0ef41Sopenharmony_ci } 28391cb0ef41Sopenharmony_ci } 28401cb0ef41Sopenharmony_ci } else if (constructor.IsFunctionTemplateInfo()) { 28411cb0ef41Sopenharmony_ci accumulator->Add("<RemoteObject>"); 28421cb0ef41Sopenharmony_ci printed = true; 28431cb0ef41Sopenharmony_ci } 28441cb0ef41Sopenharmony_ci if (!printed) { 28451cb0ef41Sopenharmony_ci accumulator->Add("<JS"); 28461cb0ef41Sopenharmony_ci if (is_global_proxy) { 28471cb0ef41Sopenharmony_ci accumulator->Add("GlobalProxy"); 28481cb0ef41Sopenharmony_ci } else if (IsJSGlobalObject()) { 28491cb0ef41Sopenharmony_ci accumulator->Add("GlobalObject"); 28501cb0ef41Sopenharmony_ci } else { 28511cb0ef41Sopenharmony_ci accumulator->Add("Object"); 28521cb0ef41Sopenharmony_ci } 28531cb0ef41Sopenharmony_ci } 28541cb0ef41Sopenharmony_ci } 28551cb0ef41Sopenharmony_ci if (IsJSPrimitiveWrapper()) { 28561cb0ef41Sopenharmony_ci accumulator->Add(" value = "); 28571cb0ef41Sopenharmony_ci JSPrimitiveWrapper::cast(*this).value().ShortPrint(accumulator); 28581cb0ef41Sopenharmony_ci } 28591cb0ef41Sopenharmony_ci accumulator->Put('>'); 28601cb0ef41Sopenharmony_ci break; 28611cb0ef41Sopenharmony_ci } 28621cb0ef41Sopenharmony_ci } 28631cb0ef41Sopenharmony_ci} 28641cb0ef41Sopenharmony_ci 28651cb0ef41Sopenharmony_civoid JSObject::PrintElementsTransition(FILE* file, Handle<JSObject> object, 28661cb0ef41Sopenharmony_ci ElementsKind from_kind, 28671cb0ef41Sopenharmony_ci Handle<FixedArrayBase> from_elements, 28681cb0ef41Sopenharmony_ci ElementsKind to_kind, 28691cb0ef41Sopenharmony_ci Handle<FixedArrayBase> to_elements) { 28701cb0ef41Sopenharmony_ci if (from_kind != to_kind) { 28711cb0ef41Sopenharmony_ci OFStream os(file); 28721cb0ef41Sopenharmony_ci os << "elements transition [" << ElementsKindToString(from_kind) << " -> " 28731cb0ef41Sopenharmony_ci << ElementsKindToString(to_kind) << "] in "; 28741cb0ef41Sopenharmony_ci JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true); 28751cb0ef41Sopenharmony_ci PrintF(file, " for "); 28761cb0ef41Sopenharmony_ci object->ShortPrint(file); 28771cb0ef41Sopenharmony_ci PrintF(file, " from "); 28781cb0ef41Sopenharmony_ci from_elements->ShortPrint(file); 28791cb0ef41Sopenharmony_ci PrintF(file, " to "); 28801cb0ef41Sopenharmony_ci to_elements->ShortPrint(file); 28811cb0ef41Sopenharmony_ci PrintF(file, "\n"); 28821cb0ef41Sopenharmony_ci } 28831cb0ef41Sopenharmony_ci} 28841cb0ef41Sopenharmony_ci 28851cb0ef41Sopenharmony_civoid JSObject::PrintInstanceMigration(FILE* file, Map original_map, 28861cb0ef41Sopenharmony_ci Map new_map) { 28871cb0ef41Sopenharmony_ci if (new_map.is_dictionary_map()) { 28881cb0ef41Sopenharmony_ci PrintF(file, "[migrating to slow]\n"); 28891cb0ef41Sopenharmony_ci return; 28901cb0ef41Sopenharmony_ci } 28911cb0ef41Sopenharmony_ci PrintF(file, "[migrating]"); 28921cb0ef41Sopenharmony_ci Isolate* isolate = GetIsolate(); 28931cb0ef41Sopenharmony_ci DescriptorArray o = original_map.instance_descriptors(isolate); 28941cb0ef41Sopenharmony_ci DescriptorArray n = new_map.instance_descriptors(isolate); 28951cb0ef41Sopenharmony_ci for (InternalIndex i : original_map.IterateOwnDescriptors()) { 28961cb0ef41Sopenharmony_ci Representation o_r = o.GetDetails(i).representation(); 28971cb0ef41Sopenharmony_ci Representation n_r = n.GetDetails(i).representation(); 28981cb0ef41Sopenharmony_ci if (!o_r.Equals(n_r)) { 28991cb0ef41Sopenharmony_ci String::cast(o.GetKey(i)).PrintOn(file); 29001cb0ef41Sopenharmony_ci PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic()); 29011cb0ef41Sopenharmony_ci } else if (o.GetDetails(i).location() == PropertyLocation::kDescriptor && 29021cb0ef41Sopenharmony_ci n.GetDetails(i).location() == PropertyLocation::kField) { 29031cb0ef41Sopenharmony_ci Name name = o.GetKey(i); 29041cb0ef41Sopenharmony_ci if (name.IsString()) { 29051cb0ef41Sopenharmony_ci String::cast(name).PrintOn(file); 29061cb0ef41Sopenharmony_ci } else { 29071cb0ef41Sopenharmony_ci PrintF(file, "{symbol %p}", reinterpret_cast<void*>(name.ptr())); 29081cb0ef41Sopenharmony_ci } 29091cb0ef41Sopenharmony_ci PrintF(file, " "); 29101cb0ef41Sopenharmony_ci } 29111cb0ef41Sopenharmony_ci } 29121cb0ef41Sopenharmony_ci if (original_map.elements_kind() != new_map.elements_kind()) { 29131cb0ef41Sopenharmony_ci PrintF(file, "elements_kind[%i->%i]", original_map.elements_kind(), 29141cb0ef41Sopenharmony_ci new_map.elements_kind()); 29151cb0ef41Sopenharmony_ci } 29161cb0ef41Sopenharmony_ci PrintF(file, "\n"); 29171cb0ef41Sopenharmony_ci} 29181cb0ef41Sopenharmony_ci 29191cb0ef41Sopenharmony_cibool JSObject::IsUnmodifiedApiObject(FullObjectSlot o) { 29201cb0ef41Sopenharmony_ci Object object = *o; 29211cb0ef41Sopenharmony_ci if (object.IsSmi()) return false; 29221cb0ef41Sopenharmony_ci HeapObject heap_object = HeapObject::cast(object); 29231cb0ef41Sopenharmony_ci if (!object.IsJSObject()) return false; 29241cb0ef41Sopenharmony_ci JSObject js_object = JSObject::cast(object); 29251cb0ef41Sopenharmony_ci if (!js_object.IsDroppableApiObject()) return false; 29261cb0ef41Sopenharmony_ci Object maybe_constructor = js_object.map().GetConstructor(); 29271cb0ef41Sopenharmony_ci if (!maybe_constructor.IsJSFunction()) return false; 29281cb0ef41Sopenharmony_ci JSFunction constructor = JSFunction::cast(maybe_constructor); 29291cb0ef41Sopenharmony_ci if (js_object.elements().length() != 0) return false; 29301cb0ef41Sopenharmony_ci // Check that the object is not a key in a WeakMap (over-approximation). 29311cb0ef41Sopenharmony_ci if (!js_object.GetIdentityHash().IsUndefined()) return false; 29321cb0ef41Sopenharmony_ci 29331cb0ef41Sopenharmony_ci return constructor.initial_map() == heap_object.map(); 29341cb0ef41Sopenharmony_ci} 29351cb0ef41Sopenharmony_ci 29361cb0ef41Sopenharmony_ci// static 29371cb0ef41Sopenharmony_civoid JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map, 29381cb0ef41Sopenharmony_ci Handle<Map> new_map, 29391cb0ef41Sopenharmony_ci Isolate* isolate) { 29401cb0ef41Sopenharmony_ci DCHECK(old_map->is_prototype_map()); 29411cb0ef41Sopenharmony_ci DCHECK(new_map->is_prototype_map()); 29421cb0ef41Sopenharmony_ci bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); 29431cb0ef41Sopenharmony_ci new_map->set_prototype_info(old_map->prototype_info(), kReleaseStore); 29441cb0ef41Sopenharmony_ci old_map->set_prototype_info(Smi::zero(), kReleaseStore); 29451cb0ef41Sopenharmony_ci if (FLAG_trace_prototype_users) { 29461cb0ef41Sopenharmony_ci PrintF("Moving prototype_info %p from map %p to map %p.\n", 29471cb0ef41Sopenharmony_ci reinterpret_cast<void*>(new_map->prototype_info().ptr()), 29481cb0ef41Sopenharmony_ci reinterpret_cast<void*>(old_map->ptr()), 29491cb0ef41Sopenharmony_ci reinterpret_cast<void*>(new_map->ptr())); 29501cb0ef41Sopenharmony_ci } 29511cb0ef41Sopenharmony_ci if (was_registered) { 29521cb0ef41Sopenharmony_ci if (new_map->prototype_info().IsPrototypeInfo()) { 29531cb0ef41Sopenharmony_ci // The new map isn't registered with its prototype yet; reflect this fact 29541cb0ef41Sopenharmony_ci // in the PrototypeInfo it just inherited from the old map. 29551cb0ef41Sopenharmony_ci PrototypeInfo::cast(new_map->prototype_info()) 29561cb0ef41Sopenharmony_ci .set_registry_slot(PrototypeInfo::UNREGISTERED); 29571cb0ef41Sopenharmony_ci } 29581cb0ef41Sopenharmony_ci JSObject::LazyRegisterPrototypeUser(new_map, isolate); 29591cb0ef41Sopenharmony_ci } 29601cb0ef41Sopenharmony_ci} 29611cb0ef41Sopenharmony_ci 29621cb0ef41Sopenharmony_ci// static 29631cb0ef41Sopenharmony_civoid JSObject::NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map, 29641cb0ef41Sopenharmony_ci Isolate* isolate) { 29651cb0ef41Sopenharmony_ci if (!old_map->is_prototype_map()) return; 29661cb0ef41Sopenharmony_ci 29671cb0ef41Sopenharmony_ci InvalidatePrototypeChains(*old_map); 29681cb0ef41Sopenharmony_ci 29691cb0ef41Sopenharmony_ci // If the map was registered with its prototype before, ensure that it 29701cb0ef41Sopenharmony_ci // registers with its new prototype now. This preserves the invariant that 29711cb0ef41Sopenharmony_ci // when a map on a prototype chain is registered with its prototype, then 29721cb0ef41Sopenharmony_ci // all prototypes further up the chain are also registered with their 29731cb0ef41Sopenharmony_ci // respective prototypes. 29741cb0ef41Sopenharmony_ci UpdatePrototypeUserRegistration(old_map, new_map, isolate); 29751cb0ef41Sopenharmony_ci} 29761cb0ef41Sopenharmony_ci 29771cb0ef41Sopenharmony_cinamespace { 29781cb0ef41Sopenharmony_ci 29791cb0ef41Sopenharmony_ci// To migrate a fast instance to a fast map: 29801cb0ef41Sopenharmony_ci// - First check whether the instance needs to be rewritten. If not, simply 29811cb0ef41Sopenharmony_ci// change the map. 29821cb0ef41Sopenharmony_ci// - Otherwise, allocate a fixed array large enough to hold all fields, in 29831cb0ef41Sopenharmony_ci// addition to unused space. 29841cb0ef41Sopenharmony_ci// - Copy all existing properties in, in the following order: backing store 29851cb0ef41Sopenharmony_ci// properties, unused fields, inobject properties. 29861cb0ef41Sopenharmony_ci// - If all allocation succeeded, commit the state atomically: 29871cb0ef41Sopenharmony_ci// * Copy inobject properties from the backing store back into the object. 29881cb0ef41Sopenharmony_ci// * Trim the difference in instance size of the object. This also cleanly 29891cb0ef41Sopenharmony_ci// frees inobject properties that moved to the backing store. 29901cb0ef41Sopenharmony_ci// * If there are properties left in the backing store, trim of the space used 29911cb0ef41Sopenharmony_ci// to temporarily store the inobject properties. 29921cb0ef41Sopenharmony_ci// * If there are properties left in the backing store, install the backing 29931cb0ef41Sopenharmony_ci// store. 29941cb0ef41Sopenharmony_civoid MigrateFastToFast(Isolate* isolate, Handle<JSObject> object, 29951cb0ef41Sopenharmony_ci Handle<Map> new_map) { 29961cb0ef41Sopenharmony_ci Handle<Map> old_map(object->map(), isolate); 29971cb0ef41Sopenharmony_ci // In case of a regular transition. 29981cb0ef41Sopenharmony_ci if (new_map->GetBackPointer(isolate) == *old_map) { 29991cb0ef41Sopenharmony_ci // If the map does not add named properties, simply set the map. 30001cb0ef41Sopenharmony_ci if (old_map->NumberOfOwnDescriptors() == 30011cb0ef41Sopenharmony_ci new_map->NumberOfOwnDescriptors()) { 30021cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 30031cb0ef41Sopenharmony_ci return; 30041cb0ef41Sopenharmony_ci } 30051cb0ef41Sopenharmony_ci 30061cb0ef41Sopenharmony_ci // If the map adds a new kDescriptor property, simply set the map. 30071cb0ef41Sopenharmony_ci PropertyDetails details = new_map->GetLastDescriptorDetails(isolate); 30081cb0ef41Sopenharmony_ci if (details.location() == PropertyLocation::kDescriptor) { 30091cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 30101cb0ef41Sopenharmony_ci return; 30111cb0ef41Sopenharmony_ci } 30121cb0ef41Sopenharmony_ci 30131cb0ef41Sopenharmony_ci // Check if we still have space in the {object}, in which case we 30141cb0ef41Sopenharmony_ci // can also simply set the map (modulo a special case for mutable 30151cb0ef41Sopenharmony_ci // double boxes). 30161cb0ef41Sopenharmony_ci FieldIndex index = 30171cb0ef41Sopenharmony_ci FieldIndex::ForDescriptor(isolate, *new_map, new_map->LastAdded()); 30181cb0ef41Sopenharmony_ci if (index.is_inobject() || index.outobject_array_index() < 30191cb0ef41Sopenharmony_ci object->property_array(isolate).length()) { 30201cb0ef41Sopenharmony_ci // Allocate HeapNumbers for double fields. 30211cb0ef41Sopenharmony_ci if (index.is_double()) { 30221cb0ef41Sopenharmony_ci auto value = isolate->factory()->NewHeapNumberWithHoleNaN(); 30231cb0ef41Sopenharmony_ci object->FastPropertyAtPut(index, *value); 30241cb0ef41Sopenharmony_ci } 30251cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 30261cb0ef41Sopenharmony_ci return; 30271cb0ef41Sopenharmony_ci } 30281cb0ef41Sopenharmony_ci 30291cb0ef41Sopenharmony_ci // This migration is a transition from a map that has run out of property 30301cb0ef41Sopenharmony_ci // space. Extend the backing store. 30311cb0ef41Sopenharmony_ci int grow_by = new_map->UnusedPropertyFields() + 1; 30321cb0ef41Sopenharmony_ci Handle<PropertyArray> old_storage(object->property_array(isolate), isolate); 30331cb0ef41Sopenharmony_ci Handle<PropertyArray> new_storage = 30341cb0ef41Sopenharmony_ci isolate->factory()->CopyPropertyArrayAndGrow(old_storage, grow_by); 30351cb0ef41Sopenharmony_ci 30361cb0ef41Sopenharmony_ci // Properly initialize newly added property. 30371cb0ef41Sopenharmony_ci Handle<Object> value; 30381cb0ef41Sopenharmony_ci if (details.representation().IsDouble()) { 30391cb0ef41Sopenharmony_ci value = isolate->factory()->NewHeapNumberWithHoleNaN(); 30401cb0ef41Sopenharmony_ci } else { 30411cb0ef41Sopenharmony_ci value = isolate->factory()->uninitialized_value(); 30421cb0ef41Sopenharmony_ci } 30431cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyLocation::kField, details.location()); 30441cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyKind::kData, details.kind()); 30451cb0ef41Sopenharmony_ci DCHECK(!index.is_inobject()); // Must be a backing store index. 30461cb0ef41Sopenharmony_ci new_storage->set(index.outobject_array_index(), *value); 30471cb0ef41Sopenharmony_ci 30481cb0ef41Sopenharmony_ci // From here on we cannot fail and we shouldn't GC anymore. 30491cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 30501cb0ef41Sopenharmony_ci 30511cb0ef41Sopenharmony_ci // Set the new property value and do the map transition. 30521cb0ef41Sopenharmony_ci object->SetProperties(*new_storage); 30531cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 30541cb0ef41Sopenharmony_ci return; 30551cb0ef41Sopenharmony_ci } 30561cb0ef41Sopenharmony_ci 30571cb0ef41Sopenharmony_ci int old_number_of_fields; 30581cb0ef41Sopenharmony_ci int number_of_fields = new_map->NumberOfFields(ConcurrencyMode::kSynchronous); 30591cb0ef41Sopenharmony_ci int inobject = new_map->GetInObjectProperties(); 30601cb0ef41Sopenharmony_ci int unused = new_map->UnusedPropertyFields(); 30611cb0ef41Sopenharmony_ci 30621cb0ef41Sopenharmony_ci // Nothing to do if no functions were converted to fields and no smis were 30631cb0ef41Sopenharmony_ci // converted to doubles. 30641cb0ef41Sopenharmony_ci if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject, 30651cb0ef41Sopenharmony_ci unused, &old_number_of_fields, 30661cb0ef41Sopenharmony_ci ConcurrencyMode::kSynchronous)) { 30671cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 30681cb0ef41Sopenharmony_ci return; 30691cb0ef41Sopenharmony_ci } 30701cb0ef41Sopenharmony_ci 30711cb0ef41Sopenharmony_ci int total_size = number_of_fields + unused; 30721cb0ef41Sopenharmony_ci int external = total_size - inobject; 30731cb0ef41Sopenharmony_ci Handle<PropertyArray> array = isolate->factory()->NewPropertyArray(external); 30741cb0ef41Sopenharmony_ci 30751cb0ef41Sopenharmony_ci // We use this array to temporarily store the inobject properties. 30761cb0ef41Sopenharmony_ci Handle<FixedArray> inobject_props = 30771cb0ef41Sopenharmony_ci isolate->factory()->NewFixedArray(inobject); 30781cb0ef41Sopenharmony_ci 30791cb0ef41Sopenharmony_ci Handle<DescriptorArray> old_descriptors( 30801cb0ef41Sopenharmony_ci old_map->instance_descriptors(isolate), isolate); 30811cb0ef41Sopenharmony_ci Handle<DescriptorArray> new_descriptors( 30821cb0ef41Sopenharmony_ci new_map->instance_descriptors(isolate), isolate); 30831cb0ef41Sopenharmony_ci int old_nof = old_map->NumberOfOwnDescriptors(); 30841cb0ef41Sopenharmony_ci int new_nof = new_map->NumberOfOwnDescriptors(); 30851cb0ef41Sopenharmony_ci 30861cb0ef41Sopenharmony_ci // This method only supports generalizing instances to at least the same 30871cb0ef41Sopenharmony_ci // number of properties. 30881cb0ef41Sopenharmony_ci DCHECK(old_nof <= new_nof); 30891cb0ef41Sopenharmony_ci 30901cb0ef41Sopenharmony_ci for (InternalIndex i : InternalIndex::Range(old_nof)) { 30911cb0ef41Sopenharmony_ci PropertyDetails details = new_descriptors->GetDetails(i); 30921cb0ef41Sopenharmony_ci if (details.location() != PropertyLocation::kField) continue; 30931cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyKind::kData, details.kind()); 30941cb0ef41Sopenharmony_ci PropertyDetails old_details = old_descriptors->GetDetails(i); 30951cb0ef41Sopenharmony_ci Representation old_representation = old_details.representation(); 30961cb0ef41Sopenharmony_ci Representation representation = details.representation(); 30971cb0ef41Sopenharmony_ci Handle<Object> value; 30981cb0ef41Sopenharmony_ci if (old_details.location() == PropertyLocation::kDescriptor) { 30991cb0ef41Sopenharmony_ci if (old_details.kind() == PropertyKind::kAccessor) { 31001cb0ef41Sopenharmony_ci // In case of kAccessor -> kData property reconfiguration, the property 31011cb0ef41Sopenharmony_ci // must already be prepared for data of certain type. 31021cb0ef41Sopenharmony_ci DCHECK(!details.representation().IsNone()); 31031cb0ef41Sopenharmony_ci if (details.representation().IsDouble()) { 31041cb0ef41Sopenharmony_ci value = isolate->factory()->NewHeapNumberWithHoleNaN(); 31051cb0ef41Sopenharmony_ci } else { 31061cb0ef41Sopenharmony_ci value = isolate->factory()->uninitialized_value(); 31071cb0ef41Sopenharmony_ci } 31081cb0ef41Sopenharmony_ci } else { 31091cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyKind::kData, old_details.kind()); 31101cb0ef41Sopenharmony_ci value = handle(old_descriptors->GetStrongValue(isolate, i), isolate); 31111cb0ef41Sopenharmony_ci DCHECK(!old_representation.IsDouble() && !representation.IsDouble()); 31121cb0ef41Sopenharmony_ci } 31131cb0ef41Sopenharmony_ci } else { 31141cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyLocation::kField, old_details.location()); 31151cb0ef41Sopenharmony_ci FieldIndex index = FieldIndex::ForDescriptor(isolate, *old_map, i); 31161cb0ef41Sopenharmony_ci value = handle(object->RawFastPropertyAt(isolate, index), isolate); 31171cb0ef41Sopenharmony_ci if (!old_representation.IsDouble() && representation.IsDouble()) { 31181cb0ef41Sopenharmony_ci DCHECK_IMPLIES(old_representation.IsNone(), 31191cb0ef41Sopenharmony_ci value->IsUninitialized(isolate)); 31201cb0ef41Sopenharmony_ci value = Object::NewStorageFor(isolate, value, representation); 31211cb0ef41Sopenharmony_ci } else if (old_representation.IsDouble() && !representation.IsDouble()) { 31221cb0ef41Sopenharmony_ci value = Object::WrapForRead(isolate, value, old_representation); 31231cb0ef41Sopenharmony_ci } 31241cb0ef41Sopenharmony_ci } 31251cb0ef41Sopenharmony_ci DCHECK(!(representation.IsDouble() && value->IsSmi())); 31261cb0ef41Sopenharmony_ci int target_index = new_descriptors->GetFieldIndex(i); 31271cb0ef41Sopenharmony_ci if (target_index < inobject) { 31281cb0ef41Sopenharmony_ci inobject_props->set(target_index, *value); 31291cb0ef41Sopenharmony_ci } else { 31301cb0ef41Sopenharmony_ci array->set(target_index - inobject, *value); 31311cb0ef41Sopenharmony_ci } 31321cb0ef41Sopenharmony_ci } 31331cb0ef41Sopenharmony_ci 31341cb0ef41Sopenharmony_ci for (InternalIndex i : InternalIndex::Range(old_nof, new_nof)) { 31351cb0ef41Sopenharmony_ci PropertyDetails details = new_descriptors->GetDetails(i); 31361cb0ef41Sopenharmony_ci if (details.location() != PropertyLocation::kField) continue; 31371cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyKind::kData, details.kind()); 31381cb0ef41Sopenharmony_ci Handle<Object> value; 31391cb0ef41Sopenharmony_ci if (details.representation().IsDouble()) { 31401cb0ef41Sopenharmony_ci value = isolate->factory()->NewHeapNumberWithHoleNaN(); 31411cb0ef41Sopenharmony_ci } else { 31421cb0ef41Sopenharmony_ci value = isolate->factory()->uninitialized_value(); 31431cb0ef41Sopenharmony_ci } 31441cb0ef41Sopenharmony_ci int target_index = new_descriptors->GetFieldIndex(i); 31451cb0ef41Sopenharmony_ci if (target_index < inobject) { 31461cb0ef41Sopenharmony_ci inobject_props->set(target_index, *value); 31471cb0ef41Sopenharmony_ci } else { 31481cb0ef41Sopenharmony_ci array->set(target_index - inobject, *value); 31491cb0ef41Sopenharmony_ci } 31501cb0ef41Sopenharmony_ci } 31511cb0ef41Sopenharmony_ci 31521cb0ef41Sopenharmony_ci // From here on we cannot fail and we shouldn't GC anymore. 31531cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 31541cb0ef41Sopenharmony_ci 31551cb0ef41Sopenharmony_ci Heap* heap = isolate->heap(); 31561cb0ef41Sopenharmony_ci 31571cb0ef41Sopenharmony_ci // Copy (real) inobject properties. If necessary, stop at number_of_fields to 31581cb0ef41Sopenharmony_ci // avoid overwriting |one_pointer_filler_map|. 31591cb0ef41Sopenharmony_ci int limit = std::min(inobject, number_of_fields); 31601cb0ef41Sopenharmony_ci for (int i = 0; i < limit; i++) { 31611cb0ef41Sopenharmony_ci FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); 31621cb0ef41Sopenharmony_ci Object value = inobject_props->get(isolate, i); 31631cb0ef41Sopenharmony_ci object->FastPropertyAtPut(index, value); 31641cb0ef41Sopenharmony_ci } 31651cb0ef41Sopenharmony_ci 31661cb0ef41Sopenharmony_ci object->SetProperties(*array); 31671cb0ef41Sopenharmony_ci 31681cb0ef41Sopenharmony_ci // Create filler object past the new instance size. 31691cb0ef41Sopenharmony_ci int old_instance_size = old_map->instance_size(); 31701cb0ef41Sopenharmony_ci int new_instance_size = new_map->instance_size(); 31711cb0ef41Sopenharmony_ci int instance_size_delta = old_instance_size - new_instance_size; 31721cb0ef41Sopenharmony_ci DCHECK_GE(instance_size_delta, 0); 31731cb0ef41Sopenharmony_ci 31741cb0ef41Sopenharmony_ci if (instance_size_delta > 0) { 31751cb0ef41Sopenharmony_ci Address address = object->address(); 31761cb0ef41Sopenharmony_ci heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta, 31771cb0ef41Sopenharmony_ci ClearRecordedSlots::kYes); 31781cb0ef41Sopenharmony_ci } 31791cb0ef41Sopenharmony_ci 31801cb0ef41Sopenharmony_ci // We are storing the new map using release store after creating a filler for 31811cb0ef41Sopenharmony_ci // the left-over space to avoid races with the sweeper thread. 31821cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 31831cb0ef41Sopenharmony_ci} 31841cb0ef41Sopenharmony_ci 31851cb0ef41Sopenharmony_civoid MigrateFastToSlow(Isolate* isolate, Handle<JSObject> object, 31861cb0ef41Sopenharmony_ci Handle<Map> new_map, 31871cb0ef41Sopenharmony_ci int expected_additional_properties) { 31881cb0ef41Sopenharmony_ci // The global object is always normalized. 31891cb0ef41Sopenharmony_ci DCHECK(!object->IsJSGlobalObject(isolate)); 31901cb0ef41Sopenharmony_ci // JSGlobalProxy must never be normalized 31911cb0ef41Sopenharmony_ci DCHECK(!object->IsJSGlobalProxy(isolate)); 31921cb0ef41Sopenharmony_ci 31931cb0ef41Sopenharmony_ci DCHECK_IMPLIES(new_map->is_prototype_map(), 31941cb0ef41Sopenharmony_ci Map::IsPrototypeChainInvalidated(*new_map)); 31951cb0ef41Sopenharmony_ci 31961cb0ef41Sopenharmony_ci HandleScope scope(isolate); 31971cb0ef41Sopenharmony_ci Handle<Map> map(object->map(isolate), isolate); 31981cb0ef41Sopenharmony_ci 31991cb0ef41Sopenharmony_ci // Allocate new content. 32001cb0ef41Sopenharmony_ci int real_size = map->NumberOfOwnDescriptors(); 32011cb0ef41Sopenharmony_ci int property_count = real_size; 32021cb0ef41Sopenharmony_ci if (expected_additional_properties > 0) { 32031cb0ef41Sopenharmony_ci property_count += expected_additional_properties; 32041cb0ef41Sopenharmony_ci } else { 32051cb0ef41Sopenharmony_ci // Make space for two more properties. 32061cb0ef41Sopenharmony_ci int initial_capacity = V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL 32071cb0ef41Sopenharmony_ci ? SwissNameDictionary::kInitialCapacity 32081cb0ef41Sopenharmony_ci : NameDictionary::kInitialCapacity; 32091cb0ef41Sopenharmony_ci property_count += initial_capacity; 32101cb0ef41Sopenharmony_ci } 32111cb0ef41Sopenharmony_ci 32121cb0ef41Sopenharmony_ci Handle<NameDictionary> dictionary; 32131cb0ef41Sopenharmony_ci Handle<SwissNameDictionary> ord_dictionary; 32141cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 32151cb0ef41Sopenharmony_ci ord_dictionary = isolate->factory()->NewSwissNameDictionary(property_count); 32161cb0ef41Sopenharmony_ci } else { 32171cb0ef41Sopenharmony_ci dictionary = isolate->factory()->NewNameDictionary(property_count); 32181cb0ef41Sopenharmony_ci } 32191cb0ef41Sopenharmony_ci 32201cb0ef41Sopenharmony_ci Handle<DescriptorArray> descs(map->instance_descriptors(isolate), isolate); 32211cb0ef41Sopenharmony_ci for (InternalIndex i : InternalIndex::Range(real_size)) { 32221cb0ef41Sopenharmony_ci PropertyDetails details = descs->GetDetails(i); 32231cb0ef41Sopenharmony_ci Handle<Name> key(descs->GetKey(isolate, i), isolate); 32241cb0ef41Sopenharmony_ci Handle<Object> value; 32251cb0ef41Sopenharmony_ci if (details.location() == PropertyLocation::kField) { 32261cb0ef41Sopenharmony_ci FieldIndex index = FieldIndex::ForDescriptor(isolate, *map, i); 32271cb0ef41Sopenharmony_ci if (details.kind() == PropertyKind::kData) { 32281cb0ef41Sopenharmony_ci value = handle(object->RawFastPropertyAt(isolate, index), isolate); 32291cb0ef41Sopenharmony_ci if (details.representation().IsDouble()) { 32301cb0ef41Sopenharmony_ci DCHECK(value->IsHeapNumber(isolate)); 32311cb0ef41Sopenharmony_ci double old_value = Handle<HeapNumber>::cast(value)->value(); 32321cb0ef41Sopenharmony_ci value = isolate->factory()->NewHeapNumber(old_value); 32331cb0ef41Sopenharmony_ci } 32341cb0ef41Sopenharmony_ci } else { 32351cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyKind::kAccessor, details.kind()); 32361cb0ef41Sopenharmony_ci value = handle(object->RawFastPropertyAt(isolate, index), isolate); 32371cb0ef41Sopenharmony_ci } 32381cb0ef41Sopenharmony_ci 32391cb0ef41Sopenharmony_ci } else { 32401cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyLocation::kDescriptor, details.location()); 32411cb0ef41Sopenharmony_ci value = handle(descs->GetStrongValue(isolate, i), isolate); 32421cb0ef41Sopenharmony_ci } 32431cb0ef41Sopenharmony_ci DCHECK(!value.is_null()); 32441cb0ef41Sopenharmony_ci PropertyConstness constness = V8_DICT_PROPERTY_CONST_TRACKING_BOOL 32451cb0ef41Sopenharmony_ci ? details.constness() 32461cb0ef41Sopenharmony_ci : PropertyConstness::kMutable; 32471cb0ef41Sopenharmony_ci PropertyDetails d(details.kind(), details.attributes(), constness); 32481cb0ef41Sopenharmony_ci 32491cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 32501cb0ef41Sopenharmony_ci ord_dictionary = 32511cb0ef41Sopenharmony_ci SwissNameDictionary::Add(isolate, ord_dictionary, key, value, d); 32521cb0ef41Sopenharmony_ci } else { 32531cb0ef41Sopenharmony_ci dictionary = NameDictionary::Add(isolate, dictionary, key, value, d); 32541cb0ef41Sopenharmony_ci } 32551cb0ef41Sopenharmony_ci } 32561cb0ef41Sopenharmony_ci 32571cb0ef41Sopenharmony_ci if (!V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 32581cb0ef41Sopenharmony_ci // Copy the next enumeration index from instance descriptor. 32591cb0ef41Sopenharmony_ci dictionary->set_next_enumeration_index(real_size + 1); 32601cb0ef41Sopenharmony_ci } 32611cb0ef41Sopenharmony_ci 32621cb0ef41Sopenharmony_ci // From here on we cannot fail and we shouldn't GC anymore. 32631cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 32641cb0ef41Sopenharmony_ci 32651cb0ef41Sopenharmony_ci Heap* heap = isolate->heap(); 32661cb0ef41Sopenharmony_ci 32671cb0ef41Sopenharmony_ci // Resize the object in the heap if necessary. 32681cb0ef41Sopenharmony_ci int old_instance_size = map->instance_size(); 32691cb0ef41Sopenharmony_ci int new_instance_size = new_map->instance_size(); 32701cb0ef41Sopenharmony_ci int instance_size_delta = old_instance_size - new_instance_size; 32711cb0ef41Sopenharmony_ci DCHECK_GE(instance_size_delta, 0); 32721cb0ef41Sopenharmony_ci 32731cb0ef41Sopenharmony_ci if (instance_size_delta > 0) { 32741cb0ef41Sopenharmony_ci heap->CreateFillerObjectAt(object->address() + new_instance_size, 32751cb0ef41Sopenharmony_ci instance_size_delta, ClearRecordedSlots::kYes); 32761cb0ef41Sopenharmony_ci } 32771cb0ef41Sopenharmony_ci 32781cb0ef41Sopenharmony_ci // We are storing the new map using release store after creating a filler for 32791cb0ef41Sopenharmony_ci // the left-over space to avoid races with the sweeper thread. 32801cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 32811cb0ef41Sopenharmony_ci 32821cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 32831cb0ef41Sopenharmony_ci object->SetProperties(*ord_dictionary); 32841cb0ef41Sopenharmony_ci } else { 32851cb0ef41Sopenharmony_ci object->SetProperties(*dictionary); 32861cb0ef41Sopenharmony_ci } 32871cb0ef41Sopenharmony_ci 32881cb0ef41Sopenharmony_ci // Ensure that in-object space of slow-mode object does not contain random 32891cb0ef41Sopenharmony_ci // garbage. 32901cb0ef41Sopenharmony_ci int inobject_properties = new_map->GetInObjectProperties(); 32911cb0ef41Sopenharmony_ci if (inobject_properties) { 32921cb0ef41Sopenharmony_ci for (int i = 0; i < inobject_properties; i++) { 32931cb0ef41Sopenharmony_ci FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); 32941cb0ef41Sopenharmony_ci object->FastPropertyAtPut(index, Smi::zero()); 32951cb0ef41Sopenharmony_ci } 32961cb0ef41Sopenharmony_ci } 32971cb0ef41Sopenharmony_ci 32981cb0ef41Sopenharmony_ci isolate->counters()->props_to_dictionary()->Increment(); 32991cb0ef41Sopenharmony_ci 33001cb0ef41Sopenharmony_ci#ifdef DEBUG 33011cb0ef41Sopenharmony_ci if (FLAG_trace_normalization) { 33021cb0ef41Sopenharmony_ci StdoutStream os; 33031cb0ef41Sopenharmony_ci os << "Object properties have been normalized:\n"; 33041cb0ef41Sopenharmony_ci object->Print(os); 33051cb0ef41Sopenharmony_ci } 33061cb0ef41Sopenharmony_ci#endif 33071cb0ef41Sopenharmony_ci} 33081cb0ef41Sopenharmony_ci 33091cb0ef41Sopenharmony_ci} // namespace 33101cb0ef41Sopenharmony_ci 33111cb0ef41Sopenharmony_civoid JSObject::MigrateToMap(Isolate* isolate, Handle<JSObject> object, 33121cb0ef41Sopenharmony_ci Handle<Map> new_map, 33131cb0ef41Sopenharmony_ci int expected_additional_properties) { 33141cb0ef41Sopenharmony_ci if (object->map(isolate) == *new_map) return; 33151cb0ef41Sopenharmony_ci Handle<Map> old_map(object->map(isolate), isolate); 33161cb0ef41Sopenharmony_ci NotifyMapChange(old_map, new_map, isolate); 33171cb0ef41Sopenharmony_ci 33181cb0ef41Sopenharmony_ci if (old_map->is_dictionary_map()) { 33191cb0ef41Sopenharmony_ci // For slow-to-fast migrations JSObject::MigrateSlowToFast() 33201cb0ef41Sopenharmony_ci // must be used instead. 33211cb0ef41Sopenharmony_ci CHECK(new_map->is_dictionary_map()); 33221cb0ef41Sopenharmony_ci 33231cb0ef41Sopenharmony_ci // Slow-to-slow migration is trivial. 33241cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 33251cb0ef41Sopenharmony_ci } else if (!new_map->is_dictionary_map()) { 33261cb0ef41Sopenharmony_ci MigrateFastToFast(isolate, object, new_map); 33271cb0ef41Sopenharmony_ci if (old_map->is_prototype_map()) { 33281cb0ef41Sopenharmony_ci DCHECK(!old_map->is_stable()); 33291cb0ef41Sopenharmony_ci DCHECK(new_map->is_stable()); 33301cb0ef41Sopenharmony_ci DCHECK(new_map->owns_descriptors()); 33311cb0ef41Sopenharmony_ci DCHECK(old_map->owns_descriptors()); 33321cb0ef41Sopenharmony_ci // Transfer ownership to the new map. Keep the descriptor pointer of the 33331cb0ef41Sopenharmony_ci // old map intact because the concurrent marker might be iterating the 33341cb0ef41Sopenharmony_ci // object with the old map. 33351cb0ef41Sopenharmony_ci old_map->set_owns_descriptors(false); 33361cb0ef41Sopenharmony_ci DCHECK(old_map->is_abandoned_prototype_map()); 33371cb0ef41Sopenharmony_ci // Ensure that no transition was inserted for prototype migrations. 33381cb0ef41Sopenharmony_ci DCHECK_EQ(0, 33391cb0ef41Sopenharmony_ci TransitionsAccessor(isolate, *old_map).NumberOfTransitions()); 33401cb0ef41Sopenharmony_ci DCHECK(new_map->GetBackPointer(isolate).IsUndefined(isolate)); 33411cb0ef41Sopenharmony_ci DCHECK(object->map(isolate) != *old_map); 33421cb0ef41Sopenharmony_ci } 33431cb0ef41Sopenharmony_ci } else { 33441cb0ef41Sopenharmony_ci MigrateFastToSlow(isolate, object, new_map, expected_additional_properties); 33451cb0ef41Sopenharmony_ci } 33461cb0ef41Sopenharmony_ci 33471cb0ef41Sopenharmony_ci // Careful: Don't allocate here! 33481cb0ef41Sopenharmony_ci // For some callers of this method, |object| might be in an inconsistent 33491cb0ef41Sopenharmony_ci // state now: the new map might have a new elements_kind, but the object's 33501cb0ef41Sopenharmony_ci // elements pointer hasn't been updated yet. Callers will fix this, but in 33511cb0ef41Sopenharmony_ci // the meantime, (indirectly) calling JSObjectVerify() must be avoided. 33521cb0ef41Sopenharmony_ci // When adding code here, add a DisallowGarbageCollection too. 33531cb0ef41Sopenharmony_ci} 33541cb0ef41Sopenharmony_ci 33551cb0ef41Sopenharmony_civoid JSObject::ForceSetPrototype(Isolate* isolate, Handle<JSObject> object, 33561cb0ef41Sopenharmony_ci Handle<HeapObject> proto) { 33571cb0ef41Sopenharmony_ci // object.__proto__ = proto; 33581cb0ef41Sopenharmony_ci Handle<Map> old_map = Handle<Map>(object->map(), isolate); 33591cb0ef41Sopenharmony_ci Handle<Map> new_map = Map::Copy(isolate, old_map, "ForceSetPrototype"); 33601cb0ef41Sopenharmony_ci Map::SetPrototype(isolate, new_map, proto); 33611cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map); 33621cb0ef41Sopenharmony_ci} 33631cb0ef41Sopenharmony_ci 33641cb0ef41Sopenharmony_ciMaybe<bool> JSObject::SetPropertyWithInterceptor( 33651cb0ef41Sopenharmony_ci LookupIterator* it, Maybe<ShouldThrow> should_throw, Handle<Object> value) { 33661cb0ef41Sopenharmony_ci DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); 33671cb0ef41Sopenharmony_ci return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(), 33681cb0ef41Sopenharmony_ci should_throw, value); 33691cb0ef41Sopenharmony_ci} 33701cb0ef41Sopenharmony_ci 33711cb0ef41Sopenharmony_ciHandle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, 33721cb0ef41Sopenharmony_ci ElementsKind to_kind) { 33731cb0ef41Sopenharmony_ci Handle<Map> map(object->map(), object->GetIsolate()); 33741cb0ef41Sopenharmony_ci return Map::TransitionElementsTo(object->GetIsolate(), map, to_kind); 33751cb0ef41Sopenharmony_ci} 33761cb0ef41Sopenharmony_ci 33771cb0ef41Sopenharmony_civoid JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { 33781cb0ef41Sopenharmony_ci DCHECK(object->map().GetInObjectProperties() == map->GetInObjectProperties()); 33791cb0ef41Sopenharmony_ci ElementsKind obj_kind = object->map().elements_kind(); 33801cb0ef41Sopenharmony_ci ElementsKind map_kind = map->elements_kind(); 33811cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 33821cb0ef41Sopenharmony_ci if (map_kind != obj_kind) { 33831cb0ef41Sopenharmony_ci ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind); 33841cb0ef41Sopenharmony_ci if (IsDictionaryElementsKind(obj_kind)) { 33851cb0ef41Sopenharmony_ci to_kind = obj_kind; 33861cb0ef41Sopenharmony_ci } 33871cb0ef41Sopenharmony_ci if (IsDictionaryElementsKind(to_kind)) { 33881cb0ef41Sopenharmony_ci NormalizeElements(object); 33891cb0ef41Sopenharmony_ci } else { 33901cb0ef41Sopenharmony_ci TransitionElementsKind(object, to_kind); 33911cb0ef41Sopenharmony_ci } 33921cb0ef41Sopenharmony_ci map = MapUpdater{isolate, map}.ReconfigureElementsKind(to_kind); 33931cb0ef41Sopenharmony_ci } 33941cb0ef41Sopenharmony_ci int number_of_fields = map->NumberOfFields(ConcurrencyMode::kSynchronous); 33951cb0ef41Sopenharmony_ci int inobject = map->GetInObjectProperties(); 33961cb0ef41Sopenharmony_ci int unused = map->UnusedPropertyFields(); 33971cb0ef41Sopenharmony_ci int total_size = number_of_fields + unused; 33981cb0ef41Sopenharmony_ci int external = total_size - inobject; 33991cb0ef41Sopenharmony_ci // Allocate mutable double boxes if necessary. It is always necessary if we 34001cb0ef41Sopenharmony_ci // have external properties, but is also necessary if we only have inobject 34011cb0ef41Sopenharmony_ci // properties but don't unbox double fields. 34021cb0ef41Sopenharmony_ci 34031cb0ef41Sopenharmony_ci Handle<DescriptorArray> descriptors(map->instance_descriptors(isolate), 34041cb0ef41Sopenharmony_ci isolate); 34051cb0ef41Sopenharmony_ci Handle<FixedArray> storage = isolate->factory()->NewFixedArray(inobject); 34061cb0ef41Sopenharmony_ci 34071cb0ef41Sopenharmony_ci Handle<PropertyArray> array = isolate->factory()->NewPropertyArray(external); 34081cb0ef41Sopenharmony_ci 34091cb0ef41Sopenharmony_ci for (InternalIndex i : map->IterateOwnDescriptors()) { 34101cb0ef41Sopenharmony_ci PropertyDetails details = descriptors->GetDetails(i); 34111cb0ef41Sopenharmony_ci Representation representation = details.representation(); 34121cb0ef41Sopenharmony_ci if (!representation.IsDouble()) continue; 34131cb0ef41Sopenharmony_ci FieldIndex index = FieldIndex::ForDescriptor(*map, i); 34141cb0ef41Sopenharmony_ci auto box = isolate->factory()->NewHeapNumberWithHoleNaN(); 34151cb0ef41Sopenharmony_ci if (index.is_inobject()) { 34161cb0ef41Sopenharmony_ci storage->set(index.property_index(), *box); 34171cb0ef41Sopenharmony_ci } else { 34181cb0ef41Sopenharmony_ci array->set(index.outobject_array_index(), *box); 34191cb0ef41Sopenharmony_ci } 34201cb0ef41Sopenharmony_ci } 34211cb0ef41Sopenharmony_ci 34221cb0ef41Sopenharmony_ci object->SetProperties(*array); 34231cb0ef41Sopenharmony_ci for (int i = 0; i < inobject; i++) { 34241cb0ef41Sopenharmony_ci FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); 34251cb0ef41Sopenharmony_ci Object value = storage->get(i); 34261cb0ef41Sopenharmony_ci object->FastPropertyAtPut(index, value); 34271cb0ef41Sopenharmony_ci } 34281cb0ef41Sopenharmony_ci object->set_map(*map, kReleaseStore); 34291cb0ef41Sopenharmony_ci} 34301cb0ef41Sopenharmony_ci 34311cb0ef41Sopenharmony_civoid JSObject::MigrateInstance(Isolate* isolate, Handle<JSObject> object) { 34321cb0ef41Sopenharmony_ci Handle<Map> original_map(object->map(), isolate); 34331cb0ef41Sopenharmony_ci Handle<Map> map = Map::Update(isolate, original_map); 34341cb0ef41Sopenharmony_ci map->set_is_migration_target(true); 34351cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, map); 34361cb0ef41Sopenharmony_ci if (FLAG_trace_migration) { 34371cb0ef41Sopenharmony_ci object->PrintInstanceMigration(stdout, *original_map, *map); 34381cb0ef41Sopenharmony_ci } 34391cb0ef41Sopenharmony_ci#if VERIFY_HEAP 34401cb0ef41Sopenharmony_ci if (FLAG_verify_heap) { 34411cb0ef41Sopenharmony_ci object->JSObjectVerify(isolate); 34421cb0ef41Sopenharmony_ci } 34431cb0ef41Sopenharmony_ci#endif 34441cb0ef41Sopenharmony_ci} 34451cb0ef41Sopenharmony_ci 34461cb0ef41Sopenharmony_ci// static 34471cb0ef41Sopenharmony_cibool JSObject::TryMigrateInstance(Isolate* isolate, Handle<JSObject> object) { 34481cb0ef41Sopenharmony_ci DisallowDeoptimization no_deoptimization(isolate); 34491cb0ef41Sopenharmony_ci Handle<Map> original_map(object->map(), isolate); 34501cb0ef41Sopenharmony_ci Handle<Map> new_map; 34511cb0ef41Sopenharmony_ci if (!Map::TryUpdate(isolate, original_map).ToHandle(&new_map)) { 34521cb0ef41Sopenharmony_ci return false; 34531cb0ef41Sopenharmony_ci } 34541cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map); 34551cb0ef41Sopenharmony_ci if (FLAG_trace_migration && *original_map != object->map()) { 34561cb0ef41Sopenharmony_ci object->PrintInstanceMigration(stdout, *original_map, object->map()); 34571cb0ef41Sopenharmony_ci } 34581cb0ef41Sopenharmony_ci#if VERIFY_HEAP 34591cb0ef41Sopenharmony_ci if (FLAG_verify_heap) { 34601cb0ef41Sopenharmony_ci object->JSObjectVerify(isolate); 34611cb0ef41Sopenharmony_ci } 34621cb0ef41Sopenharmony_ci#endif 34631cb0ef41Sopenharmony_ci return true; 34641cb0ef41Sopenharmony_ci} 34651cb0ef41Sopenharmony_ci 34661cb0ef41Sopenharmony_civoid JSObject::AddProperty(Isolate* isolate, Handle<JSObject> object, 34671cb0ef41Sopenharmony_ci Handle<Name> name, Handle<Object> value, 34681cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 34691cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, name, object, 34701cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 34711cb0ef41Sopenharmony_ci CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); 34721cb0ef41Sopenharmony_ci#ifdef DEBUG 34731cb0ef41Sopenharmony_ci uint32_t index; 34741cb0ef41Sopenharmony_ci DCHECK(!object->IsJSProxy()); 34751cb0ef41Sopenharmony_ci DCHECK(!name->AsArrayIndex(&index)); 34761cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); 34771cb0ef41Sopenharmony_ci DCHECK(maybe.IsJust()); 34781cb0ef41Sopenharmony_ci DCHECK(!it.IsFound()); 34791cb0ef41Sopenharmony_ci DCHECK(object->map().is_extensible() || name->IsPrivate()); 34801cb0ef41Sopenharmony_ci#endif 34811cb0ef41Sopenharmony_ci CHECK(Object::AddDataProperty(&it, value, attributes, 34821cb0ef41Sopenharmony_ci Just(ShouldThrow::kThrowOnError), 34831cb0ef41Sopenharmony_ci StoreOrigin::kNamed) 34841cb0ef41Sopenharmony_ci .IsJust()); 34851cb0ef41Sopenharmony_ci} 34861cb0ef41Sopenharmony_ci 34871cb0ef41Sopenharmony_civoid JSObject::AddProperty(Isolate* isolate, Handle<JSObject> object, 34881cb0ef41Sopenharmony_ci const char* name, Handle<Object> value, 34891cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 34901cb0ef41Sopenharmony_ci JSObject::AddProperty(isolate, object, 34911cb0ef41Sopenharmony_ci isolate->factory()->InternalizeUtf8String(name), value, 34921cb0ef41Sopenharmony_ci attributes); 34931cb0ef41Sopenharmony_ci} 34941cb0ef41Sopenharmony_ci 34951cb0ef41Sopenharmony_ci// Reconfigures a property to a data property with attributes, even if it is not 34961cb0ef41Sopenharmony_ci// reconfigurable. 34971cb0ef41Sopenharmony_ci// Requires a LookupIterator that does not look at the prototype chain beyond 34981cb0ef41Sopenharmony_ci// hidden prototypes. 34991cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( 35001cb0ef41Sopenharmony_ci LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 35011cb0ef41Sopenharmony_ci AccessorInfoHandling handling, EnforceDefineSemantics semantics) { 35021cb0ef41Sopenharmony_ci MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes( 35031cb0ef41Sopenharmony_ci it, value, attributes, Just(ShouldThrow::kThrowOnError), handling, 35041cb0ef41Sopenharmony_ci semantics)); 35051cb0ef41Sopenharmony_ci return value; 35061cb0ef41Sopenharmony_ci} 35071cb0ef41Sopenharmony_ci 35081cb0ef41Sopenharmony_ciMaybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes( 35091cb0ef41Sopenharmony_ci LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 35101cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw, AccessorInfoHandling handling, 35111cb0ef41Sopenharmony_ci EnforceDefineSemantics semantics, StoreOrigin store_origin) { 35121cb0ef41Sopenharmony_ci it->UpdateProtector(); 35131cb0ef41Sopenharmony_ci 35141cb0ef41Sopenharmony_ci for (; it->IsFound(); it->Next()) { 35151cb0ef41Sopenharmony_ci switch (it->state()) { 35161cb0ef41Sopenharmony_ci case LookupIterator::JSPROXY: 35171cb0ef41Sopenharmony_ci case LookupIterator::TRANSITION: 35181cb0ef41Sopenharmony_ci case LookupIterator::NOT_FOUND: 35191cb0ef41Sopenharmony_ci UNREACHABLE(); 35201cb0ef41Sopenharmony_ci 35211cb0ef41Sopenharmony_ci case LookupIterator::ACCESS_CHECK: 35221cb0ef41Sopenharmony_ci if (!it->HasAccess()) { 35231cb0ef41Sopenharmony_ci it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>()); 35241cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); 35251cb0ef41Sopenharmony_ci return Just(true); 35261cb0ef41Sopenharmony_ci } 35271cb0ef41Sopenharmony_ci break; 35281cb0ef41Sopenharmony_ci 35291cb0ef41Sopenharmony_ci // If there's an interceptor, try to store the property with the 35301cb0ef41Sopenharmony_ci // interceptor. 35311cb0ef41Sopenharmony_ci // In case of success, the attributes will have been reset to the default 35321cb0ef41Sopenharmony_ci // attributes of the interceptor, rather than the incoming attributes. 35331cb0ef41Sopenharmony_ci // 35341cb0ef41Sopenharmony_ci // TODO(verwaest): JSProxy afterwards verify the attributes that the 35351cb0ef41Sopenharmony_ci // JSProxy claims it has, and verifies that they are compatible. If not, 35361cb0ef41Sopenharmony_ci // they throw. Here we should do the same. 35371cb0ef41Sopenharmony_ci case LookupIterator::INTERCEPTOR: { 35381cb0ef41Sopenharmony_ci Maybe<bool> result = Just(false); 35391cb0ef41Sopenharmony_ci if (semantics == EnforceDefineSemantics::kDefine) { 35401cb0ef41Sopenharmony_ci PropertyDescriptor descriptor; 35411cb0ef41Sopenharmony_ci descriptor.set_configurable((attributes & DONT_DELETE) != 0); 35421cb0ef41Sopenharmony_ci descriptor.set_enumerable((attributes & DONT_ENUM) != 0); 35431cb0ef41Sopenharmony_ci descriptor.set_writable((attributes & READ_ONLY) != 0); 35441cb0ef41Sopenharmony_ci descriptor.set_value(value); 35451cb0ef41Sopenharmony_ci result = DefinePropertyWithInterceptorInternal( 35461cb0ef41Sopenharmony_ci it, it->GetInterceptor(), should_throw, &descriptor); 35471cb0ef41Sopenharmony_ci } else { 35481cb0ef41Sopenharmony_ci DCHECK_EQ(semantics, EnforceDefineSemantics::kSet); 35491cb0ef41Sopenharmony_ci if (handling == DONT_FORCE_FIELD) { 35501cb0ef41Sopenharmony_ci result = 35511cb0ef41Sopenharmony_ci JSObject::SetPropertyWithInterceptor(it, should_throw, value); 35521cb0ef41Sopenharmony_ci } 35531cb0ef41Sopenharmony_ci } 35541cb0ef41Sopenharmony_ci if (result.IsNothing() || result.FromJust()) return result; 35551cb0ef41Sopenharmony_ci 35561cb0ef41Sopenharmony_ci if (semantics == EnforceDefineSemantics::kDefine) { 35571cb0ef41Sopenharmony_ci it->Restart(); 35581cb0ef41Sopenharmony_ci Maybe<bool> can_define = JSReceiver::CheckIfCanDefine( 35591cb0ef41Sopenharmony_ci it->isolate(), it, value, should_throw); 35601cb0ef41Sopenharmony_ci if (can_define.IsNothing() || !can_define.FromJust()) { 35611cb0ef41Sopenharmony_ci return can_define; 35621cb0ef41Sopenharmony_ci } 35631cb0ef41Sopenharmony_ci } 35641cb0ef41Sopenharmony_ci 35651cb0ef41Sopenharmony_ci // The interceptor declined to handle the operation, so proceed defining 35661cb0ef41Sopenharmony_ci // own property without the interceptor. 35671cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 35681cb0ef41Sopenharmony_ci Handle<Object> receiver = it->GetReceiver(); 35691cb0ef41Sopenharmony_ci LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR; 35701cb0ef41Sopenharmony_ci LookupIterator own_lookup = 35711cb0ef41Sopenharmony_ci it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c) 35721cb0ef41Sopenharmony_ci : LookupIterator(isolate, receiver, it->name(), c); 35731cb0ef41Sopenharmony_ci return JSObject::DefineOwnPropertyIgnoreAttributes( 35741cb0ef41Sopenharmony_ci &own_lookup, value, attributes, should_throw, handling, semantics, 35751cb0ef41Sopenharmony_ci store_origin); 35761cb0ef41Sopenharmony_ci } 35771cb0ef41Sopenharmony_ci 35781cb0ef41Sopenharmony_ci case LookupIterator::ACCESSOR: { 35791cb0ef41Sopenharmony_ci Handle<Object> accessors = it->GetAccessors(); 35801cb0ef41Sopenharmony_ci 35811cb0ef41Sopenharmony_ci // Special handling for AccessorInfo, which behaves like a data 35821cb0ef41Sopenharmony_ci // property. 35831cb0ef41Sopenharmony_ci if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) { 35841cb0ef41Sopenharmony_ci PropertyAttributes current_attributes = it->property_attributes(); 35851cb0ef41Sopenharmony_ci // Ensure the context isn't changed after calling into accessors. 35861cb0ef41Sopenharmony_ci AssertNoContextChange ncc(it->isolate()); 35871cb0ef41Sopenharmony_ci 35881cb0ef41Sopenharmony_ci // Update the attributes before calling the setter. The setter may 35891cb0ef41Sopenharmony_ci // later change the shape of the property. 35901cb0ef41Sopenharmony_ci if (current_attributes != attributes) { 35911cb0ef41Sopenharmony_ci it->TransitionToAccessorPair(accessors, attributes); 35921cb0ef41Sopenharmony_ci } 35931cb0ef41Sopenharmony_ci 35941cb0ef41Sopenharmony_ci return Object::SetPropertyWithAccessor(it, value, should_throw); 35951cb0ef41Sopenharmony_ci } 35961cb0ef41Sopenharmony_ci 35971cb0ef41Sopenharmony_ci it->ReconfigureDataProperty(value, attributes); 35981cb0ef41Sopenharmony_ci return Just(true); 35991cb0ef41Sopenharmony_ci } 36001cb0ef41Sopenharmony_ci case LookupIterator::INTEGER_INDEXED_EXOTIC: 36011cb0ef41Sopenharmony_ci return Object::RedefineIncompatibleProperty( 36021cb0ef41Sopenharmony_ci it->isolate(), it->GetName(), value, should_throw); 36031cb0ef41Sopenharmony_ci 36041cb0ef41Sopenharmony_ci case LookupIterator::DATA: { 36051cb0ef41Sopenharmony_ci // Regular property update if the attributes match. 36061cb0ef41Sopenharmony_ci if (it->property_attributes() == attributes) { 36071cb0ef41Sopenharmony_ci return Object::SetDataProperty(it, value); 36081cb0ef41Sopenharmony_ci } 36091cb0ef41Sopenharmony_ci 36101cb0ef41Sopenharmony_ci // The non-matching attribute case for JSTypedArrays has already been 36111cb0ef41Sopenharmony_ci // handled by JSTypedArray::DefineOwnProperty. 36121cb0ef41Sopenharmony_ci DCHECK(!it->IsElement() || 36131cb0ef41Sopenharmony_ci !Handle<JSObject>::cast(it->GetReceiver()) 36141cb0ef41Sopenharmony_ci ->HasTypedArrayOrRabGsabTypedArrayElements()); 36151cb0ef41Sopenharmony_ci // Reconfigure the data property if the attributes mismatch. 36161cb0ef41Sopenharmony_ci it->ReconfigureDataProperty(value, attributes); 36171cb0ef41Sopenharmony_ci 36181cb0ef41Sopenharmony_ci return Just(true); 36191cb0ef41Sopenharmony_ci } 36201cb0ef41Sopenharmony_ci } 36211cb0ef41Sopenharmony_ci } 36221cb0ef41Sopenharmony_ci 36231cb0ef41Sopenharmony_ci return Object::AddDataProperty(it, value, attributes, should_throw, 36241cb0ef41Sopenharmony_ci store_origin, semantics); 36251cb0ef41Sopenharmony_ci} 36261cb0ef41Sopenharmony_ci 36271cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( 36281cb0ef41Sopenharmony_ci Handle<JSObject> object, Handle<Name> name, Handle<Object> value, 36291cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 36301cb0ef41Sopenharmony_ci DCHECK(!value->IsTheHole()); 36311cb0ef41Sopenharmony_ci LookupIterator it(object->GetIsolate(), object, name, object, 36321cb0ef41Sopenharmony_ci LookupIterator::OWN); 36331cb0ef41Sopenharmony_ci return DefineOwnPropertyIgnoreAttributes(&it, value, attributes); 36341cb0ef41Sopenharmony_ci} 36351cb0ef41Sopenharmony_ci 36361cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes( 36371cb0ef41Sopenharmony_ci Handle<JSObject> object, size_t index, Handle<Object> value, 36381cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 36391cb0ef41Sopenharmony_ci DCHECK(!object->IsJSTypedArray()); 36401cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 36411cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, index, object, LookupIterator::OWN); 36421cb0ef41Sopenharmony_ci return DefineOwnPropertyIgnoreAttributes(&it, value, attributes); 36431cb0ef41Sopenharmony_ci} 36441cb0ef41Sopenharmony_ci 36451cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes( 36461cb0ef41Sopenharmony_ci Handle<JSObject> object, Handle<Name> name, Handle<Object> value, 36471cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 36481cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 36491cb0ef41Sopenharmony_ci PropertyKey key(isolate, name); 36501cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, key, object, LookupIterator::OWN); 36511cb0ef41Sopenharmony_ci return DefineOwnPropertyIgnoreAttributes(&it, value, attributes); 36521cb0ef41Sopenharmony_ci} 36531cb0ef41Sopenharmony_ci 36541cb0ef41Sopenharmony_ciMaybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( 36551cb0ef41Sopenharmony_ci LookupIterator* it) { 36561cb0ef41Sopenharmony_ci return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor()); 36571cb0ef41Sopenharmony_ci} 36581cb0ef41Sopenharmony_ci 36591cb0ef41Sopenharmony_civoid JSObject::NormalizeProperties(Isolate* isolate, Handle<JSObject> object, 36601cb0ef41Sopenharmony_ci PropertyNormalizationMode mode, 36611cb0ef41Sopenharmony_ci int expected_additional_properties, 36621cb0ef41Sopenharmony_ci const char* reason) { 36631cb0ef41Sopenharmony_ci if (!object->HasFastProperties()) return; 36641cb0ef41Sopenharmony_ci 36651cb0ef41Sopenharmony_ci Handle<Map> map(object->map(), isolate); 36661cb0ef41Sopenharmony_ci Handle<Map> new_map = 36671cb0ef41Sopenharmony_ci Map::Normalize(isolate, map, map->elements_kind(), mode, reason); 36681cb0ef41Sopenharmony_ci 36691cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map, 36701cb0ef41Sopenharmony_ci expected_additional_properties); 36711cb0ef41Sopenharmony_ci} 36721cb0ef41Sopenharmony_ci 36731cb0ef41Sopenharmony_civoid JSObject::MigrateSlowToFast(Handle<JSObject> object, 36741cb0ef41Sopenharmony_ci int unused_property_fields, 36751cb0ef41Sopenharmony_ci const char* reason) { 36761cb0ef41Sopenharmony_ci if (object->HasFastProperties()) return; 36771cb0ef41Sopenharmony_ci DCHECK(!object->IsJSGlobalObject()); 36781cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 36791cb0ef41Sopenharmony_ci Factory* factory = isolate->factory(); 36801cb0ef41Sopenharmony_ci 36811cb0ef41Sopenharmony_ci Handle<NameDictionary> dictionary; 36821cb0ef41Sopenharmony_ci Handle<SwissNameDictionary> swiss_dictionary; 36831cb0ef41Sopenharmony_ci int number_of_elements; 36841cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 36851cb0ef41Sopenharmony_ci swiss_dictionary = handle(object->property_dictionary_swiss(), isolate); 36861cb0ef41Sopenharmony_ci number_of_elements = swiss_dictionary->NumberOfElements(); 36871cb0ef41Sopenharmony_ci } else { 36881cb0ef41Sopenharmony_ci dictionary = handle(object->property_dictionary(), isolate); 36891cb0ef41Sopenharmony_ci number_of_elements = dictionary->NumberOfElements(); 36901cb0ef41Sopenharmony_ci } 36911cb0ef41Sopenharmony_ci 36921cb0ef41Sopenharmony_ci // Make sure we preserve dictionary representation if there are too many 36931cb0ef41Sopenharmony_ci // descriptors. 36941cb0ef41Sopenharmony_ci if (number_of_elements > kMaxNumberOfDescriptors) return; 36951cb0ef41Sopenharmony_ci 36961cb0ef41Sopenharmony_ci Handle<FixedArray> iteration_order; 36971cb0ef41Sopenharmony_ci int iteration_length; 36981cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 36991cb0ef41Sopenharmony_ci // |iteration_order| remains empty handle, we don't need it. 37001cb0ef41Sopenharmony_ci iteration_length = swiss_dictionary->UsedCapacity(); 37011cb0ef41Sopenharmony_ci } else { 37021cb0ef41Sopenharmony_ci iteration_order = NameDictionary::IterationIndices(isolate, dictionary); 37031cb0ef41Sopenharmony_ci iteration_length = dictionary->NumberOfElements(); 37041cb0ef41Sopenharmony_ci } 37051cb0ef41Sopenharmony_ci 37061cb0ef41Sopenharmony_ci int number_of_fields = 0; 37071cb0ef41Sopenharmony_ci 37081cb0ef41Sopenharmony_ci // Compute the length of the instance descriptor. 37091cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 37101cb0ef41Sopenharmony_ci for (int i = 0; i < iteration_length; i++) { 37111cb0ef41Sopenharmony_ci PropertyKind kind; 37121cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 37131cb0ef41Sopenharmony_ci InternalIndex index(swiss_dictionary->EntryForEnumerationIndex(i)); 37141cb0ef41Sopenharmony_ci Object key = swiss_dictionary->KeyAt(index); 37151cb0ef41Sopenharmony_ci if (!SwissNameDictionary::IsKey(roots, key)) { 37161cb0ef41Sopenharmony_ci // Ignore deleted entries. 37171cb0ef41Sopenharmony_ci continue; 37181cb0ef41Sopenharmony_ci } 37191cb0ef41Sopenharmony_ci kind = swiss_dictionary->DetailsAt(index).kind(); 37201cb0ef41Sopenharmony_ci } else { 37211cb0ef41Sopenharmony_ci InternalIndex index(Smi::ToInt(iteration_order->get(i))); 37221cb0ef41Sopenharmony_ci DCHECK(dictionary->IsKey(roots, dictionary->KeyAt(isolate, index))); 37231cb0ef41Sopenharmony_ci kind = dictionary->DetailsAt(index).kind(); 37241cb0ef41Sopenharmony_ci } 37251cb0ef41Sopenharmony_ci 37261cb0ef41Sopenharmony_ci if (kind == PropertyKind::kData) { 37271cb0ef41Sopenharmony_ci number_of_fields += 1; 37281cb0ef41Sopenharmony_ci } 37291cb0ef41Sopenharmony_ci } 37301cb0ef41Sopenharmony_ci 37311cb0ef41Sopenharmony_ci Handle<Map> old_map(object->map(), isolate); 37321cb0ef41Sopenharmony_ci 37331cb0ef41Sopenharmony_ci int inobject_props = old_map->GetInObjectProperties(); 37341cb0ef41Sopenharmony_ci 37351cb0ef41Sopenharmony_ci // Allocate new map. 37361cb0ef41Sopenharmony_ci Handle<Map> new_map = Map::CopyDropDescriptors(isolate, old_map); 37371cb0ef41Sopenharmony_ci // We should not only set this bit if we need to. We should not retain the 37381cb0ef41Sopenharmony_ci // old bit because turning a map into dictionary always sets this bit. 37391cb0ef41Sopenharmony_ci new_map->set_may_have_interesting_symbols(new_map->has_named_interceptor() || 37401cb0ef41Sopenharmony_ci new_map->is_access_check_needed()); 37411cb0ef41Sopenharmony_ci new_map->set_is_dictionary_map(false); 37421cb0ef41Sopenharmony_ci 37431cb0ef41Sopenharmony_ci NotifyMapChange(old_map, new_map, isolate); 37441cb0ef41Sopenharmony_ci 37451cb0ef41Sopenharmony_ci if (number_of_elements == 0) { 37461cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 37471cb0ef41Sopenharmony_ci DCHECK_LE(unused_property_fields, inobject_props); 37481cb0ef41Sopenharmony_ci // Transform the object. 37491cb0ef41Sopenharmony_ci new_map->SetInObjectUnusedPropertyFields(inobject_props); 37501cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 37511cb0ef41Sopenharmony_ci object->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array()); 37521cb0ef41Sopenharmony_ci // Check that it really works. 37531cb0ef41Sopenharmony_ci DCHECK(object->HasFastProperties()); 37541cb0ef41Sopenharmony_ci if (FLAG_log_maps) { 37551cb0ef41Sopenharmony_ci LOG(isolate, MapEvent("SlowToFast", old_map, new_map, reason)); 37561cb0ef41Sopenharmony_ci } 37571cb0ef41Sopenharmony_ci return; 37581cb0ef41Sopenharmony_ci } 37591cb0ef41Sopenharmony_ci 37601cb0ef41Sopenharmony_ci // Allocate the instance descriptor. 37611cb0ef41Sopenharmony_ci Handle<DescriptorArray> descriptors = 37621cb0ef41Sopenharmony_ci DescriptorArray::Allocate(isolate, number_of_elements, 0); 37631cb0ef41Sopenharmony_ci 37641cb0ef41Sopenharmony_ci int number_of_allocated_fields = 37651cb0ef41Sopenharmony_ci number_of_fields + unused_property_fields - inobject_props; 37661cb0ef41Sopenharmony_ci if (number_of_allocated_fields < 0) { 37671cb0ef41Sopenharmony_ci // There is enough inobject space for all fields (including unused). 37681cb0ef41Sopenharmony_ci number_of_allocated_fields = 0; 37691cb0ef41Sopenharmony_ci unused_property_fields = inobject_props - number_of_fields; 37701cb0ef41Sopenharmony_ci } 37711cb0ef41Sopenharmony_ci 37721cb0ef41Sopenharmony_ci // Allocate the property array for the fields. 37731cb0ef41Sopenharmony_ci Handle<PropertyArray> fields = 37741cb0ef41Sopenharmony_ci factory->NewPropertyArray(number_of_allocated_fields); 37751cb0ef41Sopenharmony_ci 37761cb0ef41Sopenharmony_ci bool is_transitionable_elements_kind = 37771cb0ef41Sopenharmony_ci IsTransitionableFastElementsKind(old_map->elements_kind()); 37781cb0ef41Sopenharmony_ci 37791cb0ef41Sopenharmony_ci // Fill in the instance descriptor and the fields. 37801cb0ef41Sopenharmony_ci int current_offset = 0; 37811cb0ef41Sopenharmony_ci int descriptor_index = 0; 37821cb0ef41Sopenharmony_ci for (int i = 0; i < iteration_length; i++) { 37831cb0ef41Sopenharmony_ci Name k; 37841cb0ef41Sopenharmony_ci Object value; 37851cb0ef41Sopenharmony_ci PropertyDetails details = PropertyDetails::Empty(); 37861cb0ef41Sopenharmony_ci 37871cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 37881cb0ef41Sopenharmony_ci InternalIndex index(swiss_dictionary->EntryForEnumerationIndex(i)); 37891cb0ef41Sopenharmony_ci Object key_obj = swiss_dictionary->KeyAt(index); 37901cb0ef41Sopenharmony_ci if (!SwissNameDictionary::IsKey(roots, key_obj)) { 37911cb0ef41Sopenharmony_ci continue; 37921cb0ef41Sopenharmony_ci } 37931cb0ef41Sopenharmony_ci k = Name::cast(key_obj); 37941cb0ef41Sopenharmony_ci 37951cb0ef41Sopenharmony_ci value = swiss_dictionary->ValueAt(index); 37961cb0ef41Sopenharmony_ci details = swiss_dictionary->DetailsAt(index); 37971cb0ef41Sopenharmony_ci } else { 37981cb0ef41Sopenharmony_ci InternalIndex index(Smi::ToInt(iteration_order->get(i))); 37991cb0ef41Sopenharmony_ci k = dictionary->NameAt(index); 38001cb0ef41Sopenharmony_ci 38011cb0ef41Sopenharmony_ci value = dictionary->ValueAt(index); 38021cb0ef41Sopenharmony_ci details = dictionary->DetailsAt(index); 38031cb0ef41Sopenharmony_ci } 38041cb0ef41Sopenharmony_ci 38051cb0ef41Sopenharmony_ci // Dictionary keys are internalized upon insertion. 38061cb0ef41Sopenharmony_ci // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild. 38071cb0ef41Sopenharmony_ci CHECK(k.IsUniqueName()); 38081cb0ef41Sopenharmony_ci Handle<Name> key(k, isolate); 38091cb0ef41Sopenharmony_ci 38101cb0ef41Sopenharmony_ci // Properly mark the {new_map} if the {key} is an "interesting symbol". 38111cb0ef41Sopenharmony_ci if (key->IsInterestingSymbol()) { 38121cb0ef41Sopenharmony_ci new_map->set_may_have_interesting_symbols(true); 38131cb0ef41Sopenharmony_ci } 38141cb0ef41Sopenharmony_ci 38151cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyLocation::kField, details.location()); 38161cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!V8_DICT_PROPERTY_CONST_TRACKING_BOOL, 38171cb0ef41Sopenharmony_ci details.constness() == PropertyConstness::kMutable); 38181cb0ef41Sopenharmony_ci 38191cb0ef41Sopenharmony_ci Descriptor d; 38201cb0ef41Sopenharmony_ci if (details.kind() == PropertyKind::kData) { 38211cb0ef41Sopenharmony_ci // Ensure that we make constant field only when elements kind is not 38221cb0ef41Sopenharmony_ci // transitionable. 38231cb0ef41Sopenharmony_ci PropertyConstness constness = is_transitionable_elements_kind 38241cb0ef41Sopenharmony_ci ? PropertyConstness::kMutable 38251cb0ef41Sopenharmony_ci : PropertyConstness::kConst; 38261cb0ef41Sopenharmony_ci // TODO(v8:11248): Consider always setting constness to kMutable 38271cb0ef41Sopenharmony_ci // once all prototypes stay in dictionary mode and we are not interested 38281cb0ef41Sopenharmony_ci // in tracking constness for fast mode properties anymore. 38291cb0ef41Sopenharmony_ci 38301cb0ef41Sopenharmony_ci d = Descriptor::DataField( 38311cb0ef41Sopenharmony_ci key, current_offset, details.attributes(), constness, 38321cb0ef41Sopenharmony_ci // TODO(verwaest): value->OptimalRepresentation(); 38331cb0ef41Sopenharmony_ci Representation::Tagged(), MaybeObjectHandle(FieldType::Any(isolate))); 38341cb0ef41Sopenharmony_ci } else { 38351cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyKind::kAccessor, details.kind()); 38361cb0ef41Sopenharmony_ci d = Descriptor::AccessorConstant(key, handle(value, isolate), 38371cb0ef41Sopenharmony_ci details.attributes()); 38381cb0ef41Sopenharmony_ci } 38391cb0ef41Sopenharmony_ci details = d.GetDetails(); 38401cb0ef41Sopenharmony_ci if (details.location() == PropertyLocation::kField) { 38411cb0ef41Sopenharmony_ci if (current_offset < inobject_props) { 38421cb0ef41Sopenharmony_ci object->InObjectPropertyAtPut(current_offset, value, 38431cb0ef41Sopenharmony_ci UPDATE_WRITE_BARRIER); 38441cb0ef41Sopenharmony_ci } else { 38451cb0ef41Sopenharmony_ci int offset = current_offset - inobject_props; 38461cb0ef41Sopenharmony_ci fields->set(offset, value); 38471cb0ef41Sopenharmony_ci } 38481cb0ef41Sopenharmony_ci current_offset += details.field_width_in_words(); 38491cb0ef41Sopenharmony_ci } 38501cb0ef41Sopenharmony_ci descriptors->Set(InternalIndex(descriptor_index++), &d); 38511cb0ef41Sopenharmony_ci } 38521cb0ef41Sopenharmony_ci DCHECK_EQ(current_offset, number_of_fields); 38531cb0ef41Sopenharmony_ci DCHECK_EQ(descriptor_index, number_of_elements); 38541cb0ef41Sopenharmony_ci 38551cb0ef41Sopenharmony_ci descriptors->Sort(); 38561cb0ef41Sopenharmony_ci 38571cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 38581cb0ef41Sopenharmony_ci new_map->InitializeDescriptors(isolate, *descriptors); 38591cb0ef41Sopenharmony_ci if (number_of_allocated_fields == 0) { 38601cb0ef41Sopenharmony_ci new_map->SetInObjectUnusedPropertyFields(unused_property_fields); 38611cb0ef41Sopenharmony_ci } else { 38621cb0ef41Sopenharmony_ci new_map->SetOutOfObjectUnusedPropertyFields(unused_property_fields); 38631cb0ef41Sopenharmony_ci } 38641cb0ef41Sopenharmony_ci 38651cb0ef41Sopenharmony_ci if (FLAG_log_maps) { 38661cb0ef41Sopenharmony_ci LOG(isolate, MapEvent("SlowToFast", old_map, new_map, reason)); 38671cb0ef41Sopenharmony_ci } 38681cb0ef41Sopenharmony_ci // Transform the object. 38691cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 38701cb0ef41Sopenharmony_ci 38711cb0ef41Sopenharmony_ci object->SetProperties(*fields); 38721cb0ef41Sopenharmony_ci DCHECK(object->IsJSObject()); 38731cb0ef41Sopenharmony_ci 38741cb0ef41Sopenharmony_ci // Check that it really works. 38751cb0ef41Sopenharmony_ci DCHECK(object->HasFastProperties()); 38761cb0ef41Sopenharmony_ci} 38771cb0ef41Sopenharmony_ci 38781cb0ef41Sopenharmony_civoid JSObject::RequireSlowElements(NumberDictionary dictionary) { 38791cb0ef41Sopenharmony_ci DCHECK_NE(dictionary, 38801cb0ef41Sopenharmony_ci ReadOnlyRoots(GetIsolate()).empty_slow_element_dictionary()); 38811cb0ef41Sopenharmony_ci if (dictionary.requires_slow_elements()) return; 38821cb0ef41Sopenharmony_ci dictionary.set_requires_slow_elements(); 38831cb0ef41Sopenharmony_ci if (map().is_prototype_map()) { 38841cb0ef41Sopenharmony_ci // If this object is a prototype (the callee will check), invalidate any 38851cb0ef41Sopenharmony_ci // prototype chains involving it. 38861cb0ef41Sopenharmony_ci InvalidatePrototypeChains(map()); 38871cb0ef41Sopenharmony_ci } 38881cb0ef41Sopenharmony_ci} 38891cb0ef41Sopenharmony_ci 38901cb0ef41Sopenharmony_ciHandle<NumberDictionary> JSObject::NormalizeElements(Handle<JSObject> object) { 38911cb0ef41Sopenharmony_ci DCHECK(!object->HasTypedArrayOrRabGsabTypedArrayElements()); 38921cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 38931cb0ef41Sopenharmony_ci bool is_sloppy_arguments = object->HasSloppyArgumentsElements(); 38941cb0ef41Sopenharmony_ci { 38951cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 38961cb0ef41Sopenharmony_ci FixedArrayBase elements = object->elements(); 38971cb0ef41Sopenharmony_ci 38981cb0ef41Sopenharmony_ci if (is_sloppy_arguments) { 38991cb0ef41Sopenharmony_ci elements = SloppyArgumentsElements::cast(elements).arguments(); 39001cb0ef41Sopenharmony_ci } 39011cb0ef41Sopenharmony_ci 39021cb0ef41Sopenharmony_ci if (elements.IsNumberDictionary()) { 39031cb0ef41Sopenharmony_ci return handle(NumberDictionary::cast(elements), isolate); 39041cb0ef41Sopenharmony_ci } 39051cb0ef41Sopenharmony_ci } 39061cb0ef41Sopenharmony_ci 39071cb0ef41Sopenharmony_ci DCHECK(object->HasSmiOrObjectElements() || object->HasDoubleElements() || 39081cb0ef41Sopenharmony_ci object->HasFastArgumentsElements() || 39091cb0ef41Sopenharmony_ci object->HasFastStringWrapperElements() || 39101cb0ef41Sopenharmony_ci object->HasSealedElements() || object->HasNonextensibleElements()); 39111cb0ef41Sopenharmony_ci 39121cb0ef41Sopenharmony_ci Handle<NumberDictionary> dictionary = 39131cb0ef41Sopenharmony_ci object->GetElementsAccessor()->Normalize(object); 39141cb0ef41Sopenharmony_ci 39151cb0ef41Sopenharmony_ci // Switch to using the dictionary as the backing storage for elements. 39161cb0ef41Sopenharmony_ci ElementsKind target_kind = is_sloppy_arguments 39171cb0ef41Sopenharmony_ci ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS 39181cb0ef41Sopenharmony_ci : object->HasFastStringWrapperElements() 39191cb0ef41Sopenharmony_ci ? SLOW_STRING_WRAPPER_ELEMENTS 39201cb0ef41Sopenharmony_ci : DICTIONARY_ELEMENTS; 39211cb0ef41Sopenharmony_ci Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind); 39221cb0ef41Sopenharmony_ci // Set the new map first to satify the elements type assert in set_elements(). 39231cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map); 39241cb0ef41Sopenharmony_ci 39251cb0ef41Sopenharmony_ci if (is_sloppy_arguments) { 39261cb0ef41Sopenharmony_ci SloppyArgumentsElements::cast(object->elements()) 39271cb0ef41Sopenharmony_ci .set_arguments(*dictionary); 39281cb0ef41Sopenharmony_ci } else { 39291cb0ef41Sopenharmony_ci object->set_elements(*dictionary); 39301cb0ef41Sopenharmony_ci } 39311cb0ef41Sopenharmony_ci 39321cb0ef41Sopenharmony_ci isolate->counters()->elements_to_dictionary()->Increment(); 39331cb0ef41Sopenharmony_ci 39341cb0ef41Sopenharmony_ci#ifdef DEBUG 39351cb0ef41Sopenharmony_ci if (FLAG_trace_normalization) { 39361cb0ef41Sopenharmony_ci StdoutStream os; 39371cb0ef41Sopenharmony_ci os << "Object elements have been normalized:\n"; 39381cb0ef41Sopenharmony_ci object->Print(os); 39391cb0ef41Sopenharmony_ci } 39401cb0ef41Sopenharmony_ci#endif 39411cb0ef41Sopenharmony_ci 39421cb0ef41Sopenharmony_ci DCHECK(object->HasDictionaryElements() || 39431cb0ef41Sopenharmony_ci object->HasSlowArgumentsElements() || 39441cb0ef41Sopenharmony_ci object->HasSlowStringWrapperElements()); 39451cb0ef41Sopenharmony_ci return dictionary; 39461cb0ef41Sopenharmony_ci} 39471cb0ef41Sopenharmony_ci 39481cb0ef41Sopenharmony_ciMaybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it, 39491cb0ef41Sopenharmony_ci ShouldThrow should_throw) { 39501cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 39511cb0ef41Sopenharmony_ci // Make sure that the top context does not change when doing callbacks or 39521cb0ef41Sopenharmony_ci // interceptor calls. 39531cb0ef41Sopenharmony_ci AssertNoContextChange ncc(isolate); 39541cb0ef41Sopenharmony_ci 39551cb0ef41Sopenharmony_ci DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); 39561cb0ef41Sopenharmony_ci Handle<InterceptorInfo> interceptor(it->GetInterceptor()); 39571cb0ef41Sopenharmony_ci if (interceptor->deleter().IsUndefined(isolate)) return Nothing<bool>(); 39581cb0ef41Sopenharmony_ci 39591cb0ef41Sopenharmony_ci Handle<JSObject> holder = it->GetHolder<JSObject>(); 39601cb0ef41Sopenharmony_ci Handle<Object> receiver = it->GetReceiver(); 39611cb0ef41Sopenharmony_ci if (!receiver->IsJSReceiver()) { 39621cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver, 39631cb0ef41Sopenharmony_ci Object::ConvertReceiver(isolate, receiver), 39641cb0ef41Sopenharmony_ci Nothing<bool>()); 39651cb0ef41Sopenharmony_ci } 39661cb0ef41Sopenharmony_ci 39671cb0ef41Sopenharmony_ci PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, 39681cb0ef41Sopenharmony_ci *holder, Just(should_throw)); 39691cb0ef41Sopenharmony_ci Handle<Object> result; 39701cb0ef41Sopenharmony_ci if (it->IsElement(*holder)) { 39711cb0ef41Sopenharmony_ci result = args.CallIndexedDeleter(interceptor, it->array_index()); 39721cb0ef41Sopenharmony_ci } else { 39731cb0ef41Sopenharmony_ci result = args.CallNamedDeleter(interceptor, it->name()); 39741cb0ef41Sopenharmony_ci } 39751cb0ef41Sopenharmony_ci 39761cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 39771cb0ef41Sopenharmony_ci if (result.is_null()) return Nothing<bool>(); 39781cb0ef41Sopenharmony_ci 39791cb0ef41Sopenharmony_ci DCHECK(result->IsBoolean()); 39801cb0ef41Sopenharmony_ci // Rebox CustomArguments::kReturnValueOffset before returning. 39811cb0ef41Sopenharmony_ci return Just(result->IsTrue(isolate)); 39821cb0ef41Sopenharmony_ci} 39831cb0ef41Sopenharmony_ci 39841cb0ef41Sopenharmony_ciMaybe<bool> JSObject::CreateDataProperty(LookupIterator* it, 39851cb0ef41Sopenharmony_ci Handle<Object> value, 39861cb0ef41Sopenharmony_ci Maybe<ShouldThrow> should_throw) { 39871cb0ef41Sopenharmony_ci DCHECK(it->GetReceiver()->IsJSObject()); 39881cb0ef41Sopenharmony_ci MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>()); 39891cb0ef41Sopenharmony_ci Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); 39901cb0ef41Sopenharmony_ci Isolate* isolate = receiver->GetIsolate(); 39911cb0ef41Sopenharmony_ci 39921cb0ef41Sopenharmony_ci Maybe<bool> can_define = 39931cb0ef41Sopenharmony_ci JSReceiver::CheckIfCanDefine(isolate, it, value, should_throw); 39941cb0ef41Sopenharmony_ci if (can_define.IsNothing() || !can_define.FromJust()) { 39951cb0ef41Sopenharmony_ci return can_define; 39961cb0ef41Sopenharmony_ci } 39971cb0ef41Sopenharmony_ci 39981cb0ef41Sopenharmony_ci RETURN_ON_EXCEPTION_VALUE(it->isolate(), 39991cb0ef41Sopenharmony_ci DefineOwnPropertyIgnoreAttributes(it, value, NONE), 40001cb0ef41Sopenharmony_ci Nothing<bool>()); 40011cb0ef41Sopenharmony_ci 40021cb0ef41Sopenharmony_ci return Just(true); 40031cb0ef41Sopenharmony_ci} 40041cb0ef41Sopenharmony_ci 40051cb0ef41Sopenharmony_cinamespace { 40061cb0ef41Sopenharmony_ci 40071cb0ef41Sopenharmony_citemplate <typename Dictionary> 40081cb0ef41Sopenharmony_cibool TestDictionaryPropertiesIntegrityLevel(Dictionary dict, 40091cb0ef41Sopenharmony_ci ReadOnlyRoots roots, 40101cb0ef41Sopenharmony_ci PropertyAttributes level) { 40111cb0ef41Sopenharmony_ci DCHECK(level == SEALED || level == FROZEN); 40121cb0ef41Sopenharmony_ci 40131cb0ef41Sopenharmony_ci for (InternalIndex i : dict.IterateEntries()) { 40141cb0ef41Sopenharmony_ci Object key; 40151cb0ef41Sopenharmony_ci if (!dict.ToKey(roots, i, &key)) continue; 40161cb0ef41Sopenharmony_ci if (key.FilterKey(ALL_PROPERTIES)) continue; 40171cb0ef41Sopenharmony_ci PropertyDetails details = dict.DetailsAt(i); 40181cb0ef41Sopenharmony_ci if (details.IsConfigurable()) return false; 40191cb0ef41Sopenharmony_ci if (level == FROZEN && details.kind() == PropertyKind::kData && 40201cb0ef41Sopenharmony_ci !details.IsReadOnly()) { 40211cb0ef41Sopenharmony_ci return false; 40221cb0ef41Sopenharmony_ci } 40231cb0ef41Sopenharmony_ci } 40241cb0ef41Sopenharmony_ci return true; 40251cb0ef41Sopenharmony_ci} 40261cb0ef41Sopenharmony_ci 40271cb0ef41Sopenharmony_cibool TestFastPropertiesIntegrityLevel(Map map, PropertyAttributes level) { 40281cb0ef41Sopenharmony_ci DCHECK(level == SEALED || level == FROZEN); 40291cb0ef41Sopenharmony_ci DCHECK(!map.IsCustomElementsReceiverMap()); 40301cb0ef41Sopenharmony_ci DCHECK(!map.is_dictionary_map()); 40311cb0ef41Sopenharmony_ci 40321cb0ef41Sopenharmony_ci DescriptorArray descriptors = map.instance_descriptors(); 40331cb0ef41Sopenharmony_ci for (InternalIndex i : map.IterateOwnDescriptors()) { 40341cb0ef41Sopenharmony_ci if (descriptors.GetKey(i).IsPrivate()) continue; 40351cb0ef41Sopenharmony_ci PropertyDetails details = descriptors.GetDetails(i); 40361cb0ef41Sopenharmony_ci if (details.IsConfigurable()) return false; 40371cb0ef41Sopenharmony_ci if (level == FROZEN && details.kind() == PropertyKind::kData && 40381cb0ef41Sopenharmony_ci !details.IsReadOnly()) { 40391cb0ef41Sopenharmony_ci return false; 40401cb0ef41Sopenharmony_ci } 40411cb0ef41Sopenharmony_ci } 40421cb0ef41Sopenharmony_ci return true; 40431cb0ef41Sopenharmony_ci} 40441cb0ef41Sopenharmony_ci 40451cb0ef41Sopenharmony_cibool TestPropertiesIntegrityLevel(JSObject object, PropertyAttributes level) { 40461cb0ef41Sopenharmony_ci DCHECK(!object.map().IsCustomElementsReceiverMap()); 40471cb0ef41Sopenharmony_ci 40481cb0ef41Sopenharmony_ci if (object.HasFastProperties()) { 40491cb0ef41Sopenharmony_ci return TestFastPropertiesIntegrityLevel(object.map(), level); 40501cb0ef41Sopenharmony_ci } 40511cb0ef41Sopenharmony_ci 40521cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 40531cb0ef41Sopenharmony_ci return TestDictionaryPropertiesIntegrityLevel( 40541cb0ef41Sopenharmony_ci object.property_dictionary_swiss(), object.GetReadOnlyRoots(), level); 40551cb0ef41Sopenharmony_ci } else { 40561cb0ef41Sopenharmony_ci return TestDictionaryPropertiesIntegrityLevel( 40571cb0ef41Sopenharmony_ci object.property_dictionary(), object.GetReadOnlyRoots(), level); 40581cb0ef41Sopenharmony_ci } 40591cb0ef41Sopenharmony_ci} 40601cb0ef41Sopenharmony_ci 40611cb0ef41Sopenharmony_cibool TestElementsIntegrityLevel(JSObject object, PropertyAttributes level) { 40621cb0ef41Sopenharmony_ci DCHECK(!object.HasSloppyArgumentsElements()); 40631cb0ef41Sopenharmony_ci 40641cb0ef41Sopenharmony_ci ElementsKind kind = object.GetElementsKind(); 40651cb0ef41Sopenharmony_ci 40661cb0ef41Sopenharmony_ci if (IsDictionaryElementsKind(kind)) { 40671cb0ef41Sopenharmony_ci return TestDictionaryPropertiesIntegrityLevel( 40681cb0ef41Sopenharmony_ci NumberDictionary::cast(object.elements()), object.GetReadOnlyRoots(), 40691cb0ef41Sopenharmony_ci level); 40701cb0ef41Sopenharmony_ci } 40711cb0ef41Sopenharmony_ci if (IsTypedArrayElementsKind(kind)) { 40721cb0ef41Sopenharmony_ci if (level == FROZEN && JSArrayBufferView::cast(object).byte_length() > 0) { 40731cb0ef41Sopenharmony_ci return false; // TypedArrays with elements can't be frozen. 40741cb0ef41Sopenharmony_ci } 40751cb0ef41Sopenharmony_ci return TestPropertiesIntegrityLevel(object, level); 40761cb0ef41Sopenharmony_ci } 40771cb0ef41Sopenharmony_ci if (IsFrozenElementsKind(kind)) return true; 40781cb0ef41Sopenharmony_ci if (IsSealedElementsKind(kind) && level != FROZEN) return true; 40791cb0ef41Sopenharmony_ci if (IsNonextensibleElementsKind(kind) && level == NONE) return true; 40801cb0ef41Sopenharmony_ci 40811cb0ef41Sopenharmony_ci ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); 40821cb0ef41Sopenharmony_ci // Only DICTIONARY_ELEMENTS and SLOW_SLOPPY_ARGUMENTS_ELEMENTS have 40831cb0ef41Sopenharmony_ci // PropertyAttributes so just test if empty 40841cb0ef41Sopenharmony_ci return accessor->NumberOfElements(object) == 0; 40851cb0ef41Sopenharmony_ci} 40861cb0ef41Sopenharmony_ci 40871cb0ef41Sopenharmony_cibool FastTestIntegrityLevel(JSObject object, PropertyAttributes level) { 40881cb0ef41Sopenharmony_ci DCHECK(!object.map().IsCustomElementsReceiverMap()); 40891cb0ef41Sopenharmony_ci 40901cb0ef41Sopenharmony_ci return !object.map().is_extensible() && 40911cb0ef41Sopenharmony_ci TestElementsIntegrityLevel(object, level) && 40921cb0ef41Sopenharmony_ci TestPropertiesIntegrityLevel(object, level); 40931cb0ef41Sopenharmony_ci} 40941cb0ef41Sopenharmony_ci 40951cb0ef41Sopenharmony_ci} // namespace 40961cb0ef41Sopenharmony_ci 40971cb0ef41Sopenharmony_ciMaybe<bool> JSObject::TestIntegrityLevel(Handle<JSObject> object, 40981cb0ef41Sopenharmony_ci IntegrityLevel level) { 40991cb0ef41Sopenharmony_ci if (!object->map().IsCustomElementsReceiverMap() && 41001cb0ef41Sopenharmony_ci !object->HasSloppyArgumentsElements()) { 41011cb0ef41Sopenharmony_ci return Just(FastTestIntegrityLevel(*object, level)); 41021cb0ef41Sopenharmony_ci } 41031cb0ef41Sopenharmony_ci return GenericTestIntegrityLevel(Handle<JSReceiver>::cast(object), level); 41041cb0ef41Sopenharmony_ci} 41051cb0ef41Sopenharmony_ci 41061cb0ef41Sopenharmony_ciMaybe<bool> JSObject::PreventExtensions(Handle<JSObject> object, 41071cb0ef41Sopenharmony_ci ShouldThrow should_throw) { 41081cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 41091cb0ef41Sopenharmony_ci 41101cb0ef41Sopenharmony_ci if (!object->HasSloppyArgumentsElements()) { 41111cb0ef41Sopenharmony_ci return PreventExtensionsWithTransition<NONE>(object, should_throw); 41121cb0ef41Sopenharmony_ci } 41131cb0ef41Sopenharmony_ci 41141cb0ef41Sopenharmony_ci if (object->IsAccessCheckNeeded() && 41151cb0ef41Sopenharmony_ci !isolate->MayAccess(handle(isolate->context(), isolate), object)) { 41161cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(object); 41171cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 41181cb0ef41Sopenharmony_ci RETURN_FAILURE(isolate, should_throw, 41191cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kNoAccess)); 41201cb0ef41Sopenharmony_ci } 41211cb0ef41Sopenharmony_ci 41221cb0ef41Sopenharmony_ci if (!object->map().is_extensible()) return Just(true); 41231cb0ef41Sopenharmony_ci 41241cb0ef41Sopenharmony_ci if (object->IsJSGlobalProxy()) { 41251cb0ef41Sopenharmony_ci PrototypeIterator iter(isolate, object); 41261cb0ef41Sopenharmony_ci if (iter.IsAtEnd()) return Just(true); 41271cb0ef41Sopenharmony_ci DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); 41281cb0ef41Sopenharmony_ci return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter), 41291cb0ef41Sopenharmony_ci should_throw); 41301cb0ef41Sopenharmony_ci } 41311cb0ef41Sopenharmony_ci 41321cb0ef41Sopenharmony_ci if (object->map().has_named_interceptor() || 41331cb0ef41Sopenharmony_ci object->map().has_indexed_interceptor()) { 41341cb0ef41Sopenharmony_ci RETURN_FAILURE(isolate, should_throw, 41351cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kCannotPreventExt)); 41361cb0ef41Sopenharmony_ci } 41371cb0ef41Sopenharmony_ci 41381cb0ef41Sopenharmony_ci DCHECK(!object->HasTypedArrayOrRabGsabTypedArrayElements()); 41391cb0ef41Sopenharmony_ci 41401cb0ef41Sopenharmony_ci // Normalize fast elements. 41411cb0ef41Sopenharmony_ci Handle<NumberDictionary> dictionary = NormalizeElements(object); 41421cb0ef41Sopenharmony_ci DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); 41431cb0ef41Sopenharmony_ci 41441cb0ef41Sopenharmony_ci // Make sure that we never go back to fast case. 41451cb0ef41Sopenharmony_ci if (*dictionary != ReadOnlyRoots(isolate).empty_slow_element_dictionary()) { 41461cb0ef41Sopenharmony_ci object->RequireSlowElements(*dictionary); 41471cb0ef41Sopenharmony_ci } 41481cb0ef41Sopenharmony_ci 41491cb0ef41Sopenharmony_ci // Do a map transition, other objects with this map may still 41501cb0ef41Sopenharmony_ci // be extensible. 41511cb0ef41Sopenharmony_ci // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 41521cb0ef41Sopenharmony_ci Handle<Map> new_map = 41531cb0ef41Sopenharmony_ci Map::Copy(isolate, handle(object->map(), isolate), "PreventExtensions"); 41541cb0ef41Sopenharmony_ci 41551cb0ef41Sopenharmony_ci new_map->set_is_extensible(false); 41561cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map); 41571cb0ef41Sopenharmony_ci DCHECK(!object->map().is_extensible()); 41581cb0ef41Sopenharmony_ci 41591cb0ef41Sopenharmony_ci return Just(true); 41601cb0ef41Sopenharmony_ci} 41611cb0ef41Sopenharmony_ci 41621cb0ef41Sopenharmony_cibool JSObject::IsExtensible(Handle<JSObject> object) { 41631cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 41641cb0ef41Sopenharmony_ci if (object->IsAccessCheckNeeded() && 41651cb0ef41Sopenharmony_ci !isolate->MayAccess(handle(isolate->context(), isolate), object)) { 41661cb0ef41Sopenharmony_ci return true; 41671cb0ef41Sopenharmony_ci } 41681cb0ef41Sopenharmony_ci if (object->IsJSGlobalProxy()) { 41691cb0ef41Sopenharmony_ci PrototypeIterator iter(isolate, *object); 41701cb0ef41Sopenharmony_ci if (iter.IsAtEnd()) return false; 41711cb0ef41Sopenharmony_ci DCHECK(iter.GetCurrent().IsJSGlobalObject()); 41721cb0ef41Sopenharmony_ci return iter.GetCurrent<JSObject>().map().is_extensible(); 41731cb0ef41Sopenharmony_ci } 41741cb0ef41Sopenharmony_ci return object->map().is_extensible(); 41751cb0ef41Sopenharmony_ci} 41761cb0ef41Sopenharmony_ci 41771cb0ef41Sopenharmony_ci// static 41781cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::ReadFromOptionsBag(Handle<Object> options, 41791cb0ef41Sopenharmony_ci Handle<String> option_name, 41801cb0ef41Sopenharmony_ci Isolate* isolate) { 41811cb0ef41Sopenharmony_ci if (options->IsJSReceiver()) { 41821cb0ef41Sopenharmony_ci Handle<JSReceiver> js_options = Handle<JSReceiver>::cast(options); 41831cb0ef41Sopenharmony_ci return JSObject::GetProperty(isolate, js_options, option_name); 41841cb0ef41Sopenharmony_ci } 41851cb0ef41Sopenharmony_ci return MaybeHandle<Object>(isolate->factory()->undefined_value()); 41861cb0ef41Sopenharmony_ci} 41871cb0ef41Sopenharmony_ci 41881cb0ef41Sopenharmony_citemplate <typename Dictionary> 41891cb0ef41Sopenharmony_civoid JSObject::ApplyAttributesToDictionary( 41901cb0ef41Sopenharmony_ci Isolate* isolate, ReadOnlyRoots roots, Handle<Dictionary> dictionary, 41911cb0ef41Sopenharmony_ci const PropertyAttributes attributes) { 41921cb0ef41Sopenharmony_ci for (InternalIndex i : dictionary->IterateEntries()) { 41931cb0ef41Sopenharmony_ci Object k; 41941cb0ef41Sopenharmony_ci if (!dictionary->ToKey(roots, i, &k)) continue; 41951cb0ef41Sopenharmony_ci if (k.FilterKey(ALL_PROPERTIES)) continue; 41961cb0ef41Sopenharmony_ci PropertyDetails details = dictionary->DetailsAt(i); 41971cb0ef41Sopenharmony_ci int attrs = attributes; 41981cb0ef41Sopenharmony_ci // READ_ONLY is an invalid attribute for JS setters/getters. 41991cb0ef41Sopenharmony_ci if ((attributes & READ_ONLY) && details.kind() == PropertyKind::kAccessor) { 42001cb0ef41Sopenharmony_ci Object v = dictionary->ValueAt(i); 42011cb0ef41Sopenharmony_ci if (v.IsAccessorPair()) attrs &= ~READ_ONLY; 42021cb0ef41Sopenharmony_ci } 42031cb0ef41Sopenharmony_ci details = details.CopyAddAttributes(PropertyAttributesFromInt(attrs)); 42041cb0ef41Sopenharmony_ci dictionary->DetailsAtPut(i, details); 42051cb0ef41Sopenharmony_ci } 42061cb0ef41Sopenharmony_ci} 42071cb0ef41Sopenharmony_ci 42081cb0ef41Sopenharmony_citemplate void JSObject::ApplyAttributesToDictionary( 42091cb0ef41Sopenharmony_ci Isolate* isolate, ReadOnlyRoots roots, Handle<NumberDictionary> dictionary, 42101cb0ef41Sopenharmony_ci const PropertyAttributes attributes); 42111cb0ef41Sopenharmony_ci 42121cb0ef41Sopenharmony_ciHandle<NumberDictionary> CreateElementDictionary(Isolate* isolate, 42131cb0ef41Sopenharmony_ci Handle<JSObject> object) { 42141cb0ef41Sopenharmony_ci Handle<NumberDictionary> new_element_dictionary; 42151cb0ef41Sopenharmony_ci if (!object->HasTypedArrayOrRabGsabTypedArrayElements() && 42161cb0ef41Sopenharmony_ci !object->HasDictionaryElements() && 42171cb0ef41Sopenharmony_ci !object->HasSlowStringWrapperElements()) { 42181cb0ef41Sopenharmony_ci int length = object->IsJSArray() 42191cb0ef41Sopenharmony_ci ? Smi::ToInt(Handle<JSArray>::cast(object)->length()) 42201cb0ef41Sopenharmony_ci : object->elements().length(); 42211cb0ef41Sopenharmony_ci new_element_dictionary = 42221cb0ef41Sopenharmony_ci length == 0 ? isolate->factory()->empty_slow_element_dictionary() 42231cb0ef41Sopenharmony_ci : object->GetElementsAccessor()->Normalize(object); 42241cb0ef41Sopenharmony_ci } 42251cb0ef41Sopenharmony_ci return new_element_dictionary; 42261cb0ef41Sopenharmony_ci} 42271cb0ef41Sopenharmony_ci 42281cb0ef41Sopenharmony_citemplate <PropertyAttributes attrs> 42291cb0ef41Sopenharmony_ciMaybe<bool> JSObject::PreventExtensionsWithTransition( 42301cb0ef41Sopenharmony_ci Handle<JSObject> object, ShouldThrow should_throw) { 42311cb0ef41Sopenharmony_ci STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN); 42321cb0ef41Sopenharmony_ci 42331cb0ef41Sopenharmony_ci // Sealing/freezing sloppy arguments or namespace objects should be handled 42341cb0ef41Sopenharmony_ci // elsewhere. 42351cb0ef41Sopenharmony_ci DCHECK(!object->HasSloppyArgumentsElements()); 42361cb0ef41Sopenharmony_ci DCHECK_IMPLIES(object->IsJSModuleNamespace(), attrs == NONE); 42371cb0ef41Sopenharmony_ci 42381cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 42391cb0ef41Sopenharmony_ci if (object->IsAccessCheckNeeded() && 42401cb0ef41Sopenharmony_ci !isolate->MayAccess(handle(isolate->context(), isolate), object)) { 42411cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(object); 42421cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 42431cb0ef41Sopenharmony_ci RETURN_FAILURE(isolate, should_throw, 42441cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kNoAccess)); 42451cb0ef41Sopenharmony_ci } 42461cb0ef41Sopenharmony_ci 42471cb0ef41Sopenharmony_ci if (attrs == NONE && !object->map().is_extensible()) { 42481cb0ef41Sopenharmony_ci return Just(true); 42491cb0ef41Sopenharmony_ci } 42501cb0ef41Sopenharmony_ci 42511cb0ef41Sopenharmony_ci { 42521cb0ef41Sopenharmony_ci ElementsKind old_elements_kind = object->map().elements_kind(); 42531cb0ef41Sopenharmony_ci if (IsFrozenElementsKind(old_elements_kind)) return Just(true); 42541cb0ef41Sopenharmony_ci if (attrs != FROZEN && IsSealedElementsKind(old_elements_kind)) { 42551cb0ef41Sopenharmony_ci return Just(true); 42561cb0ef41Sopenharmony_ci } 42571cb0ef41Sopenharmony_ci } 42581cb0ef41Sopenharmony_ci 42591cb0ef41Sopenharmony_ci if (object->IsJSGlobalProxy()) { 42601cb0ef41Sopenharmony_ci PrototypeIterator iter(isolate, object); 42611cb0ef41Sopenharmony_ci if (iter.IsAtEnd()) return Just(true); 42621cb0ef41Sopenharmony_ci DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); 42631cb0ef41Sopenharmony_ci return PreventExtensionsWithTransition<attrs>( 42641cb0ef41Sopenharmony_ci PrototypeIterator::GetCurrent<JSObject>(iter), should_throw); 42651cb0ef41Sopenharmony_ci } 42661cb0ef41Sopenharmony_ci 42671cb0ef41Sopenharmony_ci if (object->map().has_named_interceptor() || 42681cb0ef41Sopenharmony_ci object->map().has_indexed_interceptor()) { 42691cb0ef41Sopenharmony_ci MessageTemplate message = MessageTemplate::kNone; 42701cb0ef41Sopenharmony_ci switch (attrs) { 42711cb0ef41Sopenharmony_ci case NONE: 42721cb0ef41Sopenharmony_ci message = MessageTemplate::kCannotPreventExt; 42731cb0ef41Sopenharmony_ci break; 42741cb0ef41Sopenharmony_ci 42751cb0ef41Sopenharmony_ci case SEALED: 42761cb0ef41Sopenharmony_ci message = MessageTemplate::kCannotSeal; 42771cb0ef41Sopenharmony_ci break; 42781cb0ef41Sopenharmony_ci 42791cb0ef41Sopenharmony_ci case FROZEN: 42801cb0ef41Sopenharmony_ci message = MessageTemplate::kCannotFreeze; 42811cb0ef41Sopenharmony_ci break; 42821cb0ef41Sopenharmony_ci } 42831cb0ef41Sopenharmony_ci RETURN_FAILURE(isolate, should_throw, NewTypeError(message)); 42841cb0ef41Sopenharmony_ci } 42851cb0ef41Sopenharmony_ci 42861cb0ef41Sopenharmony_ci Handle<Symbol> transition_marker; 42871cb0ef41Sopenharmony_ci if (attrs == NONE) { 42881cb0ef41Sopenharmony_ci transition_marker = isolate->factory()->nonextensible_symbol(); 42891cb0ef41Sopenharmony_ci } else if (attrs == SEALED) { 42901cb0ef41Sopenharmony_ci transition_marker = isolate->factory()->sealed_symbol(); 42911cb0ef41Sopenharmony_ci } else { 42921cb0ef41Sopenharmony_ci DCHECK(attrs == FROZEN); 42931cb0ef41Sopenharmony_ci transition_marker = isolate->factory()->frozen_symbol(); 42941cb0ef41Sopenharmony_ci } 42951cb0ef41Sopenharmony_ci 42961cb0ef41Sopenharmony_ci // Currently, there are only have sealed/frozen Object element kinds and 42971cb0ef41Sopenharmony_ci // Map::MigrateToMap doesn't handle properties' attributes reconfiguring and 42981cb0ef41Sopenharmony_ci // elements kind change in one go. If seal or freeze with Smi or Double 42991cb0ef41Sopenharmony_ci // elements kind, we will transition to Object elements kind first to make 43001cb0ef41Sopenharmony_ci // sure of valid element access. 43011cb0ef41Sopenharmony_ci if (FLAG_enable_sealed_frozen_elements_kind) { 43021cb0ef41Sopenharmony_ci switch (object->map().elements_kind()) { 43031cb0ef41Sopenharmony_ci case PACKED_SMI_ELEMENTS: 43041cb0ef41Sopenharmony_ci case PACKED_DOUBLE_ELEMENTS: 43051cb0ef41Sopenharmony_ci JSObject::TransitionElementsKind(object, PACKED_ELEMENTS); 43061cb0ef41Sopenharmony_ci break; 43071cb0ef41Sopenharmony_ci case HOLEY_SMI_ELEMENTS: 43081cb0ef41Sopenharmony_ci case HOLEY_DOUBLE_ELEMENTS: 43091cb0ef41Sopenharmony_ci JSObject::TransitionElementsKind(object, HOLEY_ELEMENTS); 43101cb0ef41Sopenharmony_ci break; 43111cb0ef41Sopenharmony_ci default: 43121cb0ef41Sopenharmony_ci break; 43131cb0ef41Sopenharmony_ci } 43141cb0ef41Sopenharmony_ci } 43151cb0ef41Sopenharmony_ci 43161cb0ef41Sopenharmony_ci // Make sure we only use this element dictionary in case we can't transition 43171cb0ef41Sopenharmony_ci // to sealed, frozen elements kind. 43181cb0ef41Sopenharmony_ci Handle<NumberDictionary> new_element_dictionary; 43191cb0ef41Sopenharmony_ci 43201cb0ef41Sopenharmony_ci Handle<Map> old_map(object->map(), isolate); 43211cb0ef41Sopenharmony_ci old_map = Map::Update(isolate, old_map); 43221cb0ef41Sopenharmony_ci Handle<Map> transition_map; 43231cb0ef41Sopenharmony_ci MaybeHandle<Map> maybe_transition_map = 43241cb0ef41Sopenharmony_ci TransitionsAccessor::SearchSpecial(isolate, old_map, *transition_marker); 43251cb0ef41Sopenharmony_ci if (maybe_transition_map.ToHandle(&transition_map)) { 43261cb0ef41Sopenharmony_ci DCHECK(transition_map->has_dictionary_elements() || 43271cb0ef41Sopenharmony_ci transition_map->has_typed_array_or_rab_gsab_typed_array_elements() || 43281cb0ef41Sopenharmony_ci transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS || 43291cb0ef41Sopenharmony_ci transition_map->has_any_nonextensible_elements()); 43301cb0ef41Sopenharmony_ci DCHECK(!transition_map->is_extensible()); 43311cb0ef41Sopenharmony_ci if (!transition_map->has_any_nonextensible_elements()) { 43321cb0ef41Sopenharmony_ci new_element_dictionary = CreateElementDictionary(isolate, object); 43331cb0ef41Sopenharmony_ci } 43341cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, transition_map); 43351cb0ef41Sopenharmony_ci } else if (TransitionsAccessor::CanHaveMoreTransitions(isolate, old_map)) { 43361cb0ef41Sopenharmony_ci // Create a new descriptor array with the appropriate property attributes 43371cb0ef41Sopenharmony_ci Handle<Map> new_map = Map::CopyForPreventExtensions( 43381cb0ef41Sopenharmony_ci isolate, old_map, attrs, transition_marker, "CopyForPreventExtensions"); 43391cb0ef41Sopenharmony_ci if (!new_map->has_any_nonextensible_elements()) { 43401cb0ef41Sopenharmony_ci new_element_dictionary = CreateElementDictionary(isolate, object); 43411cb0ef41Sopenharmony_ci } 43421cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map); 43431cb0ef41Sopenharmony_ci } else { 43441cb0ef41Sopenharmony_ci DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); 43451cb0ef41Sopenharmony_ci // Slow path: need to normalize properties for safety 43461cb0ef41Sopenharmony_ci NormalizeProperties(isolate, object, CLEAR_INOBJECT_PROPERTIES, 0, 43471cb0ef41Sopenharmony_ci "SlowPreventExtensions"); 43481cb0ef41Sopenharmony_ci 43491cb0ef41Sopenharmony_ci // Create a new map, since other objects with this map may be extensible. 43501cb0ef41Sopenharmony_ci // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 43511cb0ef41Sopenharmony_ci Handle<Map> new_map = Map::Copy(isolate, handle(object->map(), isolate), 43521cb0ef41Sopenharmony_ci "SlowCopyForPreventExtensions"); 43531cb0ef41Sopenharmony_ci new_map->set_is_extensible(false); 43541cb0ef41Sopenharmony_ci new_element_dictionary = CreateElementDictionary(isolate, object); 43551cb0ef41Sopenharmony_ci if (!new_element_dictionary.is_null()) { 43561cb0ef41Sopenharmony_ci ElementsKind new_kind = 43571cb0ef41Sopenharmony_ci IsStringWrapperElementsKind(old_map->elements_kind()) 43581cb0ef41Sopenharmony_ci ? SLOW_STRING_WRAPPER_ELEMENTS 43591cb0ef41Sopenharmony_ci : DICTIONARY_ELEMENTS; 43601cb0ef41Sopenharmony_ci new_map->set_elements_kind(new_kind); 43611cb0ef41Sopenharmony_ci } 43621cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map); 43631cb0ef41Sopenharmony_ci 43641cb0ef41Sopenharmony_ci if (attrs != NONE) { 43651cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 43661cb0ef41Sopenharmony_ci if (object->IsJSGlobalObject()) { 43671cb0ef41Sopenharmony_ci Handle<GlobalDictionary> dictionary( 43681cb0ef41Sopenharmony_ci JSGlobalObject::cast(*object).global_dictionary(kAcquireLoad), 43691cb0ef41Sopenharmony_ci isolate); 43701cb0ef41Sopenharmony_ci JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary, 43711cb0ef41Sopenharmony_ci attrs); 43721cb0ef41Sopenharmony_ci } else if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 43731cb0ef41Sopenharmony_ci Handle<SwissNameDictionary> dictionary( 43741cb0ef41Sopenharmony_ci object->property_dictionary_swiss(), isolate); 43751cb0ef41Sopenharmony_ci JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary, 43761cb0ef41Sopenharmony_ci attrs); 43771cb0ef41Sopenharmony_ci } else { 43781cb0ef41Sopenharmony_ci Handle<NameDictionary> dictionary(object->property_dictionary(), 43791cb0ef41Sopenharmony_ci isolate); 43801cb0ef41Sopenharmony_ci JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary, 43811cb0ef41Sopenharmony_ci attrs); 43821cb0ef41Sopenharmony_ci } 43831cb0ef41Sopenharmony_ci } 43841cb0ef41Sopenharmony_ci } 43851cb0ef41Sopenharmony_ci 43861cb0ef41Sopenharmony_ci if (object->map().has_any_nonextensible_elements()) { 43871cb0ef41Sopenharmony_ci DCHECK(new_element_dictionary.is_null()); 43881cb0ef41Sopenharmony_ci return Just(true); 43891cb0ef41Sopenharmony_ci } 43901cb0ef41Sopenharmony_ci 43911cb0ef41Sopenharmony_ci // Both seal and preventExtensions always go through without modifications to 43921cb0ef41Sopenharmony_ci // typed array elements. Freeze works only if there are no actual elements. 43931cb0ef41Sopenharmony_ci if (object->HasTypedArrayOrRabGsabTypedArrayElements()) { 43941cb0ef41Sopenharmony_ci DCHECK(new_element_dictionary.is_null()); 43951cb0ef41Sopenharmony_ci if (attrs == FROZEN && JSTypedArray::cast(*object).GetLength() > 0) { 43961cb0ef41Sopenharmony_ci isolate->Throw(*isolate->factory()->NewTypeError( 43971cb0ef41Sopenharmony_ci MessageTemplate::kCannotFreezeArrayBufferView)); 43981cb0ef41Sopenharmony_ci return Nothing<bool>(); 43991cb0ef41Sopenharmony_ci } 44001cb0ef41Sopenharmony_ci return Just(true); 44011cb0ef41Sopenharmony_ci } 44021cb0ef41Sopenharmony_ci 44031cb0ef41Sopenharmony_ci DCHECK(object->map().has_dictionary_elements() || 44041cb0ef41Sopenharmony_ci object->map().elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS); 44051cb0ef41Sopenharmony_ci if (!new_element_dictionary.is_null()) { 44061cb0ef41Sopenharmony_ci object->set_elements(*new_element_dictionary); 44071cb0ef41Sopenharmony_ci } 44081cb0ef41Sopenharmony_ci 44091cb0ef41Sopenharmony_ci if (object->elements() != 44101cb0ef41Sopenharmony_ci ReadOnlyRoots(isolate).empty_slow_element_dictionary()) { 44111cb0ef41Sopenharmony_ci Handle<NumberDictionary> dictionary(object->element_dictionary(), isolate); 44121cb0ef41Sopenharmony_ci // Make sure we never go back to the fast case 44131cb0ef41Sopenharmony_ci object->RequireSlowElements(*dictionary); 44141cb0ef41Sopenharmony_ci if (attrs != NONE) { 44151cb0ef41Sopenharmony_ci JSObject::ApplyAttributesToDictionary(isolate, ReadOnlyRoots(isolate), 44161cb0ef41Sopenharmony_ci dictionary, attrs); 44171cb0ef41Sopenharmony_ci } 44181cb0ef41Sopenharmony_ci } 44191cb0ef41Sopenharmony_ci 44201cb0ef41Sopenharmony_ci return Just(true); 44211cb0ef41Sopenharmony_ci} 44221cb0ef41Sopenharmony_ci 44231cb0ef41Sopenharmony_ciHandle<Object> JSObject::FastPropertyAt(Isolate* isolate, 44241cb0ef41Sopenharmony_ci Handle<JSObject> object, 44251cb0ef41Sopenharmony_ci Representation representation, 44261cb0ef41Sopenharmony_ci FieldIndex index) { 44271cb0ef41Sopenharmony_ci Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate); 44281cb0ef41Sopenharmony_ci return Object::WrapForRead(isolate, raw_value, representation); 44291cb0ef41Sopenharmony_ci} 44301cb0ef41Sopenharmony_ci 44311cb0ef41Sopenharmony_ciHandle<Object> JSObject::FastPropertyAt(Isolate* isolate, 44321cb0ef41Sopenharmony_ci Handle<JSObject> object, 44331cb0ef41Sopenharmony_ci Representation representation, 44341cb0ef41Sopenharmony_ci FieldIndex index, SeqCstAccessTag tag) { 44351cb0ef41Sopenharmony_ci Handle<Object> raw_value(object->RawFastPropertyAt(index, tag), isolate); 44361cb0ef41Sopenharmony_ci return Object::WrapForRead(isolate, raw_value, representation); 44371cb0ef41Sopenharmony_ci} 44381cb0ef41Sopenharmony_ci 44391cb0ef41Sopenharmony_ci// static 44401cb0ef41Sopenharmony_ciHandle<Object> JSObject::DictionaryPropertyAt(Isolate* isolate, 44411cb0ef41Sopenharmony_ci Handle<JSObject> object, 44421cb0ef41Sopenharmony_ci InternalIndex dict_index) { 44431cb0ef41Sopenharmony_ci DCHECK_EQ(ThreadId::Current(), isolate->thread_id()); 44441cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 44451cb0ef41Sopenharmony_ci SwissNameDictionary dict = object->property_dictionary_swiss(); 44461cb0ef41Sopenharmony_ci return handle(dict.ValueAt(dict_index), isolate); 44471cb0ef41Sopenharmony_ci } else { 44481cb0ef41Sopenharmony_ci NameDictionary dict = object->property_dictionary(); 44491cb0ef41Sopenharmony_ci return handle(dict.ValueAt(dict_index), isolate); 44501cb0ef41Sopenharmony_ci } 44511cb0ef41Sopenharmony_ci} 44521cb0ef41Sopenharmony_ci 44531cb0ef41Sopenharmony_ci// static 44541cb0ef41Sopenharmony_cibase::Optional<Object> JSObject::DictionaryPropertyAt(Handle<JSObject> object, 44551cb0ef41Sopenharmony_ci InternalIndex dict_index, 44561cb0ef41Sopenharmony_ci Heap* heap) { 44571cb0ef41Sopenharmony_ci Object backing_store = object->raw_properties_or_hash(kRelaxedLoad); 44581cb0ef41Sopenharmony_ci if (!backing_store.IsHeapObject()) return {}; 44591cb0ef41Sopenharmony_ci if (heap->IsPendingAllocation(HeapObject::cast(backing_store))) return {}; 44601cb0ef41Sopenharmony_ci 44611cb0ef41Sopenharmony_ci base::Optional<Object> maybe_obj; 44621cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 44631cb0ef41Sopenharmony_ci if (!backing_store.IsSwissNameDictionary()) return {}; 44641cb0ef41Sopenharmony_ci maybe_obj = SwissNameDictionary::cast(backing_store).TryValueAt(dict_index); 44651cb0ef41Sopenharmony_ci } else { 44661cb0ef41Sopenharmony_ci if (!backing_store.IsNameDictionary()) return {}; 44671cb0ef41Sopenharmony_ci maybe_obj = NameDictionary::cast(backing_store).TryValueAt(dict_index); 44681cb0ef41Sopenharmony_ci } 44691cb0ef41Sopenharmony_ci 44701cb0ef41Sopenharmony_ci if (!maybe_obj) return {}; 44711cb0ef41Sopenharmony_ci return maybe_obj.value(); 44721cb0ef41Sopenharmony_ci} 44731cb0ef41Sopenharmony_ci 44741cb0ef41Sopenharmony_ci// TODO(cbruni/jkummerow): Consider moving this into elements.cc. 44751cb0ef41Sopenharmony_cibool JSObject::HasEnumerableElements() { 44761cb0ef41Sopenharmony_ci // TODO(cbruni): cleanup 44771cb0ef41Sopenharmony_ci JSObject object = *this; 44781cb0ef41Sopenharmony_ci switch (object.GetElementsKind()) { 44791cb0ef41Sopenharmony_ci case PACKED_SMI_ELEMENTS: 44801cb0ef41Sopenharmony_ci case PACKED_ELEMENTS: 44811cb0ef41Sopenharmony_ci case PACKED_FROZEN_ELEMENTS: 44821cb0ef41Sopenharmony_ci case PACKED_SEALED_ELEMENTS: 44831cb0ef41Sopenharmony_ci case PACKED_NONEXTENSIBLE_ELEMENTS: 44841cb0ef41Sopenharmony_ci case PACKED_DOUBLE_ELEMENTS: { 44851cb0ef41Sopenharmony_ci int length = object.IsJSArray() 44861cb0ef41Sopenharmony_ci ? Smi::ToInt(JSArray::cast(object).length()) 44871cb0ef41Sopenharmony_ci : object.elements().length(); 44881cb0ef41Sopenharmony_ci return length > 0; 44891cb0ef41Sopenharmony_ci } 44901cb0ef41Sopenharmony_ci case HOLEY_SMI_ELEMENTS: 44911cb0ef41Sopenharmony_ci case HOLEY_FROZEN_ELEMENTS: 44921cb0ef41Sopenharmony_ci case HOLEY_SEALED_ELEMENTS: 44931cb0ef41Sopenharmony_ci case HOLEY_NONEXTENSIBLE_ELEMENTS: 44941cb0ef41Sopenharmony_ci case HOLEY_ELEMENTS: { 44951cb0ef41Sopenharmony_ci FixedArray elements = FixedArray::cast(object.elements()); 44961cb0ef41Sopenharmony_ci int length = object.IsJSArray() 44971cb0ef41Sopenharmony_ci ? Smi::ToInt(JSArray::cast(object).length()) 44981cb0ef41Sopenharmony_ci : elements.length(); 44991cb0ef41Sopenharmony_ci Isolate* isolate = GetIsolate(); 45001cb0ef41Sopenharmony_ci for (int i = 0; i < length; i++) { 45011cb0ef41Sopenharmony_ci if (!elements.is_the_hole(isolate, i)) return true; 45021cb0ef41Sopenharmony_ci } 45031cb0ef41Sopenharmony_ci return false; 45041cb0ef41Sopenharmony_ci } 45051cb0ef41Sopenharmony_ci case HOLEY_DOUBLE_ELEMENTS: { 45061cb0ef41Sopenharmony_ci int length = object.IsJSArray() 45071cb0ef41Sopenharmony_ci ? Smi::ToInt(JSArray::cast(object).length()) 45081cb0ef41Sopenharmony_ci : object.elements().length(); 45091cb0ef41Sopenharmony_ci // Zero-length arrays would use the empty FixedArray... 45101cb0ef41Sopenharmony_ci if (length == 0) return false; 45111cb0ef41Sopenharmony_ci // ...so only cast to FixedDoubleArray otherwise. 45121cb0ef41Sopenharmony_ci FixedDoubleArray elements = FixedDoubleArray::cast(object.elements()); 45131cb0ef41Sopenharmony_ci for (int i = 0; i < length; i++) { 45141cb0ef41Sopenharmony_ci if (!elements.is_the_hole(i)) return true; 45151cb0ef41Sopenharmony_ci } 45161cb0ef41Sopenharmony_ci return false; 45171cb0ef41Sopenharmony_ci } 45181cb0ef41Sopenharmony_ci#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS: 45191cb0ef41Sopenharmony_ci 45201cb0ef41Sopenharmony_ci TYPED_ARRAYS(TYPED_ARRAY_CASE) { 45211cb0ef41Sopenharmony_ci size_t length = JSTypedArray::cast(object).length(); 45221cb0ef41Sopenharmony_ci return length > 0; 45231cb0ef41Sopenharmony_ci } 45241cb0ef41Sopenharmony_ci 45251cb0ef41Sopenharmony_ci RAB_GSAB_TYPED_ARRAYS(TYPED_ARRAY_CASE) 45261cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_CASE 45271cb0ef41Sopenharmony_ci { 45281cb0ef41Sopenharmony_ci size_t length = JSTypedArray::cast(object).GetLength(); 45291cb0ef41Sopenharmony_ci return length > 0; 45301cb0ef41Sopenharmony_ci } 45311cb0ef41Sopenharmony_ci case DICTIONARY_ELEMENTS: { 45321cb0ef41Sopenharmony_ci NumberDictionary elements = NumberDictionary::cast(object.elements()); 45331cb0ef41Sopenharmony_ci return elements.NumberOfEnumerableProperties() > 0; 45341cb0ef41Sopenharmony_ci } 45351cb0ef41Sopenharmony_ci case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 45361cb0ef41Sopenharmony_ci case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 45371cb0ef41Sopenharmony_ci // We're approximating non-empty arguments objects here. 45381cb0ef41Sopenharmony_ci return true; 45391cb0ef41Sopenharmony_ci case FAST_STRING_WRAPPER_ELEMENTS: 45401cb0ef41Sopenharmony_ci case SLOW_STRING_WRAPPER_ELEMENTS: 45411cb0ef41Sopenharmony_ci if (String::cast(JSPrimitiveWrapper::cast(object).value()).length() > 0) { 45421cb0ef41Sopenharmony_ci return true; 45431cb0ef41Sopenharmony_ci } 45441cb0ef41Sopenharmony_ci return object.elements().length() > 0; 45451cb0ef41Sopenharmony_ci case WASM_ARRAY_ELEMENTS: 45461cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 45471cb0ef41Sopenharmony_ci 45481cb0ef41Sopenharmony_ci case NO_ELEMENTS: 45491cb0ef41Sopenharmony_ci return false; 45501cb0ef41Sopenharmony_ci } 45511cb0ef41Sopenharmony_ci UNREACHABLE(); 45521cb0ef41Sopenharmony_ci} 45531cb0ef41Sopenharmony_ci 45541cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, 45551cb0ef41Sopenharmony_ci Handle<Name> name, 45561cb0ef41Sopenharmony_ci Handle<Object> getter, 45571cb0ef41Sopenharmony_ci Handle<Object> setter, 45581cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 45591cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 45601cb0ef41Sopenharmony_ci 45611cb0ef41Sopenharmony_ci PropertyKey key(isolate, name); 45621cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, key, LookupIterator::OWN_SKIP_INTERCEPTOR); 45631cb0ef41Sopenharmony_ci return DefineAccessor(&it, getter, setter, attributes); 45641cb0ef41Sopenharmony_ci} 45651cb0ef41Sopenharmony_ci 45661cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it, 45671cb0ef41Sopenharmony_ci Handle<Object> getter, 45681cb0ef41Sopenharmony_ci Handle<Object> setter, 45691cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 45701cb0ef41Sopenharmony_ci Isolate* isolate = it->isolate(); 45711cb0ef41Sopenharmony_ci 45721cb0ef41Sopenharmony_ci it->UpdateProtector(); 45731cb0ef41Sopenharmony_ci 45741cb0ef41Sopenharmony_ci if (it->state() == LookupIterator::ACCESS_CHECK) { 45751cb0ef41Sopenharmony_ci if (!it->HasAccess()) { 45761cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()); 45771cb0ef41Sopenharmony_ci RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 45781cb0ef41Sopenharmony_ci return isolate->factory()->undefined_value(); 45791cb0ef41Sopenharmony_ci } 45801cb0ef41Sopenharmony_ci it->Next(); 45811cb0ef41Sopenharmony_ci } 45821cb0ef41Sopenharmony_ci 45831cb0ef41Sopenharmony_ci Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); 45841cb0ef41Sopenharmony_ci // Ignore accessors on typed arrays. 45851cb0ef41Sopenharmony_ci if (it->IsElement() && object->HasTypedArrayOrRabGsabTypedArrayElements()) { 45861cb0ef41Sopenharmony_ci return it->factory()->undefined_value(); 45871cb0ef41Sopenharmony_ci } 45881cb0ef41Sopenharmony_ci 45891cb0ef41Sopenharmony_ci DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) || 45901cb0ef41Sopenharmony_ci getter->IsNull(isolate) || getter->IsFunctionTemplateInfo()); 45911cb0ef41Sopenharmony_ci DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) || 45921cb0ef41Sopenharmony_ci setter->IsNull(isolate) || setter->IsFunctionTemplateInfo()); 45931cb0ef41Sopenharmony_ci it->TransitionToAccessorProperty(getter, setter, attributes); 45941cb0ef41Sopenharmony_ci 45951cb0ef41Sopenharmony_ci return isolate->factory()->undefined_value(); 45961cb0ef41Sopenharmony_ci} 45971cb0ef41Sopenharmony_ci 45981cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object, 45991cb0ef41Sopenharmony_ci Handle<Name> name, 46001cb0ef41Sopenharmony_ci Handle<AccessorInfo> info, 46011cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 46021cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 46031cb0ef41Sopenharmony_ci 46041cb0ef41Sopenharmony_ci PropertyKey key(isolate, name); 46051cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, key, LookupIterator::OWN_SKIP_INTERCEPTOR); 46061cb0ef41Sopenharmony_ci 46071cb0ef41Sopenharmony_ci // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that 46081cb0ef41Sopenharmony_ci // the FailedAccessCheckCallbackFunction doesn't throw an exception. 46091cb0ef41Sopenharmony_ci // 46101cb0ef41Sopenharmony_ci // TODO(verwaest): Force throw an exception if the callback doesn't, so we can 46111cb0ef41Sopenharmony_ci // remove reliance on default return values. 46121cb0ef41Sopenharmony_ci if (it.state() == LookupIterator::ACCESS_CHECK) { 46131cb0ef41Sopenharmony_ci if (!it.HasAccess()) { 46141cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(object); 46151cb0ef41Sopenharmony_ci RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 46161cb0ef41Sopenharmony_ci return it.factory()->undefined_value(); 46171cb0ef41Sopenharmony_ci } 46181cb0ef41Sopenharmony_ci it.Next(); 46191cb0ef41Sopenharmony_ci } 46201cb0ef41Sopenharmony_ci 46211cb0ef41Sopenharmony_ci // Ignore accessors on typed arrays. 46221cb0ef41Sopenharmony_ci if (it.IsElement() && object->HasTypedArrayOrRabGsabTypedArrayElements()) { 46231cb0ef41Sopenharmony_ci return it.factory()->undefined_value(); 46241cb0ef41Sopenharmony_ci } 46251cb0ef41Sopenharmony_ci 46261cb0ef41Sopenharmony_ci CHECK(GetPropertyAttributes(&it).IsJust()); 46271cb0ef41Sopenharmony_ci 46281cb0ef41Sopenharmony_ci // ES5 forbids turning a property into an accessor if it's not 46291cb0ef41Sopenharmony_ci // configurable. See 8.6.1 (Table 5). 46301cb0ef41Sopenharmony_ci if (it.IsFound() && !it.IsConfigurable()) { 46311cb0ef41Sopenharmony_ci return it.factory()->undefined_value(); 46321cb0ef41Sopenharmony_ci } 46331cb0ef41Sopenharmony_ci 46341cb0ef41Sopenharmony_ci it.TransitionToAccessorPair(info, attributes); 46351cb0ef41Sopenharmony_ci 46361cb0ef41Sopenharmony_ci return object; 46371cb0ef41Sopenharmony_ci} 46381cb0ef41Sopenharmony_ci 46391cb0ef41Sopenharmony_ciObject JSObject::SlowReverseLookup(Object value) { 46401cb0ef41Sopenharmony_ci if (HasFastProperties()) { 46411cb0ef41Sopenharmony_ci DescriptorArray descs = map().instance_descriptors(); 46421cb0ef41Sopenharmony_ci bool value_is_number = value.IsNumber(); 46431cb0ef41Sopenharmony_ci for (InternalIndex i : map().IterateOwnDescriptors()) { 46441cb0ef41Sopenharmony_ci PropertyDetails details = descs.GetDetails(i); 46451cb0ef41Sopenharmony_ci if (details.location() == PropertyLocation::kField) { 46461cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyKind::kData, details.kind()); 46471cb0ef41Sopenharmony_ci FieldIndex field_index = FieldIndex::ForDescriptor(map(), i); 46481cb0ef41Sopenharmony_ci Object property = RawFastPropertyAt(field_index); 46491cb0ef41Sopenharmony_ci if (field_index.is_double()) { 46501cb0ef41Sopenharmony_ci DCHECK(property.IsHeapNumber()); 46511cb0ef41Sopenharmony_ci if (value_is_number && property.Number() == value.Number()) { 46521cb0ef41Sopenharmony_ci return descs.GetKey(i); 46531cb0ef41Sopenharmony_ci } 46541cb0ef41Sopenharmony_ci } else if (property == value) { 46551cb0ef41Sopenharmony_ci return descs.GetKey(i); 46561cb0ef41Sopenharmony_ci } 46571cb0ef41Sopenharmony_ci } else { 46581cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyLocation::kDescriptor, details.location()); 46591cb0ef41Sopenharmony_ci if (details.kind() == PropertyKind::kData) { 46601cb0ef41Sopenharmony_ci if (descs.GetStrongValue(i) == value) { 46611cb0ef41Sopenharmony_ci return descs.GetKey(i); 46621cb0ef41Sopenharmony_ci } 46631cb0ef41Sopenharmony_ci } 46641cb0ef41Sopenharmony_ci } 46651cb0ef41Sopenharmony_ci } 46661cb0ef41Sopenharmony_ci return GetReadOnlyRoots().undefined_value(); 46671cb0ef41Sopenharmony_ci } else if (IsJSGlobalObject()) { 46681cb0ef41Sopenharmony_ci return JSGlobalObject::cast(*this) 46691cb0ef41Sopenharmony_ci .global_dictionary(kAcquireLoad) 46701cb0ef41Sopenharmony_ci .SlowReverseLookup(value); 46711cb0ef41Sopenharmony_ci } else if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 46721cb0ef41Sopenharmony_ci return property_dictionary_swiss().SlowReverseLookup(GetIsolate(), value); 46731cb0ef41Sopenharmony_ci } else { 46741cb0ef41Sopenharmony_ci return property_dictionary().SlowReverseLookup(value); 46751cb0ef41Sopenharmony_ci } 46761cb0ef41Sopenharmony_ci} 46771cb0ef41Sopenharmony_ci 46781cb0ef41Sopenharmony_civoid JSObject::PrototypeRegistryCompactionCallback(HeapObject value, 46791cb0ef41Sopenharmony_ci int old_index, 46801cb0ef41Sopenharmony_ci int new_index) { 46811cb0ef41Sopenharmony_ci DCHECK(value.IsMap() && Map::cast(value).is_prototype_map()); 46821cb0ef41Sopenharmony_ci Map map = Map::cast(value); 46831cb0ef41Sopenharmony_ci DCHECK(map.prototype_info().IsPrototypeInfo()); 46841cb0ef41Sopenharmony_ci PrototypeInfo proto_info = PrototypeInfo::cast(map.prototype_info()); 46851cb0ef41Sopenharmony_ci DCHECK_EQ(old_index, proto_info.registry_slot()); 46861cb0ef41Sopenharmony_ci proto_info.set_registry_slot(new_index); 46871cb0ef41Sopenharmony_ci} 46881cb0ef41Sopenharmony_ci 46891cb0ef41Sopenharmony_ci// static 46901cb0ef41Sopenharmony_civoid JSObject::MakePrototypesFast(Handle<Object> receiver, 46911cb0ef41Sopenharmony_ci WhereToStart where_to_start, 46921cb0ef41Sopenharmony_ci Isolate* isolate) { 46931cb0ef41Sopenharmony_ci if (!receiver->IsJSReceiver()) return; 46941cb0ef41Sopenharmony_ci for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver), 46951cb0ef41Sopenharmony_ci where_to_start); 46961cb0ef41Sopenharmony_ci !iter.IsAtEnd(); iter.Advance()) { 46971cb0ef41Sopenharmony_ci Handle<Object> current = PrototypeIterator::GetCurrent(iter); 46981cb0ef41Sopenharmony_ci if (!current->IsJSObject()) return; 46991cb0ef41Sopenharmony_ci Handle<JSObject> current_obj = Handle<JSObject>::cast(current); 47001cb0ef41Sopenharmony_ci Map current_map = current_obj->map(); 47011cb0ef41Sopenharmony_ci if (current_map.is_prototype_map()) { 47021cb0ef41Sopenharmony_ci // If the map is already marked as should be fast, we're done. Its 47031cb0ef41Sopenharmony_ci // prototypes will have been marked already as well. 47041cb0ef41Sopenharmony_ci if (current_map.should_be_fast_prototype_map()) return; 47051cb0ef41Sopenharmony_ci Handle<Map> map(current_map, isolate); 47061cb0ef41Sopenharmony_ci Map::SetShouldBeFastPrototypeMap(map, true, isolate); 47071cb0ef41Sopenharmony_ci JSObject::OptimizeAsPrototype(current_obj); 47081cb0ef41Sopenharmony_ci } 47091cb0ef41Sopenharmony_ci } 47101cb0ef41Sopenharmony_ci} 47111cb0ef41Sopenharmony_ci 47121cb0ef41Sopenharmony_cistatic bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) { 47131cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 47141cb0ef41Sopenharmony_ci if (!object->HasFastProperties()) return false; 47151cb0ef41Sopenharmony_ci if (object->IsJSGlobalProxy()) return false; 47161cb0ef41Sopenharmony_ci // TODO(v8:11248) make bootstrapper create dict mode prototypes, too? 47171cb0ef41Sopenharmony_ci if (object->GetIsolate()->bootstrapper()->IsActive()) return false; 47181cb0ef41Sopenharmony_ci if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL) return true; 47191cb0ef41Sopenharmony_ci return !object->map().is_prototype_map() || 47201cb0ef41Sopenharmony_ci !object->map().should_be_fast_prototype_map(); 47211cb0ef41Sopenharmony_ci} 47221cb0ef41Sopenharmony_ci 47231cb0ef41Sopenharmony_ci// static 47241cb0ef41Sopenharmony_civoid JSObject::OptimizeAsPrototype(Handle<JSObject> object, 47251cb0ef41Sopenharmony_ci bool enable_setup_mode) { 47261cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 47271cb0ef41Sopenharmony_ci if (object->IsJSGlobalObject()) return; 47281cb0ef41Sopenharmony_ci if (enable_setup_mode && PrototypeBenefitsFromNormalization(object)) { 47291cb0ef41Sopenharmony_ci // First normalize to ensure all JSFunctions are DATA_CONSTANT. 47301cb0ef41Sopenharmony_ci JSObject::NormalizeProperties(isolate, object, KEEP_INOBJECT_PROPERTIES, 0, 47311cb0ef41Sopenharmony_ci "NormalizeAsPrototype"); 47321cb0ef41Sopenharmony_ci } 47331cb0ef41Sopenharmony_ci if (object->map().is_prototype_map()) { 47341cb0ef41Sopenharmony_ci if (!V8_DICT_PROPERTY_CONST_TRACKING_BOOL && 47351cb0ef41Sopenharmony_ci object->map().should_be_fast_prototype_map() && 47361cb0ef41Sopenharmony_ci !object->HasFastProperties()) { 47371cb0ef41Sopenharmony_ci JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); 47381cb0ef41Sopenharmony_ci } 47391cb0ef41Sopenharmony_ci } else { 47401cb0ef41Sopenharmony_ci Handle<Map> new_map = 47411cb0ef41Sopenharmony_ci Map::Copy(isolate, handle(object->map(), isolate), "CopyAsPrototype"); 47421cb0ef41Sopenharmony_ci new_map->set_is_prototype_map(true); 47431cb0ef41Sopenharmony_ci 47441cb0ef41Sopenharmony_ci // Replace the pointer to the exact constructor with the Object function 47451cb0ef41Sopenharmony_ci // from the same context if undetectable from JS. This is to avoid keeping 47461cb0ef41Sopenharmony_ci // memory alive unnecessarily. 47471cb0ef41Sopenharmony_ci Object maybe_constructor = new_map->GetConstructor(); 47481cb0ef41Sopenharmony_ci if (maybe_constructor.IsJSFunction()) { 47491cb0ef41Sopenharmony_ci JSFunction constructor = JSFunction::cast(maybe_constructor); 47501cb0ef41Sopenharmony_ci if (!constructor.shared().IsApiFunction()) { 47511cb0ef41Sopenharmony_ci Context context = constructor.native_context(); 47521cb0ef41Sopenharmony_ci JSFunction object_function = context.object_function(); 47531cb0ef41Sopenharmony_ci new_map->SetConstructor(object_function); 47541cb0ef41Sopenharmony_ci } 47551cb0ef41Sopenharmony_ci } 47561cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map); 47571cb0ef41Sopenharmony_ci 47581cb0ef41Sopenharmony_ci if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL && !object->HasFastProperties()) { 47591cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 47601cb0ef41Sopenharmony_ci DisallowHeapAllocation no_gc; 47611cb0ef41Sopenharmony_ci 47621cb0ef41Sopenharmony_ci auto make_constant = [&](auto dict) { 47631cb0ef41Sopenharmony_ci for (InternalIndex index : dict.IterateEntries()) { 47641cb0ef41Sopenharmony_ci Object k; 47651cb0ef41Sopenharmony_ci if (!dict.ToKey(roots, index, &k)) continue; 47661cb0ef41Sopenharmony_ci 47671cb0ef41Sopenharmony_ci PropertyDetails details = dict.DetailsAt(index); 47681cb0ef41Sopenharmony_ci details = details.CopyWithConstness(PropertyConstness::kConst); 47691cb0ef41Sopenharmony_ci dict.DetailsAtPut(index, details); 47701cb0ef41Sopenharmony_ci } 47711cb0ef41Sopenharmony_ci }; 47721cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 47731cb0ef41Sopenharmony_ci make_constant(object->property_dictionary_swiss()); 47741cb0ef41Sopenharmony_ci } else { 47751cb0ef41Sopenharmony_ci make_constant(object->property_dictionary()); 47761cb0ef41Sopenharmony_ci } 47771cb0ef41Sopenharmony_ci } 47781cb0ef41Sopenharmony_ci } 47791cb0ef41Sopenharmony_ci#ifdef DEBUG 47801cb0ef41Sopenharmony_ci bool should_be_dictionary = V8_DICT_PROPERTY_CONST_TRACKING_BOOL && 47811cb0ef41Sopenharmony_ci enable_setup_mode && !object->IsJSGlobalProxy() && 47821cb0ef41Sopenharmony_ci !object->GetIsolate()->bootstrapper()->IsActive(); 47831cb0ef41Sopenharmony_ci DCHECK_IMPLIES(should_be_dictionary, object->map().is_dictionary_map()); 47841cb0ef41Sopenharmony_ci#endif 47851cb0ef41Sopenharmony_ci} 47861cb0ef41Sopenharmony_ci 47871cb0ef41Sopenharmony_ci// static 47881cb0ef41Sopenharmony_civoid JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 47891cb0ef41Sopenharmony_ci if (!object->map().is_prototype_map()) return; 47901cb0ef41Sopenharmony_ci if (!object->map().should_be_fast_prototype_map()) return; 47911cb0ef41Sopenharmony_ci OptimizeAsPrototype(object); 47921cb0ef41Sopenharmony_ci} 47931cb0ef41Sopenharmony_ci 47941cb0ef41Sopenharmony_ci// static 47951cb0ef41Sopenharmony_civoid JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { 47961cb0ef41Sopenharmony_ci // Contract: In line with InvalidatePrototypeChains()'s requirements, 47971cb0ef41Sopenharmony_ci // leaf maps don't need to register as users, only prototypes do. 47981cb0ef41Sopenharmony_ci DCHECK(user->is_prototype_map()); 47991cb0ef41Sopenharmony_ci 48001cb0ef41Sopenharmony_ci Handle<Map> current_user = user; 48011cb0ef41Sopenharmony_ci Handle<PrototypeInfo> current_user_info = 48021cb0ef41Sopenharmony_ci Map::GetOrCreatePrototypeInfo(user, isolate); 48031cb0ef41Sopenharmony_ci for (PrototypeIterator iter(isolate, user); !iter.IsAtEnd(); iter.Advance()) { 48041cb0ef41Sopenharmony_ci // Walk up the prototype chain as far as links haven't been registered yet. 48051cb0ef41Sopenharmony_ci if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) { 48061cb0ef41Sopenharmony_ci break; 48071cb0ef41Sopenharmony_ci } 48081cb0ef41Sopenharmony_ci Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); 48091cb0ef41Sopenharmony_ci // Proxies on the prototype chain are not supported. They make it 48101cb0ef41Sopenharmony_ci // impossible to make any assumptions about the prototype chain anyway. 48111cb0ef41Sopenharmony_ci if (maybe_proto->IsJSProxy()) return; 48121cb0ef41Sopenharmony_ci Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); 48131cb0ef41Sopenharmony_ci Handle<PrototypeInfo> proto_info = 48141cb0ef41Sopenharmony_ci Map::GetOrCreatePrototypeInfo(proto, isolate); 48151cb0ef41Sopenharmony_ci Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); 48161cb0ef41Sopenharmony_ci Handle<WeakArrayList> registry = 48171cb0ef41Sopenharmony_ci maybe_registry->IsSmi() 48181cb0ef41Sopenharmony_ci ? handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(), 48191cb0ef41Sopenharmony_ci isolate) 48201cb0ef41Sopenharmony_ci : Handle<WeakArrayList>::cast(maybe_registry); 48211cb0ef41Sopenharmony_ci int slot = 0; 48221cb0ef41Sopenharmony_ci Handle<WeakArrayList> new_array = 48231cb0ef41Sopenharmony_ci PrototypeUsers::Add(isolate, registry, current_user, &slot); 48241cb0ef41Sopenharmony_ci current_user_info->set_registry_slot(slot); 48251cb0ef41Sopenharmony_ci if (!maybe_registry.is_identical_to(new_array)) { 48261cb0ef41Sopenharmony_ci proto_info->set_prototype_users(*new_array); 48271cb0ef41Sopenharmony_ci } 48281cb0ef41Sopenharmony_ci if (FLAG_trace_prototype_users) { 48291cb0ef41Sopenharmony_ci PrintF("Registering %p as a user of prototype %p (map=%p).\n", 48301cb0ef41Sopenharmony_ci reinterpret_cast<void*>(current_user->ptr()), 48311cb0ef41Sopenharmony_ci reinterpret_cast<void*>(proto->ptr()), 48321cb0ef41Sopenharmony_ci reinterpret_cast<void*>(proto->map().ptr())); 48331cb0ef41Sopenharmony_ci } 48341cb0ef41Sopenharmony_ci 48351cb0ef41Sopenharmony_ci current_user = handle(proto->map(), isolate); 48361cb0ef41Sopenharmony_ci current_user_info = proto_info; 48371cb0ef41Sopenharmony_ci } 48381cb0ef41Sopenharmony_ci} 48391cb0ef41Sopenharmony_ci 48401cb0ef41Sopenharmony_ci// Can be called regardless of whether |user| was actually registered with 48411cb0ef41Sopenharmony_ci// |prototype|. Returns true when there was a registration. 48421cb0ef41Sopenharmony_ci// static 48431cb0ef41Sopenharmony_cibool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) { 48441cb0ef41Sopenharmony_ci DCHECK(user->is_prototype_map()); 48451cb0ef41Sopenharmony_ci // If it doesn't have a PrototypeInfo, it was never registered. 48461cb0ef41Sopenharmony_ci if (!user->prototype_info().IsPrototypeInfo()) return false; 48471cb0ef41Sopenharmony_ci // If it had no prototype before, see if it had users that might expect 48481cb0ef41Sopenharmony_ci // registration. 48491cb0ef41Sopenharmony_ci if (!user->prototype().IsJSObject()) { 48501cb0ef41Sopenharmony_ci Object users = 48511cb0ef41Sopenharmony_ci PrototypeInfo::cast(user->prototype_info()).prototype_users(); 48521cb0ef41Sopenharmony_ci return users.IsWeakArrayList(); 48531cb0ef41Sopenharmony_ci } 48541cb0ef41Sopenharmony_ci Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); 48551cb0ef41Sopenharmony_ci Handle<PrototypeInfo> user_info = 48561cb0ef41Sopenharmony_ci Map::GetOrCreatePrototypeInfo(user, isolate); 48571cb0ef41Sopenharmony_ci int slot = user_info->registry_slot(); 48581cb0ef41Sopenharmony_ci if (slot == PrototypeInfo::UNREGISTERED) return false; 48591cb0ef41Sopenharmony_ci DCHECK(prototype->map().is_prototype_map()); 48601cb0ef41Sopenharmony_ci Object maybe_proto_info = prototype->map().prototype_info(); 48611cb0ef41Sopenharmony_ci // User knows its registry slot, prototype info and user registry must exist. 48621cb0ef41Sopenharmony_ci DCHECK(maybe_proto_info.IsPrototypeInfo()); 48631cb0ef41Sopenharmony_ci Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), 48641cb0ef41Sopenharmony_ci isolate); 48651cb0ef41Sopenharmony_ci Handle<WeakArrayList> prototype_users( 48661cb0ef41Sopenharmony_ci WeakArrayList::cast(proto_info->prototype_users()), isolate); 48671cb0ef41Sopenharmony_ci DCHECK_EQ(prototype_users->Get(slot), HeapObjectReference::Weak(*user)); 48681cb0ef41Sopenharmony_ci PrototypeUsers::MarkSlotEmpty(*prototype_users, slot); 48691cb0ef41Sopenharmony_ci if (FLAG_trace_prototype_users) { 48701cb0ef41Sopenharmony_ci PrintF("Unregistering %p as a user of prototype %p.\n", 48711cb0ef41Sopenharmony_ci reinterpret_cast<void*>(user->ptr()), 48721cb0ef41Sopenharmony_ci reinterpret_cast<void*>(prototype->ptr())); 48731cb0ef41Sopenharmony_ci } 48741cb0ef41Sopenharmony_ci return true; 48751cb0ef41Sopenharmony_ci} 48761cb0ef41Sopenharmony_ci 48771cb0ef41Sopenharmony_cinamespace { 48781cb0ef41Sopenharmony_ci 48791cb0ef41Sopenharmony_ci// This function must be kept in sync with 48801cb0ef41Sopenharmony_ci// AccessorAssembler::InvalidateValidityCellIfPrototype() which does pre-checks 48811cb0ef41Sopenharmony_ci// before jumping here. 48821cb0ef41Sopenharmony_civoid InvalidateOnePrototypeValidityCellInternal(Map map) { 48831cb0ef41Sopenharmony_ci DCHECK(map.is_prototype_map()); 48841cb0ef41Sopenharmony_ci if (FLAG_trace_prototype_users) { 48851cb0ef41Sopenharmony_ci PrintF("Invalidating prototype map %p 's cell\n", 48861cb0ef41Sopenharmony_ci reinterpret_cast<void*>(map.ptr())); 48871cb0ef41Sopenharmony_ci } 48881cb0ef41Sopenharmony_ci Object maybe_cell = map.prototype_validity_cell(); 48891cb0ef41Sopenharmony_ci if (maybe_cell.IsCell()) { 48901cb0ef41Sopenharmony_ci // Just set the value; the cell will be replaced lazily. 48911cb0ef41Sopenharmony_ci Cell cell = Cell::cast(maybe_cell); 48921cb0ef41Sopenharmony_ci cell.set_value(Smi::FromInt(Map::kPrototypeChainInvalid)); 48931cb0ef41Sopenharmony_ci } 48941cb0ef41Sopenharmony_ci Object maybe_prototype_info = map.prototype_info(); 48951cb0ef41Sopenharmony_ci if (maybe_prototype_info.IsPrototypeInfo()) { 48961cb0ef41Sopenharmony_ci PrototypeInfo prototype_info = PrototypeInfo::cast(maybe_prototype_info); 48971cb0ef41Sopenharmony_ci prototype_info.set_prototype_chain_enum_cache(Object()); 48981cb0ef41Sopenharmony_ci } 48991cb0ef41Sopenharmony_ci 49001cb0ef41Sopenharmony_ci // We may inline accesses to constants stored in dictionary mode protoypes in 49011cb0ef41Sopenharmony_ci // optimized code. When doing so, we install depenendies of group 49021cb0ef41Sopenharmony_ci // |kPrototypeCheckGroup| on each prototype between the receiver's immediate 49031cb0ef41Sopenharmony_ci // prototype and the holder of the constant property. This dependency is used 49041cb0ef41Sopenharmony_ci // both to detect changes to the constant value itself, and other changes to 49051cb0ef41Sopenharmony_ci // the prototype chain that invalidate the access to the given property from 49061cb0ef41Sopenharmony_ci // the given receiver (like adding the property to another prototype between 49071cb0ef41Sopenharmony_ci // the receiver and the (previous) holder). This works by de-opting this group 49081cb0ef41Sopenharmony_ci // whenever the validity cell would be invalidated. However, the actual value 49091cb0ef41Sopenharmony_ci // of the validity cell is not used. Therefore, we always trigger the de-opt 49101cb0ef41Sopenharmony_ci // here, even if the cell was already invalid. 49111cb0ef41Sopenharmony_ci if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL && map.is_dictionary_map()) { 49121cb0ef41Sopenharmony_ci // TODO(11527): pass Isolate as an argument. 49131cb0ef41Sopenharmony_ci Isolate* isolate = GetIsolateFromWritableObject(map); 49141cb0ef41Sopenharmony_ci map.dependent_code().DeoptimizeDependentCodeGroup( 49151cb0ef41Sopenharmony_ci isolate, DependentCode::kPrototypeCheckGroup); 49161cb0ef41Sopenharmony_ci } 49171cb0ef41Sopenharmony_ci} 49181cb0ef41Sopenharmony_ci 49191cb0ef41Sopenharmony_civoid InvalidatePrototypeChainsInternal(Map map) { 49201cb0ef41Sopenharmony_ci // We handle linear prototype chains by looping, and multiple children 49211cb0ef41Sopenharmony_ci // by recursion, in order to reduce the likelihood of running into stack 49221cb0ef41Sopenharmony_ci // overflows. So, conceptually, the outer loop iterates the depth of the 49231cb0ef41Sopenharmony_ci // prototype tree, and the inner loop iterates the breadth of a node. 49241cb0ef41Sopenharmony_ci Map next_map; 49251cb0ef41Sopenharmony_ci for (; !map.is_null(); map = next_map, next_map = Map()) { 49261cb0ef41Sopenharmony_ci InvalidateOnePrototypeValidityCellInternal(map); 49271cb0ef41Sopenharmony_ci 49281cb0ef41Sopenharmony_ci Object maybe_proto_info = map.prototype_info(); 49291cb0ef41Sopenharmony_ci if (!maybe_proto_info.IsPrototypeInfo()) return; 49301cb0ef41Sopenharmony_ci PrototypeInfo proto_info = PrototypeInfo::cast(maybe_proto_info); 49311cb0ef41Sopenharmony_ci if (!proto_info.prototype_users().IsWeakArrayList()) { 49321cb0ef41Sopenharmony_ci return; 49331cb0ef41Sopenharmony_ci } 49341cb0ef41Sopenharmony_ci WeakArrayList prototype_users = 49351cb0ef41Sopenharmony_ci WeakArrayList::cast(proto_info.prototype_users()); 49361cb0ef41Sopenharmony_ci // For now, only maps register themselves as users. 49371cb0ef41Sopenharmony_ci for (int i = PrototypeUsers::kFirstIndex; i < prototype_users.length(); 49381cb0ef41Sopenharmony_ci ++i) { 49391cb0ef41Sopenharmony_ci HeapObject heap_object; 49401cb0ef41Sopenharmony_ci if (prototype_users.Get(i)->GetHeapObjectIfWeak(&heap_object) && 49411cb0ef41Sopenharmony_ci heap_object.IsMap()) { 49421cb0ef41Sopenharmony_ci // Walk the prototype chain (backwards, towards leaf objects) if 49431cb0ef41Sopenharmony_ci // necessary. 49441cb0ef41Sopenharmony_ci if (next_map.is_null()) { 49451cb0ef41Sopenharmony_ci next_map = Map::cast(heap_object); 49461cb0ef41Sopenharmony_ci } else { 49471cb0ef41Sopenharmony_ci InvalidatePrototypeChainsInternal(Map::cast(heap_object)); 49481cb0ef41Sopenharmony_ci } 49491cb0ef41Sopenharmony_ci } 49501cb0ef41Sopenharmony_ci } 49511cb0ef41Sopenharmony_ci } 49521cb0ef41Sopenharmony_ci} 49531cb0ef41Sopenharmony_ci 49541cb0ef41Sopenharmony_ci} // namespace 49551cb0ef41Sopenharmony_ci 49561cb0ef41Sopenharmony_ci// static 49571cb0ef41Sopenharmony_ciMap JSObject::InvalidatePrototypeChains(Map map) { 49581cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 49591cb0ef41Sopenharmony_ci InvalidatePrototypeChainsInternal(map); 49601cb0ef41Sopenharmony_ci return map; 49611cb0ef41Sopenharmony_ci} 49621cb0ef41Sopenharmony_ci 49631cb0ef41Sopenharmony_ci// We also invalidate global objects validity cell when a new lexical 49641cb0ef41Sopenharmony_ci// environment variable is added. This is necessary to ensure that 49651cb0ef41Sopenharmony_ci// Load/StoreGlobalIC handlers that load/store from global object's prototype 49661cb0ef41Sopenharmony_ci// get properly invalidated. 49671cb0ef41Sopenharmony_ci// Note, that the normal Load/StoreICs that load/store through the global object 49681cb0ef41Sopenharmony_ci// in the prototype chain are not affected by appearance of a new lexical 49691cb0ef41Sopenharmony_ci// variable and therefore we don't propagate invalidation down. 49701cb0ef41Sopenharmony_ci// static 49711cb0ef41Sopenharmony_civoid JSObject::InvalidatePrototypeValidityCell(JSGlobalObject global) { 49721cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 49731cb0ef41Sopenharmony_ci InvalidateOnePrototypeValidityCellInternal(global.map()); 49741cb0ef41Sopenharmony_ci} 49751cb0ef41Sopenharmony_ci 49761cb0ef41Sopenharmony_ciMaybe<bool> JSObject::SetPrototype(Isolate* isolate, Handle<JSObject> object, 49771cb0ef41Sopenharmony_ci Handle<Object> value, bool from_javascript, 49781cb0ef41Sopenharmony_ci ShouldThrow should_throw) { 49791cb0ef41Sopenharmony_ci#ifdef DEBUG 49801cb0ef41Sopenharmony_ci int size = object->Size(); 49811cb0ef41Sopenharmony_ci#endif 49821cb0ef41Sopenharmony_ci 49831cb0ef41Sopenharmony_ci if (from_javascript) { 49841cb0ef41Sopenharmony_ci if (object->IsAccessCheckNeeded() && 49851cb0ef41Sopenharmony_ci !isolate->MayAccess(handle(isolate->context(), isolate), object)) { 49861cb0ef41Sopenharmony_ci isolate->ReportFailedAccessCheck(object); 49871cb0ef41Sopenharmony_ci RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 49881cb0ef41Sopenharmony_ci RETURN_FAILURE(isolate, should_throw, 49891cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kNoAccess)); 49901cb0ef41Sopenharmony_ci } 49911cb0ef41Sopenharmony_ci } else { 49921cb0ef41Sopenharmony_ci DCHECK(!object->IsAccessCheckNeeded()); 49931cb0ef41Sopenharmony_ci } 49941cb0ef41Sopenharmony_ci 49951cb0ef41Sopenharmony_ci // Silently ignore the change if value is not a JSObject or null. 49961cb0ef41Sopenharmony_ci // SpiderMonkey behaves this way. 49971cb0ef41Sopenharmony_ci if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true); 49981cb0ef41Sopenharmony_ci 49991cb0ef41Sopenharmony_ci bool all_extensible = object->map().is_extensible(); 50001cb0ef41Sopenharmony_ci Handle<JSObject> real_receiver = object; 50011cb0ef41Sopenharmony_ci if (from_javascript) { 50021cb0ef41Sopenharmony_ci // Find the first object in the chain whose prototype object is not 50031cb0ef41Sopenharmony_ci // hidden. 50041cb0ef41Sopenharmony_ci PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype, 50051cb0ef41Sopenharmony_ci PrototypeIterator::END_AT_NON_HIDDEN); 50061cb0ef41Sopenharmony_ci while (!iter.IsAtEnd()) { 50071cb0ef41Sopenharmony_ci // Casting to JSObject is fine because hidden prototypes are never 50081cb0ef41Sopenharmony_ci // JSProxies. 50091cb0ef41Sopenharmony_ci real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter); 50101cb0ef41Sopenharmony_ci iter.Advance(); 50111cb0ef41Sopenharmony_ci all_extensible = all_extensible && real_receiver->map().is_extensible(); 50121cb0ef41Sopenharmony_ci } 50131cb0ef41Sopenharmony_ci } 50141cb0ef41Sopenharmony_ci Handle<Map> map(real_receiver->map(), isolate); 50151cb0ef41Sopenharmony_ci 50161cb0ef41Sopenharmony_ci // Nothing to do if prototype is already set. 50171cb0ef41Sopenharmony_ci if (map->prototype() == *value) return Just(true); 50181cb0ef41Sopenharmony_ci 50191cb0ef41Sopenharmony_ci bool immutable_proto = map->is_immutable_proto(); 50201cb0ef41Sopenharmony_ci if (immutable_proto) { 50211cb0ef41Sopenharmony_ci RETURN_FAILURE( 50221cb0ef41Sopenharmony_ci isolate, should_throw, 50231cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kImmutablePrototypeSet, object)); 50241cb0ef41Sopenharmony_ci } 50251cb0ef41Sopenharmony_ci 50261cb0ef41Sopenharmony_ci // From 6.1.7.3 Invariants of the Essential Internal Methods 50271cb0ef41Sopenharmony_ci // 50281cb0ef41Sopenharmony_ci // [[SetPrototypeOf]] ( V ) 50291cb0ef41Sopenharmony_ci // * ... 50301cb0ef41Sopenharmony_ci // * If target is non-extensible, [[SetPrototypeOf]] must return false, 50311cb0ef41Sopenharmony_ci // unless V is the SameValue as the target's observed [[GetPrototypeOf]] 50321cb0ef41Sopenharmony_ci // value. 50331cb0ef41Sopenharmony_ci if (!all_extensible) { 50341cb0ef41Sopenharmony_ci RETURN_FAILURE(isolate, should_throw, 50351cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kNonExtensibleProto, object)); 50361cb0ef41Sopenharmony_ci } 50371cb0ef41Sopenharmony_ci 50381cb0ef41Sopenharmony_ci // Before we can set the prototype we need to be sure prototype cycles are 50391cb0ef41Sopenharmony_ci // prevented. It is sufficient to validate that the receiver is not in the 50401cb0ef41Sopenharmony_ci // new prototype chain. 50411cb0ef41Sopenharmony_ci if (value->IsJSReceiver()) { 50421cb0ef41Sopenharmony_ci for (PrototypeIterator iter(isolate, JSReceiver::cast(*value), 50431cb0ef41Sopenharmony_ci kStartAtReceiver); 50441cb0ef41Sopenharmony_ci !iter.IsAtEnd(); iter.Advance()) { 50451cb0ef41Sopenharmony_ci if (iter.GetCurrent<JSReceiver>() == *object) { 50461cb0ef41Sopenharmony_ci // Cycle detected. 50471cb0ef41Sopenharmony_ci RETURN_FAILURE(isolate, should_throw, 50481cb0ef41Sopenharmony_ci NewTypeError(MessageTemplate::kCyclicProto)); 50491cb0ef41Sopenharmony_ci } 50501cb0ef41Sopenharmony_ci } 50511cb0ef41Sopenharmony_ci } 50521cb0ef41Sopenharmony_ci 50531cb0ef41Sopenharmony_ci // Set the new prototype of the object. 50541cb0ef41Sopenharmony_ci 50551cb0ef41Sopenharmony_ci isolate->UpdateNoElementsProtectorOnSetPrototype(real_receiver); 50561cb0ef41Sopenharmony_ci 50571cb0ef41Sopenharmony_ci Handle<Map> new_map = 50581cb0ef41Sopenharmony_ci Map::TransitionToPrototype(isolate, map, Handle<HeapObject>::cast(value)); 50591cb0ef41Sopenharmony_ci DCHECK(new_map->prototype() == *value); 50601cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, real_receiver, new_map); 50611cb0ef41Sopenharmony_ci 50621cb0ef41Sopenharmony_ci DCHECK(size == object->Size()); 50631cb0ef41Sopenharmony_ci return Just(true); 50641cb0ef41Sopenharmony_ci} 50651cb0ef41Sopenharmony_ci 50661cb0ef41Sopenharmony_ci// static 50671cb0ef41Sopenharmony_civoid JSObject::SetImmutableProto(Handle<JSObject> object) { 50681cb0ef41Sopenharmony_ci Handle<Map> map(object->map(), object->GetIsolate()); 50691cb0ef41Sopenharmony_ci 50701cb0ef41Sopenharmony_ci // Nothing to do if prototype is already set. 50711cb0ef41Sopenharmony_ci if (map->is_immutable_proto()) return; 50721cb0ef41Sopenharmony_ci 50731cb0ef41Sopenharmony_ci Handle<Map> new_map = 50741cb0ef41Sopenharmony_ci Map::TransitionToImmutableProto(object->GetIsolate(), map); 50751cb0ef41Sopenharmony_ci object->set_map(*new_map, kReleaseStore); 50761cb0ef41Sopenharmony_ci} 50771cb0ef41Sopenharmony_ci 50781cb0ef41Sopenharmony_civoid JSObject::EnsureCanContainElements(Handle<JSObject> object, 50791cb0ef41Sopenharmony_ci JavaScriptArguments* args, 50801cb0ef41Sopenharmony_ci uint32_t arg_count, 50811cb0ef41Sopenharmony_ci EnsureElementsMode mode) { 50821cb0ef41Sopenharmony_ci return EnsureCanContainElements(object, args->first_slot(), arg_count, mode); 50831cb0ef41Sopenharmony_ci} 50841cb0ef41Sopenharmony_ci 50851cb0ef41Sopenharmony_civoid JSObject::ValidateElements(JSObject object) { 50861cb0ef41Sopenharmony_ci#ifdef ENABLE_SLOW_DCHECKS 50871cb0ef41Sopenharmony_ci if (FLAG_enable_slow_asserts) { 50881cb0ef41Sopenharmony_ci object.GetElementsAccessor()->Validate(object); 50891cb0ef41Sopenharmony_ci } 50901cb0ef41Sopenharmony_ci#endif 50911cb0ef41Sopenharmony_ci} 50921cb0ef41Sopenharmony_ci 50931cb0ef41Sopenharmony_cibool JSObject::WouldConvertToSlowElements(uint32_t index) { 50941cb0ef41Sopenharmony_ci if (!HasFastElements()) return false; 50951cb0ef41Sopenharmony_ci uint32_t capacity = static_cast<uint32_t>(elements().length()); 50961cb0ef41Sopenharmony_ci uint32_t new_capacity; 50971cb0ef41Sopenharmony_ci return ShouldConvertToSlowElements(*this, capacity, index, &new_capacity); 50981cb0ef41Sopenharmony_ci} 50991cb0ef41Sopenharmony_ci 51001cb0ef41Sopenharmony_cistatic bool ShouldConvertToFastElements(JSObject object, 51011cb0ef41Sopenharmony_ci NumberDictionary dictionary, 51021cb0ef41Sopenharmony_ci uint32_t index, 51031cb0ef41Sopenharmony_ci uint32_t* new_capacity) { 51041cb0ef41Sopenharmony_ci // If properties with non-standard attributes or accessors were added, we 51051cb0ef41Sopenharmony_ci // cannot go back to fast elements. 51061cb0ef41Sopenharmony_ci if (dictionary.requires_slow_elements()) return false; 51071cb0ef41Sopenharmony_ci 51081cb0ef41Sopenharmony_ci // Adding a property with this index will require slow elements. 51091cb0ef41Sopenharmony_ci if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false; 51101cb0ef41Sopenharmony_ci 51111cb0ef41Sopenharmony_ci if (object.IsJSArray()) { 51121cb0ef41Sopenharmony_ci Object length = JSArray::cast(object).length(); 51131cb0ef41Sopenharmony_ci if (!length.IsSmi()) return false; 51141cb0ef41Sopenharmony_ci *new_capacity = static_cast<uint32_t>(Smi::ToInt(length)); 51151cb0ef41Sopenharmony_ci } else if (object.IsJSArgumentsObject()) { 51161cb0ef41Sopenharmony_ci return false; 51171cb0ef41Sopenharmony_ci } else { 51181cb0ef41Sopenharmony_ci *new_capacity = dictionary.max_number_key() + 1; 51191cb0ef41Sopenharmony_ci } 51201cb0ef41Sopenharmony_ci *new_capacity = std::max(index + 1, *new_capacity); 51211cb0ef41Sopenharmony_ci 51221cb0ef41Sopenharmony_ci uint32_t dictionary_size = static_cast<uint32_t>(dictionary.Capacity()) * 51231cb0ef41Sopenharmony_ci NumberDictionary::kEntrySize; 51241cb0ef41Sopenharmony_ci 51251cb0ef41Sopenharmony_ci // Turn fast if the dictionary only saves 50% space. 51261cb0ef41Sopenharmony_ci return 2 * dictionary_size >= *new_capacity; 51271cb0ef41Sopenharmony_ci} 51281cb0ef41Sopenharmony_ci 51291cb0ef41Sopenharmony_cistatic ElementsKind BestFittingFastElementsKind(JSObject object) { 51301cb0ef41Sopenharmony_ci if (!object.map().CanHaveFastTransitionableElementsKind()) { 51311cb0ef41Sopenharmony_ci return HOLEY_ELEMENTS; 51321cb0ef41Sopenharmony_ci } 51331cb0ef41Sopenharmony_ci if (object.HasSloppyArgumentsElements()) { 51341cb0ef41Sopenharmony_ci return FAST_SLOPPY_ARGUMENTS_ELEMENTS; 51351cb0ef41Sopenharmony_ci } 51361cb0ef41Sopenharmony_ci if (object.HasStringWrapperElements()) { 51371cb0ef41Sopenharmony_ci return FAST_STRING_WRAPPER_ELEMENTS; 51381cb0ef41Sopenharmony_ci } 51391cb0ef41Sopenharmony_ci DCHECK(object.HasDictionaryElements()); 51401cb0ef41Sopenharmony_ci NumberDictionary dictionary = object.element_dictionary(); 51411cb0ef41Sopenharmony_ci ElementsKind kind = HOLEY_SMI_ELEMENTS; 51421cb0ef41Sopenharmony_ci for (InternalIndex i : dictionary.IterateEntries()) { 51431cb0ef41Sopenharmony_ci Object key = dictionary.KeyAt(i); 51441cb0ef41Sopenharmony_ci if (key.IsNumber()) { 51451cb0ef41Sopenharmony_ci Object value = dictionary.ValueAt(i); 51461cb0ef41Sopenharmony_ci if (!value.IsNumber()) return HOLEY_ELEMENTS; 51471cb0ef41Sopenharmony_ci if (!value.IsSmi()) { 51481cb0ef41Sopenharmony_ci if (!FLAG_unbox_double_arrays) return HOLEY_ELEMENTS; 51491cb0ef41Sopenharmony_ci kind = HOLEY_DOUBLE_ELEMENTS; 51501cb0ef41Sopenharmony_ci } 51511cb0ef41Sopenharmony_ci } 51521cb0ef41Sopenharmony_ci } 51531cb0ef41Sopenharmony_ci return kind; 51541cb0ef41Sopenharmony_ci} 51551cb0ef41Sopenharmony_ci 51561cb0ef41Sopenharmony_ci// static 51571cb0ef41Sopenharmony_ciMaybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index, 51581cb0ef41Sopenharmony_ci Handle<Object> value, 51591cb0ef41Sopenharmony_ci PropertyAttributes attributes) { 51601cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 51611cb0ef41Sopenharmony_ci 51621cb0ef41Sopenharmony_ci DCHECK(object->map(isolate).is_extensible()); 51631cb0ef41Sopenharmony_ci 51641cb0ef41Sopenharmony_ci uint32_t old_length = 0; 51651cb0ef41Sopenharmony_ci uint32_t new_capacity = 0; 51661cb0ef41Sopenharmony_ci 51671cb0ef41Sopenharmony_ci if (object->IsJSArray(isolate)) { 51681cb0ef41Sopenharmony_ci CHECK(JSArray::cast(*object).length().ToArrayLength(&old_length)); 51691cb0ef41Sopenharmony_ci } 51701cb0ef41Sopenharmony_ci 51711cb0ef41Sopenharmony_ci ElementsKind kind = object->GetElementsKind(isolate); 51721cb0ef41Sopenharmony_ci FixedArrayBase elements = object->elements(isolate); 51731cb0ef41Sopenharmony_ci ElementsKind dictionary_kind = DICTIONARY_ELEMENTS; 51741cb0ef41Sopenharmony_ci if (IsSloppyArgumentsElementsKind(kind)) { 51751cb0ef41Sopenharmony_ci elements = SloppyArgumentsElements::cast(elements).arguments(isolate); 51761cb0ef41Sopenharmony_ci dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS; 51771cb0ef41Sopenharmony_ci } else if (IsStringWrapperElementsKind(kind)) { 51781cb0ef41Sopenharmony_ci dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS; 51791cb0ef41Sopenharmony_ci } 51801cb0ef41Sopenharmony_ci 51811cb0ef41Sopenharmony_ci if (attributes != NONE) { 51821cb0ef41Sopenharmony_ci kind = dictionary_kind; 51831cb0ef41Sopenharmony_ci } else if (elements.IsNumberDictionary(isolate)) { 51841cb0ef41Sopenharmony_ci kind = ShouldConvertToFastElements( 51851cb0ef41Sopenharmony_ci *object, NumberDictionary::cast(elements), index, &new_capacity) 51861cb0ef41Sopenharmony_ci ? BestFittingFastElementsKind(*object) 51871cb0ef41Sopenharmony_ci : dictionary_kind; 51881cb0ef41Sopenharmony_ci } else if (ShouldConvertToSlowElements( 51891cb0ef41Sopenharmony_ci *object, static_cast<uint32_t>(elements.length()), index, 51901cb0ef41Sopenharmony_ci &new_capacity)) { 51911cb0ef41Sopenharmony_ci kind = dictionary_kind; 51921cb0ef41Sopenharmony_ci } 51931cb0ef41Sopenharmony_ci 51941cb0ef41Sopenharmony_ci ElementsKind to = value->OptimalElementsKind(isolate); 51951cb0ef41Sopenharmony_ci if (IsHoleyElementsKind(kind) || !object->IsJSArray(isolate) || 51961cb0ef41Sopenharmony_ci index > old_length) { 51971cb0ef41Sopenharmony_ci to = GetHoleyElementsKind(to); 51981cb0ef41Sopenharmony_ci kind = GetHoleyElementsKind(kind); 51991cb0ef41Sopenharmony_ci } 52001cb0ef41Sopenharmony_ci to = GetMoreGeneralElementsKind(kind, to); 52011cb0ef41Sopenharmony_ci ElementsAccessor* accessor = ElementsAccessor::ForKind(to); 52021cb0ef41Sopenharmony_ci MAYBE_RETURN(accessor->Add(object, index, value, attributes, new_capacity), 52031cb0ef41Sopenharmony_ci Nothing<bool>()); 52041cb0ef41Sopenharmony_ci 52051cb0ef41Sopenharmony_ci if (object->IsJSArray(isolate) && index >= old_length) { 52061cb0ef41Sopenharmony_ci Handle<Object> new_length = 52071cb0ef41Sopenharmony_ci isolate->factory()->NewNumberFromUint(index + 1); 52081cb0ef41Sopenharmony_ci JSArray::cast(*object).set_length(*new_length); 52091cb0ef41Sopenharmony_ci } 52101cb0ef41Sopenharmony_ci return Just(true); 52111cb0ef41Sopenharmony_ci} 52121cb0ef41Sopenharmony_ci 52131cb0ef41Sopenharmony_citemplate <AllocationSiteUpdateMode update_or_check> 52141cb0ef41Sopenharmony_cibool JSObject::UpdateAllocationSite(Handle<JSObject> object, 52151cb0ef41Sopenharmony_ci ElementsKind to_kind) { 52161cb0ef41Sopenharmony_ci if (!object->IsJSArray()) return false; 52171cb0ef41Sopenharmony_ci 52181cb0ef41Sopenharmony_ci if (!Heap::InYoungGeneration(*object)) return false; 52191cb0ef41Sopenharmony_ci 52201cb0ef41Sopenharmony_ci if (Heap::IsLargeObject(*object)) return false; 52211cb0ef41Sopenharmony_ci 52221cb0ef41Sopenharmony_ci Handle<AllocationSite> site; 52231cb0ef41Sopenharmony_ci { 52241cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 52251cb0ef41Sopenharmony_ci 52261cb0ef41Sopenharmony_ci Heap* heap = object->GetHeap(); 52271cb0ef41Sopenharmony_ci AllocationMemento memento = 52281cb0ef41Sopenharmony_ci heap->FindAllocationMemento<Heap::kForRuntime>(object->map(), *object); 52291cb0ef41Sopenharmony_ci if (memento.is_null()) return false; 52301cb0ef41Sopenharmony_ci 52311cb0ef41Sopenharmony_ci // Walk through to the Allocation Site 52321cb0ef41Sopenharmony_ci site = handle(memento.GetAllocationSite(), heap->isolate()); 52331cb0ef41Sopenharmony_ci } 52341cb0ef41Sopenharmony_ci return AllocationSite::DigestTransitionFeedback<update_or_check>(site, 52351cb0ef41Sopenharmony_ci to_kind); 52361cb0ef41Sopenharmony_ci} 52371cb0ef41Sopenharmony_ci 52381cb0ef41Sopenharmony_citemplate bool 52391cb0ef41Sopenharmony_ciJSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>( 52401cb0ef41Sopenharmony_ci Handle<JSObject> object, ElementsKind to_kind); 52411cb0ef41Sopenharmony_ci 52421cb0ef41Sopenharmony_citemplate bool JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kUpdate>( 52431cb0ef41Sopenharmony_ci Handle<JSObject> object, ElementsKind to_kind); 52441cb0ef41Sopenharmony_ci 52451cb0ef41Sopenharmony_civoid JSObject::TransitionElementsKind(Handle<JSObject> object, 52461cb0ef41Sopenharmony_ci ElementsKind to_kind) { 52471cb0ef41Sopenharmony_ci ElementsKind from_kind = object->GetElementsKind(); 52481cb0ef41Sopenharmony_ci 52491cb0ef41Sopenharmony_ci if (IsHoleyElementsKind(from_kind)) { 52501cb0ef41Sopenharmony_ci to_kind = GetHoleyElementsKind(to_kind); 52511cb0ef41Sopenharmony_ci } 52521cb0ef41Sopenharmony_ci 52531cb0ef41Sopenharmony_ci if (from_kind == to_kind) return; 52541cb0ef41Sopenharmony_ci 52551cb0ef41Sopenharmony_ci // This method should never be called for any other case. 52561cb0ef41Sopenharmony_ci DCHECK(IsFastElementsKind(from_kind) || 52571cb0ef41Sopenharmony_ci IsNonextensibleElementsKind(from_kind)); 52581cb0ef41Sopenharmony_ci DCHECK(IsFastElementsKind(to_kind) || IsNonextensibleElementsKind(to_kind)); 52591cb0ef41Sopenharmony_ci DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind); 52601cb0ef41Sopenharmony_ci 52611cb0ef41Sopenharmony_ci UpdateAllocationSite(object, to_kind); 52621cb0ef41Sopenharmony_ci Isolate* isolate = object->GetIsolate(); 52631cb0ef41Sopenharmony_ci if (object->elements() == ReadOnlyRoots(isolate).empty_fixed_array() || 52641cb0ef41Sopenharmony_ci IsDoubleElementsKind(from_kind) == IsDoubleElementsKind(to_kind)) { 52651cb0ef41Sopenharmony_ci // No change is needed to the elements() buffer, the transition 52661cb0ef41Sopenharmony_ci // only requires a map change. 52671cb0ef41Sopenharmony_ci Handle<Map> new_map = GetElementsTransitionMap(object, to_kind); 52681cb0ef41Sopenharmony_ci JSObject::MigrateToMap(isolate, object, new_map); 52691cb0ef41Sopenharmony_ci if (FLAG_trace_elements_transitions) { 52701cb0ef41Sopenharmony_ci Handle<FixedArrayBase> elms(object->elements(), isolate); 52711cb0ef41Sopenharmony_ci PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms); 52721cb0ef41Sopenharmony_ci } 52731cb0ef41Sopenharmony_ci } else { 52741cb0ef41Sopenharmony_ci DCHECK((IsSmiElementsKind(from_kind) && IsDoubleElementsKind(to_kind)) || 52751cb0ef41Sopenharmony_ci (IsDoubleElementsKind(from_kind) && IsObjectElementsKind(to_kind))); 52761cb0ef41Sopenharmony_ci uint32_t c = static_cast<uint32_t>(object->elements().length()); 52771cb0ef41Sopenharmony_ci if (ElementsAccessor::ForKind(to_kind) 52781cb0ef41Sopenharmony_ci ->GrowCapacityAndConvert(object, c) 52791cb0ef41Sopenharmony_ci .IsNothing()) { 52801cb0ef41Sopenharmony_ci // TODO(victorgomes): Temporarily forcing a fatal error here in case of 52811cb0ef41Sopenharmony_ci // overflow, until all users of TransitionElementsKind can handle 52821cb0ef41Sopenharmony_ci // exceptions. 52831cb0ef41Sopenharmony_ci FATAL( 52841cb0ef41Sopenharmony_ci "Fatal JavaScript invalid size error when transitioning elements " 52851cb0ef41Sopenharmony_ci "kind"); 52861cb0ef41Sopenharmony_ci UNREACHABLE(); 52871cb0ef41Sopenharmony_ci } 52881cb0ef41Sopenharmony_ci } 52891cb0ef41Sopenharmony_ci} 52901cb0ef41Sopenharmony_ci 52911cb0ef41Sopenharmony_citemplate <typename BackingStore> 52921cb0ef41Sopenharmony_cistatic int HoleyElementsUsage(JSObject object, BackingStore store) { 52931cb0ef41Sopenharmony_ci Isolate* isolate = object.GetIsolate(); 52941cb0ef41Sopenharmony_ci int limit = object.IsJSArray() ? Smi::ToInt(JSArray::cast(object).length()) 52951cb0ef41Sopenharmony_ci : store.length(); 52961cb0ef41Sopenharmony_ci int used = 0; 52971cb0ef41Sopenharmony_ci for (int i = 0; i < limit; ++i) { 52981cb0ef41Sopenharmony_ci if (!store.is_the_hole(isolate, i)) ++used; 52991cb0ef41Sopenharmony_ci } 53001cb0ef41Sopenharmony_ci return used; 53011cb0ef41Sopenharmony_ci} 53021cb0ef41Sopenharmony_ci 53031cb0ef41Sopenharmony_ciint JSObject::GetFastElementsUsage() { 53041cb0ef41Sopenharmony_ci FixedArrayBase store = elements(); 53051cb0ef41Sopenharmony_ci switch (GetElementsKind()) { 53061cb0ef41Sopenharmony_ci case PACKED_SMI_ELEMENTS: 53071cb0ef41Sopenharmony_ci case PACKED_DOUBLE_ELEMENTS: 53081cb0ef41Sopenharmony_ci case PACKED_ELEMENTS: 53091cb0ef41Sopenharmony_ci case PACKED_FROZEN_ELEMENTS: 53101cb0ef41Sopenharmony_ci case PACKED_SEALED_ELEMENTS: 53111cb0ef41Sopenharmony_ci case PACKED_NONEXTENSIBLE_ELEMENTS: 53121cb0ef41Sopenharmony_ci return IsJSArray() ? Smi::ToInt(JSArray::cast(*this).length()) 53131cb0ef41Sopenharmony_ci : store.length(); 53141cb0ef41Sopenharmony_ci case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 53151cb0ef41Sopenharmony_ci store = SloppyArgumentsElements::cast(store).arguments(); 53161cb0ef41Sopenharmony_ci V8_FALLTHROUGH; 53171cb0ef41Sopenharmony_ci case HOLEY_SMI_ELEMENTS: 53181cb0ef41Sopenharmony_ci case HOLEY_ELEMENTS: 53191cb0ef41Sopenharmony_ci case HOLEY_FROZEN_ELEMENTS: 53201cb0ef41Sopenharmony_ci case HOLEY_SEALED_ELEMENTS: 53211cb0ef41Sopenharmony_ci case HOLEY_NONEXTENSIBLE_ELEMENTS: 53221cb0ef41Sopenharmony_ci case FAST_STRING_WRAPPER_ELEMENTS: 53231cb0ef41Sopenharmony_ci return HoleyElementsUsage(*this, FixedArray::cast(store)); 53241cb0ef41Sopenharmony_ci case HOLEY_DOUBLE_ELEMENTS: 53251cb0ef41Sopenharmony_ci if (elements().length() == 0) return 0; 53261cb0ef41Sopenharmony_ci return HoleyElementsUsage(*this, FixedDoubleArray::cast(store)); 53271cb0ef41Sopenharmony_ci 53281cb0ef41Sopenharmony_ci case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 53291cb0ef41Sopenharmony_ci case SLOW_STRING_WRAPPER_ELEMENTS: 53301cb0ef41Sopenharmony_ci case DICTIONARY_ELEMENTS: 53311cb0ef41Sopenharmony_ci case WASM_ARRAY_ELEMENTS: 53321cb0ef41Sopenharmony_ci case NO_ELEMENTS: 53331cb0ef41Sopenharmony_ci#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS: 53341cb0ef41Sopenharmony_ci 53351cb0ef41Sopenharmony_ci TYPED_ARRAYS(TYPED_ARRAY_CASE) 53361cb0ef41Sopenharmony_ci RAB_GSAB_TYPED_ARRAYS(TYPED_ARRAY_CASE) 53371cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_CASE 53381cb0ef41Sopenharmony_ci UNREACHABLE(); 53391cb0ef41Sopenharmony_ci } 53401cb0ef41Sopenharmony_ci return 0; 53411cb0ef41Sopenharmony_ci} 53421cb0ef41Sopenharmony_ci 53431cb0ef41Sopenharmony_ciMaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it, 53441cb0ef41Sopenharmony_ci bool* done) { 53451cb0ef41Sopenharmony_ci DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); 53461cb0ef41Sopenharmony_ci return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done); 53471cb0ef41Sopenharmony_ci} 53481cb0ef41Sopenharmony_ci 53491cb0ef41Sopenharmony_ciMaybe<bool> JSObject::HasRealNamedProperty(Isolate* isolate, 53501cb0ef41Sopenharmony_ci Handle<JSObject> object, 53511cb0ef41Sopenharmony_ci Handle<Name> name) { 53521cb0ef41Sopenharmony_ci PropertyKey key(isolate, name); 53531cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, key, LookupIterator::OWN_SKIP_INTERCEPTOR); 53541cb0ef41Sopenharmony_ci return HasProperty(&it); 53551cb0ef41Sopenharmony_ci} 53561cb0ef41Sopenharmony_ci 53571cb0ef41Sopenharmony_ciMaybe<bool> JSObject::HasRealElementProperty(Isolate* isolate, 53581cb0ef41Sopenharmony_ci Handle<JSObject> object, 53591cb0ef41Sopenharmony_ci uint32_t index) { 53601cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, index, object, 53611cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 53621cb0ef41Sopenharmony_ci return HasProperty(&it); 53631cb0ef41Sopenharmony_ci} 53641cb0ef41Sopenharmony_ci 53651cb0ef41Sopenharmony_ciMaybe<bool> JSObject::HasRealNamedCallbackProperty(Isolate* isolate, 53661cb0ef41Sopenharmony_ci Handle<JSObject> object, 53671cb0ef41Sopenharmony_ci Handle<Name> name) { 53681cb0ef41Sopenharmony_ci PropertyKey key(isolate, name); 53691cb0ef41Sopenharmony_ci LookupIterator it(isolate, object, key, LookupIterator::OWN_SKIP_INTERCEPTOR); 53701cb0ef41Sopenharmony_ci Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it); 53711cb0ef41Sopenharmony_ci return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR) 53721cb0ef41Sopenharmony_ci : Nothing<bool>(); 53731cb0ef41Sopenharmony_ci} 53741cb0ef41Sopenharmony_ci 53751cb0ef41Sopenharmony_cibool JSGlobalProxy::IsDetached() const { 53761cb0ef41Sopenharmony_ci return native_context().IsNull(GetIsolate()); 53771cb0ef41Sopenharmony_ci} 53781cb0ef41Sopenharmony_ci 53791cb0ef41Sopenharmony_civoid JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global, 53801cb0ef41Sopenharmony_ci Handle<Name> name) { 53811cb0ef41Sopenharmony_ci Isolate* isolate = global->GetIsolate(); 53821cb0ef41Sopenharmony_ci // Regardless of whether the property is there or not invalidate 53831cb0ef41Sopenharmony_ci // Load/StoreGlobalICs that load/store through global object's prototype. 53841cb0ef41Sopenharmony_ci JSObject::InvalidatePrototypeValidityCell(*global); 53851cb0ef41Sopenharmony_ci DCHECK(!global->HasFastProperties()); 53861cb0ef41Sopenharmony_ci auto dictionary = handle(global->global_dictionary(kAcquireLoad), isolate); 53871cb0ef41Sopenharmony_ci InternalIndex entry = dictionary->FindEntry(isolate, name); 53881cb0ef41Sopenharmony_ci if (entry.is_not_found()) return; 53891cb0ef41Sopenharmony_ci 53901cb0ef41Sopenharmony_ci Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate); 53911cb0ef41Sopenharmony_ci Handle<Object> value(cell->value(), isolate); 53921cb0ef41Sopenharmony_ci PropertyDetails details = cell->property_details(); 53931cb0ef41Sopenharmony_ci details = details.set_cell_type(PropertyCellType::kMutable); 53941cb0ef41Sopenharmony_ci PropertyCell::InvalidateAndReplaceEntry(isolate, dictionary, entry, details, 53951cb0ef41Sopenharmony_ci value); 53961cb0ef41Sopenharmony_ci} 53971cb0ef41Sopenharmony_ci 53981cb0ef41Sopenharmony_ci// static 53991cb0ef41Sopenharmony_ciMaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor, 54001cb0ef41Sopenharmony_ci Handle<JSReceiver> new_target, double tv) { 54011cb0ef41Sopenharmony_ci Isolate* const isolate = constructor->GetIsolate(); 54021cb0ef41Sopenharmony_ci Handle<JSObject> result; 54031cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 54041cb0ef41Sopenharmony_ci isolate, result, 54051cb0ef41Sopenharmony_ci JSObject::New(constructor, new_target, Handle<AllocationSite>::null()), 54061cb0ef41Sopenharmony_ci JSDate); 54071cb0ef41Sopenharmony_ci if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) { 54081cb0ef41Sopenharmony_ci tv = DoubleToInteger(tv) + 0.0; 54091cb0ef41Sopenharmony_ci } else { 54101cb0ef41Sopenharmony_ci tv = std::numeric_limits<double>::quiet_NaN(); 54111cb0ef41Sopenharmony_ci } 54121cb0ef41Sopenharmony_ci Handle<Object> value = isolate->factory()->NewNumber(tv); 54131cb0ef41Sopenharmony_ci Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv)); 54141cb0ef41Sopenharmony_ci return Handle<JSDate>::cast(result); 54151cb0ef41Sopenharmony_ci} 54161cb0ef41Sopenharmony_ci 54171cb0ef41Sopenharmony_ci// static 54181cb0ef41Sopenharmony_cidouble JSDate::CurrentTimeValue(Isolate* isolate) { 54191cb0ef41Sopenharmony_ci if (FLAG_log_internal_timer_events) LOG(isolate, CurrentTimeEvent()); 54201cb0ef41Sopenharmony_ci if (FLAG_correctness_fuzzer_suppressions) return 4.2; 54211cb0ef41Sopenharmony_ci 54221cb0ef41Sopenharmony_ci // According to ECMA-262, section 15.9.1, page 117, the precision of 54231cb0ef41Sopenharmony_ci // the number in a Date object representing a particular instant in 54241cb0ef41Sopenharmony_ci // time is milliseconds. Therefore, we floor the result of getting 54251cb0ef41Sopenharmony_ci // the OS time. 54261cb0ef41Sopenharmony_ci return std::floor(V8::GetCurrentPlatform()->CurrentClockTimeMillis()); 54271cb0ef41Sopenharmony_ci} 54281cb0ef41Sopenharmony_ci 54291cb0ef41Sopenharmony_ci// static 54301cb0ef41Sopenharmony_ciAddress JSDate::GetField(Isolate* isolate, Address raw_object, 54311cb0ef41Sopenharmony_ci Address smi_index) { 54321cb0ef41Sopenharmony_ci // Called through CallCFunction. 54331cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 54341cb0ef41Sopenharmony_ci DisallowHandleAllocation no_handles; 54351cb0ef41Sopenharmony_ci DisallowJavascriptExecution no_js(isolate); 54361cb0ef41Sopenharmony_ci 54371cb0ef41Sopenharmony_ci Object object(raw_object); 54381cb0ef41Sopenharmony_ci Smi index(smi_index); 54391cb0ef41Sopenharmony_ci return JSDate::cast(object) 54401cb0ef41Sopenharmony_ci .DoGetField(isolate, static_cast<FieldIndex>(index.value())) 54411cb0ef41Sopenharmony_ci .ptr(); 54421cb0ef41Sopenharmony_ci} 54431cb0ef41Sopenharmony_ci 54441cb0ef41Sopenharmony_ciObject JSDate::DoGetField(Isolate* isolate, FieldIndex index) { 54451cb0ef41Sopenharmony_ci DCHECK_NE(index, kDateValue); 54461cb0ef41Sopenharmony_ci 54471cb0ef41Sopenharmony_ci DateCache* date_cache = isolate->date_cache(); 54481cb0ef41Sopenharmony_ci 54491cb0ef41Sopenharmony_ci if (index < kFirstUncachedField) { 54501cb0ef41Sopenharmony_ci Object stamp = cache_stamp(); 54511cb0ef41Sopenharmony_ci if (stamp != date_cache->stamp() && stamp.IsSmi()) { 54521cb0ef41Sopenharmony_ci // Since the stamp is not NaN, the value is also not NaN. 54531cb0ef41Sopenharmony_ci int64_t local_time_ms = 54541cb0ef41Sopenharmony_ci date_cache->ToLocal(static_cast<int64_t>(value().Number())); 54551cb0ef41Sopenharmony_ci SetCachedFields(local_time_ms, date_cache); 54561cb0ef41Sopenharmony_ci } 54571cb0ef41Sopenharmony_ci switch (index) { 54581cb0ef41Sopenharmony_ci case kYear: 54591cb0ef41Sopenharmony_ci return year(); 54601cb0ef41Sopenharmony_ci case kMonth: 54611cb0ef41Sopenharmony_ci return month(); 54621cb0ef41Sopenharmony_ci case kDay: 54631cb0ef41Sopenharmony_ci return day(); 54641cb0ef41Sopenharmony_ci case kWeekday: 54651cb0ef41Sopenharmony_ci return weekday(); 54661cb0ef41Sopenharmony_ci case kHour: 54671cb0ef41Sopenharmony_ci return hour(); 54681cb0ef41Sopenharmony_ci case kMinute: 54691cb0ef41Sopenharmony_ci return min(); 54701cb0ef41Sopenharmony_ci case kSecond: 54711cb0ef41Sopenharmony_ci return sec(); 54721cb0ef41Sopenharmony_ci default: 54731cb0ef41Sopenharmony_ci UNREACHABLE(); 54741cb0ef41Sopenharmony_ci } 54751cb0ef41Sopenharmony_ci } 54761cb0ef41Sopenharmony_ci 54771cb0ef41Sopenharmony_ci if (index >= kFirstUTCField) { 54781cb0ef41Sopenharmony_ci return GetUTCField(index, value().Number(), date_cache); 54791cb0ef41Sopenharmony_ci } 54801cb0ef41Sopenharmony_ci 54811cb0ef41Sopenharmony_ci double time = value().Number(); 54821cb0ef41Sopenharmony_ci if (std::isnan(time)) return GetReadOnlyRoots().nan_value(); 54831cb0ef41Sopenharmony_ci 54841cb0ef41Sopenharmony_ci int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time)); 54851cb0ef41Sopenharmony_ci int days = DateCache::DaysFromTime(local_time_ms); 54861cb0ef41Sopenharmony_ci 54871cb0ef41Sopenharmony_ci if (index == kDays) return Smi::FromInt(days); 54881cb0ef41Sopenharmony_ci 54891cb0ef41Sopenharmony_ci int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days); 54901cb0ef41Sopenharmony_ci if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000); 54911cb0ef41Sopenharmony_ci DCHECK_EQ(index, kTimeInDay); 54921cb0ef41Sopenharmony_ci return Smi::FromInt(time_in_day_ms); 54931cb0ef41Sopenharmony_ci} 54941cb0ef41Sopenharmony_ci 54951cb0ef41Sopenharmony_ciObject JSDate::GetUTCField(FieldIndex index, double value, 54961cb0ef41Sopenharmony_ci DateCache* date_cache) { 54971cb0ef41Sopenharmony_ci DCHECK_GE(index, kFirstUTCField); 54981cb0ef41Sopenharmony_ci 54991cb0ef41Sopenharmony_ci if (std::isnan(value)) return GetReadOnlyRoots().nan_value(); 55001cb0ef41Sopenharmony_ci 55011cb0ef41Sopenharmony_ci int64_t time_ms = static_cast<int64_t>(value); 55021cb0ef41Sopenharmony_ci 55031cb0ef41Sopenharmony_ci if (index == kTimezoneOffset) { 55041cb0ef41Sopenharmony_ci return Smi::FromInt(date_cache->TimezoneOffset(time_ms)); 55051cb0ef41Sopenharmony_ci } 55061cb0ef41Sopenharmony_ci 55071cb0ef41Sopenharmony_ci int days = DateCache::DaysFromTime(time_ms); 55081cb0ef41Sopenharmony_ci 55091cb0ef41Sopenharmony_ci if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days)); 55101cb0ef41Sopenharmony_ci 55111cb0ef41Sopenharmony_ci if (index <= kDayUTC) { 55121cb0ef41Sopenharmony_ci int year, month, day; 55131cb0ef41Sopenharmony_ci date_cache->YearMonthDayFromDays(days, &year, &month, &day); 55141cb0ef41Sopenharmony_ci if (index == kYearUTC) return Smi::FromInt(year); 55151cb0ef41Sopenharmony_ci if (index == kMonthUTC) return Smi::FromInt(month); 55161cb0ef41Sopenharmony_ci DCHECK_EQ(index, kDayUTC); 55171cb0ef41Sopenharmony_ci return Smi::FromInt(day); 55181cb0ef41Sopenharmony_ci } 55191cb0ef41Sopenharmony_ci 55201cb0ef41Sopenharmony_ci int time_in_day_ms = DateCache::TimeInDay(time_ms, days); 55211cb0ef41Sopenharmony_ci switch (index) { 55221cb0ef41Sopenharmony_ci case kHourUTC: 55231cb0ef41Sopenharmony_ci return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000)); 55241cb0ef41Sopenharmony_ci case kMinuteUTC: 55251cb0ef41Sopenharmony_ci return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60); 55261cb0ef41Sopenharmony_ci case kSecondUTC: 55271cb0ef41Sopenharmony_ci return Smi::FromInt((time_in_day_ms / 1000) % 60); 55281cb0ef41Sopenharmony_ci case kMillisecondUTC: 55291cb0ef41Sopenharmony_ci return Smi::FromInt(time_in_day_ms % 1000); 55301cb0ef41Sopenharmony_ci case kDaysUTC: 55311cb0ef41Sopenharmony_ci return Smi::FromInt(days); 55321cb0ef41Sopenharmony_ci case kTimeInDayUTC: 55331cb0ef41Sopenharmony_ci return Smi::FromInt(time_in_day_ms); 55341cb0ef41Sopenharmony_ci default: 55351cb0ef41Sopenharmony_ci UNREACHABLE(); 55361cb0ef41Sopenharmony_ci } 55371cb0ef41Sopenharmony_ci 55381cb0ef41Sopenharmony_ci UNREACHABLE(); 55391cb0ef41Sopenharmony_ci} 55401cb0ef41Sopenharmony_ci 55411cb0ef41Sopenharmony_ci// static 55421cb0ef41Sopenharmony_ciHandle<Object> JSDate::SetValue(Handle<JSDate> date, double v) { 55431cb0ef41Sopenharmony_ci Isolate* const isolate = date->GetIsolate(); 55441cb0ef41Sopenharmony_ci Handle<Object> value = isolate->factory()->NewNumber(v); 55451cb0ef41Sopenharmony_ci bool value_is_nan = std::isnan(v); 55461cb0ef41Sopenharmony_ci date->SetValue(*value, value_is_nan); 55471cb0ef41Sopenharmony_ci return value; 55481cb0ef41Sopenharmony_ci} 55491cb0ef41Sopenharmony_ci 55501cb0ef41Sopenharmony_civoid JSDate::SetValue(Object value, bool is_value_nan) { 55511cb0ef41Sopenharmony_ci set_value(value); 55521cb0ef41Sopenharmony_ci if (is_value_nan) { 55531cb0ef41Sopenharmony_ci HeapNumber nan = GetReadOnlyRoots().nan_value(); 55541cb0ef41Sopenharmony_ci set_cache_stamp(nan, SKIP_WRITE_BARRIER); 55551cb0ef41Sopenharmony_ci set_year(nan, SKIP_WRITE_BARRIER); 55561cb0ef41Sopenharmony_ci set_month(nan, SKIP_WRITE_BARRIER); 55571cb0ef41Sopenharmony_ci set_day(nan, SKIP_WRITE_BARRIER); 55581cb0ef41Sopenharmony_ci set_hour(nan, SKIP_WRITE_BARRIER); 55591cb0ef41Sopenharmony_ci set_min(nan, SKIP_WRITE_BARRIER); 55601cb0ef41Sopenharmony_ci set_sec(nan, SKIP_WRITE_BARRIER); 55611cb0ef41Sopenharmony_ci set_weekday(nan, SKIP_WRITE_BARRIER); 55621cb0ef41Sopenharmony_ci } else { 55631cb0ef41Sopenharmony_ci set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER); 55641cb0ef41Sopenharmony_ci } 55651cb0ef41Sopenharmony_ci} 55661cb0ef41Sopenharmony_ci 55671cb0ef41Sopenharmony_civoid JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) { 55681cb0ef41Sopenharmony_ci int days = DateCache::DaysFromTime(local_time_ms); 55691cb0ef41Sopenharmony_ci int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days); 55701cb0ef41Sopenharmony_ci int year, month, day; 55711cb0ef41Sopenharmony_ci date_cache->YearMonthDayFromDays(days, &year, &month, &day); 55721cb0ef41Sopenharmony_ci int weekday = date_cache->Weekday(days); 55731cb0ef41Sopenharmony_ci int hour = time_in_day_ms / (60 * 60 * 1000); 55741cb0ef41Sopenharmony_ci int min = (time_in_day_ms / (60 * 1000)) % 60; 55751cb0ef41Sopenharmony_ci int sec = (time_in_day_ms / 1000) % 60; 55761cb0ef41Sopenharmony_ci set_cache_stamp(date_cache->stamp()); 55771cb0ef41Sopenharmony_ci set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 55781cb0ef41Sopenharmony_ci set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 55791cb0ef41Sopenharmony_ci set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 55801cb0ef41Sopenharmony_ci set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 55811cb0ef41Sopenharmony_ci set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 55821cb0ef41Sopenharmony_ci set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 55831cb0ef41Sopenharmony_ci set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 55841cb0ef41Sopenharmony_ci} 55851cb0ef41Sopenharmony_ci 55861cb0ef41Sopenharmony_ci// static 55871cb0ef41Sopenharmony_civoid JSMessageObject::EnsureSourcePositionsAvailable( 55881cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSMessageObject> message) { 55891cb0ef41Sopenharmony_ci if (!message->DidEnsureSourcePositionsAvailable()) { 55901cb0ef41Sopenharmony_ci DCHECK_EQ(message->start_position(), -1); 55911cb0ef41Sopenharmony_ci DCHECK_GE(message->bytecode_offset().value(), kFunctionEntryBytecodeOffset); 55921cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared_info( 55931cb0ef41Sopenharmony_ci SharedFunctionInfo::cast(message->shared_info()), isolate); 55941cb0ef41Sopenharmony_ci IsCompiledScope is_compiled_scope; 55951cb0ef41Sopenharmony_ci SharedFunctionInfo::EnsureBytecodeArrayAvailable( 55961cb0ef41Sopenharmony_ci isolate, shared_info, &is_compiled_scope, CreateSourcePositions::kYes); 55971cb0ef41Sopenharmony_ci SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate, shared_info); 55981cb0ef41Sopenharmony_ci DCHECK(shared_info->HasBytecodeArray()); 55991cb0ef41Sopenharmony_ci int position = shared_info->abstract_code(isolate).SourcePosition( 56001cb0ef41Sopenharmony_ci message->bytecode_offset().value()); 56011cb0ef41Sopenharmony_ci DCHECK_GE(position, 0); 56021cb0ef41Sopenharmony_ci message->set_start_position(position); 56031cb0ef41Sopenharmony_ci message->set_end_position(position + 1); 56041cb0ef41Sopenharmony_ci message->set_shared_info(ReadOnlyRoots(isolate).undefined_value()); 56051cb0ef41Sopenharmony_ci } 56061cb0ef41Sopenharmony_ci} 56071cb0ef41Sopenharmony_ci 56081cb0ef41Sopenharmony_ciint JSMessageObject::GetLineNumber() const { 56091cb0ef41Sopenharmony_ci DCHECK(DidEnsureSourcePositionsAvailable()); 56101cb0ef41Sopenharmony_ci if (start_position() == -1) return Message::kNoLineNumberInfo; 56111cb0ef41Sopenharmony_ci 56121cb0ef41Sopenharmony_ci Handle<Script> the_script(script(), GetIsolate()); 56131cb0ef41Sopenharmony_ci 56141cb0ef41Sopenharmony_ci Script::PositionInfo info; 56151cb0ef41Sopenharmony_ci const Script::OffsetFlag offset_flag = Script::WITH_OFFSET; 56161cb0ef41Sopenharmony_ci if (!Script::GetPositionInfo(the_script, start_position(), &info, 56171cb0ef41Sopenharmony_ci offset_flag)) { 56181cb0ef41Sopenharmony_ci return Message::kNoLineNumberInfo; 56191cb0ef41Sopenharmony_ci } 56201cb0ef41Sopenharmony_ci 56211cb0ef41Sopenharmony_ci return info.line + 1; 56221cb0ef41Sopenharmony_ci} 56231cb0ef41Sopenharmony_ci 56241cb0ef41Sopenharmony_ciint JSMessageObject::GetColumnNumber() const { 56251cb0ef41Sopenharmony_ci DCHECK(DidEnsureSourcePositionsAvailable()); 56261cb0ef41Sopenharmony_ci if (start_position() == -1) return -1; 56271cb0ef41Sopenharmony_ci 56281cb0ef41Sopenharmony_ci Handle<Script> the_script(script(), GetIsolate()); 56291cb0ef41Sopenharmony_ci 56301cb0ef41Sopenharmony_ci Script::PositionInfo info; 56311cb0ef41Sopenharmony_ci const Script::OffsetFlag offset_flag = Script::WITH_OFFSET; 56321cb0ef41Sopenharmony_ci if (!Script::GetPositionInfo(the_script, start_position(), &info, 56331cb0ef41Sopenharmony_ci offset_flag)) { 56341cb0ef41Sopenharmony_ci return -1; 56351cb0ef41Sopenharmony_ci } 56361cb0ef41Sopenharmony_ci 56371cb0ef41Sopenharmony_ci return info.column; // Note: No '+1' in contrast to GetLineNumber. 56381cb0ef41Sopenharmony_ci} 56391cb0ef41Sopenharmony_ci 56401cb0ef41Sopenharmony_ciString JSMessageObject::GetSource() const { 56411cb0ef41Sopenharmony_ci Script script_object = script(); 56421cb0ef41Sopenharmony_ci if (script_object.HasValidSource()) { 56431cb0ef41Sopenharmony_ci Object source = script_object.source(); 56441cb0ef41Sopenharmony_ci if (source.IsString()) return String::cast(source); 56451cb0ef41Sopenharmony_ci } 56461cb0ef41Sopenharmony_ci return ReadOnlyRoots(GetIsolate()).empty_string(); 56471cb0ef41Sopenharmony_ci} 56481cb0ef41Sopenharmony_ci 56491cb0ef41Sopenharmony_ciHandle<String> JSMessageObject::GetSourceLine() const { 56501cb0ef41Sopenharmony_ci Isolate* isolate = GetIsolate(); 56511cb0ef41Sopenharmony_ci Handle<Script> the_script(script(), isolate); 56521cb0ef41Sopenharmony_ci 56531cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 56541cb0ef41Sopenharmony_ci if (the_script->type() == Script::TYPE_WASM) { 56551cb0ef41Sopenharmony_ci return isolate->factory()->empty_string(); 56561cb0ef41Sopenharmony_ci } 56571cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 56581cb0ef41Sopenharmony_ci 56591cb0ef41Sopenharmony_ci Script::PositionInfo info; 56601cb0ef41Sopenharmony_ci const Script::OffsetFlag offset_flag = Script::WITH_OFFSET; 56611cb0ef41Sopenharmony_ci DCHECK(DidEnsureSourcePositionsAvailable()); 56621cb0ef41Sopenharmony_ci if (!Script::GetPositionInfo(the_script, start_position(), &info, 56631cb0ef41Sopenharmony_ci offset_flag)) { 56641cb0ef41Sopenharmony_ci return isolate->factory()->empty_string(); 56651cb0ef41Sopenharmony_ci } 56661cb0ef41Sopenharmony_ci 56671cb0ef41Sopenharmony_ci Handle<String> src = handle(String::cast(the_script->source()), isolate); 56681cb0ef41Sopenharmony_ci return isolate->factory()->NewSubString(src, info.line_start, info.line_end); 56691cb0ef41Sopenharmony_ci} 56701cb0ef41Sopenharmony_ci 56711cb0ef41Sopenharmony_ci} // namespace internal 56721cb0ef41Sopenharmony_ci} // namespace v8 5673