v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
js-objects.cc
Go to the documentation of this file.
1// Copyright 2019 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <limits>
8#include <optional>
9
11#include "src/api/api-natives.h"
13#include "src/common/globals.h"
14#include "src/date/date.h"
22#include "src/heap/heap-inl.h"
28#include "src/logging/log.h"
54#include "src/objects/lookup.h"
55#include "src/objects/map-inl.h"
57#include "src/objects/module.h"
60#include "src/objects/oddball.h"
68#include "src/objects/tagged.h"
72#include "src/utils/ostreams.h"
73
74#if V8_ENABLE_WEBASSEMBLY
77#endif // V8_ENABLE_WEBASSEMBLY
78
79#ifdef V8_INTL_SUPPORT
93#endif // V8_INTL_SUPPORT
94
95namespace v8::internal {
96
97// static
99 for (;; it->Next()) {
100 switch (it->state()) {
102 UNREACHABLE();
104 return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
105 it->GetName());
107 continue; // Continue to the prototype, if present.
111 if (result.IsNothing()) return Nothing<bool>();
112 if (result.FromJust() != ABSENT) return Just(true);
113 continue;
114 }
116 if (it->HasAccess()) continue;
119 if (result.IsNothing()) return Nothing<bool>();
120 return Just(result.FromJust() != ABSENT);
121 }
123 // TypedArray out-of-bounds access.
124 return Just(false);
127 return Just(true);
129 return Just(false);
130 }
131 UNREACHABLE();
132 }
133}
134
135// static
138 DirectHandle<Name> name) {
139 if (IsJSModuleNamespace(*object)) {
141 return JSReceiver::GetOwnPropertyDescriptor(isolate, object, name, &desc);
142 }
143
144 if (IsJSObject(*object)) { // Shortcut.
145 PropertyKey key(isolate, name);
146 LookupIterator it(isolate, object, key, LookupIterator::OWN);
147 return HasProperty(&it);
148 }
149
150 Maybe<PropertyAttributes> attributes =
151 JSReceiver::GetOwnPropertyAttributes(isolate, object, name);
152 MAYBE_RETURN(attributes, Nothing<bool>());
153 return Just(attributes.FromJust() != ABSENT);
154}
155
157 AllocationPolicy allocation_policy) {
158 for (;; it->Next()) {
159 switch (it->state()) {
162 UNREACHABLE();
164 // Support calling this method without an active context, but refuse
165 // access to access-checked objects in that case.
166 if (!it->isolate()->context().is_null() && it->HasAccess()) continue;
167 [[fallthrough]];
169 it->NotFound();
170 return it->isolate()->factory()->undefined_value();
172 continue; // Continue to the prototype, if present.
174 // TODO(verwaest): For now this doesn't call into AccessorInfo, since
175 // clients don't need it. Update once relevant.
176 it->NotFound();
177 return it->isolate()->factory()->undefined_value();
179 return it->isolate()->factory()->undefined_value();
181 return it->GetDataValue(allocation_policy);
183 return it->isolate()->factory()->undefined_value();
184 }
185 UNREACHABLE();
186 }
187}
188
189// static
192 DirectHandle<Object> proto) {
193 PrototypeIterator iter(isolate, object, kStartAtReceiver);
194 while (true) {
195 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
196 if (iter.IsAtEnd()) return Just(false);
197 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
198 return Just(true);
199 }
200 }
201}
202
203// static
205 bool is_define) {
206 DCHECK(it->GetName()->IsPrivateName());
207 Isolate* isolate = it->isolate();
208 DirectHandle<String> name_string(
209 Cast<String>(Cast<Symbol>(it->GetName())->description()), isolate);
210 for (;; it->Next()) {
211 switch (it->state()) {
217 UNREACHABLE();
219 if (!it->HasAccess()) {
221 isolate->ReportFailedAccessCheck(
222 Cast<JSObject>(it->GetReceiver())),
223 Nothing<bool>());
224 UNREACHABLE();
225 }
226 continue;
228 if (is_define) {
229 MessageTemplate message =
230 it->GetName()->IsPrivateBrand()
231 ? MessageTemplate::kInvalidPrivateBrandReinitialization
232 : MessageTemplate::kInvalidPrivateFieldReinitialization;
233 RETURN_FAILURE(isolate,
235 NewTypeError(message, name_string, it->GetReceiver()));
236 }
237 return Just(true);
240 NewTypeError(MessageTemplate::kWasmObjectsAreOpaque));
242 if (!is_define) {
244 isolate, GetShouldThrow(isolate, Nothing<ShouldThrow>()),
245 NewTypeError(MessageTemplate::kInvalidPrivateMemberWrite,
246 name_string, it->GetReceiver()));
247
248 } else if (it->ExtendingNonExtensible(
249 it->GetStoreTarget<JSReceiver>())) {
251 isolate, kThrowOnError,
252 NewTypeError(MessageTemplate::kDefineDisallowed, name_string));
253 }
254 return Just(true);
255 }
256 UNREACHABLE();
257 }
258}
259
260namespace {
261
262bool HasExcludedProperty(base::Vector<DirectHandle<Object>> excluded_properties,
263 DirectHandle<Object> search_element) {
264 // TODO(gsathya): Change this to be a hashtable.
265 for (DirectHandle<Object> object : excluded_properties) {
266 if (Object::SameValue(*search_element, *object)) {
267 return true;
268 }
269 }
270
271 return false;
272}
273
274// If direct handles are enabled, it is the responsibility of the caller to
275// ensure that the memory pointed to by `excluded_properties` is scanned
276// during CSS, e.g., it comes from a `DirectHandleVector<Object>`.
277V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
278 Isolate* isolate, DirectHandle<JSReceiver> target,
279 DirectHandle<Object> source, PropertiesEnumerationMode mode,
280 base::Vector<DirectHandle<Object>> excluded_properties, bool use_set) {
281 // Non-empty strings are the only non-JSReceivers that need to be handled
282 // explicitly by Object.assign.
283 if (!IsJSReceiver(*source)) {
284 return Just(!IsString(*source) || Cast<String>(*source)->length() == 0);
285 }
286
287 // If the target is deprecated, the object will be updated on first store. If
288 // the source for that store equals the target, this will invalidate the
289 // cached representation of the source. Preventively upgrade the target.
290 // Do this on each iteration since any property load could cause deprecation.
291 if (target->map()->is_deprecated()) {
293 }
294
295 DirectHandle<Map> map(Cast<JSReceiver>(*source)->map(), isolate);
296
297 if (!IsJSObjectMap(*map)) return Just(false);
298 if (!map->OnlyHasSimpleProperties()) return Just(false);
299
300 DirectHandle<JSObject> from = Cast<JSObject>(source);
301 if (from->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
302 return Just(false);
303 }
304
305 // We should never try to copy properties from an object itself.
306 CHECK_IMPLIES(!use_set, !target.is_identical_to(from));
307
308 bool stable = true;
309
310 // Process symbols last and only do that if we found symbols.
311 bool has_symbol = false;
312 bool process_symbol_only = false;
313 while (true) {
314 for (InternalIndex i : map->IterateOwnDescriptors()) {
315 HandleScope inner_scope(isolate);
316
317 // The descriptor array is not cached on purpose since it has to stay in
318 // sync with map->instance_descriptors to avoid it from being pruned.
319 DirectHandle<Name> next_key(map->instance_descriptors(isolate)->GetKey(i),
320 isolate);
322 if (IsSymbol(*next_key)) {
323 has_symbol = true;
324 if (!process_symbol_only) continue;
325 } else {
326 if (process_symbol_only) continue;
327 }
328 }
329 DirectHandle<Object> prop_value;
330 // Directly decode from the descriptor array if |from| did not change
331 // shape.
332 if (stable) {
333 DCHECK_EQ(from->map(), *map);
334
335 PropertyDetails details =
336 map->instance_descriptors(isolate)->GetDetails(i);
337 if (!details.IsEnumerable()) continue;
338 if (details.kind() == PropertyKind::kData) {
339 CHECK_EQ(details.location(), PropertyLocation::kField);
340 Representation representation = details.representation();
341 FieldIndex index = FieldIndex::ForPropertyIndex(
342 *map, details.field_index(), representation);
343 prop_value =
344 JSObject::FastPropertyAt(isolate, from, representation, index);
345 } else {
346 LookupIterator it(isolate, from, next_key,
349 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
350 stable = from->map() == *map;
351 }
352 } else {
353 // If the map did change, do a slower lookup. We are still guaranteed
354 // that the object has a simple shape, and that the key is a name.
355 LookupIterator it(isolate, from, next_key, from,
357 if (!it.IsFound()) continue;
358 DCHECK(it.state() == LookupIterator::DATA ||
359 it.state() == LookupIterator::ACCESSOR);
360 if (!it.IsEnumerable()) continue;
362 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
363 }
364
365 if (use_set) {
366 // The lookup will walk the prototype chain, so we have to be careful
367 // to treat any key correctly for any receiver/holder.
368 PropertyKey key(isolate, next_key);
369 LookupIterator it(isolate, target, key);
370 Maybe<bool> result =
373 if (result.IsNothing()) return result;
374 if (stable) {
375 stable = from->map() == *map;
376 }
377 } else {
378 // No element indexes should get here or the exclusion check may
379 // yield false negatives for type mismatch.
380 if (!excluded_properties.empty() &&
381 HasExcludedProperty(excluded_properties, next_key)) {
382 continue;
383 }
384
385 // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue).
386 // This is an OWN lookup, so constructing a named-mode LookupIterator
387 // from {next_key} is safe.
388 CHECK(JSReceiver::CreateDataProperty(isolate, target, next_key,
389 prop_value, Just(kThrowOnError))
390 .FromJust());
391 }
392 }
394 if (process_symbol_only || !has_symbol) {
395 return Just(true);
396 }
397 if (has_symbol) {
398 process_symbol_only = true;
399 }
400 } else {
402 return Just(true);
403 }
404 }
405 UNREACHABLE();
406}
407} // namespace
408
409// static
411 Isolate* isolate, DirectHandle<JSReceiver> target,
413 base::Vector<DirectHandle<Object>> excluded_properties, bool use_set) {
414 Maybe<bool> fast_assign =
415 FastAssign(isolate, target, source, mode, excluded_properties, use_set);
416 if (fast_assign.IsNothing()) return Nothing<bool>();
417 if (fast_assign.FromJust()) return Just(true);
418
420 Object::ToObject(isolate, source).ToHandleChecked();
421
422 // 3b. Let keys be ? from.[[OwnPropertyKeys]]().
425 isolate, keys,
428 Nothing<bool>());
429
430 if (!from->HasFastProperties() && target->HasFastProperties() &&
431 IsJSObject(*target) && !IsJSGlobalProxy(*target)) {
432 // Convert to slow properties if we're guaranteed to overflow the number of
433 // descriptors.
434 int source_length;
435 if (IsJSGlobalObject(*from)) {
436 source_length = Cast<JSGlobalObject>(*from)
437 ->global_dictionary(kAcquireLoad)
438 ->NumberOfEnumerableProperties();
439 } else if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
440 source_length =
441 from->property_dictionary_swiss()->NumberOfEnumerableProperties();
442 } else {
443 source_length =
444 from->property_dictionary()->NumberOfEnumerableProperties();
445 }
446 if (source_length > kMaxNumberOfDescriptors) {
448 CLEAR_INOBJECT_PROPERTIES, source_length,
449 "Copying data properties");
450 }
451 }
452
453 // 4. Repeat for each element nextKey of keys in List order,
454 for (int i = 0; i < keys->length(); ++i) {
455 DirectHandle<Object> next_key(keys->get(i), isolate);
456 if (!excluded_properties.empty() &&
457 HasExcludedProperty(excluded_properties, next_key)) {
458 continue;
459 }
460
461 // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey).
463 Maybe<bool> found =
464 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
465 if (found.IsNothing()) return Nothing<bool>();
466 // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then
467 if (found.FromJust() && desc.enumerable()) {
468 // 4a ii 1. Let propValue be ? Get(from, nextKey).
469 DirectHandle<Object> prop_value;
471 isolate, prop_value,
472 Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>());
473
474 if (use_set) {
475 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
478 isolate, status,
479 Runtime::SetObjectProperty(isolate, target, next_key, prop_value,
482 Nothing<bool>());
483 } else {
484 // 4a ii 2. Perform ! CreateDataProperty(target, nextKey, propValue).
485 PropertyKey key(isolate, next_key);
486 CHECK(JSReceiver::CreateDataProperty(isolate, target, key, prop_value,
488 .FromJust());
489 }
490 }
491 }
492
493 return Just(true);
494}
495
498 if (IsJSFunctionOrBoundFunctionOrWrappedFunction(*this)) {
499 return roots.Function_string();
500 }
501 if (IsJSArgumentsObject(*this)) return roots.Arguments_string();
502 if (IsJSArray(*this)) return roots.Array_string();
503 if (IsJSArrayBuffer(*this)) {
504 if (Cast<JSArrayBuffer>(*this)->is_shared()) {
505 return roots.SharedArrayBuffer_string();
506 }
507 return roots.ArrayBuffer_string();
508 }
509 if (IsJSArrayIterator(*this)) return roots.ArrayIterator_string();
510 if (IsJSDate(*this)) return roots.Date_string();
511 if (IsJSError(*this)) return roots.Error_string();
512 if (IsJSGeneratorObject(*this)) return roots.Generator_string();
513 if (IsJSMap(*this)) return roots.Map_string();
514 if (IsJSMapIterator(*this)) return roots.MapIterator_string();
515 if (IsJSProxy(*this)) {
516 return map()->is_callable() ? roots.Function_string()
517 : roots.Object_string();
518 }
519 if (IsJSRegExp(*this)) return roots.RegExp_string();
520 if (IsJSSet(*this)) return roots.Set_string();
521 if (IsJSSetIterator(*this)) return roots.SetIterator_string();
522 if (IsJSTypedArray(*this)) {
523#define SWITCH_KIND(Type, type, TYPE, ctype) \
524 if (map()->elements_kind() == TYPE##_ELEMENTS) { \
525 return roots.Type##Array_string(); \
526 }
528#undef SWITCH_KIND
529 }
530 if (IsJSPrimitiveWrapper(*this)) {
531 Tagged<Object> value = Cast<JSPrimitiveWrapper>(*this)->value();
532 if (IsBoolean(value)) return roots.Boolean_string();
533 if (IsString(value)) return roots.String_string();
534 if (IsNumber(value)) return roots.Number_string();
535 if (IsBigInt(value)) return roots.BigInt_string();
536 if (IsSymbol(value)) return roots.Symbol_string();
537 if (IsScript(value)) return roots.Script_string();
538 UNREACHABLE();
539 }
540 if (IsJSWeakMap(*this)) return roots.WeakMap_string();
541 if (IsJSWeakSet(*this)) return roots.WeakSet_string();
542 if (IsJSGlobalProxy(*this)) return roots.global_string();
543 if (IsShared(*this)) {
544 if (IsJSSharedStruct(*this)) return roots.SharedStruct_string();
545 if (IsJSSharedArray(*this)) return roots.SharedArray_string();
546 if (IsJSAtomicsMutex(*this)) return roots.AtomicsMutex_string();
547 if (IsJSAtomicsCondition(*this)) return roots.AtomicsCondition_string();
548 // Other shared values are primitives.
549 UNREACHABLE();
550 }
551
552 return roots.Object_string();
553}
554
555namespace {
556std::pair<MaybeDirectHandle<JSFunction>, DirectHandle<String>>
557GetConstructorHelper(Isolate* isolate, DirectHandle<JSReceiver> receiver) {
558 // If the object was instantiated simply with base == new.target, the
559 // constructor on the map provides the most accurate name.
560 // Don't provide the info for prototypes, since their constructors are
561 // reclaimed and replaced by Object in OptimizeAsPrototype.
562 if (!IsJSProxy(*receiver) && receiver->map()->new_target_is_base() &&
563 !receiver->map()->is_prototype_map()) {
564 DirectHandle<Object> maybe_constructor(receiver->map()->GetConstructor(),
565 isolate);
566 if (IsJSFunction(*maybe_constructor)) {
567 DirectHandle<JSFunction> constructor =
568 Cast<JSFunction>(maybe_constructor);
570 isolate, direct_handle(constructor->shared(), isolate));
571 if (name->length() != 0 &&
572 !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
573 return std::make_pair(indirect_handle(constructor, isolate), name);
574 }
575 } else if (IsFunctionTemplateInfo(*maybe_constructor)) {
576 DirectHandle<FunctionTemplateInfo> function_template =
577 Cast<FunctionTemplateInfo>(maybe_constructor);
578 if (!IsUndefined(function_template->class_name(), isolate)) {
579 return std::make_pair(
580 MaybeHandle<JSFunction>(),
581 handle(Cast<String>(function_template->class_name()), isolate));
582 }
583 }
584 }
585
586 for (PrototypeIterator it(isolate, receiver, kStartAtReceiver); !it.IsAtEnd();
587 it.AdvanceIgnoringProxies()) {
589
590 LookupIterator it_to_string_tag(
591 isolate, receiver, isolate->factory()->to_string_tag_symbol(), current,
593 auto maybe_to_string_tag = JSReceiver::GetDataProperty(
594 &it_to_string_tag, AllocationPolicy::kAllocationDisallowed);
595 if (IsString(*maybe_to_string_tag)) {
596 return std::make_pair(MaybeHandle<JSFunction>(),
597 Cast<String>(maybe_to_string_tag));
598 }
599
600 // Consider the following example:
601 //
602 // function A() {}
603 // function B() {}
604 // B.prototype = new A();
605 // B.prototype.constructor = B;
606 //
607 // The constructor name for `B.prototype` must yield "A", so we don't take
608 // "constructor" into account for the receiver itself, but only starting
609 // on the prototype chain.
610 if (!receiver.is_identical_to(current)) {
611 LookupIterator it_constructor(
612 isolate, receiver, isolate->factory()->constructor_string(), current,
614 auto maybe_constructor = JSReceiver::GetDataProperty(
616 if (IsJSFunction(*maybe_constructor)) {
617 auto constructor = Cast<JSFunction>(maybe_constructor);
619 isolate, direct_handle(constructor->shared(), isolate));
620
621 if (name->length() != 0 &&
622 !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
623 return std::make_pair(constructor, name);
624 }
625 }
626 }
627 }
628
629 return std::make_pair(MaybeHandle<JSFunction>(),
630 handle(receiver->class_name(), isolate));
631}
632} // anonymous namespace
633
634// static
637 return GetConstructorHelper(isolate, receiver).first;
638}
639
640// static
643 return GetConstructorHelper(isolate, receiver).second;
644}
645
646// static
649 Isolate* isolate = receiver->GetIsolate();
650 // This is implemented as a loop because it's possible to construct very
651 // long chains of bound functions or proxies where a recursive implementation
652 // would run out of stack space.
654 Tagged<JSReceiver> current = *receiver;
655 do {
656 DCHECK(current->map()->is_constructor());
657 InstanceType instance_type = current->map()->instance_type();
658 if (InstanceTypeChecker::IsJSProxy(instance_type)) {
659 Tagged<JSProxy> proxy = Cast<JSProxy>(current);
660 if (proxy->IsRevoked()) {
661 AllowGarbageCollection allow_allocating_errors;
662 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyRevoked));
663 }
664 current = Cast<JSReceiver>(proxy->target());
665 continue;
666 }
667 if (InstanceTypeChecker::IsJSFunction(instance_type)) {
668 Tagged<JSFunction> function = Cast<JSFunction>(current);
669 return direct_handle(function->native_context(), isolate);
670 }
671 if (InstanceTypeChecker::IsJSBoundFunction(instance_type)) {
673 current = function->bound_target_function();
674 continue;
675 }
676 if (InstanceTypeChecker::IsJSWrappedFunction(instance_type)) {
678 current = function->wrapped_target_function();
679 continue;
680 }
681 Tagged<JSObject> object = Cast<JSObject>(current);
682 DCHECK(!IsJSFunction(object));
683 return object->GetCreationContext(isolate);
684 } while (true);
685}
686
687// static
690 Isolate* isolate = receiver->GetIsolate();
691 while (IsJSBoundFunction(*receiver) || IsJSProxy(*receiver)) {
692 if (IsJSBoundFunction(*receiver)) {
694 Cast<JSBoundFunction>(receiver)->bound_target_function(), isolate);
695 } else {
696 DCHECK(IsJSProxy(*receiver));
698 if (!IsJSReceiver(*target)) return MaybeHandle<NativeContext>();
699 receiver = Cast<JSReceiver>(target);
700 }
701 }
702
703 if (!IsJSFunction(*receiver)) return MaybeHandle<NativeContext>();
704 return handle(Cast<JSFunction>(receiver)->native_context(), isolate);
705}
706
708 LookupIterator* it) {
709 for (;; it->Next()) {
710 switch (it->state()) {
712 UNREACHABLE();
716 return Just(ABSENT);
720 if (result.IsNothing()) return result;
721 if (result.FromJust() != ABSENT) return result;
722 continue;
723 }
725 if (it->HasAccess()) continue;
728 return Just(ABSENT);
730 if (IsJSModuleNamespace(*it->GetHolder<Object>())) {
732 } else {
733 return Just(it->property_attributes());
734 }
736 return Just(it->property_attributes());
738 return Just(ABSENT);
739 }
740 UNREACHABLE();
741 }
742}
743
744namespace {
745
746Tagged<Object> SetHashAndUpdateProperties(Tagged<HeapObject> properties,
747 int hash) {
750
752 if (properties == roots.empty_fixed_array() ||
753 properties == roots.empty_property_array() ||
754 properties == roots.empty_property_dictionary() ||
755 properties == roots.empty_swiss_property_dictionary()) {
756 return Smi::FromInt(hash);
757 }
758
759 if (IsPropertyArray(properties)) {
760 Cast<PropertyArray>(properties)->SetHash(hash);
761 DCHECK_LT(0, Cast<PropertyArray>(properties)->length());
762 return properties;
763 }
764
765 if (IsGlobalDictionary(properties)) {
766 Cast<GlobalDictionary>(properties)->SetHash(hash);
767 return properties;
768 }
769
770 DCHECK(IsPropertyDictionary(properties));
771 Cast<PropertyDictionary>(properties)->SetHash(hash);
772
773 return properties;
774}
775
776int GetIdentityHashHelper(Tagged<JSReceiver> object) {
778 Tagged<Object> properties = object->raw_properties_or_hash();
779 if (IsSmi(properties)) {
780 return Smi::ToInt(properties);
781 }
782
783 if (IsPropertyArray(properties)) {
784 return Cast<PropertyArray>(properties)->Hash();
785 }
786
787 if (IsPropertyDictionary(properties)) {
788 return Cast<PropertyDictionary>(properties)->Hash();
789 }
790
791 if (IsGlobalDictionary(properties)) {
792 return Cast<GlobalDictionary>(properties)->Hash();
793 }
794
795#ifdef DEBUG
796 ReadOnlyRoots roots = GetReadOnlyRoots();
797 DCHECK(properties == roots.empty_fixed_array() ||
798 properties == roots.empty_property_dictionary() ||
799 properties == roots.empty_swiss_property_dictionary());
800#endif
801
803}
804} // namespace
805
810
811 Tagged<HeapObject> existing_properties =
813 Tagged<Object> new_properties =
814 SetHashAndUpdateProperties(existing_properties, hash);
815 set_raw_properties_or_hash(new_properties, kRelaxedStore);
816}
817
819 DCHECK_IMPLIES(IsPropertyArray(properties) &&
820 Cast<PropertyArray>(properties)->length() == 0,
821 properties == GetReadOnlyRoots().empty_property_array());
823 int hash = GetIdentityHashHelper(*this);
824 Tagged<Object> new_properties = properties;
825
826 // TODO(cbruni): Make GetIdentityHashHelper return a bool so that we
827 // don't have to manually compare against kNoHashSentinel.
828 if (hash != PropertyArray::kNoHashSentinel) {
829 new_properties = SetHashAndUpdateProperties(properties, hash);
830 }
831
832 set_raw_properties_or_hash(new_properties, kRelaxedStore);
833}
834
837
838 int hash = GetIdentityHashHelper(*this);
839 if (hash == PropertyArray::kNoHashSentinel) {
840 return GetReadOnlyRoots().undefined_value();
841 }
842
843 return Smi::FromInt(hash);
844}
845
846// static
850 int hash = isolate->GenerateIdentityHash(PropertyArray::HashField::kMax);
852
853 key->SetIdentityHash(hash);
854 return Smi::FromInt(hash);
855}
856
859
860 int hash = GetIdentityHashHelper(*this);
861 if (hash != PropertyArray::kNoHashSentinel) {
862 return Smi::FromInt(hash);
863 }
864
865 return JSReceiver::CreateIdentityHash(isolate, *this);
866}
867
869 InternalIndex entry) {
870 DCHECK(!object->HasFastProperties());
871 Isolate* isolate = object->GetIsolate();
872 DCHECK(entry.is_found());
873
874 if (IsJSGlobalObject(*object)) {
875 // If we have a global object, invalidate the cell and remove it from the
876 // global object's dictionary.
878 Cast<JSGlobalObject>(*object)->global_dictionary(kAcquireLoad),
879 isolate);
880
881 DirectHandle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
882
883 DirectHandle<GlobalDictionary> new_dictionary =
884 GlobalDictionary::DeleteEntry(isolate, dictionary, entry);
885 Cast<JSGlobalObject>(*object)->set_global_dictionary(*new_dictionary,
887
888 cell->ClearAndInvalidate(isolate);
889 } else {
892 object->property_dictionary_swiss(), isolate);
893
894 dictionary = SwissNameDictionary::DeleteEntry(isolate, dictionary, entry);
895 object->SetProperties(*dictionary);
896 } else {
897 DirectHandle<NameDictionary> dictionary(object->property_dictionary(),
898 isolate);
899
900 dictionary = NameDictionary::DeleteEntry(isolate, dictionary, entry);
901 object->SetProperties(*dictionary);
902 }
903 }
904 if (object->map()->is_prototype_map()) {
905 // Invalidate prototype validity cell as this may invalidate transitioning
906 // store IC handlers.
908 }
909}
910
912 LanguageMode language_mode) {
913 it->UpdateProtector();
914
915 Isolate* isolate = it->isolate();
916
917 if (it->state() == LookupIterator::JSPROXY) {
918 return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
919 it->GetName(), language_mode);
920 }
921
922 if (IsJSProxy(*it->GetReceiver())) {
923 if (it->state() != LookupIterator::NOT_FOUND) {
924 DCHECK_EQ(LookupIterator::DATA, it->state());
925 DCHECK(it->name()->IsPrivate());
926 it->Delete();
927 }
928 return Just(true);
929 }
930
931 for (;; it->Next()) {
932 switch (it->state()) {
935 UNREACHABLE();
938 NewTypeError(MessageTemplate::kWasmObjectsAreOpaque));
940 if (it->HasAccess()) continue;
942 isolate,
943 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()),
944 Nothing<bool>());
945 UNREACHABLE();
947 ShouldThrow should_throw =
948 is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
950 if (!JSObject::DeletePropertyWithInterceptor(it, should_throw)
951 .To(&result)) {
952 // An exception was thrown in the interceptor. Propagate.
953 return Nothing<bool>();
954 }
955 switch (result) {
957 return Just(false);
959 return Just(true);
961 // Proceed lookup.
962 continue;
963 }
964 UNREACHABLE();
965 }
967 return Just(true);
970 DirectHandle<JSObject> holder = it->GetHolder<JSObject>();
971 if (!it->IsConfigurable() ||
972 (IsJSTypedArray(*holder) && it->IsElement(*holder))) {
973 // Fail if the property is not configurable if the property is a
974 // TypedArray element.
975 if (is_strict(language_mode)) {
976 isolate->Throw(*isolate->factory()->NewTypeError(
977 MessageTemplate::kStrictDeleteProperty, it->GetName(),
978 it->GetReceiver()));
979 return Nothing<bool>();
980 }
981 return Just(false);
982 }
983
984 it->Delete();
985
986 return Just(true);
987 }
989 return Just(true);
990 }
991 UNREACHABLE();
992 }
993}
994
997 uint32_t index,
998 LanguageMode language_mode) {
999 LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
1000 return DeleteProperty(&it, language_mode);
1001}
1002
1005 DirectHandle<Name> name,
1006 LanguageMode language_mode) {
1007 LookupIterator it(isolate, object, name, object, LookupIterator::OWN);
1008 return DeleteProperty(&it, language_mode);
1009}
1010
1013 DirectHandle<Name> name,
1014 LanguageMode language_mode) {
1015 return DeletePropertyOrElement(isolate, object, PropertyKey(isolate, name),
1016 language_mode);
1017}
1018
1022 LanguageMode language_mode) {
1023 LookupIterator it(isolate, object, key, object, LookupIterator::OWN);
1024 return DeleteProperty(&it, language_mode);
1025}
1026
1027// ES6 19.1.2.4
1028// static
1030 DirectHandle<Object> object,
1032 Handle<Object> attributes) {
1033 // 1. If Type(O) is not Object, throw a TypeError exception.
1034 if (!IsJSReceiver(*object)) {
1035 DirectHandle<String> fun_name =
1036 isolate->factory()->InternalizeUtf8String("Object.defineProperty");
1038 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
1039 }
1040 // 2. Let key be ToPropertyKey(P).
1041 // 3. ReturnIfAbrupt(key).
1043 Object::ToPropertyKey(isolate, key));
1044 // 4. Let desc be ToPropertyDescriptor(Attributes).
1045 // 5. ReturnIfAbrupt(desc).
1046 PropertyDescriptor desc;
1048 isolate, Cast<JSAny>(attributes), &desc)) {
1049 return ReadOnlyRoots(isolate).exception();
1050 }
1051 // 6. Let success be DefinePropertyOrThrow(O,key, desc).
1052 Maybe<bool> success = DefineOwnProperty(isolate, Cast<JSReceiver>(object),
1053 key, &desc, Just(kThrowOnError));
1054 // 7. ReturnIfAbrupt(success).
1055 MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
1056 CHECK(success.FromJust());
1057 // 8. Return O.
1058 return *object;
1059}
1060
1061// ES6 19.1.2.3.1
1062// static
1064 Isolate* isolate, DirectHandle<Object> object,
1065 DirectHandle<Object> properties) {
1066 // 1. If Type(O) is not Object, throw a TypeError exception.
1067 if (!IsJSReceiver(*object)) {
1068 DirectHandle<String> fun_name =
1069 isolate->factory()->InternalizeUtf8String("Object.defineProperties");
1071 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
1072 }
1073 // 2. Let props be ToObject(Properties).
1074 // 3. ReturnIfAbrupt(props).
1076 ASSIGN_RETURN_ON_EXCEPTION(isolate, props,
1077 Object::ToObject(isolate, properties));
1078
1079 // 4. Let keys be props.[[OwnPropertyKeys]]().
1080 // 5. ReturnIfAbrupt(keys).
1083 isolate, keys,
1086 // 6. Let descriptors be an empty List.s
1087 int capacity = keys->length();
1088 std::vector<PropertyDescriptor> descriptors(capacity);
1089 size_t descriptors_index = 0;
1090 // 7. Repeat for each element nextKey of keys in List order,
1091 for (int i = 0; i < keys->length(); ++i) {
1092 DirectHandle<JSAny> next_key(Cast<JSAny>(keys->get(i)), isolate);
1093 // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey).
1094 // 7b. ReturnIfAbrupt(propDesc).
1095 PropertyKey key(isolate, next_key);
1096 LookupIterator it(isolate, props, key, LookupIterator::OWN);
1098 if (maybe.IsNothing()) return MaybeDirectHandle<Object>();
1099 PropertyAttributes attrs = maybe.FromJust();
1100 // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
1101 if (attrs == ABSENT) continue;
1102 if (attrs & DONT_ENUM) continue;
1103 // 7c i. Let descObj be Get(props, nextKey).
1104 // 7c ii. ReturnIfAbrupt(descObj).
1105 Handle<JSAny> desc_obj;
1106 ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj,
1108 // 7c iii. Let desc be ToPropertyDescriptor(descObj).
1110 isolate, desc_obj, &descriptors[descriptors_index]);
1111 // 7c iv. ReturnIfAbrupt(desc).
1112 if (!success) return MaybeDirectHandle<Object>();
1113 // 7c v. Append the pair (a two element List) consisting of nextKey and
1114 // desc to the end of descriptors.
1115 descriptors[descriptors_index].set_name(next_key);
1116 descriptors_index++;
1117 }
1118 // 8. For each pair from descriptors in list order,
1119 for (size_t i = 0; i < descriptors_index; ++i) {
1120 PropertyDescriptor* desc = &descriptors[i];
1121 // 8a. Let P be the first element of pair.
1122 // 8b. Let desc be the second element of pair.
1123 // 8c. Let status be DefinePropertyOrThrow(O, P, desc).
1124 Maybe<bool> status =
1125 DefineOwnProperty(isolate, Cast<JSReceiver>(object), desc->name(), desc,
1127 // 8d. ReturnIfAbrupt(status).
1128 if (status.IsNothing()) return MaybeDirectHandle<Object>();
1129 CHECK(status.FromJust());
1130 }
1131 // 9. Return o.
1132 return object;
1133}
1134
1135// static
1139 PropertyDescriptor* desc,
1140 Maybe<ShouldThrow> should_throw) {
1141 if (IsJSArray(*object)) {
1142 return JSArray::DefineOwnProperty(isolate, Cast<JSArray>(object), key, desc,
1143 should_throw);
1144 }
1145 if (IsJSProxy(*object)) {
1146 return JSProxy::DefineOwnProperty(isolate, Cast<JSProxy>(object), key, desc,
1147 should_throw);
1148 }
1149 if (IsJSTypedArray(*object)) {
1151 key, desc, should_throw);
1152 }
1153 if (IsJSModuleNamespace(*object)) {
1155 isolate, Cast<JSModuleNamespace>(object), key, desc, should_throw);
1156 }
1157 if (IsWasmObject(*object)) {
1159 NewTypeError(MessageTemplate::kWasmObjectsAreOpaque));
1160 }
1161 if (IsAlwaysSharedSpaceJSObject(*object)) {
1163 isolate, Cast<AlwaysSharedSpaceJSObject>(object), key, desc,
1164 should_throw);
1165 }
1166
1167 // OrdinaryDefineOwnProperty, by virtue of calling
1168 // DefineOwnPropertyIgnoreAttributes, can handle arguments
1169 // (ES#sec-arguments-exotic-objects-defineownproperty-p-desc).
1170 return OrdinaryDefineOwnProperty(isolate, Cast<JSObject>(object), key, desc,
1171 should_throw);
1172}
1173
1174// static
1177 PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw) {
1178 DCHECK(IsName(*key) || IsNumber(*key)); // |key| is a PropertyKey.
1179 PropertyKey lookup_key(isolate, key);
1180 return OrdinaryDefineOwnProperty(isolate, object, lookup_key, desc,
1181 should_throw);
1182}
1183
1184namespace {
1185
1186MaybeHandle<JSAny> GetPropertyWithInterceptorInternal(
1187 LookupIterator* it, DirectHandle<InterceptorInfo> interceptor, bool* done) {
1188 *done = false;
1189 Isolate* isolate = it->isolate();
1190 // Make sure that the top context does not change when doing callbacks or
1191 // interceptor calls.
1192 AssertNoContextChange ncc(isolate);
1193
1194 if (!interceptor->has_getter()) {
1195 return isolate->factory()->undefined_value();
1196 }
1197
1198 DirectHandle<JSObject> holder = it->GetHolder<JSObject>();
1199 DirectHandle<JSAny> result;
1200 DirectHandle<Object> receiver = it->GetReceiver();
1201 if (!IsJSReceiver(*receiver)) {
1204 }
1205 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1206 *holder, Just(kDontThrow));
1207
1208 if (it->IsElement(*holder)) {
1209 result = args.CallIndexedGetter(interceptor, it->array_index());
1210 } else {
1211 result = args.CallNamedGetter(interceptor, it->name());
1212 }
1213 // An exception was thrown in the interceptor. Propagate.
1215 if (result.is_null()) return isolate->factory()->undefined_value();
1216 *done = true;
1217 args.AcceptSideEffects();
1218 // Rebox handle before return
1219 return handle(*result, isolate);
1220}
1221
1222Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
1223 LookupIterator* it, DirectHandle<InterceptorInfo> interceptor) {
1224 Isolate* isolate = it->isolate();
1225 // Make sure that the top context does not change when doing
1226 // callbacks or interceptor calls.
1227 AssertNoContextChange ncc(isolate);
1228 HandleScope scope(isolate);
1229
1230 DirectHandle<JSObject> holder = it->GetHolder<JSObject>();
1231 DCHECK_IMPLIES(!it->IsElement(*holder) && IsSymbol(*it->name()),
1232 interceptor->can_intercept_symbols());
1233 DirectHandle<Object> receiver = it->GetReceiver();
1234 if (!IsJSReceiver(*receiver)) {
1238 }
1239 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1240 *holder, Just(kDontThrow));
1241 if (interceptor->has_query()) {
1242 DirectHandle<Object> result;
1243 if (it->IsElement(*holder)) {
1244 result = args.CallIndexedQuery(interceptor, it->array_index());
1245 } else {
1246 result = args.CallNamedQuery(interceptor, it->name());
1247 }
1248 // An exception was thrown in the interceptor. Propagate.
1251
1252 if (!result.is_null()) {
1253 int32_t value;
1254 CHECK(Object::ToInt32(*result, &value));
1257 // In case of absent property side effects are not allowed.
1258 // TODO(ishell): PropertyAttributes::ABSENT is not exposed in the Api,
1259 // so it can't be officially returned. We should fix the tests instead.
1260 if (value != PropertyAttributes::ABSENT) {
1261 args.AcceptSideEffects();
1262 }
1263 return Just(static_cast<PropertyAttributes>(value));
1264 }
1265 } else if (interceptor->has_getter()) {
1266 // TODO(verwaest): Use GetPropertyWithInterceptor?
1267 DirectHandle<Object> result;
1268 if (it->IsElement(*holder)) {
1269 result = args.CallIndexedGetter(interceptor, it->array_index());
1270 } else {
1271 result = args.CallNamedGetter(interceptor, it->name());
1272 }
1273 // An exception was thrown in the interceptor. Propagate.
1276
1277 if (!result.is_null()) {
1278 args.AcceptSideEffects();
1279 return Just(DONT_ENUM);
1280 }
1281 }
1282 return Just(ABSENT);
1283}
1284
1285Maybe<InterceptorResult> SetPropertyWithInterceptorInternal(
1286 LookupIterator* it, DirectHandle<InterceptorInfo> interceptor,
1287 Maybe<ShouldThrow> should_throw, DirectHandle<Object> value) {
1288 Isolate* isolate = it->isolate();
1289 // Make sure that the top context does not change when doing callbacks or
1290 // interceptor calls.
1291 AssertNoContextChange ncc(isolate);
1292
1293 if (!interceptor->has_setter()) {
1295 }
1296
1297 DirectHandle<JSObject> holder = it->GetHolder<JSObject>();
1298 DirectHandle<Object> receiver = it->GetReceiver();
1299 if (!IsJSReceiver(*receiver)) {
1303 }
1304 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1305 *holder, should_throw);
1306
1307 v8::Intercepted intercepted =
1308 it->IsElement(*holder)
1309 ? args.CallIndexedSetter(interceptor, it->array_index(), value)
1310 : args.CallNamedSetter(interceptor, it->name(), value);
1311
1312 return args.GetBooleanReturnValue(intercepted, "Setter");
1313}
1314
1315Maybe<InterceptorResult> DefinePropertyWithInterceptorInternal(
1316 LookupIterator* it, DirectHandle<InterceptorInfo> interceptor,
1317 Maybe<ShouldThrow> should_throw, PropertyDescriptor* desc) {
1318 Isolate* isolate = it->isolate();
1319 // Make sure that the top context does not change when doing callbacks or
1320 // interceptor calls.
1321 AssertNoContextChange ncc(isolate);
1322
1323 if (!interceptor->has_definer()) {
1325 }
1326
1327 DirectHandle<JSObject> holder = it->GetHolder<JSObject>();
1328 DirectHandle<Object> receiver = it->GetReceiver();
1329 if (!IsJSReceiver(*receiver)) {
1333 }
1334
1335 std::unique_ptr<v8::PropertyDescriptor> descriptor(
1338 DirectHandle<Object> getter = desc->get();
1339 if (!getter.is_null() && IsFunctionTemplateInfo(*getter)) {
1341 isolate, getter,
1344 MaybeDirectHandle<Name>()),
1346 }
1347 DirectHandle<Object> setter = desc->set();
1348 if (!setter.is_null() && IsFunctionTemplateInfo(*setter)) {
1350 isolate, setter,
1353 MaybeDirectHandle<Name>()),
1355 }
1356 descriptor.reset(new v8::PropertyDescriptor(v8::Utils::ToLocal(getter),
1357 v8::Utils::ToLocal(setter)));
1358 } else if (PropertyDescriptor::IsDataDescriptor(desc)) {
1359 if (desc->has_writable()) {
1360 descriptor.reset(new v8::PropertyDescriptor(
1361 v8::Utils::ToLocal(desc->value()), desc->writable()));
1362 } else {
1363 descriptor.reset(
1364 new v8::PropertyDescriptor(v8::Utils::ToLocal(desc->value())));
1365 }
1366 }
1367 if (desc->has_enumerable()) {
1368 descriptor->set_enumerable(desc->enumerable());
1369 }
1370 if (desc->has_configurable()) {
1371 descriptor->set_configurable(desc->configurable());
1372 }
1373
1374 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1375 *holder, should_throw);
1376
1377 v8::Intercepted intercepted =
1378 it->IsElement(*holder)
1379 ? args.CallIndexedDefiner(interceptor, it->array_index(), *descriptor)
1380 : args.CallNamedDefiner(interceptor, it->name(), *descriptor);
1381
1382 return args.GetBooleanReturnValue(intercepted, "Definer");
1383}
1384
1385} // namespace
1386
1387// ES6 9.1.6.1
1388// static
1390 Isolate* isolate, DirectHandle<JSObject> object, const PropertyKey& key,
1391 PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw) {
1392 LookupIterator it(isolate, object, key, LookupIterator::OWN);
1393
1394 // Deal with access checks first.
1395 while (it.state() == LookupIterator::ACCESS_CHECK) {
1396 if (!it.HasAccess()) {
1398 isolate, isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()),
1399 Nothing<bool>());
1400 UNREACHABLE();
1401 }
1402 it.Next();
1403 }
1404
1405 // 1. Let current be O.[[GetOwnProperty]](P).
1406 // 2. ReturnIfAbrupt(current).
1409
1410 // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset
1411 // the iterator every time. Currently, the reasons why we need it are because
1412 // GetOwnPropertyDescriptor can have side effects, namely:
1413 // - Interceptors
1414 // - Accessors (which might change the holder's map)
1415 it.Restart();
1416
1417 // Skip over the access check after restarting -- we've already checked it.
1418 while (it.state() == LookupIterator::ACCESS_CHECK) {
1419 DCHECK(it.HasAccess());
1420 it.Next();
1421 }
1422
1423 // Handle interceptor.
1424 if (it.state() == LookupIterator::INTERCEPTOR) {
1425 if (it.HolderIsReceiverOrHiddenPrototype()) {
1427 if (!DefinePropertyWithInterceptorInternal(&it, it.GetInterceptor(),
1428 should_throw, desc)
1429 .To(&result)) {
1430 // An exception was thrown in the interceptor. Propagate.
1431 return Nothing<bool>();
1432 }
1433 switch (result) {
1435 return Just(false);
1437 return Just(true);
1438
1440 // Proceed lookup.
1441 break;
1442 }
1443 // We need to restart the lookup in case the interceptor ran with side
1444 // effects.
1445 it.Restart();
1446 }
1447 }
1448
1449 // 3. Let extensible be the value of the [[Extensible]] internal slot of O.
1450 bool extensible = JSObject::IsExtensible(isolate, object);
1451
1452 return ValidateAndApplyPropertyDescriptor(isolate, &it, extensible, desc,
1453 &current, should_throw, {});
1454}
1455
1456// ES6 9.1.6.2
1457// static
1459 Isolate* isolate, bool extensible, PropertyDescriptor* desc,
1460 PropertyDescriptor* current, DirectHandle<Name> property_name,
1461 Maybe<ShouldThrow> should_throw) {
1462 // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined,
1463 // Extensible, Desc, Current).
1465 isolate, nullptr, extensible, desc, current, should_throw, property_name);
1466}
1467
1468// https://tc39.es/ecma262/#sec-validateandapplypropertydescriptor
1469// static
1471 Isolate* isolate, LookupIterator* it, bool extensible,
1472 PropertyDescriptor* desc, PropertyDescriptor* current,
1473 Maybe<ShouldThrow> should_throw, DirectHandle<Name> property_name) {
1474 // We either need a LookupIterator, or a property name.
1475 DCHECK((it == nullptr) != property_name.is_null());
1476 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
1477 bool desc_is_accessor_descriptor =
1479 bool desc_is_generic_descriptor =
1481 // 1. (Assert)
1482 // 2. If current is undefined, then
1483 if (current->is_empty()) {
1484 // 2a. If extensible is false, return false.
1485 if (!extensible) {
1487 isolate, GetShouldThrow(isolate, should_throw),
1488 NewTypeError(MessageTemplate::kDefineDisallowed,
1489 it != nullptr ? it->GetName() : property_name));
1490 }
1491 // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then:
1492 // (This is equivalent to !IsAccessorDescriptor(desc).)
1493 DCHECK_EQ(desc_is_generic_descriptor || desc_is_data_descriptor,
1494 !desc_is_accessor_descriptor);
1495 if (!desc_is_accessor_descriptor) {
1496 // 2c i. If O is not undefined, create an own data property named P of
1497 // object O whose [[Value]], [[Writable]], [[Enumerable]] and
1498 // [[Configurable]] attribute values are described by Desc. If the value
1499 // of an attribute field of Desc is absent, the attribute of the newly
1500 // created property is set to its default value.
1501 if (it != nullptr) {
1502 if (!desc->has_writable()) desc->set_writable(false);
1503 if (!desc->has_enumerable()) desc->set_enumerable(false);
1504 if (!desc->has_configurable()) desc->set_configurable(false);
1506 desc->has_value()
1507 ? desc->value()
1508 : Cast<Object>(isolate->factory()->undefined_value()));
1511 desc->ToAttributes());
1512 if (result.is_null()) return Nothing<bool>();
1513 }
1514 } else {
1515 // 2d. Else Desc must be an accessor Property Descriptor,
1516 DCHECK(desc_is_accessor_descriptor);
1517 // 2d i. If O is not undefined, create an own accessor property named P
1518 // of object O whose [[Get]], [[Set]], [[Enumerable]] and
1519 // [[Configurable]] attribute values are described by Desc. If the value
1520 // of an attribute field of Desc is absent, the attribute of the newly
1521 // created property is set to its default value.
1522 if (it != nullptr) {
1523 if (!desc->has_enumerable()) desc->set_enumerable(false);
1524 if (!desc->has_configurable()) desc->set_configurable(false);
1526 desc->has_get() ? desc->get()
1527 : Cast<Object>(isolate->factory()->null_value()));
1529 desc->has_set() ? desc->set()
1530 : Cast<Object>(isolate->factory()->null_value()));
1533 desc->ToAttributes());
1534 if (result.is_null()) return Nothing<bool>();
1535 }
1536 }
1537 // 2e. Return true.
1538 return Just(true);
1539 }
1540 // 3. If every field in Desc is absent, return true. (This also has a shortcut
1541 // not in the spec: if every field value matches the current value, return.)
1542 if ((!desc->has_enumerable() ||
1543 desc->enumerable() == current->enumerable()) &&
1544 (!desc->has_configurable() ||
1545 desc->configurable() == current->configurable()) &&
1546 !desc->has_value() &&
1547 (!desc->has_writable() ||
1548 (current->has_writable() && current->writable() == desc->writable())) &&
1549 (!desc->has_get() ||
1550 (current->has_get() &&
1551 Object::SameValue(*current->get(), *desc->get()))) &&
1552 (!desc->has_set() ||
1553 (current->has_set() &&
1554 Object::SameValue(*current->set(), *desc->set())))) {
1555 return Just(true);
1556 }
1557 // 4. If current.[[Configurable]] is false, then
1558 if (!current->configurable()) {
1559 // 4a. If Desc.[[Configurable]] is present and its value is true, return
1560 // false.
1561 if (desc->has_configurable() && desc->configurable()) {
1563 isolate, GetShouldThrow(isolate, should_throw),
1564 NewTypeError(MessageTemplate::kRedefineDisallowed,
1565 it != nullptr ? it->GetName() : property_name));
1566 }
1567 // 4b. If Desc.[[Enumerable]] is present and
1568 // ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return
1569 // false.
1570 if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
1572 isolate, GetShouldThrow(isolate, should_throw),
1573 NewTypeError(MessageTemplate::kRedefineDisallowed,
1574 it != nullptr ? it->GetName() : property_name));
1575 }
1576 }
1577
1578 bool current_is_data_descriptor =
1580 // 5. If ! IsGenericDescriptor(Desc) is true, no further validation is
1581 // required.
1582 if (desc_is_generic_descriptor) {
1583 // Nothing to see here.
1584
1585 // 6. Else if ! SameValue(!IsDataDescriptor(current),
1586 // !IsDataDescriptor(Desc)) is false, the
1587 } else if (current_is_data_descriptor != desc_is_data_descriptor) {
1588 // 6a. If current.[[Configurable]] is false, return false.
1589 if (!current->configurable()) {
1591 isolate, GetShouldThrow(isolate, should_throw),
1592 NewTypeError(MessageTemplate::kRedefineDisallowed,
1593 it != nullptr ? it->GetName() : property_name));
1594 }
1595 // 6b. If IsDataDescriptor(current) is true, then:
1596 if (current_is_data_descriptor) {
1597 // 6b i. If O is not undefined, convert the property named P of object O
1598 // from a data property to an accessor property. Preserve the existing
1599 // values of the converted property's [[Configurable]] and [[Enumerable]]
1600 // attributes and set the rest of the property's attributes to their
1601 // default values.
1602 // --> Folded into step 9
1603 } else {
1604 // 6c i. If O is not undefined, convert the property named P of object O
1605 // from an accessor property to a data property. Preserve the existing
1606 // values of the converted property’s [[Configurable]] and [[Enumerable]]
1607 // attributes and set the rest of the property’s attributes to their
1608 // default values.
1609 // --> Folded into step 9
1610 }
1611
1612 // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both
1613 // true, then:
1614 } else if (current_is_data_descriptor && desc_is_data_descriptor) {
1615 // 7a. If current.[[Configurable]] is false and current.[[Writable]] is
1616 // false, then
1617 if (!current->configurable() && !current->writable()) {
1618 // 7a i. If Desc.[[Writable]] is present and Desc.[[Writable]] is true,
1619 // return false.
1620 if (desc->has_writable() && desc->writable()) {
1622 isolate, GetShouldThrow(isolate, should_throw),
1623 NewTypeError(MessageTemplate::kRedefineDisallowed,
1624 it != nullptr ? it->GetName() : property_name));
1625 }
1626 // 7a ii. If Desc.[[Value]] is present and SameValue(Desc.[[Value]],
1627 // current.[[Value]]) is false, return false.
1628 if (desc->has_value()) {
1629 // We'll succeed applying the property, but the value is already the
1630 // same and the property is read-only, so skip actually writing the
1631 // property. Otherwise we may try to e.g., write to frozen elements.
1632 if (Object::SameValue(*desc->value(), *current->value()))
1633 return Just(true);
1635 isolate, GetShouldThrow(isolate, should_throw),
1636 NewTypeError(MessageTemplate::kRedefineDisallowed,
1637 it != nullptr ? it->GetName() : property_name));
1638 }
1639 }
1640 } else {
1641 // 8. Else,
1642 // 8a. Assert: ! IsAccessorDescriptor(current) and
1643 // ! IsAccessorDescriptor(Desc) are both true.
1645 desc_is_accessor_descriptor);
1646 // 8b. If current.[[Configurable]] is false, then:
1647 if (!current->configurable()) {
1648 // 8a i. If Desc.[[Set]] is present and SameValue(Desc.[[Set]],
1649 // current.[[Set]]) is false, return false.
1650 if (desc->has_set() &&
1651 !Object::SameValue(*desc->set(), *current->set())) {
1653 isolate, GetShouldThrow(isolate, should_throw),
1654 NewTypeError(MessageTemplate::kRedefineDisallowed,
1655 it != nullptr ? it->GetName() : property_name));
1656 }
1657 // 8a ii. If Desc.[[Get]] is present and SameValue(Desc.[[Get]],
1658 // current.[[Get]]) is false, return false.
1659 if (desc->has_get() &&
1660 !Object::SameValue(*desc->get(), *current->get())) {
1662 isolate, GetShouldThrow(isolate, should_throw),
1663 NewTypeError(MessageTemplate::kRedefineDisallowed,
1664 it != nullptr ? it->GetName() : property_name));
1665 }
1666 }
1667 }
1668
1669 // 9. If O is not undefined, then:
1670 if (it != nullptr) {
1671 // 9a. For each field of Desc that is present, set the corresponding
1672 // attribute of the property named P of object O to the value of the field.
1673 PropertyAttributes attrs = NONE;
1674
1675 if (desc->has_enumerable()) {
1676 attrs = static_cast<PropertyAttributes>(
1677 attrs | (desc->enumerable() ? NONE : DONT_ENUM));
1678 } else {
1679 attrs = static_cast<PropertyAttributes>(
1680 attrs | (current->enumerable() ? NONE : DONT_ENUM));
1681 }
1682 if (desc->has_configurable()) {
1683 attrs = static_cast<PropertyAttributes>(
1684 attrs | (desc->configurable() ? NONE : DONT_DELETE));
1685 } else {
1686 attrs = static_cast<PropertyAttributes>(
1687 attrs | (current->configurable() ? NONE : DONT_DELETE));
1688 }
1689 if (desc_is_data_descriptor ||
1690 (desc_is_generic_descriptor && current_is_data_descriptor)) {
1691 if (desc->has_writable()) {
1692 attrs = static_cast<PropertyAttributes>(
1693 attrs | (desc->writable() ? NONE : READ_ONLY));
1694 } else {
1695 attrs = static_cast<PropertyAttributes>(
1696 attrs | (current->writable() ? NONE : READ_ONLY));
1697 }
1699 desc->has_value() ? desc->value()
1700 : current->has_value()
1701 ? current->value()
1702 : Cast<Object>(isolate->factory()->undefined_value()));
1703 return JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs,
1704 should_throw);
1705 } else {
1706 DCHECK(desc_is_accessor_descriptor ||
1707 (desc_is_generic_descriptor &&
1710 desc->has_get() ? desc->get()
1711 : current->has_get()
1712 ? current->get()
1713 : Cast<Object>(isolate->factory()->null_value()));
1715 desc->has_set() ? desc->set()
1716 : current->has_set()
1717 ? current->set()
1718 : Cast<Object>(isolate->factory()->null_value()));
1721 attrs);
1722 if (result.is_null()) return Nothing<bool>();
1723 }
1724 }
1725
1726 // 10. Return true.
1727 return Just(true);
1728}
1729
1730// static
1735 Maybe<ShouldThrow> should_throw) {
1736 return CreateDataProperty(isolate, object, PropertyKey(isolate, key), value,
1737 should_throw);
1738}
1739
1740// static
1742 DirectHandle<JSAny> object,
1745 Maybe<ShouldThrow> should_throw) {
1746 if (!IsJSReceiver(*object)) {
1747 return Object::CannotCreateProperty(isolate, object, key.GetName(isolate),
1748 value, Nothing<ShouldThrow>());
1749 }
1750 return CreateDataProperty(isolate, Cast<JSReceiver>(object), key, value,
1751 should_throw);
1752}
1753
1754// static
1759 Maybe<ShouldThrow> should_throw) {
1760 if (IsJSObject(*object)) {
1761 return JSObject::CreateDataProperty(isolate, Cast<JSObject>(object), key,
1762 value, should_throw); // Shortcut.
1763 }
1764
1765 PropertyDescriptor new_desc;
1766 new_desc.set_value(Cast<JSAny>(value));
1767 new_desc.set_writable(true);
1768 new_desc.set_enumerable(true);
1769 new_desc.set_configurable(true);
1770
1771 return JSReceiver::DefineOwnProperty(isolate, object, key.GetName(isolate),
1772 &new_desc, should_throw);
1773}
1774
1775// static
1778 Maybe<ShouldThrow> should_throw) {
1780 DCHECK(!IsAlwaysSharedSpaceJSObject(*receiver));
1781 Isolate* isolate = it->isolate();
1782 DCHECK(it->GetName()->IsPrivateName());
1783 DirectHandle<Symbol> symbol = Cast<Symbol>(it->GetName());
1784
1785 switch (it->state()) {
1787 PropertyDescriptor new_desc;
1788 new_desc.set_value(Cast<JSAny>(value));
1789 new_desc.set_writable(true);
1790 new_desc.set_enumerable(true);
1791 new_desc.set_configurable(true);
1792 return JSProxy::SetPrivateSymbol(isolate, Cast<JSProxy>(receiver), symbol,
1793 &new_desc, should_throw);
1794 }
1797 NewTypeError(MessageTemplate::kWasmObjectsAreOpaque));
1802 UNREACHABLE();
1803
1805 if (!it->HasAccess()) {
1807 isolate,
1808 it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>()),
1809 Nothing<bool>());
1810 UNREACHABLE();
1811 }
1812 break;
1813 }
1814
1817 break;
1818 }
1819
1820 return Object::TransitionAndWriteDataProperty(it, value, NONE, should_throw,
1822}
1823
1824// static
1827 PropertyDescriptor* desc) {
1828 DCHECK(IsName(*key) || IsNumber(*key)); // |key| is a PropertyKey.
1829 PropertyKey lookup_key(isolate, key);
1830 LookupIterator it(isolate, object, lookup_key, LookupIterator::OWN);
1831 return GetOwnPropertyDescriptor(&it, desc);
1832}
1833
1834namespace {
1835
1836Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
1837 PropertyDescriptor* desc) {
1839
1840 while (it->state() == LookupIterator::ACCESS_CHECK) {
1841 if (it->HasAccess()) {
1842 it->Next();
1843 } else {
1844 interceptor = it->GetInterceptorForFailedAccessCheck();
1845 if (interceptor.is_null()) {
1846 it->Restart();
1847 return Just(false);
1848 }
1849 CHECK(!interceptor.is_null());
1850 break;
1851 }
1852 }
1853 if (it->state() == LookupIterator::INTERCEPTOR) {
1854 interceptor = it->GetInterceptor();
1855 }
1856 if (interceptor.is_null()) return Just(false);
1857 Isolate* isolate = it->isolate();
1858 if (!interceptor->has_descriptor()) return Just(false);
1859
1861 DirectHandle<JSObject> holder = it->GetHolder<JSObject>();
1862
1863 DirectHandle<Object> receiver = it->GetReceiver();
1864 if (!IsJSReceiver(*receiver)) {
1867 Nothing<bool>());
1868 }
1869
1870 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
1871 *holder, Just(kDontThrow));
1872 if (it->IsElement(*holder)) {
1873 result = args.CallIndexedDescriptor(interceptor, it->array_index());
1874 } else {
1875 result = args.CallNamedDescriptor(interceptor, it->name());
1876 }
1877 // An exception was thrown in the interceptor. Propagate.
1879 if (!result.is_null()) {
1880 // Request was successfully intercepted, try to set the property
1881 // descriptor.
1882 args.AcceptSideEffects();
1885 it->IsElement(*holder) ? "v8::IndexedPropertyDescriptorCallback"
1886 : "v8::NamedPropertyDescriptorCallback",
1887 "Invalid property descriptor.");
1888
1889 return Just(true);
1890 }
1891
1892 it->Next();
1893 return Just(false);
1894}
1895} // namespace
1896
1897// ES6 9.1.5.1
1898// Returns true on success, false if the property didn't exist, nothing if
1899// an exception was thrown.
1900// static
1902 PropertyDescriptor* desc) {
1903 Isolate* isolate = it->isolate();
1904 // "Virtual" dispatch.
1905 if (it->IsFound() && IsJSProxy(*it->GetHolder<JSReceiver>())) {
1906 return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
1907 it->GetName(), desc);
1908 }
1909
1910 Maybe<bool> intercepted = GetPropertyDescriptorWithInterceptor(it, desc);
1911 MAYBE_RETURN(intercepted, Nothing<bool>());
1912 if (intercepted.FromJust()) {
1913 return Just(true);
1914 }
1915
1916 // Request was not intercepted, continue as normal.
1917 // 1. (Assert)
1918 // 2. If O does not have an own property with key P, return undefined.
1919 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
1920 MAYBE_RETURN(maybe, Nothing<bool>());
1921 PropertyAttributes attrs = maybe.FromJust();
1922 if (attrs == ABSENT) return Just(false);
1923 DCHECK(!isolate->has_exception());
1924
1925 // 3. Let D be a newly created Property Descriptor with no fields.
1926 DCHECK(desc->is_empty());
1927 // 4. Let X be O's own property whose key is P.
1928 // 5. If X is a data property, then
1929 bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
1930 IsAccessorPair(*it->GetAccessors());
1931 if (!is_accessor_pair) {
1932 // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute.
1934 if (!Cast<JSAny>(Object::GetProperty(it)).ToHandle(&value)) {
1935 DCHECK(isolate->has_exception());
1936 return Nothing<bool>();
1937 }
1938 desc->set_value(value);
1939 // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute
1940 desc->set_writable((attrs & READ_ONLY) == 0);
1941 } else {
1942 // 6. Else X is an accessor property, so
1943 auto accessors = Cast<AccessorPair>(it->GetAccessors());
1944 DirectHandle<NativeContext> holder_realm(
1945 it->GetHolder<JSReceiver>()->GetCreationContext().value(), isolate);
1946 // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
1947 desc->set_get(AccessorPair::GetComponent(isolate, holder_realm, accessors,
1949 // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute.
1950 desc->set_set(AccessorPair::GetComponent(isolate, holder_realm, accessors,
1952 }
1953
1954 // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
1955 desc->set_enumerable((attrs & DONT_ENUM) == 0);
1956 // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
1957 desc->set_configurable((attrs & DONT_DELETE) == 0);
1958 // 9. Return D.
1961 return Just(true);
1962}
1963
1966 IntegrityLevel level,
1967 ShouldThrow should_throw) {
1968 DCHECK(level == SEALED || level == FROZEN);
1969
1970 if (IsJSObject(*receiver)) {
1972
1973 if (!object->HasSloppyArgumentsElements() &&
1974 !IsJSModuleNamespace(*object)) { // Fast path.
1975 // Prevent memory leaks by not adding unnecessary transitions.
1976 Maybe<bool> test = JSObject::TestIntegrityLevel(isolate, object, level);
1977 MAYBE_RETURN(test, Nothing<bool>());
1978 if (test.FromJust()) return test;
1979
1980 if (level == SEALED) {
1982 isolate, object, should_throw);
1983 } else {
1985 isolate, object, should_throw);
1986 }
1987 }
1988 }
1989
1990 MAYBE_RETURN(JSReceiver::PreventExtensions(isolate, receiver, should_throw),
1991 Nothing<bool>());
1992
1995 isolate, keys, JSReceiver::OwnPropertyKeys(isolate, receiver),
1996 Nothing<bool>());
1997
1998 PropertyDescriptor no_conf;
1999 no_conf.set_configurable(false);
2000
2001 PropertyDescriptor no_conf_no_write;
2002 no_conf_no_write.set_configurable(false);
2003 no_conf_no_write.set_writable(false);
2004
2005 if (level == SEALED) {
2006 for (int i = 0; i < keys->length(); ++i) {
2007 DirectHandle<Object> key(keys->get(i), isolate);
2008 MAYBE_RETURN(DefineOwnProperty(isolate, receiver, key, &no_conf,
2010 Nothing<bool>());
2011 }
2012 return Just(true);
2013 }
2014
2015 for (int i = 0; i < keys->length(); ++i) {
2016 DirectHandle<Object> key(keys->get(i), isolate);
2017 PropertyDescriptor current_desc;
2019 isolate, receiver, key, &current_desc);
2020 MAYBE_RETURN(owned, Nothing<bool>());
2021 if (owned.FromJust()) {
2022 PropertyDescriptor desc =
2024 ? no_conf
2025 : no_conf_no_write;
2027 DefineOwnProperty(isolate, receiver, key, &desc, Just(kThrowOnError)),
2028 Nothing<bool>());
2029 }
2030 }
2031 return Just(true);
2032}
2033
2034namespace {
2035Maybe<bool> GenericTestIntegrityLevel(Isolate* isolate,
2037 PropertyAttributes level) {
2038 DCHECK(level == SEALED || level == FROZEN);
2039
2040 Maybe<bool> extensible = JSReceiver::IsExtensible(isolate, receiver);
2041 MAYBE_RETURN(extensible, Nothing<bool>());
2042 if (extensible.FromJust()) return Just(false);
2043
2046 isolate, keys, JSReceiver::OwnPropertyKeys(isolate, receiver),
2047 Nothing<bool>());
2048
2049 for (int i = 0; i < keys->length(); ++i) {
2050 DirectHandle<Object> key(keys->get(i), isolate);
2051 PropertyDescriptor current_desc;
2053 isolate, receiver, key, &current_desc);
2054 MAYBE_RETURN(owned, Nothing<bool>());
2055 if (owned.FromJust()) {
2056 if (current_desc.configurable()) return Just(false);
2057 if (level == FROZEN &&
2058 PropertyDescriptor::IsDataDescriptor(&current_desc) &&
2059 current_desc.writable()) {
2060 return Just(false);
2061 }
2062 }
2063 }
2064 return Just(true);
2065}
2066
2067} // namespace
2068
2071 IntegrityLevel level) {
2074 level);
2075 }
2076 return GenericTestIntegrityLevel(isolate, receiver, level);
2077}
2078
2081 ShouldThrow should_throw) {
2082 if (IsJSProxy(*object)) {
2083 return JSProxy::PreventExtensions(Cast<JSProxy>(object), should_throw);
2084 }
2085 if (IsWasmObject(*object)) {
2087 NewTypeError(MessageTemplate::kWasmObjectsAreOpaque));
2088 }
2089 DCHECK(IsJSObject(*object));
2090 return JSObject::PreventExtensions(isolate, Cast<JSObject>(object),
2091 should_throw);
2092}
2093
2095 DirectHandle<JSReceiver> object) {
2096 if (IsJSProxy(*object)) {
2097 return JSProxy::IsExtensible(Cast<JSProxy>(object));
2098 }
2099 if (IsWasmObject(*object)) {
2100 return Just(false);
2101 }
2102 return Just(JSObject::IsExtensible(isolate, Cast<JSObject>(object)));
2103}
2104
2105// static
2106template <template <typename> typename HandleType>
2107 requires(
2108 std::is_convertible_v<HandleType<JSReceiver>, DirectHandle<JSReceiver>>)
2109typename HandleType<Object>::MaybeType JSReceiver::ToPrimitive(
2110 Isolate* isolate, HandleType<JSReceiver> receiver, ToPrimitiveHint hint) {
2111 DirectHandle<Object> exotic_to_prim;
2113 isolate, exotic_to_prim,
2114 Object::GetMethod(isolate, receiver,
2115 isolate->factory()->to_primitive_symbol()));
2116 if (!IsUndefined(*exotic_to_prim, isolate)) {
2117 DirectHandle<Object> hint_string =
2118 isolate->factory()->ToPrimitiveHintString(hint);
2119 HandleType<Object> result;
2121 isolate, result,
2122 Execution::Call(isolate, exotic_to_prim, receiver, {&hint_string, 1}));
2123 if (IsPrimitive(*result)) return result;
2124 THROW_NEW_ERROR(isolate,
2125 NewTypeError(MessageTemplate::kCannotConvertToPrimitive));
2126 }
2127 return OrdinaryToPrimitive<HandleType>(
2128 isolate, receiver,
2131}
2132
2137 ToPrimitiveHint hint);
2138
2139// static
2140template <template <typename> typename HandleType>
2141 requires(std::is_convertible_v<HandleType<Object>, DirectHandle<Object>>)
2142typename HandleType<Object>::MaybeType JSReceiver::OrdinaryToPrimitive(
2145 DirectHandle<String> method_names[2];
2146 switch (hint) {
2148 method_names[0] = isolate->factory()->valueOf_string();
2149 method_names[1] = isolate->factory()->toString_string();
2150 break;
2152 method_names[0] = isolate->factory()->toString_string();
2153 method_names[1] = isolate->factory()->valueOf_string();
2154 break;
2155 }
2156 for (DirectHandle<String> name : method_names) {
2159 isolate, method, JSReceiver::GetProperty(isolate, receiver, name));
2160 if (IsCallable(*method)) {
2161 HandleType<Object> result;
2163 isolate, result, Execution::Call(isolate, method, receiver, {}));
2164 if (IsPrimitive(*result)) return result;
2165 }
2166 }
2167 THROW_NEW_ERROR(isolate,
2168 NewTypeError(MessageTemplate::kCannotConvertToPrimitive));
2169}
2170
2172 Isolate* isolate, DirectHandle<JSReceiver> receiver, bool get_entries,
2174 DirectHandle<Map> map(Cast<JSReceiver>(*receiver)->map(), isolate);
2175
2176 if (!IsJSObjectMap(*map)) return Just(false);
2177 if (!map->OnlyHasSimpleProperties()) return Just(false);
2178
2180 DirectHandle<DescriptorArray> descriptors(map->instance_descriptors(isolate),
2181 isolate);
2182
2183 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2184 size_t number_of_own_elements =
2185 object->GetElementsAccessor()->GetCapacity(*object, object->elements());
2186
2187 if (number_of_own_elements >
2188 static_cast<size_t>(FixedArray::kMaxLength - number_of_own_descriptors)) {
2189 isolate->Throw(*isolate->factory()->NewRangeError(
2190 MessageTemplate::kInvalidArrayLength));
2191 return Nothing<bool>();
2192 }
2193 // The static cast is safe after the range check right above.
2194 Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray(
2195 static_cast<int>(number_of_own_descriptors + number_of_own_elements));
2196 int count = 0;
2197
2198 if (object->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
2199 MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries(
2200 isolate, object, values_or_entries, get_entries, &count,
2202 Nothing<bool>());
2203 }
2204
2205 // We may have already lost stability, if CollectValuesOrEntries had
2206 // side-effects.
2207 bool stable = *map == object->map();
2208 if (stable) {
2209 descriptors.SetValue(map->instance_descriptors(isolate));
2210 }
2211
2212 for (InternalIndex index : InternalIndex::Range(number_of_own_descriptors)) {
2213 HandleScope inner_scope(isolate);
2214
2215 DirectHandle<Name> next_key(descriptors->GetKey(index), isolate);
2216 if (!IsString(*next_key)) continue;
2217 DirectHandle<Object> prop_value;
2218
2219 // Directly decode from the descriptor array if |from| did not change shape.
2220 if (stable) {
2221 DCHECK_EQ(object->map(), *map);
2222 DCHECK_EQ(*descriptors, map->instance_descriptors(isolate));
2223
2224 PropertyDetails details = descriptors->GetDetails(index);
2225 if (!details.IsEnumerable()) continue;
2226 if (details.kind() == PropertyKind::kData) {
2227 if (details.location() == PropertyLocation::kDescriptor) {
2228 prop_value =
2229 direct_handle(descriptors->GetStrongValue(index), isolate);
2230 } else {
2231 Representation representation = details.representation();
2233 *map, details.field_index(), representation);
2234 prop_value = JSObject::FastPropertyAt(isolate, object, representation,
2235 field_index);
2236 }
2237 } else {
2238 LookupIterator it(isolate, object, next_key,
2242 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
2243 stable = object->map() == *map;
2244 descriptors.SetValue(map->instance_descriptors(isolate));
2245 }
2246 } else {
2247 // If the map did change, do a slower lookup. We are still guaranteed that
2248 // the object has a simple shape, and that the key is a name.
2249 LookupIterator it(isolate, object, next_key,
2251 if (!it.IsFound()) continue;
2252 DCHECK(it.state() == LookupIterator::DATA ||
2253 it.state() == LookupIterator::ACCESSOR);
2254 if (!it.IsEnumerable()) continue;
2256 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
2257 }
2258
2259 if (get_entries) {
2260 prop_value = MakeEntryPair(isolate, next_key, prop_value);
2261 }
2262
2263 values_or_entries->set(count, *prop_value);
2264 count++;
2265 }
2266
2267 DCHECK_LE(count, values_or_entries->length());
2268 *result = FixedArray::RightTrimOrEmpty(isolate, values_or_entries, count);
2269 return Just(true);
2270}
2271
2273 Isolate* isolate, DirectHandle<JSReceiver> object, PropertyFilter filter,
2274 bool try_fast_path, bool get_entries) {
2275 Handle<FixedArray> values_or_entries;
2276 if (try_fast_path && filter == ENUMERABLE_STRINGS) {
2277 Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
2278 isolate, object, get_entries, &values_or_entries);
2279 if (fast_values_or_entries.IsNothing())
2281 if (fast_values_or_entries.FromJust()) return values_or_entries;
2282 }
2283
2284 PropertyFilter key_filter =
2285 static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE);
2286
2289 isolate, keys,
2293
2294 values_or_entries = isolate->factory()->NewFixedArray(keys->length());
2295 int length = 0;
2296
2297 for (int i = 0; i < keys->length(); ++i) {
2298 DirectHandle<Name> key(Cast<Name>(keys->get(i)), isolate);
2299
2300 if (filter & ONLY_ENUMERABLE) {
2301 PropertyDescriptor descriptor;
2303 isolate, object, key, &descriptor);
2304 MAYBE_RETURN(did_get_descriptor, MaybeDirectHandle<FixedArray>());
2305 if (!did_get_descriptor.FromJust() || !descriptor.enumerable()) continue;
2306 }
2307
2310 isolate, value, Object::GetPropertyOrElement(isolate, object, key),
2312
2313 if (get_entries) {
2314 DirectHandle<FixedArray> entry_storage =
2315 isolate->factory()->NewFixedArray(2);
2316 entry_storage->set(0, *key);
2317 entry_storage->set(1, *value);
2318 value = isolate->factory()->NewJSArrayWithElements(entry_storage,
2319 PACKED_ELEMENTS, 2);
2320 }
2321
2322 values_or_entries->set(length, *value);
2323 length++;
2324 }
2325 DCHECK_LE(length, values_or_entries->length());
2326 return FixedArray::RightTrimOrEmpty(isolate, values_or_entries, length);
2327}
2328
2330 Isolate* isolate, DirectHandle<JSReceiver> object, PropertyFilter filter,
2331 bool try_fast_path) {
2332 return GetOwnValuesOrEntries(isolate, object, filter, try_fast_path, false);
2333}
2334
2336 Isolate* isolate, DirectHandle<JSReceiver> object, PropertyFilter filter,
2337 bool try_fast_path) {
2338 return GetOwnValuesOrEntries(isolate, object, filter, try_fast_path, true);
2339}
2340
2344 bool from_javascript,
2345 ShouldThrow should_throw) {
2346 if (IsWasmObject(*object)) {
2347 RETURN_FAILURE(isolate, should_throw,
2348 NewTypeError(MessageTemplate::kWasmObjectsAreOpaque));
2349 }
2350
2351 if (IsJSProxy(*object)) {
2352 return JSProxy::SetPrototype(isolate, Cast<JSProxy>(object), value,
2353 from_javascript, should_throw);
2354 }
2355 return JSObject::SetPrototype(isolate, Cast<JSObject>(object), value,
2356 from_javascript, should_throw);
2357}
2358
2360 for (PrototypeIterator iter(isolate, *this, kStartAtReceiver,
2362 !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
2363 if (IsJSProxy(iter.GetCurrent())) return true;
2364 }
2365 return false;
2366}
2367
2368bool JSReceiver::IsCodeLike(Isolate* isolate) const {
2370 Tagged<Object> maybe_constructor = map()->GetConstructor();
2371 if (!IsJSFunction(maybe_constructor)) return false;
2372 if (!Cast<JSFunction>(maybe_constructor)->shared()->IsApiFunction()) {
2373 return false;
2374 }
2375 Tagged<Object> instance_template = Cast<JSFunction>(maybe_constructor)
2376 ->shared()
2377 ->api_func_data()
2378 ->GetInstanceTemplate();
2379 if (IsUndefined(instance_template, isolate)) return false;
2380 return Cast<ObjectTemplateInfo>(instance_template)->code_like();
2381}
2382
2383// static
2387 NewJSObjectType new_js_object_type) {
2388 // If called through new, new.target can be:
2389 // - a subclass of constructor,
2390 // - a proxy wrapper around constructor, or
2391 // - the constructor itself.
2392 // If called through Reflect.construct, it's guaranteed to be a constructor.
2393 Isolate* const isolate = constructor->GetIsolate();
2394 DCHECK(IsConstructor(*constructor));
2395 DCHECK(IsConstructor(*new_target));
2396 DCHECK(!constructor->has_initial_map() ||
2397 !InstanceTypeChecker::IsJSFunction(
2398 constructor->initial_map()->instance_type()));
2399
2400 DirectHandle<Map> initial_map;
2402 isolate, initial_map,
2403 JSFunction::GetDerivedMap(isolate, constructor, new_target));
2404 constexpr int initial_capacity = PropertyDictionary::kInitialCapacity;
2405 Handle<JSObject> result = isolate->factory()->NewFastOrSlowJSObjectFromMap(
2406 initial_map, initial_capacity, AllocationType::kYoung, site,
2407 new_js_object_type);
2408 return result;
2409}
2410
2411// static
2413 Isolate* isolate, DirectHandle<Map> initial_map,
2414 DirectHandle<AllocationSite> site, NewJSObjectType new_js_object_type) {
2415 constexpr int initial_capacity = PropertyDictionary::kInitialCapacity;
2417 isolate->factory()->NewFastOrSlowJSObjectFromMap(
2418 initial_map, initial_capacity, AllocationType::kYoung, site,
2419 new_js_object_type);
2420 return result;
2421}
2422
2423// 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )
2424// Notice: This is NOT 19.1.2.2 Object.create ( O, Properties )
2426 Isolate* isolate, DirectHandle<JSPrototype> prototype) {
2427 // Generate the map with the specified {prototype} based on the Object
2428 // function's initial map from the current native context.
2429 // TODO(bmeurer): Use a dedicated cache for Object.create; think about
2430 // slack tracking for Object.create.
2431 DirectHandle<Map> map = Map::GetObjectCreateMap(isolate, prototype);
2432
2433 // Actually allocate the object.
2434 return isolate->factory()->NewFastOrSlowJSObjectFromMap(map);
2435}
2436
2438 DCHECK(object->HasSmiOrObjectElements() ||
2439 object->HasFastStringWrapperElements() ||
2440 object->HasAnyNonextensibleElements());
2441 Tagged<FixedArray> raw_elems = Cast<FixedArray>(object->elements());
2442 Isolate* isolate = object->GetIsolate();
2443 if (raw_elems->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) return;
2444 DirectHandle<FixedArray> elems(raw_elems, isolate);
2445 DirectHandle<FixedArray> writable_elems =
2446 isolate->factory()->CopyFixedArrayWithMap(
2447 elems, isolate->factory()->fixed_array_map());
2448 object->set_elements(*writable_elems);
2449}
2450
2451// For FATAL in JSObject::GetHeaderSize
2452static const char* NonAPIInstanceTypeToString(InstanceType instance_type) {
2453 DCHECK(!InstanceTypeChecker::IsJSApiObject(instance_type));
2454 switch (instance_type) {
2455#define WRITE_TYPE(TYPE) \
2456 case TYPE: \
2457 return #TYPE;
2459#undef WRITE_TYPE
2460 }
2461 UNREACHABLE();
2462}
2463
2465 bool function_has_prototype_slot) {
2466 switch (type) {
2467 case JS_SPECIAL_API_OBJECT_TYPE:
2468 case JS_API_OBJECT_TYPE:
2470 case JS_ITERATOR_PROTOTYPE_TYPE:
2471 case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
2472 case JS_OBJECT_PROTOTYPE_TYPE:
2473 case JS_OBJECT_TYPE:
2474 case JS_PROMISE_PROTOTYPE_TYPE:
2475 case JS_REG_EXP_PROTOTYPE_TYPE:
2476 case JS_SET_ITERATOR_PROTOTYPE_TYPE:
2477 case JS_SET_PROTOTYPE_TYPE:
2478 case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
2479 case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE:
2480 case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
2481 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
2482 case JS_ARGUMENTS_OBJECT_TYPE:
2483 case JS_ERROR_TYPE:
2484 return JSObject::kHeaderSize;
2485 case JS_GENERATOR_OBJECT_TYPE:
2486 return JSGeneratorObject::kHeaderSize;
2487 case JS_ASYNC_FUNCTION_OBJECT_TYPE:
2488 return JSAsyncFunctionObject::kHeaderSize;
2489 case JS_ASYNC_GENERATOR_OBJECT_TYPE:
2490 return JSAsyncGeneratorObject::kHeaderSize;
2491 case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
2492 return JSAsyncFromSyncIterator::kHeaderSize;
2493 case JS_GLOBAL_PROXY_TYPE:
2494 return JSGlobalProxy::kHeaderSize;
2495 case JS_GLOBAL_OBJECT_TYPE:
2496 return JSGlobalObject::kHeaderSize;
2497 case JS_BOUND_FUNCTION_TYPE:
2498 return JSBoundFunction::kHeaderSize;
2499 case JS_FUNCTION_TYPE:
2500 case JS_CLASS_CONSTRUCTOR_TYPE:
2501 case JS_PROMISE_CONSTRUCTOR_TYPE:
2502 case JS_REG_EXP_CONSTRUCTOR_TYPE:
2503 case JS_ARRAY_CONSTRUCTOR_TYPE:
2504#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
2505 case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
2507#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
2508 return JSFunction::GetHeaderSize(function_has_prototype_slot);
2509 case JS_PRIMITIVE_WRAPPER_TYPE:
2510 return JSPrimitiveWrapper::kHeaderSize;
2511 case JS_DATE_TYPE:
2512 return JSDate::kHeaderSize;
2513 case JS_DISPOSABLE_STACK_BASE_TYPE:
2514 return JSDisposableStackBase::kHeaderSize;
2515 case JS_ASYNC_DISPOSABLE_STACK_TYPE:
2516 return JSAsyncDisposableStack::kHeaderSize;
2517 case JS_SYNC_DISPOSABLE_STACK_TYPE:
2518 return JSSyncDisposableStack::kHeaderSize;
2519 case JS_ARRAY_TYPE:
2520 return JSArray::kHeaderSize;
2521 case JS_ARRAY_BUFFER_TYPE:
2522 return JSArrayBuffer::kHeaderSize;
2523 case JS_ARRAY_ITERATOR_TYPE:
2524 return JSArrayIterator::kHeaderSize;
2525 case JS_TYPED_ARRAY_TYPE:
2526 return JSTypedArray::kHeaderSize;
2527 case JS_DATA_VIEW_TYPE:
2528 return JSDataView::kHeaderSize;
2529 case JS_RAB_GSAB_DATA_VIEW_TYPE:
2530 return JSRabGsabDataView::kHeaderSize;
2531 case JS_SET_TYPE:
2532 return JSSet::kHeaderSize;
2533 case JS_MAP_TYPE:
2534 return JSMap::kHeaderSize;
2535 case JS_SET_KEY_VALUE_ITERATOR_TYPE:
2536 case JS_SET_VALUE_ITERATOR_TYPE:
2537 return JSSetIterator::kHeaderSize;
2538 case JS_MAP_KEY_ITERATOR_TYPE:
2539 case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
2540 case JS_MAP_VALUE_ITERATOR_TYPE:
2541 return JSMapIterator::kHeaderSize;
2542 case JS_WEAK_REF_TYPE:
2543 return JSWeakRef::kHeaderSize;
2544 case JS_FINALIZATION_REGISTRY_TYPE:
2545 return JSFinalizationRegistry::kHeaderSize;
2546 case JS_WEAK_MAP_TYPE:
2547 return JSWeakMap::kHeaderSize;
2548 case JS_WEAK_SET_TYPE:
2549 return JSWeakSet::kHeaderSize;
2550 case JS_PROMISE_TYPE:
2551 return JSPromise::kHeaderSize;
2552 case JS_REG_EXP_TYPE:
2553 return JSRegExp::kHeaderSize;
2554 case JS_REG_EXP_STRING_ITERATOR_TYPE:
2555 return JSRegExpStringIterator::kHeaderSize;
2556 case JS_MESSAGE_OBJECT_TYPE:
2557 return JSMessageObject::kHeaderSize;
2558 case JS_EXTERNAL_OBJECT_TYPE:
2559 return JSExternalObject::kHeaderSize;
2560 case JS_SHADOW_REALM_TYPE:
2561 return JSShadowRealm::kHeaderSize;
2562 case JS_STRING_ITERATOR_TYPE:
2563 return JSStringIterator::kHeaderSize;
2564 case JS_ITERATOR_MAP_HELPER_TYPE:
2565 return JSIteratorMapHelper::kHeaderSize;
2566 case JS_ITERATOR_FILTER_HELPER_TYPE:
2567 return JSIteratorFilterHelper::kHeaderSize;
2568 case JS_ITERATOR_TAKE_HELPER_TYPE:
2569 return JSIteratorTakeHelper::kHeaderSize;
2570 case JS_ITERATOR_DROP_HELPER_TYPE:
2571 return JSIteratorDropHelper::kHeaderSize;
2572 case JS_ITERATOR_FLAT_MAP_HELPER_TYPE:
2573 return JSIteratorFlatMapHelper::kHeaderSize;
2574 case JS_MODULE_NAMESPACE_TYPE:
2575 return JSModuleNamespace::kHeaderSize;
2576 case JS_SHARED_ARRAY_TYPE:
2577 return JSSharedArray::kHeaderSize;
2578 case JS_SHARED_STRUCT_TYPE:
2579 return JSSharedStruct::kHeaderSize;
2580 case JS_ATOMICS_MUTEX_TYPE:
2581 return JSAtomicsMutex::kHeaderSize;
2582 case JS_ATOMICS_CONDITION_TYPE:
2583 return JSAtomicsCondition::kHeaderSize;
2584 case JS_TEMPORAL_CALENDAR_TYPE:
2585 return JSTemporalCalendar::kHeaderSize;
2586 case JS_TEMPORAL_DURATION_TYPE:
2587 return JSTemporalDuration::kHeaderSize;
2588 case JS_TEMPORAL_INSTANT_TYPE:
2589 return JSTemporalInstant::kHeaderSize;
2590 case JS_TEMPORAL_PLAIN_DATE_TYPE:
2591 return JSTemporalPlainDate::kHeaderSize;
2592 case JS_TEMPORAL_PLAIN_DATE_TIME_TYPE:
2593 return JSTemporalPlainDateTime::kHeaderSize;
2594 case JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE:
2595 return JSTemporalPlainMonthDay::kHeaderSize;
2596 case JS_TEMPORAL_PLAIN_TIME_TYPE:
2597 return JSTemporalPlainTime::kHeaderSize;
2598 case JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE:
2599 return JSTemporalPlainYearMonth::kHeaderSize;
2600 case JS_TEMPORAL_TIME_ZONE_TYPE:
2601 return JSTemporalTimeZone::kHeaderSize;
2602 case JS_TEMPORAL_ZONED_DATE_TIME_TYPE:
2603 return JSTemporalZonedDateTime::kHeaderSize;
2604 case JS_VALID_ITERATOR_WRAPPER_TYPE:
2605 return JSValidIteratorWrapper::kHeaderSize;
2606 case JS_WRAPPED_FUNCTION_TYPE:
2607 return JSWrappedFunction::kHeaderSize;
2608 case JS_RAW_JSON_TYPE:
2609 return JSRawJson::kHeaderSize;
2610#ifdef V8_INTL_SUPPORT
2611 case JS_V8_BREAK_ITERATOR_TYPE:
2612 return JSV8BreakIterator::kHeaderSize;
2613 case JS_COLLATOR_TYPE:
2614 return JSCollator::kHeaderSize;
2615 case JS_DATE_TIME_FORMAT_TYPE:
2616 return JSDateTimeFormat::kHeaderSize;
2617 case JS_DISPLAY_NAMES_TYPE:
2618 return JSDisplayNames::kHeaderSize;
2619 case JS_DURATION_FORMAT_TYPE:
2620 return JSDurationFormat::kHeaderSize;
2621 case JS_LIST_FORMAT_TYPE:
2622 return JSListFormat::kHeaderSize;
2623 case JS_LOCALE_TYPE:
2624 return JSLocale::kHeaderSize;
2625 case JS_NUMBER_FORMAT_TYPE:
2626 return JSNumberFormat::kHeaderSize;
2627 case JS_PLURAL_RULES_TYPE:
2628 return JSPluralRules::kHeaderSize;
2629 case JS_RELATIVE_TIME_FORMAT_TYPE:
2630 return JSRelativeTimeFormat::kHeaderSize;
2631 case JS_SEGMENT_ITERATOR_TYPE:
2632 return JSSegmentIterator::kHeaderSize;
2633 case JS_SEGMENTER_TYPE:
2634 return JSSegmenter::kHeaderSize;
2635 case JS_SEGMENTS_TYPE:
2636 return JSSegments::kHeaderSize;
2637#endif // V8_INTL_SUPPORT
2638#if V8_ENABLE_WEBASSEMBLY
2639 case WASM_GLOBAL_OBJECT_TYPE:
2640 return WasmGlobalObject::kHeaderSize;
2641 case WASM_INSTANCE_OBJECT_TYPE:
2642 return WasmInstanceObject::kHeaderSize;
2643 case WASM_MEMORY_OBJECT_TYPE:
2644 return WasmMemoryObject::kHeaderSize;
2645 case WASM_MEMORY_MAP_DESCRIPTOR_TYPE:
2646 return WasmMemoryMapDescriptor::kHeaderSize;
2647 case WASM_MODULE_OBJECT_TYPE:
2648 return WasmModuleObject::kHeaderSize;
2649 case WASM_TABLE_OBJECT_TYPE:
2650 return WasmTableObject::kHeaderSize;
2651 case WASM_VALUE_OBJECT_TYPE:
2652 return WasmValueObject::kHeaderSize;
2653 case WASM_TAG_OBJECT_TYPE:
2654 return WasmTagObject::kHeaderSize;
2655 case WASM_EXCEPTION_PACKAGE_TYPE:
2656 return WasmExceptionPackage::kHeaderSize;
2657 case WASM_SUSPENDING_OBJECT_TYPE:
2658 return WasmSuspendingObject::kHeaderSize;
2659#endif // V8_ENABLE_WEBASSEMBLY
2660 default: {
2661 // Special type check for API Objects because they are in a large variable
2662 // instance type range.
2663 if (InstanceTypeChecker::IsJSApiObject(type)) {
2665 }
2666 FATAL("unexpected instance type: %s\n", NonAPIInstanceTypeToString(type));
2667 }
2668 }
2669}
2670
2672 LookupIterator* it) {
2673 Isolate* isolate = it->isolate();
2674 DirectHandle<JSObject> checked = it->GetHolder<JSObject>();
2675 DirectHandle<InterceptorInfo> interceptor =
2676 it->GetInterceptorForFailedAccessCheck();
2677 if (!interceptor.is_null()) {
2679 bool done;
2681 isolate, result,
2682 GetPropertyWithInterceptorInternal(it, interceptor, &done));
2683 if (done) return result;
2684 }
2685
2686 // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
2687 // undefined.
2688 DirectHandle<Name> name = it->GetName();
2689 if (IsSymbol(*name) && Cast<Symbol>(*name)->is_well_known_symbol()) {
2690 return it->factory()->undefined_value();
2691 }
2692
2693 RETURN_ON_EXCEPTION(isolate, isolate->ReportFailedAccessCheck(checked));
2694 UNREACHABLE();
2695}
2696
2698 LookupIterator* it) {
2699 Isolate* isolate = it->isolate();
2700 DirectHandle<JSObject> checked = it->GetHolder<JSObject>();
2701 DirectHandle<InterceptorInfo> interceptor =
2702 it->GetInterceptorForFailedAccessCheck();
2703 if (!interceptor.is_null()) {
2705 GetPropertyAttributesWithInterceptorInternal(it, interceptor);
2706 if (isolate->has_exception()) return Nothing<PropertyAttributes>();
2707 if (result.FromMaybe(ABSENT) != ABSENT) return result;
2708 }
2709 RETURN_ON_EXCEPTION_VALUE(isolate, isolate->ReportFailedAccessCheck(checked),
2711 UNREACHABLE();
2712}
2713
2716 Maybe<ShouldThrow> should_throw) {
2717 Isolate* isolate = it->isolate();
2718 DirectHandle<JSObject> checked = it->GetHolder<JSObject>();
2719 DirectHandle<InterceptorInfo> interceptor =
2720 it->GetInterceptorForFailedAccessCheck();
2721 if (!interceptor.is_null()) {
2723 if (!SetPropertyWithInterceptorInternal(it, interceptor, should_throw,
2724 value)
2725 .To(&result)) {
2726 // An exception was thrown in the interceptor. Propagate.
2727 return Nothing<bool>();
2728 }
2729 switch (result) {
2731 return Just(false);
2733 return Just(true);
2735 // Fall through to report failed access check.
2736 break;
2737 }
2738 }
2739 RETURN_ON_EXCEPTION_VALUE(isolate, isolate->ReportFailedAccessCheck(checked),
2740 Nothing<bool>());
2741 UNREACHABLE();
2742}
2743
2745 DirectHandle<Name> name,
2747 PropertyDetails details) {
2748 DCHECK(!object->HasFastProperties());
2749 DCHECK(IsUniqueName(*name));
2750 Isolate* isolate = object->GetIsolate();
2751
2752 uint32_t hash = name->hash();
2753
2754 if (IsJSGlobalObject(*object)) {
2755 auto global_obj = Cast<JSGlobalObject>(object);
2757 global_obj->global_dictionary(kAcquireLoad), isolate);
2758 ReadOnlyRoots roots(isolate);
2759 InternalIndex entry = dictionary->FindEntry(isolate, roots, name, hash);
2760
2761 if (entry.is_not_found()) {
2762 DCHECK_IMPLIES(global_obj->map()->is_prototype_map(),
2763 Map::IsPrototypeChainInvalidated(global_obj->map()));
2764 auto cell_type = IsUndefined(*value, roots) ? PropertyCellType::kUndefined
2766 details = details.set_cell_type(cell_type);
2767 auto cell = isolate->factory()->NewPropertyCell(name, details, value);
2768 dictionary =
2769 GlobalDictionary::Add(isolate, dictionary, name, cell, details);
2770 global_obj->set_global_dictionary(*dictionary, kReleaseStore);
2771 } else {
2772 PropertyCell::PrepareForAndSetValue(isolate, dictionary, entry, value,
2773 details);
2774 DCHECK_EQ(dictionary->CellAt(entry)->value(), *value);
2775 }
2776 } else {
2779 object->property_dictionary_swiss(), isolate);
2780 InternalIndex entry = dictionary->FindEntry(isolate, *name);
2781 if (entry.is_not_found()) {
2782 DCHECK_IMPLIES(object->map()->is_prototype_map(),
2783 Map::IsPrototypeChainInvalidated(object->map()));
2784 dictionary =
2785 SwissNameDictionary::Add(isolate, dictionary, name, value, details);
2786 object->SetProperties(*dictionary);
2787 } else {
2788 dictionary->ValueAtPut(entry, *value);
2789 dictionary->DetailsAtPut(entry, details);
2790 }
2791 } else {
2792 DirectHandle<NameDictionary> dictionary(object->property_dictionary(),
2793 isolate);
2794 InternalIndex entry = dictionary->FindEntry(isolate, name);
2795 if (entry.is_not_found()) {
2796 DCHECK_IMPLIES(object->map()->is_prototype_map(),
2797 Map::IsPrototypeChainInvalidated(object->map()));
2798 dictionary =
2799 NameDictionary::Add(isolate, dictionary, name, value, details);
2800 object->SetProperties(*dictionary);
2801 } else {
2802 PropertyDetails original_details = dictionary->DetailsAt(entry);
2803 int enumeration_index = original_details.dictionary_index();
2804 DCHECK_GT(enumeration_index, 0);
2805 details = details.set_index(enumeration_index);
2806 dictionary->SetEntry(entry, *name, *value, details);
2807 }
2808 // TODO(pthier): Add flags to swiss dictionaries.
2809 if (name->IsInteresting(isolate)) {
2810 dictionary->set_may_have_interesting_properties(true);
2811 }
2812 }
2813 }
2814}
2815
2817 uint32_t index, DirectHandle<Object> value,
2818 PropertyDetails details) {
2819 DCHECK_EQ(object->GetElementsKind(), DICTIONARY_ELEMENTS);
2820
2821 Isolate* isolate = object->GetIsolate();
2822
2824 Cast<NumberDictionary>(object->elements()), isolate);
2825 dictionary =
2826 NumberDictionary::Set(isolate, dictionary, index, value, object, details);
2827 object->set_elements(*dictionary);
2828}
2829
2831 switch (map()->instance_type()) {
2832 case JS_ARRAY_TYPE: {
2833 double length = IsUndefined(Cast<JSArray>(*this)->length())
2834 ? 0
2835 : Object::NumberValue(Cast<JSArray>(*this)->length());
2836 accumulator->Add("<JSArray[%u]>", static_cast<uint32_t>(length));
2837 break;
2838 }
2839 case JS_BOUND_FUNCTION_TYPE: {
2840 Tagged<JSBoundFunction> bound_function = Cast<JSBoundFunction>(*this);
2841 accumulator->Add("<JSBoundFunction");
2842 accumulator->Add(" (BoundTargetFunction %p)>",
2843 reinterpret_cast<void*>(
2844 bound_function->bound_target_function().ptr()));
2845 break;
2846 }
2847 case JS_WEAK_MAP_TYPE: {
2848 accumulator->Add("<JSWeakMap>");
2849 break;
2850 }
2851 case JS_WEAK_SET_TYPE: {
2852 accumulator->Add("<JSWeakSet>");
2853 break;
2854 }
2855 case JS_REG_EXP_TYPE: {
2856 accumulator->Add("<JSRegExp");
2857 Tagged<JSRegExp> regexp = Cast<JSRegExp>(*this);
2858 if (IsString(regexp->source())) {
2859 accumulator->Add(" ");
2860 Cast<String>(regexp->source())->StringShortPrint(accumulator);
2861 }
2862 accumulator->Add(">");
2863
2864 break;
2865 }
2866 case JS_PROMISE_CONSTRUCTOR_TYPE:
2867 case JS_REG_EXP_CONSTRUCTOR_TYPE:
2868 case JS_ARRAY_CONSTRUCTOR_TYPE:
2869#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
2870 case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
2872#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
2873 case JS_CLASS_CONSTRUCTOR_TYPE:
2874 case JS_FUNCTION_TYPE: {
2875 Tagged<JSFunction> function = Cast<JSFunction>(*this);
2876 std::unique_ptr<char[]> fun_name = function->shared()->DebugNameCStr();
2877 if (fun_name[0] != '\0') {
2878 accumulator->Add("<JSFunction ");
2879 accumulator->Add(fun_name.get());
2880 } else {
2881 accumulator->Add("<JSFunction");
2882 }
2883 if (v8_flags.trace_file_names) {
2884 Tagged<Object> source_name =
2885 Cast<Script>(function->shared()->script())->name();
2886 if (IsString(source_name)) {
2887 Tagged<String> str = Cast<String>(source_name);
2888 if (str->length() > 0) {
2889 accumulator->Add(" <");
2890 accumulator->Put(str);
2891 accumulator->Add(">");
2892 }
2893 }
2894 }
2895 accumulator->Add(" (sfi = %p)",
2896 reinterpret_cast<void*>(function->shared().ptr()));
2897 accumulator->Put('>');
2898 break;
2899 }
2900 case JS_GENERATOR_OBJECT_TYPE: {
2901 accumulator->Add("<JSGenerator>");
2902 break;
2903 }
2904 case JS_ASYNC_FUNCTION_OBJECT_TYPE: {
2905 accumulator->Add("<JSAsyncFunctionObject>");
2906 break;
2907 }
2908 case JS_ASYNC_GENERATOR_OBJECT_TYPE: {
2909 accumulator->Add("<JS AsyncGenerator>");
2910 break;
2911 }
2912 case JS_SHARED_ARRAY_TYPE:
2913 accumulator->Add("<JSSharedArray>");
2914 break;
2915 case JS_SHARED_STRUCT_TYPE:
2916 accumulator->Add("<JSSharedStruct>");
2917 break;
2918 case JS_ATOMICS_MUTEX_TYPE:
2919 accumulator->Add("<JSAtomicsMutex>");
2920 break;
2921 case JS_ATOMICS_CONDITION_TYPE:
2922 accumulator->Add("<JSAtomicsCondition>");
2923 break;
2924 case JS_MESSAGE_OBJECT_TYPE:
2925 accumulator->Add("<JSMessageObject>");
2926 break;
2927 case JS_EXTERNAL_OBJECT_TYPE:
2928 accumulator->Add("<JSExternalObject>");
2929 break;
2930
2931 default: {
2932 Tagged<Map> map_of_this = map();
2933 Tagged<Object> constructor = map_of_this->GetConstructor();
2934 bool printed = false;
2935 bool is_global_proxy = IsJSGlobalProxy(*this);
2936 if (IsJSFunction(constructor)) {
2938 Cast<JSFunction>(constructor)->shared();
2939 Tagged<String> constructor_name = sfi->Name();
2940 if (constructor_name->length() > 0) {
2941 accumulator->Add(is_global_proxy ? "<GlobalObject " : "<");
2942 accumulator->Put(constructor_name);
2943 accumulator->Add(" %smap = %p",
2944 map_of_this->is_deprecated() ? "deprecated-" : "",
2945 map_of_this);
2946 printed = true;
2947 }
2948 } else if (IsFunctionTemplateInfo(constructor)) {
2949 accumulator->Add("<RemoteObject>");
2950 printed = true;
2951 }
2952 if (!printed) {
2953 accumulator->Add("<JS");
2954 if (is_global_proxy) {
2955 accumulator->Add("GlobalProxy");
2956 } else if (IsJSGlobalObject(*this)) {
2957 accumulator->Add("GlobalObject");
2958 } else {
2959 accumulator->Add("Object");
2960 }
2961 }
2962 if (IsJSPrimitiveWrapper(*this)) {
2963 accumulator->Add(" value = ");
2964 ShortPrint(Cast<JSPrimitiveWrapper>(*this)->value(), accumulator);
2965 }
2966 accumulator->Put('>');
2967 break;
2968 }
2969 }
2970}
2971
2973 FILE* file, DirectHandle<JSObject> object, ElementsKind from_kind,
2974 DirectHandle<FixedArrayBase> from_elements, ElementsKind to_kind,
2975 DirectHandle<FixedArrayBase> to_elements) {
2976 if (from_kind != to_kind) {
2977 OFStream os(file);
2978 os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
2979 << ElementsKindToString(to_kind) << "] in ";
2980 JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
2981 PrintF(file, " for ");
2982 ShortPrint(*object, file);
2983 PrintF(file, " from ");
2984 ShortPrint(*from_elements, file);
2985 PrintF(file, " to ");
2986 ShortPrint(*to_elements, file);
2987 PrintF(file, "\n");
2988 }
2989}
2990
2991void JSObject::PrintInstanceMigration(FILE* file, Tagged<Map> original_map,
2992 Tagged<Map> new_map) {
2993 if (new_map->is_dictionary_map()) {
2994 PrintF(file, "[migrating to slow]\n");
2995 return;
2996 }
2997 PrintF(file, "[migrating]");
2998 Isolate* isolate = GetIsolate();
2999 Tagged<DescriptorArray> o = original_map->instance_descriptors(isolate);
3000 Tagged<DescriptorArray> n = new_map->instance_descriptors(isolate);
3001 for (InternalIndex i : original_map->IterateOwnDescriptors()) {
3002 Representation o_r = o->GetDetails(i).representation();
3003 Representation n_r = n->GetDetails(i).representation();
3004 if (!o_r.Equals(n_r)) {
3005 Cast<String>(o->GetKey(i))->PrintOn(file);
3006 PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
3007 } else if (o->GetDetails(i).location() == PropertyLocation::kDescriptor &&
3008 n->GetDetails(i).location() == PropertyLocation::kField) {
3009 Tagged<Name> name = o->GetKey(i);
3010 if (IsString(name)) {
3011 Cast<String>(name)->PrintOn(file);
3012 } else {
3013 PrintF(file, "{symbol %p}", reinterpret_cast<void*>(name.ptr()));
3014 }
3015 PrintF(file, " ");
3016 }
3017 }
3018 if (original_map->elements_kind() != new_map->elements_kind()) {
3019 PrintF(file, "elements_kind[%i->%i]", original_map->elements_kind(),
3020 new_map->elements_kind());
3021 }
3022 PrintF(file, "\n");
3023}
3024
3025// static
3027 Tagged<Object> object = *o;
3028 if (IsSmi(object)) return false;
3029 Tagged<HeapObject> heap_object = Cast<HeapObject>(object);
3030 Tagged<Map> map = heap_object->map();
3031 if (!InstanceTypeChecker::IsJSObject(map)) return false;
3032 if (!JSObject::IsDroppableApiObject(map)) return false;
3033 Tagged<Object> maybe_constructor = map->GetConstructor();
3034 if (!IsJSFunction(maybe_constructor)) return false;
3035 Tagged<JSObject> js_object = Cast<JSObject>(object);
3036 if (js_object->elements()->length() != 0) return false;
3037 // Check that the object is not a key in a WeakMap (over-approximation).
3038 if (!IsUndefined(js_object->GetIdentityHash())) return false;
3039
3040 Tagged<JSFunction> constructor = Cast<JSFunction>(maybe_constructor);
3041 return constructor->initial_map() == map;
3042}
3043
3044// static
3046 DirectHandle<Map> new_map,
3047 Isolate* isolate) {
3048 DCHECK(old_map->is_prototype_map());
3049 DCHECK(new_map->is_prototype_map());
3050 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
3051 new_map->set_prototype_info(old_map->prototype_info(), kReleaseStore);
3052 old_map->set_prototype_info(Smi::zero(), kReleaseStore);
3053 if (v8_flags.trace_prototype_users) {
3054 PrintF("Moving prototype_info %p from map %p to map %p.\n",
3055 reinterpret_cast<void*>(new_map->prototype_info().ptr()),
3056 reinterpret_cast<void*>(old_map->ptr()),
3057 reinterpret_cast<void*>(new_map->ptr()));
3058 }
3059 if (was_registered) {
3060 if (new_map->has_prototype_info()) {
3061 // The new map isn't registered with its prototype yet; reflect this fact
3062 // in the PrototypeInfo it just inherited from the old map.
3063 Cast<PrototypeInfo>(new_map->prototype_info())
3064 ->set_registry_slot(MemoryChunk::UNREGISTERED);
3065 }
3066 JSObject::LazyRegisterPrototypeUser(new_map, isolate);
3067 }
3068}
3069
3070// static
3072 DirectHandle<Map> new_map, Isolate* isolate) {
3073 if (!old_map->is_prototype_map()) return;
3074
3075 InvalidatePrototypeChains(*old_map);
3076
3077 // If the map was registered with its prototype before, ensure that it
3078 // registers with its new prototype now. This preserves the invariant that
3079 // when a map on a prototype chain is registered with its prototype, then
3080 // all prototypes further up the chain are also registered with their
3081 // respective prototypes.
3082 UpdatePrototypeUserRegistration(old_map, new_map, isolate);
3083}
3084
3085namespace {
3086
3087// To migrate a fast instance to a fast map:
3088// - First check whether the instance needs to be rewritten. If not, simply
3089// change the map.
3090// - Otherwise, allocate a fixed array large enough to hold all fields, in
3091// addition to unused space.
3092// - Copy all existing properties in, in the following order: backing store
3093// properties, unused fields, inobject properties.
3094// - If all allocation succeeded, commit the state atomically:
3095// * Copy inobject properties from the backing store back into the object.
3096// * Trim the difference in instance size of the object. This also cleanly
3097// frees inobject properties that moved to the backing store.
3098// * If there are properties left in the backing store, trim of the space used
3099// to temporarily store the inobject properties.
3100// * If there are properties left in the backing store, install the backing
3101// store.
3102void MigrateFastToFast(Isolate* isolate, DirectHandle<JSObject> object,
3103 DirectHandle<Map> new_map) {
3104 DirectHandle<Map> old_map(object->map(), isolate);
3105 // In case of a regular transition.
3106 if (new_map->GetBackPointer(isolate) == *old_map) {
3107 // If the map does not add named properties, simply set the map.
3108 if (old_map->NumberOfOwnDescriptors() ==
3109 new_map->NumberOfOwnDescriptors()) {
3110 object->set_map(isolate, *new_map, kReleaseStore);
3111 return;
3112 }
3113
3114 // If the map adds a new kDescriptor property, simply set the map.
3115 PropertyDetails details = new_map->GetLastDescriptorDetails(isolate);
3116 if (details.location() == PropertyLocation::kDescriptor) {
3117 object->set_map(isolate, *new_map, kReleaseStore);
3118 return;
3119 }
3120
3121 // Check if we still have space in the {object}, in which case we
3122 // can also simply set the map (modulo a special case for mutable
3123 // double boxes).
3124 FieldIndex index = FieldIndex::ForDetails(*new_map, details);
3125 if (index.is_inobject() || index.outobject_array_index() <
3126 object->property_array(isolate)->length()) {
3127 // Allocate HeapNumbers for double fields.
3128 if (index.is_double()) {
3129 auto value = isolate->factory()->NewHeapNumberWithHoleNaN();
3130 object->FastPropertyAtPut(index, *value);
3131 }
3132 object->set_map(isolate, *new_map, kReleaseStore);
3133 return;
3134 }
3135
3136 // This migration is a transition from a map that has run out of property
3137 // space. Extend the backing store.
3138 int grow_by = new_map->UnusedPropertyFields() + 1;
3139 DirectHandle<PropertyArray> old_storage(object->property_array(isolate),
3140 isolate);
3141 DirectHandle<PropertyArray> new_storage =
3142 isolate->factory()->CopyPropertyArrayAndGrow(old_storage, grow_by);
3143
3144 // Properly initialize newly added property.
3145 DirectHandle<Object> value;
3146 if (details.representation().IsDouble()) {
3147 value = isolate->factory()->NewHeapNumberWithHoleNaN();
3148 } else {
3149 value = isolate->factory()->uninitialized_value();
3150 }
3151 DCHECK_EQ(PropertyLocation::kField, details.location());
3152 DCHECK_EQ(PropertyKind::kData, details.kind());
3153 DCHECK(!index.is_inobject()); // Must be a backing store index.
3154 new_storage->set(index.outobject_array_index(), *value);
3155
3156 // From here on we cannot fail and we shouldn't GC anymore.
3158
3159 // Set the new property value and do the map transition.
3160 object->SetProperties(*new_storage);
3161 object->set_map(isolate, *new_map, kReleaseStore);
3162 return;
3163 }
3164
3165 int old_number_of_fields;
3166 int number_of_fields = new_map->NumberOfFields(ConcurrencyMode::kSynchronous);
3167 int inobject = new_map->GetInObjectProperties();
3168 int unused = new_map->UnusedPropertyFields();
3169
3170 // Nothing to do if no functions were converted to fields and no smis were
3171 // converted to doubles.
3172 if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
3173 unused, &old_number_of_fields,
3175 object->set_map(isolate, *new_map, kReleaseStore);
3176 return;
3177 }
3178
3179 int total_size = number_of_fields + unused;
3180 int external = total_size - inobject;
3181 DirectHandle<PropertyArray> array =
3182 isolate->factory()->NewPropertyArray(external);
3183
3184 // We use this array to temporarily store the inobject properties.
3185 DirectHandle<FixedArray> inobject_props =
3186 isolate->factory()->NewFixedArray(inobject);
3187
3188 DirectHandle<DescriptorArray> old_descriptors(
3189 old_map->instance_descriptors(isolate), isolate);
3190 DirectHandle<DescriptorArray> new_descriptors(
3191 new_map->instance_descriptors(isolate), isolate);
3192 int old_nof = old_map->NumberOfOwnDescriptors();
3193 int new_nof = new_map->NumberOfOwnDescriptors();
3194
3195 // This method only supports generalizing instances to at least the same
3196 // number of properties.
3197 DCHECK(old_nof <= new_nof);
3198
3199 for (InternalIndex i : InternalIndex::Range(old_nof)) {
3200 PropertyDetails details = new_descriptors->GetDetails(i);
3201 if (details.location() != PropertyLocation::kField) continue;
3202 DCHECK_EQ(PropertyKind::kData, details.kind());
3203 PropertyDetails old_details = old_descriptors->GetDetails(i);
3204 Representation old_representation = old_details.representation();
3205 Representation representation = details.representation();
3207 if (old_details.location() == PropertyLocation::kDescriptor) {
3208 if (old_details.kind() == PropertyKind::kAccessor) {
3209 // In case of kAccessor -> kData property reconfiguration, the property
3210 // must already be prepared for data of certain type.
3211 DCHECK(!details.representation().IsNone());
3212 if (details.representation().IsDouble()) {
3213 value = isolate->factory()->NewHeapNumberWithHoleNaN();
3214 } else {
3215 value = isolate->factory()->uninitialized_value();
3216 }
3217 } else {
3218 DCHECK_EQ(PropertyKind::kData, old_details.kind());
3219 value = handle(Cast<JSAny>(old_descriptors->GetStrongValue(isolate, i)),
3220 isolate);
3221 DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
3222 }
3223 } else {
3224 DCHECK_EQ(PropertyLocation::kField, old_details.location());
3225 FieldIndex index = FieldIndex::ForDetails(*old_map, old_details);
3226 value = handle(object->RawFastPropertyAt(isolate, index), isolate);
3227 if (!old_representation.IsDouble() && representation.IsDouble()) {
3228 DCHECK_IMPLIES(old_representation.IsNone(),
3229 IsUninitialized(*value, isolate));
3230 value = Object::NewStorageFor(isolate, value, representation);
3231 } else if (old_representation.IsDouble() && !representation.IsDouble()) {
3232 value = Object::WrapForRead(isolate, Cast<JSAny>(value),
3233 old_representation);
3234 }
3235 }
3236 DCHECK(!(representation.IsDouble() && IsSmi(*value)));
3237 int target_index = new_descriptors->GetFieldIndex(i);
3238 if (target_index < inobject) {
3239 inobject_props->set(target_index, *value);
3240 } else {
3241 array->set(target_index - inobject, *value);
3242 }
3243 }
3244
3245 for (InternalIndex i : InternalIndex::Range(old_nof, new_nof)) {
3246 PropertyDetails details = new_descriptors->GetDetails(i);
3247 if (details.location() != PropertyLocation::kField) continue;
3248 DCHECK_EQ(PropertyKind::kData, details.kind());
3249 DirectHandle<Object> value;
3250 if (details.representation().IsDouble()) {
3251 value = isolate->factory()->NewHeapNumberWithHoleNaN();
3252 } else {
3253 value = isolate->factory()->uninitialized_value();
3254 }
3255 int target_index = new_descriptors->GetFieldIndex(i);
3256 if (target_index < inobject) {
3257 inobject_props->set(target_index, *value);
3258 } else {
3259 array->set(target_index - inobject, *value);
3260 }
3261 }
3262
3263 // From here on we cannot fail and we shouldn't GC anymore.
3265
3266 Heap* heap = isolate->heap();
3267
3268 // Copy (real) inobject properties. If necessary, stop at number_of_fields to
3269 // avoid overwriting |one_pointer_filler_map|.
3270 int limit = std::min(inobject, number_of_fields);
3271 for (int i = 0; i < limit; i++) {
3272 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
3273 Tagged<Object> value = inobject_props->get(i);
3274 object->FastPropertyAtPut(index, value);
3275 }
3276
3277 object->SetProperties(*array);
3278
3279 // Create filler object past the new instance size.
3280 int old_instance_size = old_map->instance_size();
3281 int new_instance_size = new_map->instance_size();
3282 int instance_size_delta = old_instance_size - new_instance_size;
3283 DCHECK_GE(instance_size_delta, 0);
3284
3285 if (instance_size_delta > 0) {
3286 heap->NotifyObjectSizeChange(*object, old_instance_size, new_instance_size,
3288 }
3289
3290 // We are storing the new map using release store after creating a filler for
3291 // the left-over space to avoid races with the sweeper thread.
3292 object->set_map(isolate, *new_map, kReleaseStore);
3293}
3294
3295void MigrateFastToSlow(Isolate* isolate, DirectHandle<JSObject> object,
3296 DirectHandle<Map> new_map,
3297 int expected_additional_properties) {
3298 // The global object is always normalized.
3299 DCHECK(!IsJSGlobalObject(*object, isolate));
3300 // JSGlobalProxy must never be normalized
3301 DCHECK(!IsJSGlobalProxy(*object, isolate));
3302
3303 DCHECK_IMPLIES(new_map->is_prototype_map(),
3305
3306 HandleScope scope(isolate);
3307 DirectHandle<Map> map(object->map(isolate), isolate);
3308
3309 // Allocate new content.
3310 int real_size = map->NumberOfOwnDescriptors();
3311 int property_count = real_size;
3312 if (expected_additional_properties > 0) {
3313 property_count += expected_additional_properties;
3314 } else {
3315 // Make space for two more properties.
3316 constexpr int initial_capacity = PropertyDictionary::kInitialCapacity;
3317 property_count += initial_capacity;
3318 }
3319
3320 DirectHandle<NameDictionary> dictionary;
3321 DirectHandle<SwissNameDictionary> ord_dictionary;
3323 ord_dictionary = isolate->factory()->NewSwissNameDictionary(property_count);
3324 } else {
3325 dictionary = isolate->factory()->NewNameDictionary(property_count);
3326 }
3327
3328 DirectHandle<DescriptorArray> descs(map->instance_descriptors(isolate),
3329 isolate);
3330 for (InternalIndex i : InternalIndex::Range(real_size)) {
3331 PropertyDetails details = descs->GetDetails(i);
3332 DirectHandle<Name> key(descs->GetKey(isolate, i), isolate);
3333 DirectHandle<Object> value;
3334 if (details.location() == PropertyLocation::kField) {
3335 FieldIndex index = FieldIndex::ForDetails(*map, details);
3336 if (details.kind() == PropertyKind::kData) {
3337 value =
3338 direct_handle(object->RawFastPropertyAt(isolate, index), isolate);
3339 if (details.representation().IsDouble()) {
3340 DCHECK(IsHeapNumber(*value, isolate));
3341 double old_value = Cast<HeapNumber>(value)->value();
3342 value = isolate->factory()->NewHeapNumber(old_value);
3343 }
3344 } else {
3345 DCHECK_EQ(PropertyKind::kAccessor, details.kind());
3346 value =
3347 direct_handle(object->RawFastPropertyAt(isolate, index), isolate);
3348 }
3349
3350 } else {
3351 DCHECK_EQ(PropertyLocation::kDescriptor, details.location());
3352 value = direct_handle(descs->GetStrongValue(isolate, i), isolate);
3353 }
3354 DCHECK(!value.is_null());
3356 ? details.constness()
3358 PropertyDetails d(details.kind(), details.attributes(), constness);
3359
3361 ord_dictionary =
3362 SwissNameDictionary::Add(isolate, ord_dictionary, key, value, d);
3363 } else {
3364 dictionary = NameDictionary::Add(isolate, dictionary, key, value, d);
3365 }
3366 }
3367
3368 if constexpr (!V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
3369 // Copy the next enumeration index from instance descriptor.
3370 dictionary->set_next_enumeration_index(real_size + 1);
3371 // TODO(pthier): Add flags to swiss dictionaries.
3372 dictionary->set_may_have_interesting_properties(
3373 map->may_have_interesting_properties());
3374 }
3375
3376 // From here on we cannot fail and we shouldn't GC anymore.
3378
3379 Heap* heap = isolate->heap();
3380
3381 // Resize the object in the heap if necessary.
3382 int old_instance_size = map->instance_size();
3383 int new_instance_size = new_map->instance_size();
3384 int instance_size_delta = old_instance_size - new_instance_size;
3385 DCHECK_GE(instance_size_delta, 0);
3386
3387 if (instance_size_delta > 0) {
3388 heap->NotifyObjectSizeChange(*object, old_instance_size, new_instance_size,
3390 }
3391
3392 // We are storing the new map using release store after creating a filler for
3393 // the left-over space to avoid races with the sweeper thread.
3394 object->set_map(isolate, *new_map, kReleaseStore);
3395
3397 object->SetProperties(*ord_dictionary);
3398 } else {
3399 object->SetProperties(*dictionary);
3400 }
3401
3402 // Ensure that in-object space of slow-mode object does not contain random
3403 // garbage.
3404 int inobject_properties = new_map->GetInObjectProperties();
3405 if (inobject_properties) {
3406 for (int i = 0; i < inobject_properties; i++) {
3407 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
3408 object->FastPropertyAtPut(index, Smi::zero());
3409 }
3410 }
3411
3412#ifdef DEBUG
3413 if (v8_flags.trace_normalization) {
3414 StdoutStream os;
3415 os << "Object properties have been normalized:\n";
3416 Print(*object, os);
3417 }
3418#endif
3419}
3420
3421} // namespace
3422
3424 DirectHandle<Map> new_map,
3425 int expected_additional_properties) {
3426 if (object->map(isolate) == *new_map) return;
3427 DirectHandle<Map> old_map(object->map(isolate), isolate);
3428 NotifyMapChange(old_map, new_map, isolate);
3429
3430 if (old_map->is_dictionary_map()) {
3431 // For slow-to-fast migrations JSObject::MigrateSlowToFast()
3432 // must be used instead.
3433 CHECK(new_map->is_dictionary_map());
3434
3435 // Slow-to-slow migration is trivial.
3436 object->set_map(isolate, *new_map, kReleaseStore);
3437 } else if (!new_map->is_dictionary_map()) {
3438 MigrateFastToFast(isolate, object, new_map);
3439 if (old_map->is_prototype_map()) {
3440 DCHECK(!old_map->is_stable());
3441 DCHECK(new_map->is_stable());
3442 DCHECK(new_map->owns_descriptors());
3443 DCHECK(old_map->owns_descriptors());
3444 // Transfer ownership to the new map. Keep the descriptor pointer of the
3445 // old map intact because the concurrent marker might be iterating the
3446 // object with the old map.
3447 old_map->set_owns_descriptors(false);
3448 DCHECK(old_map->is_abandoned_prototype_map());
3449 // Ensure that no transition was inserted for prototype migrations.
3450 DCHECK_EQ(0,
3451 TransitionsAccessor(isolate, *old_map).NumberOfTransitions());
3452 DCHECK(IsUndefined(new_map->GetBackPointer(isolate), isolate));
3453 DCHECK(object->map(isolate) != *old_map);
3454 }
3455 } else {
3456 MigrateFastToSlow(isolate, object, new_map, expected_additional_properties);
3457 }
3458
3459 // Careful: Don't allocate here!
3460 // For some callers of this method, |object| might be in an inconsistent
3461 // state now: the new map might have a new elements_kind, but the object's
3462 // elements pointer hasn't been updated yet. Callers will fix this, but in
3463 // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
3464 // When adding code here, add a DisallowGarbageCollection too.
3465}
3466
3470 // object.__proto__ = proto;
3471 DirectHandle<Map> old_map(object->map(), isolate);
3472 DirectHandle<Map> new_map = Map::Copy(isolate, old_map, "ForceSetPrototype");
3473 Map::SetPrototype(isolate, new_map, proto);
3474 JSObject::MigrateToMap(isolate, object, new_map);
3475}
3476
3478 LookupIterator* it, Maybe<ShouldThrow> should_throw,
3479 DirectHandle<Object> value) {
3481 return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
3482 should_throw, value);
3483}
3484
3486 DirectHandle<JSObject> object, ElementsKind to_kind) {
3487 DirectHandle<Map> map(object->map(), object->GetIsolate());
3488 return Map::TransitionElementsTo(object->GetIsolate(), map, to_kind);
3489}
3490
3492 DirectHandle<Map> map) {
3493 DCHECK(object->map()->GetInObjectProperties() ==
3494 map->GetInObjectProperties());
3495 ElementsKind obj_kind = object->map()->elements_kind();
3496 ElementsKind map_kind = map->elements_kind();
3497 Isolate* isolate = object->GetIsolate();
3498 if (map_kind != obj_kind) {
3499 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
3500 if (IsDictionaryElementsKind(obj_kind)) {
3501 to_kind = obj_kind;
3502 }
3503 if (IsDictionaryElementsKind(to_kind)) {
3504 NormalizeElements(object);
3505 } else {
3506 TransitionElementsKind(object, to_kind);
3507 }
3508 map = MapUpdater{isolate, map}.ReconfigureElementsKind(to_kind);
3509 }
3510 int number_of_fields = map->NumberOfFields(ConcurrencyMode::kSynchronous);
3511 int inobject = map->GetInObjectProperties();
3512 int unused = map->UnusedPropertyFields();
3513 int total_size = number_of_fields + unused;
3514 int external = total_size - inobject;
3515 // Allocate mutable double boxes if necessary. It is always necessary if we
3516 // have external properties, but is also necessary if we only have inobject
3517 // properties but don't unbox double fields.
3518
3519 DirectHandle<DescriptorArray> descriptors(map->instance_descriptors(isolate),
3520 isolate);
3521 DirectHandle<FixedArray> storage =
3522 isolate->factory()->NewFixedArray(inobject);
3523
3525 isolate->factory()->NewPropertyArray(external);
3526
3527 for (InternalIndex i : map->IterateOwnDescriptors()) {
3528 PropertyDetails details = descriptors->GetDetails(i);
3529 Representation representation = details.representation();
3530 if (!representation.IsDouble()) continue;
3531 FieldIndex index = FieldIndex::ForDetails(*map, details);
3532 auto box = isolate->factory()->NewHeapNumberWithHoleNaN();
3533 if (index.is_inobject()) {
3534 storage->set(index.property_index(), *box);
3535 } else {
3536 array->set(index.outobject_array_index(), *box);
3537 }
3538 }
3539
3540 object->SetProperties(*array);
3541 for (int i = 0; i < inobject; i++) {
3543 Tagged<Object> value = storage->get(i);
3544 object->FastPropertyAtPut(index, value);
3545 }
3546 object->set_map(isolate, *map, kReleaseStore);
3547}
3548
3550 DirectHandle<JSObject> object) {
3551 Handle<Map> original_map(object->map(), isolate);
3552 DirectHandle<Map> map = Map::Update(isolate, original_map);
3553 map->set_is_migration_target(true);
3554 JSObject::MigrateToMap(isolate, object, map);
3555 if (v8_flags.trace_migration) {
3556 object->PrintInstanceMigration(stdout, *original_map, *map);
3557 }
3558#if VERIFY_HEAP
3559 if (v8_flags.verify_heap) {
3560 object->JSObjectVerify(isolate);
3561 }
3562#endif
3563}
3564
3565// static
3567 DirectHandle<JSObject> object) {
3568 DisallowDeoptimization no_deoptimization(isolate);
3569 Handle<Map> original_map(object->map(), isolate);
3570 DirectHandle<Map> new_map;
3571 if (!Map::TryUpdate(isolate, original_map).ToHandle(&new_map)) {
3572 return false;
3573 }
3574 JSObject::MigrateToMap(isolate, object, new_map);
3575 if (v8_flags.trace_migration && *original_map != object->map()) {
3576 object->PrintInstanceMigration(stdout, *original_map, object->map());
3577 }
3578#if VERIFY_HEAP
3579 if (v8_flags.verify_heap) {
3580 object->JSObjectVerify(isolate);
3581 }
3582#endif
3583 return true;
3584}
3585
3586namespace {
3587
3588bool TryFastAddDataProperty(Isolate* isolate, DirectHandle<JSObject> object,
3590 PropertyAttributes attributes) {
3591 DCHECK(IsUniqueName(*name));
3592 Tagged<Map> map =
3593 TransitionsAccessor(isolate, object->map())
3594 .SearchTransition(*name, PropertyKind::kData, attributes);
3595 if (map.is_null()) return false;
3596 DCHECK(!map->is_dictionary_map());
3597
3598 DirectHandle<Map> new_map(map, isolate);
3599 if (map->is_deprecated()) {
3600 new_map = Map::Update(isolate, new_map);
3601 if (new_map->is_dictionary_map()) return false;
3602 }
3603
3604 InternalIndex descriptor = new_map->LastAdded();
3605 new_map = Map::PrepareForDataProperty(isolate, new_map, descriptor,
3607 JSObject::MigrateToMap(isolate, object, new_map);
3608 // TODO(leszeks): Avoid re-loading the property details, which we already
3609 // loaded in PrepareForDataProperty.
3610 object->WriteToField(descriptor,
3611 new_map->instance_descriptors()->GetDetails(descriptor),
3612 *value);
3613 return true;
3614}
3615
3616} // namespace
3617
3620 PropertyAttributes attributes) {
3621 name = isolate->factory()->InternalizeName(name);
3622 if (TryFastAddDataProperty(isolate, object, name, value, attributes)) {
3623 return;
3624 }
3625
3626 LookupIterator it(isolate, object, name, object,
3629#ifdef DEBUG
3630 uint32_t index;
3631 DCHECK(!IsJSProxy(*object));
3632 DCHECK(!IsWasmObject(*object));
3633 DCHECK(!name->AsArrayIndex(&index));
3634 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
3635 DCHECK(maybe.IsJust());
3636 DCHECK(!it.IsFound());
3637 DCHECK(object->map()->is_extensible() || name->IsPrivate());
3638#endif
3639 CHECK(Object::AddDataProperty(&it, value, attributes,
3642 .IsJust());
3643}
3644
3646 const char* name, DirectHandle<Object> value,
3647 PropertyAttributes attributes) {
3648 JSObject::AddProperty(isolate, object,
3649 isolate->factory()->InternalizeUtf8String(name), value,
3650 attributes);
3651}
3652
3653// Reconfigures a property to a data property with attributes, even if it is not
3654// reconfigurable.
3655// Requires a LookupIterator that does not look at the prototype chain beyond
3656// hidden prototypes.
3659 PropertyAttributes attributes, Maybe<ShouldThrow> should_throw,
3660 AccessorInfoHandling handling, EnforceDefineSemantics semantics,
3661 StoreOrigin store_origin) {
3662 it->UpdateProtector();
3663
3664 for (;; it->Next()) {
3665 switch (it->state()) {
3669 UNREACHABLE();
3670
3672 if (!it->HasAccess()) {
3673 Isolate* isolate = it->isolate();
3675 isolate,
3676 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()),
3677 Nothing<bool>());
3678 UNREACHABLE();
3679 }
3680 continue;
3681
3682 // If there's an interceptor, try to store the property with the
3683 // interceptor.
3684 // In case of success, the attributes will have been reset to the default
3685 // attributes of the interceptor, rather than the incoming attributes.
3686 //
3687 // TODO(verwaest): JSProxy afterwards verify the attributes that the
3688 // JSProxy claims it has, and verifies that they are compatible. If not,
3689 // they throw. Here we should do the same.
3692 if (semantics == EnforceDefineSemantics::kDefine) {
3693 PropertyDescriptor descriptor;
3694 descriptor.set_configurable((attributes & DONT_DELETE) != 0);
3695 descriptor.set_enumerable((attributes & DONT_ENUM) != 0);
3696 descriptor.set_writable((attributes & READ_ONLY) != 0);
3697 descriptor.set_value(Cast<JSAny>(value));
3698 if (!DefinePropertyWithInterceptorInternal(it, it->GetInterceptor(),
3699 should_throw, &descriptor)
3700 .To(&result)) {
3701 // An exception was thrown in the interceptor. Propagate.
3702 return Nothing<bool>();
3703 }
3704 } else {
3706 if (handling == DONT_FORCE_FIELD) {
3707 if (!JSObject::SetPropertyWithInterceptor(it, should_throw, value)
3708 .To(&result)) {
3709 // An exception was thrown in the interceptor. Propagate.
3710 return Nothing<bool>();
3711 }
3712 } else {
3714 }
3715 }
3716 switch (result) {
3718 return Just(false);
3720 return Just(true);
3722 // Proceed lookup.
3723 break;
3724 }
3725
3726 if (semantics == EnforceDefineSemantics::kDefine) {
3727 it->Restart();
3729 it->isolate(), it, value, should_throw);
3730 if (can_define.IsNothing() || !can_define.FromJust()) {
3731 return can_define;
3732 }
3733 }
3734
3735 // The interceptor declined to handle the operation, so proceed defining
3736 // own property without the interceptor.
3737 Isolate* isolate = it->isolate();
3738 DirectHandle<JSAny> receiver = it->GetReceiver();
3739 LookupIterator own_lookup(isolate, receiver, it->GetKey(),
3742 &own_lookup, value, attributes, should_throw, handling, semantics,
3743 store_origin);
3744 }
3745
3747 DirectHandle<Object> accessors = it->GetAccessors();
3748
3749 // Special handling for AccessorInfo, which behaves like a data
3750 // property.
3751 if (IsAccessorInfo(*accessors) && handling == DONT_FORCE_FIELD) {
3752 PropertyAttributes current_attributes = it->property_attributes();
3753 // Ensure the context isn't changed after calling into accessors.
3754 AssertNoContextChange ncc(it->isolate());
3755
3756 // Update the attributes before calling the setter. The setter may
3757 // later change the shape of the property.
3758 if (current_attributes != attributes) {
3759 it->TransitionToAccessorPair(accessors, attributes);
3760 }
3761
3762 return Object::SetPropertyWithAccessor(it, value, should_throw);
3763 }
3764
3765 it->ReconfigureDataProperty(value, attributes);
3766 return Just(true);
3767 }
3770 it->isolate(), it->GetName(), value, should_throw);
3771
3772 case LookupIterator::DATA: {
3773 // Regular property update if the attributes match.
3774 if (it->property_attributes() == attributes) {
3775 return Object::SetDataProperty(it, value);
3776 }
3777
3778 // The non-matching attribute case for JSTypedArrays has already been
3779 // handled by JSTypedArray::DefineOwnProperty.
3780 DCHECK(!it->IsElement() ||
3781 !Cast<JSObject>(it->GetReceiver())
3782 ->HasTypedArrayOrRabGsabTypedArrayElements());
3783 // Reconfigure the data property if the attributes mismatch.
3784 it->ReconfigureDataProperty(value, attributes);
3785
3786 return Just(true);
3787 }
3788
3790 return Object::AddDataProperty(it, value, attributes, should_throw,
3791 store_origin, semantics);
3792 }
3793 UNREACHABLE();
3794 }
3795}
3796
3799 DirectHandle<Object> value, PropertyAttributes attributes) {
3800 DCHECK(!IsTheHole(*value));
3801 LookupIterator it(object->GetIsolate(), object, name, object,
3803 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
3804}
3805
3807 DirectHandle<JSObject> object, size_t index, DirectHandle<Object> value,
3808 PropertyAttributes attributes) {
3809 DCHECK(!IsJSTypedArray(*object));
3810 Isolate* isolate = object->GetIsolate();
3811 LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
3812 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
3813}
3814
3817 DirectHandle<Object> value, PropertyAttributes attributes) {
3818 Isolate* isolate = object->GetIsolate();
3819 PropertyKey key(isolate, name);
3820 LookupIterator it(isolate, object, key, object, LookupIterator::OWN);
3821 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
3822}
3823
3825 LookupIterator* it) {
3826 return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
3827}
3828
3832 int expected_additional_properties,
3833 bool use_cache, const char* reason) {
3834 if (!object->HasFastProperties()) return;
3835
3836 DirectHandle<Map> map(object->map(), isolate);
3837 DirectHandle<Map> new_map = Map::Normalize(isolate, map, map->elements_kind(),
3838 {}, mode, use_cache, reason);
3839
3840 JSObject::MigrateToMap(isolate, object, new_map,
3841 expected_additional_properties);
3842}
3843
3845 int unused_property_fields,
3846 const char* reason) {
3847 if (object->HasFastProperties()) return;
3848 DCHECK(!IsJSGlobalObject(*object));
3849 Isolate* isolate = object->GetIsolate();
3850 Factory* factory = isolate->factory();
3851
3853 DirectHandle<SwissNameDictionary> swiss_dictionary;
3854 int number_of_elements;
3856 swiss_dictionary =
3857 direct_handle(object->property_dictionary_swiss(), isolate);
3858 number_of_elements = swiss_dictionary->NumberOfElements();
3859 } else {
3860 dictionary = direct_handle(object->property_dictionary(), isolate);
3861 number_of_elements = dictionary->NumberOfElements();
3862 }
3863
3864 // Make sure we preserve dictionary representation if there are too many
3865 // descriptors.
3866 if (number_of_elements > kMaxNumberOfDescriptors) return;
3867
3868 DirectHandle<FixedArray> iteration_order;
3869 int iteration_length;
3871 // |iteration_order| remains empty handle, we don't need it.
3872 iteration_length = swiss_dictionary->UsedCapacity();
3873 } else {
3874 iteration_order = NameDictionary::IterationIndices(isolate, dictionary);
3875 iteration_length = dictionary->NumberOfElements();
3876 }
3877
3878 int number_of_fields = 0;
3879
3880 // Compute the length of the instance descriptor.
3881 ReadOnlyRoots roots(isolate);
3882 for (int i = 0; i < iteration_length; i++) {
3885 InternalIndex index(swiss_dictionary->EntryForEnumerationIndex(i));
3886 Tagged<Object> key = swiss_dictionary->KeyAt(index);
3887 if (!SwissNameDictionary::IsKey(roots, key)) {
3888 // Ignore deleted entries.
3889 continue;
3890 }
3891 kind = swiss_dictionary->DetailsAt(index).kind();
3892 } else {
3893 InternalIndex index(Smi::ToInt(iteration_order->get(i)));
3894 DCHECK(dictionary->IsKey(roots, dictionary->KeyAt(isolate, index)));
3895 kind = dictionary->DetailsAt(index).kind();
3896 }
3897
3898 if (kind == PropertyKind::kData) {
3899 number_of_fields += 1;
3900 }
3901 }
3902
3903 DirectHandle<Map> old_map(object->map(), isolate);
3904
3905 int inobject_props = old_map->GetInObjectProperties();
3906
3907 // Allocate new map.
3908 DirectHandle<Map> new_map = Map::CopyDropDescriptors(isolate, old_map);
3909 // We should not only set this bit if we need to. We should not retain the
3910 // old bit because turning a map into dictionary always sets this bit.
3911 new_map->set_may_have_interesting_properties(
3912 new_map->has_named_interceptor() || new_map->is_access_check_needed());
3913 new_map->set_is_dictionary_map(false);
3914
3915 NotifyMapChange(old_map, new_map, isolate);
3916
3917 if (number_of_elements == 0) {
3919 DCHECK_LE(unused_property_fields, inobject_props);
3920 // Transform the object.
3921 new_map->SetInObjectUnusedPropertyFields(inobject_props);
3922 object->set_map(isolate, *new_map, kReleaseStore);
3923 object->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array());
3924 // Check that it really works.
3925 DCHECK(object->HasFastProperties());
3926 if (v8_flags.log_maps) {
3927 LOG(isolate, MapEvent("SlowToFast", old_map, new_map, reason));
3928 }
3929 return;
3930 }
3931
3932 // Allocate the instance descriptor.
3933 DirectHandle<DescriptorArray> descriptors =
3934 DescriptorArray::Allocate(isolate, number_of_elements, 0);
3935
3936 int number_of_allocated_fields =
3937 number_of_fields + unused_property_fields - inobject_props;
3938 if (number_of_allocated_fields < 0) {
3939 // There is enough inobject space for all fields (including unused).
3940 number_of_allocated_fields = 0;
3941 unused_property_fields = inobject_props - number_of_fields;
3942 }
3943
3944 // Allocate the property array for the fields.
3946 factory->NewPropertyArray(number_of_allocated_fields);
3947
3948 bool is_transitionable_elements_kind =
3949 IsTransitionableFastElementsKind(old_map->elements_kind());
3950
3951 // Fill in the instance descriptor and the fields.
3952 int current_offset = 0;
3953 int descriptor_index = 0;
3954 for (int i = 0; i < iteration_length; i++) {
3955 Tagged<Name> k;
3958
3960 InternalIndex index(swiss_dictionary->EntryForEnumerationIndex(i));
3961 Tagged<Object> key_obj = swiss_dictionary->KeyAt(index);
3962 if (!SwissNameDictionary::IsKey(roots, key_obj)) {
3963 continue;
3964 }
3965 k = Cast<Name>(key_obj);
3966
3967 value = swiss_dictionary->ValueAt(index);
3968 details = swiss_dictionary->DetailsAt(index);
3969 } else {
3970 InternalIndex index(Smi::ToInt(iteration_order->get(i)));
3971 k = dictionary->NameAt(index);
3972
3973 value = dictionary->ValueAt(index);
3974 details = dictionary->DetailsAt(index);
3975 }
3976
3977 // Dictionary keys are internalized upon insertion.
3978 // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
3979 CHECK(IsUniqueName(k));
3980 DirectHandle<Name> key(k, isolate);
3981
3982 // Properly mark the {new_map} if the {key} is an "interesting symbol".
3983 if (key->IsInteresting(isolate)) {
3984 new_map->set_may_have_interesting_properties(true);
3985 }
3986
3990
3991 Descriptor d;
3992 if (details.kind() == PropertyKind::kData) {
3993 // Ensure that we make constant field only when elements kind is not
3994 // transitionable.
3995 PropertyConstness constness = is_transitionable_elements_kind
3998 // TODO(v8:11248): Consider always setting constness to kMutable
3999 // once all prototypes stay in dictionary mode and we are not interested
4000 // in tracking constness for fast mode properties anymore.
4001
4003 key, current_offset, details.attributes(), constness,
4004 // TODO(verwaest): value->OptimalRepresentation();
4007 } else {
4009 d = Descriptor::AccessorConstant(key, direct_handle(value, isolate),
4010 details.attributes());
4011 }
4012 details = d.GetDetails();
4013 if (details.location() == PropertyLocation::kField) {
4014 if (current_offset < inobject_props) {
4015 object->InObjectPropertyAtPut(current_offset, value,
4017 } else {
4018 int offset = current_offset - inobject_props;
4019 fields->set(offset, value);
4020 }
4021 current_offset += details.field_width_in_words();
4022 }
4023 descriptors->Set(InternalIndex(descriptor_index++), &d);
4024 }
4025 DCHECK_EQ(current_offset, number_of_fields);
4026 DCHECK_EQ(descriptor_index, number_of_elements);
4027
4028 descriptors->Sort();
4029
4031 new_map->InitializeDescriptors(isolate, *descriptors);
4032 if (number_of_allocated_fields == 0) {
4033 new_map->SetInObjectUnusedPropertyFields(unused_property_fields);
4034 } else {
4035 new_map->SetOutOfObjectUnusedPropertyFields(unused_property_fields);
4036 }
4037
4038 if (v8_flags.log_maps) {
4039 LOG(isolate, MapEvent("SlowToFast", old_map, new_map, reason));
4040 }
4041 // Transform the object.
4042 object->set_map(isolate, *new_map, kReleaseStore);
4043
4044 object->SetProperties(*fields);
4045 DCHECK(IsJSObject(*object));
4046
4047 // Check that it really works.
4048 DCHECK(object->HasFastProperties());
4049}
4050
4052 DCHECK_NE(dictionary,
4053 ReadOnlyRoots(GetIsolate()).empty_slow_element_dictionary());
4054 if (dictionary->requires_slow_elements()) return;
4055 dictionary->set_requires_slow_elements();
4056 if (map()->is_prototype_map()) {
4057 // If this object is a prototype (the callee will check), invalidate any
4058 // prototype chains involving it.
4060 }
4061}
4062
4064 DirectHandle<JSObject> object) {
4065 DCHECK(!object->HasTypedArrayOrRabGsabTypedArrayElements());
4066 Isolate* isolate = object->GetIsolate();
4067 bool is_sloppy_arguments = object->HasSloppyArgumentsElements();
4068 {
4070 Tagged<FixedArrayBase> elements = object->elements();
4071
4072 if (is_sloppy_arguments) {
4074 }
4075
4076 if (IsNumberDictionary(elements)) {
4078 }
4079 }
4080
4081 DCHECK(object->HasSmiOrObjectElements() || object->HasDoubleElements() ||
4082 object->HasFastArgumentsElements() ||
4083 object->HasFastStringWrapperElements() ||
4084 object->HasSealedElements() || object->HasNonextensibleElements());
4085
4087 object->GetElementsAccessor()->Normalize(object);
4088
4089 // Switch to using the dictionary as the backing storage for elements.
4090 ElementsKind target_kind =
4091 is_sloppy_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
4092 : object->HasFastStringWrapperElements() ? SLOW_STRING_WRAPPER_ELEMENTS
4094 DirectHandle<Map> new_map =
4095 JSObject::GetElementsTransitionMap(object, target_kind);
4096 // Set the new map first to satisfy the elements type assert in
4097 // set_elements().
4098 JSObject::MigrateToMap(isolate, object, new_map);
4099
4100 if (is_sloppy_arguments) {
4101 Cast<SloppyArgumentsElements>(object->elements())
4102 ->set_arguments(*dictionary);
4103 } else {
4104 object->set_elements(*dictionary);
4105 }
4106
4107#ifdef DEBUG
4108 if (v8_flags.trace_normalization) {
4109 StdoutStream os;
4110 os << "Object elements have been normalized:\n";
4111 Print(*object, os);
4112 }
4113#endif
4114
4115 DCHECK(object->HasDictionaryElements() ||
4116 object->HasSlowArgumentsElements() ||
4117 object->HasSlowStringWrapperElements());
4118 return dictionary;
4119}
4120
4122 LookupIterator* it, ShouldThrow should_throw) {
4123 Isolate* isolate = it->isolate();
4124 // Make sure that the top context does not change when doing callbacks or
4125 // interceptor calls.
4126 AssertNoContextChange ncc(isolate);
4127
4129 DirectHandle<InterceptorInfo> interceptor(it->GetInterceptor());
4130 if (!interceptor->has_deleter()) {
4132 }
4133 DirectHandle<JSObject> holder = it->GetHolder<JSObject>();
4134 DirectHandle<Object> receiver = it->GetReceiver();
4135 if (!IsJSReceiver(*receiver)) {
4139 }
4140
4141 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
4142 *holder, Just(should_throw));
4143
4144 v8::Intercepted intercepted =
4145 it->IsElement(*holder)
4146 ? args.CallIndexedDeleter(interceptor, it->array_index())
4147 : args.CallNamedDeleter(interceptor, it->name());
4148
4149 return args.GetBooleanReturnValue(intercepted, "Deleter");
4150}
4151
4156 Maybe<ShouldThrow> should_throw) {
4157 if (!key.is_element()) {
4158 if (TryFastAddDataProperty(isolate, object, key.name(), value, NONE)) {
4159 return Just(true);
4160 }
4161 }
4162
4163 LookupIterator it(isolate, object, key, LookupIterator::OWN);
4165 isolate, &it, value, should_throw);
4166 if (can_define.IsNothing() || !can_define.FromJust()) {
4167 return can_define;
4168 }
4169
4172 Nothing<bool>());
4173
4174 return Just(true);
4175}
4176
4177namespace {
4178
4179template <typename Dictionary>
4180bool TestDictionaryPropertiesIntegrityLevel(Tagged<Dictionary> dict,
4181 ReadOnlyRoots roots,
4182 PropertyAttributes level) {
4183 DCHECK(level == SEALED || level == FROZEN);
4184
4185 for (InternalIndex i : dict->IterateEntries()) {
4187 if (!dict->ToKey(roots, i, &key)) continue;
4188 if (Object::FilterKey(key, ALL_PROPERTIES)) continue;
4189 PropertyDetails details = dict->DetailsAt(i);
4190 if (details.IsConfigurable()) return false;
4191 if (level == FROZEN && details.kind() == PropertyKind::kData &&
4192 !details.IsReadOnly()) {
4193 return false;
4194 }
4195 }
4196 return true;
4197}
4198
4199bool TestFastPropertiesIntegrityLevel(Tagged<Map> map,
4200 PropertyAttributes level) {
4201 DCHECK(level == SEALED || level == FROZEN);
4203 DCHECK(!map->is_dictionary_map());
4204
4205 Tagged<DescriptorArray> descriptors = map->instance_descriptors();
4206 for (InternalIndex i : map->IterateOwnDescriptors()) {
4207 if (descriptors->GetKey(i)->IsPrivate()) continue;
4208 PropertyDetails details = descriptors->GetDetails(i);
4209 if (details.IsConfigurable()) return false;
4210 if (level == FROZEN && details.kind() == PropertyKind::kData &&
4211 !details.IsReadOnly()) {
4212 return false;
4213 }
4214 }
4215 return true;
4216}
4217
4218bool TestPropertiesIntegrityLevel(Tagged<JSObject> object,
4219 PropertyAttributes level) {
4220 DCHECK(!IsCustomElementsReceiverMap(object->map()));
4221
4222 if (object->HasFastProperties()) {
4223 return TestFastPropertiesIntegrityLevel(object->map(), level);
4224 }
4225
4227 return TestDictionaryPropertiesIntegrityLevel(
4228 object->property_dictionary_swiss(), GetReadOnlyRoots(), level);
4229 } else {
4230 return TestDictionaryPropertiesIntegrityLevel(object->property_dictionary(),
4231 GetReadOnlyRoots(), level);
4232 }
4233}
4234
4235bool TestElementsIntegrityLevel(Isolate* isolate, Tagged<JSObject> object,
4236 PropertyAttributes level) {
4237 DCHECK(!object->HasSloppyArgumentsElements());
4238
4239 ElementsKind kind = object->GetElementsKind();
4240
4242 return TestDictionaryPropertiesIntegrityLevel(
4243 Cast<NumberDictionary>(object->elements()), GetReadOnlyRoots(), level);
4244 }
4246 if (level == FROZEN && Cast<JSArrayBufferView>(object)->byte_length() > 0) {
4247 return false; // TypedArrays with elements can't be frozen.
4248 }
4249 return TestPropertiesIntegrityLevel(object, level);
4250 }
4251 if (IsFrozenElementsKind(kind)) return true;
4252 if (IsSealedElementsKind(kind) && level != FROZEN) return true;
4253 if (IsNonextensibleElementsKind(kind) && level == NONE) return true;
4254
4255 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
4256 // Only DICTIONARY_ELEMENTS and SLOW_SLOPPY_ARGUMENTS_ELEMENTS have
4257 // PropertyAttributes so just test if empty
4258 return accessor->NumberOfElements(isolate, object) == 0;
4259}
4260
4261bool FastTestIntegrityLevel(Isolate* isolate, Tagged<JSObject> object,
4262 PropertyAttributes level) {
4263 DCHECK(!IsCustomElementsReceiverMap(object->map()));
4264
4265 return !object->map()->is_extensible() &&
4266 TestElementsIntegrityLevel(isolate, object, level) &&
4267 TestPropertiesIntegrityLevel(object, level);
4268}
4269
4270} // namespace
4271
4274 IntegrityLevel level) {
4275 if (!IsCustomElementsReceiverMap(object->map()) &&
4276 !object->HasSloppyArgumentsElements()) {
4277 return Just(FastTestIntegrityLevel(isolate, *object, level));
4278 }
4279 return GenericTestIntegrityLevel(isolate, Cast<JSReceiver>(object), level);
4280}
4281
4284 ShouldThrow should_throw) {
4285 if (!object->HasSloppyArgumentsElements()) {
4286 return PreventExtensionsWithTransition<NONE>(isolate, object, should_throw);
4287 }
4288
4289 if (IsAccessCheckNeeded(*object) &&
4290 !isolate->MayAccess(isolate->native_context(), object)) {
4291 RETURN_ON_EXCEPTION_VALUE(isolate, isolate->ReportFailedAccessCheck(object),
4292 Nothing<bool>());
4293 UNREACHABLE();
4294 }
4295
4296 if (!object->map()->is_extensible()) return Just(true);
4297
4298 if (IsJSGlobalProxy(*object)) {
4299 PrototypeIterator iter(isolate, object);
4300 if (iter.IsAtEnd()) return Just(true);
4301 DCHECK(IsJSGlobalObject(*PrototypeIterator::GetCurrent(iter)));
4302 return PreventExtensions(
4303 isolate, PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
4304 }
4305
4306 if (object->map()->has_named_interceptor() ||
4307 object->map()->has_indexed_interceptor()) {
4308 RETURN_FAILURE(isolate, should_throw,
4309 NewTypeError(MessageTemplate::kCannotPreventExt));
4310 }
4311
4312 DCHECK(!object->HasTypedArrayOrRabGsabTypedArrayElements());
4313
4314 // Normalize fast elements.
4316 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
4317
4318 // Make sure that we never go back to fast case.
4319 if (*dictionary != ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
4320 object->RequireSlowElements(*dictionary);
4321 }
4322
4323 // Do a map transition, other objects with this map may still
4324 // be extensible.
4325 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
4326 DirectHandle<Map> new_map = Map::Copy(
4327 isolate, direct_handle(object->map(), isolate), "PreventExtensions");
4328
4329 new_map->set_is_extensible(false);
4330 JSObject::MigrateToMap(isolate, object, new_map);
4331 DCHECK(!object->map()->is_extensible());
4332
4333 return Just(true);
4334}
4335
4337 if (IsAccessCheckNeeded(*object) &&
4338 !isolate->MayAccess(isolate->native_context(), object)) {
4339 return true;
4340 }
4341 if (IsJSGlobalProxy(*object)) {
4342 PrototypeIterator iter(isolate, *object);
4343 if (iter.IsAtEnd()) return false;
4344 DCHECK(IsJSGlobalObject(iter.GetCurrent()));
4345 return iter.GetCurrent<JSObject>()->map()->is_extensible();
4346 }
4347 return object->map()->is_extensible();
4348}
4349
4350// static
4352 DirectHandle<Object> options, DirectHandle<String> option_name,
4353 Isolate* isolate) {
4354 if (IsJSReceiver(*options)) {
4355 DirectHandle<JSReceiver> js_options = Cast<JSReceiver>(options);
4356 return JSObject::GetProperty(isolate, js_options, option_name);
4357 }
4358 return MaybeDirectHandle<Object>(isolate->factory()->undefined_value());
4359}
4360
4361template <typename Dictionary>
4363 Isolate* isolate, ReadOnlyRoots roots, DirectHandle<Dictionary> dictionary,
4364 const PropertyAttributes attributes) {
4365 for (InternalIndex i : dictionary->IterateEntries()) {
4367 if (!dictionary->ToKey(roots, i, &k)) continue;
4368 if (Object::FilterKey(k, ALL_PROPERTIES)) continue;
4369 PropertyDetails details = dictionary->DetailsAt(i);
4370 int attrs = attributes;
4371 // READ_ONLY is an invalid attribute for JS setters/getters.
4372 if ((attributes & READ_ONLY) && details.kind() == PropertyKind::kAccessor) {
4373 Tagged<Object> v = dictionary->ValueAt(i);
4374 if (IsAccessorPair(v)) attrs &= ~READ_ONLY;
4375 }
4376 details = details.CopyAddAttributes(PropertyAttributesFromInt(attrs));
4377 dictionary->DetailsAtPut(i, details);
4378 }
4379}
4380
4382 Isolate* isolate, ReadOnlyRoots roots,
4384 const PropertyAttributes attributes);
4385
4387 Isolate* isolate, DirectHandle<JSObject> object) {
4388 DirectHandle<NumberDictionary> new_element_dictionary;
4389 if (!object->HasTypedArrayOrRabGsabTypedArrayElements() &&
4390 !object->HasDictionaryElements() &&
4391 !object->HasSlowStringWrapperElements()) {
4392 int length = IsJSArray(*object)
4393 ? Smi::ToInt(Cast<JSArray>(object)->length())
4394 : object->elements()->length();
4395 new_element_dictionary =
4396 length == 0 ? isolate->factory()->empty_slow_element_dictionary()
4397 : object->GetElementsAccessor()->Normalize(object);
4398 }
4399 return new_element_dictionary;
4400}
4401
4402template <PropertyAttributes attrs>
4404 Isolate* isolate, DirectHandle<JSObject> object, ShouldThrow should_throw) {
4405 static_assert(attrs == NONE || attrs == SEALED || attrs == FROZEN);
4406
4407 // Sealing/freezing sloppy arguments or namespace objects should be handled
4408 // elsewhere.
4409 DCHECK(!object->HasSloppyArgumentsElements());
4410 DCHECK_IMPLIES(IsJSModuleNamespace(*object), attrs == NONE);
4411
4412 if (IsAccessCheckNeeded(*object) &&
4413 !isolate->MayAccess(isolate->native_context(), object)) {
4414 RETURN_ON_EXCEPTION_VALUE(isolate, isolate->ReportFailedAccessCheck(object),
4415 Nothing<bool>());
4416 UNREACHABLE();
4417 }
4418
4419 if (attrs == NONE && !object->map()->is_extensible()) {
4420 return Just(true);
4421 }
4422
4423 {
4424 ElementsKind old_elements_kind = object->map()->elements_kind();
4425 if (IsFrozenElementsKind(old_elements_kind)) return Just(true);
4426 if (attrs != FROZEN && IsSealedElementsKind(old_elements_kind)) {
4427 return Just(true);
4428 }
4429 }
4430
4431 if (IsJSGlobalProxy(*object)) {
4432 PrototypeIterator iter(isolate, object);
4433 if (iter.IsAtEnd()) return Just(true);
4434 DCHECK(IsJSGlobalObject(*PrototypeIterator::GetCurrent(iter)));
4436 isolate, PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
4437 }
4438
4439 // Shared objects are designed to have fixed layout, i.e. their maps are
4440 // effectively immutable. They are constructed seal, but the semantics of
4441 // ordinary ECMAScript objects allow sealed to be upgraded to frozen. This
4442 // upgrade violates the fixed layout invariant and is disallowed.
4443 if (IsAlwaysSharedSpaceJSObject(*object)) {
4444 DCHECK(FastTestIntegrityLevel(isolate, *object, SEALED));
4445 if (attrs != FROZEN) return Just(true);
4446 RETURN_FAILURE(isolate, should_throw,
4447 NewTypeError(MessageTemplate::kCannotFreeze));
4448 }
4449
4450 if (object->map()->has_named_interceptor() ||
4451 object->map()->has_indexed_interceptor() ||
4452 (object->HasTypedArrayOrRabGsabTypedArrayElements() &&
4453 Cast<JSTypedArray>(*object)->IsVariableLength())) {
4454 MessageTemplate message = MessageTemplate::kNone;
4455 switch (attrs) {
4456 case NONE:
4457 message = MessageTemplate::kCannotPreventExt;
4458 break;
4459
4460 case SEALED:
4461 message = MessageTemplate::kCannotSeal;
4462 break;
4463
4464 case FROZEN:
4465 message = MessageTemplate::kCannotFreeze;
4466 break;
4467 }
4468 RETURN_FAILURE(isolate, should_throw, NewTypeError(message));
4469 }
4470
4471 DirectHandle<Symbol> transition_marker;
4472 if (attrs == NONE) {
4473 transition_marker = isolate->factory()->nonextensible_symbol();
4474 } else if (attrs == SEALED) {
4475 transition_marker = isolate->factory()->sealed_symbol();
4476 } else {
4477 DCHECK(attrs == FROZEN);
4478 transition_marker = isolate->factory()->frozen_symbol();
4479 }
4480
4481 // Currently, there are only have sealed/frozen Object element kinds and
4482 // Map::MigrateToMap doesn't handle properties' attributes reconfiguring and
4483 // elements kind change in one go. If seal or freeze with Smi or Double
4484 // elements kind, we will transition to Object elements kind first to make
4485 // sure of valid element access.
4486 switch (object->map()->elements_kind()) {
4490 break;
4491 case HOLEY_SMI_ELEMENTS:
4494 break;
4495 default:
4496 break;
4497 }
4498
4499 // Make sure we only use this element dictionary in case we can't transition
4500 // to sealed, frozen elements kind.
4501 DirectHandle<NumberDictionary> new_element_dictionary;
4502
4503 DirectHandle<Map> old_map(object->map(), isolate);
4504 old_map = Map::Update(isolate, old_map);
4505 DirectHandle<Map> transition_map;
4506 MaybeDirectHandle<Map> maybe_transition_map =
4507 TransitionsAccessor::SearchSpecial(isolate, old_map, *transition_marker);
4508 if (maybe_transition_map.ToHandle(&transition_map)) {
4509 DCHECK(transition_map->has_dictionary_elements() ||
4510 transition_map->has_typed_array_or_rab_gsab_typed_array_elements() ||
4511 transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS ||
4512 transition_map->has_any_nonextensible_elements());
4513 DCHECK(!transition_map->is_extensible());
4514 if (!transition_map->has_any_nonextensible_elements()) {
4515 new_element_dictionary = CreateElementDictionary(isolate, object);
4516 }
4517 JSObject::MigrateToMap(isolate, object, transition_map);
4518 } else if (TransitionsAccessor::CanHaveMoreTransitions(isolate, old_map)) {
4519 // Create a new descriptor array with the appropriate property attributes
4521 isolate, old_map, attrs, transition_marker, "CopyForPreventExtensions");
4522 if (!new_map->has_any_nonextensible_elements()) {
4523 new_element_dictionary = CreateElementDictionary(isolate, object);
4524 }
4525 JSObject::MigrateToMap(isolate, object, new_map);
4526 } else {
4527 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
4528 // Slow path: need to normalize properties for safety
4530 "SlowPreventExtensions");
4531
4532 // Create a new map, since other objects with this map may be extensible.
4533 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
4534 DirectHandle<Map> new_map =
4535 Map::Copy(isolate, direct_handle(object->map(), isolate),
4536 "SlowCopyForPreventExtensions");
4537 new_map->set_is_extensible(false);
4538 new_element_dictionary = CreateElementDictionary(isolate, object);
4539 if (!new_element_dictionary.is_null()) {
4540 ElementsKind new_kind =
4541 IsStringWrapperElementsKind(old_map->elements_kind())
4544 new_map->set_elements_kind(new_kind);
4545 }
4546 JSObject::MigrateToMap(isolate, object, new_map);
4547
4548 if (attrs != NONE) {
4549 ReadOnlyRoots roots(isolate);
4550 if (IsJSGlobalObject(*object)) {
4552 Cast<JSGlobalObject>(*object)->global_dictionary(kAcquireLoad),
4553 isolate);
4554 JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
4555 attrs);
4556 } else if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
4558 object->property_dictionary_swiss(), isolate);
4559 JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
4560 attrs);
4561 } else {
4562 DirectHandle<NameDictionary> dictionary(object->property_dictionary(),
4563 isolate);
4564 JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
4565 attrs);
4566 }
4567 }
4568 }
4569
4570 if (object->map()->has_any_nonextensible_elements()) {
4571 DCHECK(new_element_dictionary.is_null());
4572 return Just(true);
4573 }
4574
4575 // PreventExtensions works without modifications to typed array elements if
4576 // the typed array is fixed length; see #sec-typedarray-preventextensions.
4577 // Seal and freeze work only if there are no actual elements, because
4578 // TypedArray elements cannot be reconfigured; see
4579 // #sec-typedarray-defineownproperty.
4580 if (object->HasTypedArrayOrRabGsabTypedArrayElements()) {
4581 DCHECK(new_element_dictionary.is_null());
4582 if (attrs != NONE && Cast<JSTypedArray>(*object)->GetLength() > 0) {
4583 isolate->Throw(*isolate->factory()->NewTypeError(
4584 attrs == SEALED ? MessageTemplate::kCannotSealArrayBufferView
4585 : MessageTemplate::kCannotFreezeArrayBufferView));
4586 return Nothing<bool>();
4587 }
4588 return Just(true);
4589 }
4590
4591 DCHECK(object->map()->has_dictionary_elements() ||
4592 object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
4593 if (!new_element_dictionary.is_null()) {
4594 object->set_elements(*new_element_dictionary);
4595 }
4596
4597 if (object->elements() !=
4598 ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
4599 DirectHandle<NumberDictionary> dictionary(object->element_dictionary(),
4600 isolate);
4601 // Make sure we never go back to the fast case
4602 object->RequireSlowElements(*dictionary);
4603 if (attrs != NONE) {
4605 dictionary, attrs);
4606 }
4607 }
4608
4609 return Just(true);
4610}
4611
4614 Representation representation,
4615 FieldIndex index) {
4616 Handle<JSAny> raw_value(object->RawFastPropertyAt(index), isolate);
4617 return Object::WrapForRead(isolate, raw_value, representation);
4618}
4619
4622 Representation representation,
4623 FieldIndex index,
4624 SeqCstAccessTag tag) {
4625 Handle<JSAny> raw_value(object->RawFastPropertyAt(index, tag), isolate);
4626 return Object::WrapForRead(isolate, raw_value, representation);
4627}
4628
4629// static
4632 InternalIndex dict_index) {
4633 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
4635 Tagged<SwissNameDictionary> dict = object->property_dictionary_swiss();
4636 return handle(dict->ValueAt(dict_index), isolate);
4637 } else {
4638 Tagged<NameDictionary> dict = object->property_dictionary();
4639 return handle(dict->ValueAt(dict_index), isolate);
4640 }
4641}
4642
4643// static
4644std::optional<Tagged<Object>> JSObject::DictionaryPropertyAt(
4645 DirectHandle<JSObject> object, InternalIndex dict_index, Heap* heap) {
4646 Tagged<Object> backing_store = object->raw_properties_or_hash(kRelaxedLoad);
4647 if (!IsHeapObject(backing_store)) return {};
4648 if (heap->IsPendingAllocation(Cast<HeapObject>(backing_store))) return {};
4649
4650 if (!IsPropertyDictionary(backing_store)) return {};
4651 std::optional<Tagged<Object>> maybe_obj =
4652 Cast<PropertyDictionary>(backing_store)->TryValueAt(dict_index);
4653
4654 if (!maybe_obj) return {};
4655 return maybe_obj.value();
4656}
4657
4658// TODO(cbruni/jkummerow): Consider moving this into elements.cc.
4660 // TODO(cbruni): cleanup
4661 Tagged<JSObject> object = *this;
4662 switch (object->GetElementsKind()) {
4664 case PACKED_ELEMENTS:
4669 case SHARED_ARRAY_ELEMENTS: {
4670 int length = IsJSArray(object)
4671 ? Smi::ToInt(Cast<JSArray>(object)->length())
4672 : object->elements()->length();
4673 return length > 0;
4674 }
4675 case HOLEY_SMI_ELEMENTS:
4679 case HOLEY_ELEMENTS: {
4680 Tagged<FixedArray> elements = Cast<FixedArray>(object->elements());
4681 int length = IsJSArray(object)
4682 ? Smi::ToInt(Cast<JSArray>(object)->length())
4683 : elements->length();
4684 Isolate* isolate = GetIsolate();
4685 for (int i = 0; i < length; i++) {
4686 if (!elements->is_the_hole(isolate, i)) return true;
4687 }
4688 return false;
4689 }
4690 case HOLEY_DOUBLE_ELEMENTS: {
4691 int length = IsJSArray(object)
4692 ? Smi::ToInt(Cast<JSArray>(object)->length())
4693 : object->elements()->length();
4694 // Zero-length arrays would use the empty FixedArray...
4695 if (length == 0) return false;
4696 // ...so only cast to FixedDoubleArray otherwise.
4698 Cast<FixedDoubleArray>(object->elements());
4699 for (int i = 0; i < length; i++) {
4700 if (!elements->is_the_hole(i)) return true;
4701 }
4702 return false;
4703 }
4704#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
4705
4707 size_t length = Cast<JSTypedArray>(object)->length();
4708 return length > 0;
4709 }
4710
4712#undef TYPED_ARRAY_CASE
4713 {
4714 size_t length = Cast<JSTypedArray>(object)->GetLength();
4715 return length > 0;
4716 }
4717 case DICTIONARY_ELEMENTS: {
4719 Cast<NumberDictionary>(object->elements());
4720 return elements->NumberOfEnumerableProperties() > 0;
4721 }
4724 // We're approximating non-empty arguments objects here.
4725 return true;
4729 0) {
4730 return true;
4731 }
4732 return object->elements()->length() > 0;
4734 UNIMPLEMENTED();
4735
4736 case NO_ELEMENTS:
4737 return false;
4738 }
4739 UNREACHABLE();
4740}
4741
4752
4756 Isolate* isolate = it->isolate();
4757
4758 it->UpdateProtector();
4759
4760 while (it->state() == LookupIterator::ACCESS_CHECK) {
4761 if (!it->HasAccess()) {
4763 isolate, isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()));
4764 UNREACHABLE();
4765 }
4766 it->Next();
4767 }
4768
4769 auto object = Cast<JSObject>(it->GetReceiver());
4770 // Ignore accessors on typed arrays.
4771 if (it->IsElement() && object->HasTypedArrayOrRabGsabTypedArrayElements()) {
4772 return it->factory()->undefined_value();
4773 }
4774
4775 DCHECK(IsCallable(*getter) || IsUndefined(*getter, isolate) ||
4776 IsNull(*getter, isolate) || IsFunctionTemplateInfo(*getter));
4777 DCHECK(IsCallable(*setter) || IsUndefined(*setter, isolate) ||
4778 IsNull(*setter, isolate) || IsFunctionTemplateInfo(*setter));
4779 it->TransitionToAccessorProperty(getter, setter, attributes);
4780
4781 return isolate->factory()->undefined_value();
4782}
4783
4785 DirectHandle<Name> name,
4787 PropertyAttributes attributes) {
4788 Isolate* isolate = object->GetIsolate();
4789
4790 PropertyKey key(isolate, name);
4792
4793 // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
4794 // the FailedAccessCheckCallbackFunction doesn't throw an exception.
4795 while (it.state() == LookupIterator::ACCESS_CHECK) {
4796 if (!it.HasAccess()) {
4797 RETURN_ON_EXCEPTION(isolate, isolate->ReportFailedAccessCheck(object));
4798 UNREACHABLE();
4799 }
4800 it.Next();
4801 }
4802
4803 // Ignore accessors on typed arrays.
4804 if (it.IsElement() && object->HasTypedArrayOrRabGsabTypedArrayElements()) {
4805 return it.factory()->undefined_value();
4806 }
4807
4809 isolate, &it, info, Nothing<ShouldThrow>());
4810 MAYBE_RETURN_NULL(can_define);
4811 if (!can_define.FromJust()) return it.factory()->undefined_value();
4812
4813 it.TransitionToAccessorPair(info, attributes);
4814
4815 return object;
4816}
4817
4818// static
4820 Isolate* isolate, LookupIterator* it, DirectHandle<Object> value,
4821 Maybe<ShouldThrow> should_throw) {
4822 DCHECK(IsJSObject(*it->GetReceiver()));
4823 if (it->IsFound()) {
4824 Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
4825 MAYBE_RETURN(attributes, Nothing<bool>());
4826 if (attributes.FromJust() != ABSENT) {
4827 if ((attributes.FromJust() & DONT_DELETE) != 0) {
4829 isolate, GetShouldThrow(isolate, should_throw),
4830 NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
4831 }
4832 return Just(true);
4833 }
4834 // Property does not exist, check object extensibility.
4835 }
4836 if (!JSObject::IsExtensible(isolate, Cast<JSObject>(it->GetReceiver()))) {
4838 isolate, GetShouldThrow(isolate, should_throw),
4839 NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
4840 }
4841 return Just(true);
4842}
4843
4845 if (HasFastProperties()) {
4846 Tagged<DescriptorArray> descs = map()->instance_descriptors();
4847 bool value_is_number = IsNumber(value);
4848 for (InternalIndex i : map()->IterateOwnDescriptors()) {
4849 PropertyDetails details = descs->GetDetails(i);
4850 if (details.location() == PropertyLocation::kField) {
4852 FieldIndex field_index = FieldIndex::ForDetails(map(), details);
4853 Tagged<Object> property = RawFastPropertyAt(field_index);
4854 if (field_index.is_double()) {
4855 DCHECK(IsHeapNumber(property));
4856 if (value_is_number && Cast<HeapNumber>(property)->value() ==
4858 return descs->GetKey(i);
4859 }
4860 } else if (property == value) {
4861 return descs->GetKey(i);
4862 }
4863 } else {
4865 if (details.kind() == PropertyKind::kData) {
4866 if (descs->GetStrongValue(i) == value) {
4867 return descs->GetKey(i);
4868 }
4869 }
4870 }
4871 }
4872 return GetReadOnlyRoots().undefined_value();
4873 } else if (IsJSGlobalObject(*this)) {
4874 return Cast<JSGlobalObject>(*this)
4875 ->global_dictionary(kAcquireLoad)
4876 ->SlowReverseLookup(value);
4877 } else if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
4878 return property_dictionary_swiss()->SlowReverseLookup(GetIsolate(), value);
4879 } else {
4880 return property_dictionary()->SlowReverseLookup(value);
4881 }
4882}
4883
4885 int old_index,
4886 int new_index) {
4887 DCHECK(IsMap(value) && Cast<Map>(value)->is_prototype_map());
4888 Tagged<Map> map = Cast<Map>(value);
4889 DCHECK(IsPrototypeInfo(map->prototype_info()));
4890 Tagged<PrototypeInfo> proto_info = Cast<PrototypeInfo>(map->prototype_info());
4891 DCHECK_EQ(old_index, proto_info->registry_slot());
4892 proto_info->set_registry_slot(new_index);
4893}
4894
4895// static
4897 WhereToStart where_to_start,
4898 Isolate* isolate) {
4899 if (!IsJSReceiver(*receiver)) return;
4900 for (PrototypeIterator iter(isolate, Cast<JSReceiver>(receiver),
4901 where_to_start);
4902 !iter.IsAtEnd(); iter.Advance()) {
4904 if (!IsJSObjectThatCanBeTrackedAsPrototype(*current)) return;
4905 DirectHandle<JSObject> current_obj = Cast<JSObject>(current);
4906 Tagged<Map> current_map = current_obj->map();
4907 if (current_map->is_prototype_map()) {
4908 // If the map is already marked as should be fast, we're done. Its
4909 // prototypes will have been marked already as well.
4910 if (current_map->should_be_fast_prototype_map()) return;
4911 DirectHandle<Map> map(current_map, isolate);
4912 Map::SetShouldBeFastPrototypeMap(map, true, isolate);
4913 JSObject::OptimizeAsPrototype(current_obj);
4914 }
4915 }
4916}
4917
4920 if (!object->HasFastProperties()) return false;
4921 if (IsJSGlobalProxy(object)) return false;
4922 // TODO(v8:11248) make bootstrapper create dict mode prototypes, too?
4923 if (object->GetIsolate()->bootstrapper()->IsActive()) return false;
4924 if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL) return true;
4925 return !object->map()->is_prototype_map() ||
4926 !object->map()->should_be_fast_prototype_map();
4927}
4928
4929// static
4931 bool enable_setup_mode) {
4933 if (IsJSGlobalObject(*object)) return;
4934 Isolate* isolate = object->GetIsolate();
4935 if (object->map()->is_prototype_map()) {
4936 if (enable_setup_mode && PrototypeBenefitsFromNormalization(*object)) {
4937 // This is the only way PrototypeBenefitsFromNormalization can be true:
4938 DCHECK(!object->map()->should_be_fast_prototype_map());
4939 // First normalize to ensure all JSFunctions are DATA_CONSTANT.
4940 constexpr bool kUseCache = true;
4942 0, kUseCache, "NormalizeAsPrototype");
4943 }
4945 object->map()->should_be_fast_prototype_map() &&
4946 !object->HasFastProperties()) {
4947 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
4948 }
4949 } else {
4950 DirectHandle<Map> new_map;
4951 if (enable_setup_mode && PrototypeBenefitsFromNormalization(*object)) {
4952#if DEBUG
4953 DirectHandle<Map> old_map(object->map(isolate), isolate);
4954#endif // DEBUG
4955 // First normalize to ensure all JSFunctions are DATA_CONSTANT. Don't use
4956 // the cache, since we're going to use the normalized version directly,
4957 // without making a copy.
4958 constexpr bool kUseCache = false;
4960 0, kUseCache,
4961 "NormalizeAndCopyAsPrototype");
4962 // A new map was created.
4963 DCHECK_NE(*old_map, object->map(isolate));
4964
4965 new_map = direct_handle(object->map(isolate), isolate);
4966 } else {
4967 new_map = Map::Copy(isolate, direct_handle(object->map(), isolate),
4968 "CopyAsPrototype");
4969 }
4970 new_map->set_is_prototype_map(true);
4971
4972 // Replace the pointer to the exact constructor with the Object function
4973 // from the same context if undetectable from JS. This is to avoid keeping
4974 // memory alive unnecessarily.
4975 Tagged<Object> maybe_constructor = new_map->GetConstructorRaw();
4976 Tagged<Tuple2> tuple;
4977 if (IsTuple2(maybe_constructor)) {
4978 // Handle the {constructor, non-instance_prototype} tuple case if the map
4979 // has non-instance prototype.
4980 tuple = Cast<Tuple2>(maybe_constructor);
4981 maybe_constructor = tuple->value1();
4982 }
4983 if (IsJSFunction(maybe_constructor)) {
4984 Tagged<JSFunction> constructor = Cast<JSFunction>(maybe_constructor);
4985 if (!constructor->shared()->IsApiFunction()) {
4986 Tagged<NativeContext> context = constructor->native_context();
4987 Tagged<JSFunction> object_function = context->object_function();
4988 if (!tuple.is_null()) {
4989 tuple->set_value1(object_function);
4990 } else {
4991 new_map->SetConstructor(object_function);
4992 }
4993 }
4994 }
4995 JSObject::MigrateToMap(isolate, object, new_map);
4996
4997 if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL && !object->HasFastProperties()) {
4998 ReadOnlyRoots roots(isolate);
5000
5001 auto make_constant = [&](auto dict) {
5002 for (InternalIndex index : dict->IterateEntries()) {
5004 if (!dict->ToKey(roots, index, &k)) continue;
5005
5006 PropertyDetails details = dict->DetailsAt(index);
5008 dict->DetailsAtPut(index, details);
5009 }
5010 };
5012 make_constant(object->property_dictionary_swiss());
5013 } else {
5014 make_constant(object->property_dictionary());
5015 }
5016 }
5017 }
5018#ifdef DEBUG
5019 bool should_be_dictionary = V8_DICT_PROPERTY_CONST_TRACKING_BOOL &&
5020 enable_setup_mode && !IsJSGlobalProxy(*object) &&
5021 !isolate->bootstrapper()->IsActive();
5022 DCHECK_IMPLIES(should_be_dictionary,
5023 object->map(isolate)->is_dictionary_map());
5024#endif
5025}
5026
5027// static
5029 {
5030 Tagged<Map> map = object->map();
5031 if (!map->is_prototype_map()) return;
5032 if (!map->should_be_fast_prototype_map()) return;
5033 }
5034 OptimizeAsPrototype(object);
5035}
5036
5037// static
5039 Isolate* isolate) {
5040 // Contract: In line with InvalidatePrototypeChains()'s requirements,
5041 // leaf maps don't need to register as users, only prototypes do.
5042 DCHECK(user->is_prototype_map());
5043
5044 DirectHandle<Map> current_user = user;
5045 DirectHandle<PrototypeInfo> current_user_info =
5046 Map::GetOrCreatePrototypeInfo(user, isolate);
5047 for (PrototypeIterator iter(isolate, user); !iter.IsAtEnd(); iter.Advance()) {
5048 // Walk up the prototype chain as far as links haven't been registered yet.
5049 if (current_user_info->registry_slot() != MemoryChunk::UNREGISTERED) {
5050 break;
5051 }
5053 // This checks for both proxies and shared objects.
5054 //
5055 // Proxies on the prototype chain are not supported. They make it
5056 // impossible to make any assumptions about the prototype chain anyway.
5057 //
5058 // Objects in the shared heap have fixed layouts and their maps never
5059 // change, so they don't need to be tracked as prototypes
5060 // anyway. Additionally, registering users of shared objects is not
5061 // threadsafe.
5062 if (!IsJSObjectThatCanBeTrackedAsPrototype(*maybe_proto)) continue;
5063 auto proto = Cast<JSObject>(maybe_proto);
5064 DirectHandle<PrototypeInfo> proto_info =
5065 Map::GetOrCreatePrototypeInfo(proto, isolate);
5066 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
5067 Handle<WeakArrayList> registry =
5068 IsSmi(*maybe_registry)
5069 ? handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(),
5070 isolate)
5071 : Cast<WeakArrayList>(maybe_registry);
5072 int slot = 0;
5073 Handle<WeakArrayList> new_array =
5074 PrototypeUsers::Add(isolate, registry, current_user, &slot);
5075 current_user_info->set_registry_slot(slot);
5076 if (!maybe_registry.is_identical_to(new_array)) {
5077 proto_info->set_prototype_users(*new_array);
5078 }
5079 if (v8_flags.trace_prototype_users) {
5080 PrintF("Registering %p as a user of prototype %p (map=%p).\n",
5081 reinterpret_cast<void*>(current_user->ptr()),
5082 reinterpret_cast<void*>(proto->ptr()),
5083 reinterpret_cast<void*>(proto->map().ptr()));
5084 }
5085
5086 current_user = direct_handle(proto->map(), isolate);
5087 current_user_info = proto_info;
5088 }
5089}
5090
5091// Can be called regardless of whether |user| was actually registered with
5092// |prototype|. Returns true when there was a registration.
5093// static
5095 Isolate* isolate) {
5096 DCHECK(user->is_prototype_map());
5097 // If it doesn't have a PrototypeInfo, it was never registered.
5098 if (!user->has_prototype_info()) return false;
5099 DCHECK(IsPrototypeInfo(user->prototype_info()));
5100 // If it had no prototype before, see if it had users that might expect
5101 // registration.
5102 if (!IsJSObject(user->prototype())) {
5103 Tagged<Object> users =
5104 Cast<PrototypeInfo>(user->prototype_info())->prototype_users();
5105 return IsWeakArrayList(users);
5106 }
5107 DirectHandle<JSObject> prototype(Cast<JSObject>(user->prototype()), isolate);
5108 DirectHandle<PrototypeInfo> user_info =
5109 Map::GetOrCreatePrototypeInfo(user, isolate);
5110 int slot = user_info->registry_slot();
5111 if (slot == MemoryChunk::UNREGISTERED) return false;
5112 DCHECK(prototype->map()->is_prototype_map());
5113 Tagged<Object> maybe_proto_info = prototype->map()->prototype_info();
5114 // User knows its registry slot, prototype info and user registry must exist.
5115 DCHECK(IsPrototypeInfo(maybe_proto_info));
5116 DirectHandle<PrototypeInfo> proto_info(Cast<PrototypeInfo>(maybe_proto_info),
5117 isolate);
5118 DirectHandle<WeakArrayList> prototype_users(
5119 Cast<WeakArrayList>(proto_info->prototype_users()), isolate);
5120 DCHECK_EQ(prototype_users->Get(slot), MakeWeak(*user));
5121 PrototypeUsers::MarkSlotEmpty(*prototype_users, slot);
5122 if (v8_flags.trace_prototype_users) {
5123 PrintF("Unregistering %p as a user of prototype %p.\n",
5124 reinterpret_cast<void*>(user->ptr()),
5125 reinterpret_cast<void*>(prototype->ptr()));
5126 }
5127 return true;
5128}
5129
5130namespace {
5131
5132// This function must be kept in sync with
5133// AccessorAssembler::InvalidateValidityCellIfPrototype() which does pre-checks
5134// before jumping here.
5135void InvalidateOnePrototypeValidityCellInternal(Tagged<Map> map) {
5136 DCHECK(map->is_prototype_map());
5137 if (v8_flags.trace_prototype_users) {
5138 PrintF("Invalidating prototype map %p 's cell\n",
5139 reinterpret_cast<void*>(map.ptr()));
5140 }
5141 Tagged<Object> maybe_cell = map->prototype_validity_cell(kRelaxedLoad);
5142 if (IsCell(maybe_cell)) {
5143 // Just set the value; the cell will be replaced lazily.
5144 Tagged<Cell> cell = Cast<Cell>(maybe_cell);
5146 if (cell->value() != invalid_value) {
5147 cell->set_value(invalid_value);
5148 }
5149 }
5150 Tagged<PrototypeInfo> prototype_info;
5151 if (map->TryGetPrototypeInfo(&prototype_info)) {
5152 prototype_info->set_prototype_chain_enum_cache(Smi::zero());
5153 }
5154
5155 // We may inline accesses to constants stored in dictionary mode prototypes in
5156 // optimized code. When doing so, we install dependencies of group
5157 // |kPrototypeCheckGroup| on each prototype between the receiver's immediate
5158 // prototype and the holder of the constant property. This dependency is used
5159 // both to detect changes to the constant value itself, and other changes to
5160 // the prototype chain that invalidate the access to the given property from
5161 // the given receiver (like adding the property to another prototype between
5162 // the receiver and the (previous) holder). This works by de-opting this group
5163 // whenever the validity cell would be invalidated. However, the actual value
5164 // of the validity cell is not used. Therefore, we always trigger the de-opt
5165 // here, even if the cell was already invalid.
5166 if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL && map->is_dictionary_map()) {
5167 // TODO(11527): pass Isolate as an argument.
5168 Isolate* isolate = GetIsolateFromWritableObject(map);
5171 }
5172}
5173
5174void InvalidatePrototypeChainsInternal(Tagged<Map> map) {
5175 // We handle linear prototype chains by looping, and multiple children
5176 // by recursion, in order to reduce the likelihood of running into stack
5177 // overflows. So, conceptually, the outer loop iterates the depth of the
5178 // prototype tree, and the inner loop iterates the breadth of a node.
5179 Tagged<Map> next_map;
5180 for (; !map.is_null(); map = next_map, next_map = Map()) {
5181 InvalidateOnePrototypeValidityCellInternal(map);
5182
5183 Tagged<PrototypeInfo> proto_info;
5184 if (!map->TryGetPrototypeInfo(&proto_info)) return;
5185 if (!IsWeakArrayList(proto_info->prototype_users())) {
5186 return;
5187 }
5188 Tagged<WeakArrayList> prototype_users =
5189 Cast<WeakArrayList>(proto_info->prototype_users());
5190 // For now, only maps register themselves as users.
5191 for (int i = PrototypeUsers::kFirstIndex; i < prototype_users->length();
5192 ++i) {
5193 Tagged<HeapObject> heap_object;
5194 if (prototype_users->Get(i).GetHeapObjectIfWeak(&heap_object) &&
5195 IsMap(heap_object)) {
5196 // Walk the prototype chain (backwards, towards leaf objects) if
5197 // necessary.
5198 if (next_map.is_null()) {
5199 next_map = Cast<Map>(heap_object);
5200 } else {
5201 InvalidatePrototypeChainsInternal(Cast<Map>(heap_object));
5202 }
5203 }
5204 }
5205 }
5206}
5207
5208} // namespace
5209
5210// static
5213 InvalidatePrototypeChainsInternal(map);
5214 return map;
5215}
5216
5217// We also invalidate global objects validity cell when a new lexical
5218// environment variable is added. This is necessary to ensure that
5219// Load/StoreGlobalIC handlers that load/store from global object's prototype
5220// get properly invalidated.
5221// Note, that the normal Load/StoreICs that load/store through the global object
5222// in the prototype chain are not affected by appearance of a new lexical
5223// variable and therefore we don't propagate invalidation down.
5224// static
5227 InvalidateOnePrototypeValidityCellInternal(global->map());
5228}
5229
5232 DirectHandle<Object> value_obj,
5233 bool from_javascript,
5234 ShouldThrow should_throw) {
5235#ifdef DEBUG
5236 int size = object->Size();
5237#endif
5238
5239 if (from_javascript) {
5240 if (IsAccessCheckNeeded(*object) &&
5241 !isolate->MayAccess(isolate->native_context(), object)) {
5243 isolate, isolate->ReportFailedAccessCheck(object), Nothing<bool>());
5244 UNREACHABLE();
5245 }
5246 } else {
5247 DCHECK(!IsAccessCheckNeeded(*object));
5248 }
5249
5250 // Silently ignore the change if value is not a JSReceiver or null.
5251 // SpiderMonkey behaves this way.
5253 if (!TryCast(value_obj, &value)) return Just(true);
5254
5255 bool all_extensible = object->map()->is_extensible();
5256 DirectHandle<JSObject> real_receiver = object;
5257 if (from_javascript) {
5258 // Find the first object in the chain whose prototype object is not
5259 // hidden.
5260 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
5262 while (!iter.IsAtEnd()) {
5263 // Casting to JSObject is fine because hidden prototypes are never
5264 // JSProxies.
5265 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
5266 iter.Advance();
5267 all_extensible = all_extensible && real_receiver->map()->is_extensible();
5268 }
5269 }
5270 DirectHandle<Map> map(real_receiver->map(), isolate);
5271
5272 // Nothing to do if prototype is already set.
5273 if (map->prototype() == *value) return Just(true);
5274
5275 bool immutable_proto = map->is_immutable_proto();
5276 if (immutable_proto) {
5278 if (IsJSObjectPrototype(*object)) { // is [[Object.prototype]]
5279 msg = isolate->factory()->Object_prototype_string();
5280 } else {
5281 msg = object;
5282 }
5283 RETURN_FAILURE(isolate, should_throw,
5284 NewTypeError(MessageTemplate::kImmutablePrototypeSet, msg));
5285 }
5286
5287 // From 6.1.7.3 Invariants of the Essential Internal Methods
5288 //
5289 // [[SetPrototypeOf]] ( V )
5290 // * ...
5291 // * If target is non-extensible, [[SetPrototypeOf]] must return false,
5292 // unless V is the SameValue as the target's observed [[GetPrototypeOf]]
5293 // value.
5294 if (!all_extensible) {
5295 RETURN_FAILURE(isolate, should_throw,
5296 NewTypeError(MessageTemplate::kNonExtensibleProto, object));
5297 }
5298
5299 // Before we can set the prototype we need to be sure prototype cycles are
5300 // prevented. It is sufficient to validate that the receiver is not in the
5301 // new prototype chain.
5303 for (PrototypeIterator iter(isolate, receiver, kStartAtReceiver);
5304 !iter.IsAtEnd(); iter.Advance()) {
5305 if (iter.GetCurrent<JSReceiver>() == *object) {
5306 // Cycle detected.
5307 RETURN_FAILURE(isolate, should_throw,
5308 NewTypeError(MessageTemplate::kCyclicProto));
5309 }
5310 }
5311 }
5312
5313 // Set the new prototype of the object.
5314
5315 isolate->UpdateProtectorsOnSetPrototype(real_receiver, value);
5316
5317 DirectHandle<Map> new_map =
5318 v8_flags.move_prototype_transitions_first
5319 ? MapUpdater(isolate, map).ApplyPrototypeTransition(value)
5320 : Map::TransitionToUpdatePrototype(isolate, map, value);
5321
5322 DCHECK(new_map->prototype() == *value);
5323 JSObject::MigrateToMap(isolate, real_receiver, new_map);
5324
5325 DCHECK_IMPLIES(!new_map->is_dictionary_map() && !map->is_deprecated() &&
5326 !IsUndefined(new_map->GetBackPointer()),
5327 size == object->Size());
5328 return Just(true);
5329}
5330
5331// static
5333 DirectHandle<JSObject> object) {
5334 DirectHandle<Map> map(object->map(), isolate);
5335
5336 // Nothing to do if prototype is already set.
5337 if (map->is_immutable_proto()) return;
5338
5339 DirectHandle<Map> new_map = Map::TransitionToImmutableProto(isolate, map);
5340 object->set_map(isolate, *new_map, kReleaseStore);
5341}
5342
5345 uint32_t arg_count,
5346 EnsureElementsMode mode) {
5348 object, FullObjectSlot(args->address_of_arg_at(0)), arg_count, mode);
5349}
5350
5352#ifdef ENABLE_SLOW_DCHECKS
5353 if (v8_flags.enable_slow_asserts) {
5354 object->GetElementsAccessor()->Validate(object);
5355 }
5356#endif
5357}
5358
5360 if (!HasFastElements()) return false;
5361 uint32_t capacity = static_cast<uint32_t>(elements()->length());
5362 uint32_t new_capacity;
5363 return ShouldConvertToSlowElements(*this, capacity, index, &new_capacity);
5364}
5365
5367 Tagged<NumberDictionary> dictionary,
5368 uint32_t index,
5369 uint32_t* new_capacity) {
5370 // If properties with non-standard attributes or accessors were added, we
5371 // cannot go back to fast elements.
5372 if (dictionary->requires_slow_elements()) return false;
5373
5374 // Adding a property with this index will require slow elements.
5375 if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
5376
5377 if (IsJSArray(object)) {
5378 Tagged<Object> length = Cast<JSArray>(object)->length();
5379 if (!IsSmi(length)) return false;
5380 *new_capacity = static_cast<uint32_t>(Smi::ToInt(length));
5381 } else if (IsJSArgumentsObject(object)) {
5382 return false;
5383 } else {
5384 *new_capacity = dictionary->max_number_key() + 1;
5385 }
5386 *new_capacity = std::max(index + 1, *new_capacity);
5387
5388 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
5389 NumberDictionary::kEntrySize;
5390
5391 // Turn fast if the dictionary only saves 50% space.
5392 return 2 * dictionary_size >= *new_capacity;
5393}
5394
5396 if (!object->map()->CanHaveFastTransitionableElementsKind()) {
5397 return HOLEY_ELEMENTS;
5398 }
5399 if (object->HasSloppyArgumentsElements()) {
5401 }
5402 if (object->HasStringWrapperElements()) {
5404 }
5405 DCHECK(object->HasDictionaryElements());
5406 Tagged<NumberDictionary> dictionary = object->element_dictionary();
5408 for (InternalIndex i : dictionary->IterateEntries()) {
5409 Tagged<Object> key = dictionary->KeyAt(i);
5410 if (IsNumber(key)) {
5411 Tagged<Object> value = dictionary->ValueAt(i);
5412 if (!IsNumber(value)) return HOLEY_ELEMENTS;
5413 if (!IsSmi(value)) {
5414 if (!v8_flags.unbox_double_arrays) return HOLEY_ELEMENTS;
5416 }
5417 }
5418 }
5419 return kind;
5420}
5421
5422// static
5424 uint32_t index, DirectHandle<Object> value,
5425 PropertyAttributes attributes) {
5426 Isolate* isolate = object->GetIsolate();
5427
5428 DCHECK(object->map(isolate)->is_extensible());
5429
5430 uint32_t old_length = 0;
5431 uint32_t new_capacity = 0;
5432
5433 if (IsJSArray(*object, isolate)) {
5434 CHECK(Object::ToArrayLength(Cast<JSArray>(*object)->length(), &old_length));
5435 }
5436
5437 ElementsKind kind = object->GetElementsKind(isolate);
5438 Tagged<FixedArrayBase> elements = object->elements(isolate);
5439 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
5442 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
5443 } else if (IsStringWrapperElementsKind(kind)) {
5444 dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
5445 }
5446
5447 if (attributes != NONE) {
5448 kind = dictionary_kind;
5449 } else if (IsNumberDictionary(elements, isolate)) {
5451 *object, Cast<NumberDictionary>(elements), index, &new_capacity)
5453 : dictionary_kind;
5454 } else if (ShouldConvertToSlowElements(
5455 *object, static_cast<uint32_t>(elements->length()), index,
5456 &new_capacity)) {
5457 kind = dictionary_kind;
5458 }
5459
5460 ElementsKind to = Object::OptimalElementsKind(*value, isolate);
5461 if (IsHoleyElementsKind(kind) || !IsJSArray(*object, isolate) ||
5462 index > old_length) {
5463 to = GetHoleyElementsKind(to);
5465 }
5468 MAYBE_RETURN(accessor->Add(object, index, value, attributes, new_capacity),
5469 Nothing<bool>());
5470
5471 if (IsJSArray(*object, isolate) && index >= old_length) {
5473 isolate->factory()->NewNumberFromUint(index + 1);
5474 Cast<JSArray>(*object)->set_length(*new_length);
5475 }
5476 return Just(true);
5477}
5478
5479template <AllocationSiteUpdateMode update_or_check>
5481 ElementsKind to_kind) {
5482 if (!IsJSArray(*object)) return false;
5483
5484 if (!HeapLayout::InYoungGeneration(*object)) return false;
5485
5486 if (Heap::IsLargeObject(*object)) return false;
5487
5489 {
5491
5492 Heap* heap = object->GetHeap();
5495 PretenuringHandler::kForRuntime>(heap, object->map(), *object);
5496 if (memento.is_null()) return false;
5497
5498 // Walk through to the Allocation Site
5499 site = direct_handle(memento->GetAllocationSite(), heap->isolate());
5500 }
5502 to_kind);
5503}
5504
5505template bool
5506JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
5507 DirectHandle<JSObject> object, ElementsKind to_kind);
5508
5509template bool JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kUpdate>(
5510 DirectHandle<JSObject> object, ElementsKind to_kind);
5511
5513 ElementsKind to_kind) {
5514 ElementsKind from_kind = object->GetElementsKind();
5515
5516 if (IsHoleyElementsKind(from_kind)) {
5517 to_kind = GetHoleyElementsKind(to_kind);
5518 }
5519
5520 if (from_kind == to_kind) return;
5521
5522 // This method should never be called for any other case.
5523 DCHECK(IsFastElementsKind(from_kind) ||
5524 IsNonextensibleElementsKind(from_kind));
5527
5528 UpdateAllocationSite(object, to_kind);
5529 Isolate* isolate = object->GetIsolate();
5530 if (object->elements() == ReadOnlyRoots(isolate).empty_fixed_array() ||
5531 IsDoubleElementsKind(from_kind) == IsDoubleElementsKind(to_kind)) {
5532 // No change is needed to the elements() buffer, the transition
5533 // only requires a map change.
5534 DirectHandle<Map> new_map = GetElementsTransitionMap(object, to_kind);
5535 JSObject::MigrateToMap(isolate, object, new_map);
5536 if (v8_flags.trace_elements_transitions) {
5537 DirectHandle<FixedArrayBase> elms(object->elements(), isolate);
5538 PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
5539 }
5540 } else {
5541 DCHECK((IsSmiElementsKind(from_kind) && IsDoubleElementsKind(to_kind)) ||
5542 (IsDoubleElementsKind(from_kind) && IsObjectElementsKind(to_kind)));
5543 uint32_t c = static_cast<uint32_t>(object->elements()->length());
5544 if (ElementsAccessor::ForKind(to_kind)
5545 ->GrowCapacityAndConvert(object, c)
5546 .IsNothing()) {
5547 // TODO(victorgomes): Temporarily forcing a fatal error here in case of
5548 // overflow, until all users of TransitionElementsKind can handle
5549 // exceptions.
5550 FATAL(
5551 "Fatal JavaScript invalid size error when transitioning elements "
5552 "kind");
5553 UNREACHABLE();
5554 }
5555 }
5556}
5557
5558template <typename BackingStore>
5560 Tagged<BackingStore> store) {
5561 Isolate* isolate = object->GetIsolate();
5562 int limit = IsJSArray(object) ? Smi::ToInt(Cast<JSArray>(object)->length())
5563 : store->length();
5564 int used = 0;
5565 for (int i = 0; i < limit; ++i) {
5566 if (!store->is_the_hole(isolate, i)) ++used;
5567 }
5568 return used;
5569}
5570
5573 switch (GetElementsKind()) {
5576 case PACKED_ELEMENTS:
5581 return IsJSArray(*this) ? Smi::ToInt(Cast<JSArray>(*this)->length())
5582 : store->length();
5584 store = Cast<SloppyArgumentsElements>(store)->arguments();
5585 [[fallthrough]];
5586 case HOLEY_SMI_ELEMENTS:
5587 case HOLEY_ELEMENTS:
5592 return HoleyElementsUsage(*this, Cast<FixedArray>(store));
5594 if (elements()->length() == 0) return 0;
5595 return HoleyElementsUsage(*this, Cast<FixedDoubleArray>(store));
5596
5601 case NO_ELEMENTS:
5602#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
5603
5606#undef TYPED_ARRAY_CASE
5607 UNREACHABLE();
5608 }
5609 return 0;
5610}
5611
5613 bool* done) {
5615 return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
5616}
5617
5620 DirectHandle<Name> name) {
5621 PropertyKey key(isolate, name);
5623 return HasProperty(&it);
5624}
5625
5628 uint32_t index) {
5629 LookupIterator it(isolate, object, index, object,
5631 return HasProperty(&it);
5632}
5633
5635 Isolate* isolate, DirectHandle<JSObject> object, DirectHandle<Name> name) {
5636 PropertyKey key(isolate, name);
5638 Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
5639 return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
5640 : Nothing<bool>();
5641}
5642
5644 FieldIndex index, Tagged<Object> expected, Tagged<Object> value,
5645 SeqCstAccessTag tag) {
5647 expected, value,
5648 [=, this](Tagged<Object> expected_value, Tagged<Object> new_value) {
5649 return RawFastPropertyAtCompareAndSwapInternal(index, expected_value,
5650 new_value, tag);
5651 });
5652}
5653
5654bool JSGlobalProxy::IsDetached() { return !GetCreationContext().has_value(); }
5655
5657 DirectHandle<Name> name) {
5658 Isolate* isolate = global->GetIsolate();
5659 // Regardless of whether the property is there or not invalidate
5660 // Load/StoreGlobalICs that load/store through global object's prototype.
5662 DCHECK(!global->HasFastProperties());
5663 auto dictionary =
5664 direct_handle(global->global_dictionary(kAcquireLoad), isolate);
5665 InternalIndex entry = dictionary->FindEntry(isolate, name);
5666 if (entry.is_not_found()) return;
5667
5668 DirectHandle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
5669 DirectHandle<Object> value(cell->value(), isolate);
5670 PropertyDetails details = cell->property_details();
5671 details = details.set_cell_type(PropertyCellType::kMutable);
5672 PropertyCell::InvalidateAndReplaceEntry(isolate, dictionary, entry, details,
5673 value);
5674}
5675
5676// static
5679 double tv) {
5682 constructor->GetIsolate(), result,
5683 Cast<JSDate>(JSObject::New(constructor, new_target, {})));
5684 if (DateCache::TryTimeClip(&tv)) {
5685 result->SetValue(tv);
5686 } else {
5687 result->SetNanValue();
5688 }
5689 return result;
5690}
5691
5692// static
5694 if (v8_flags.log_timer_events) LOG(isolate, CurrentTimeEvent());
5695 if (v8_flags.correctness_fuzzer_suppressions) return 4;
5696
5697 // According to ECMA-262, section 15.9.1, page 117, the precision of
5698 // the number in a Date object representing a particular instant in
5699 // time is milliseconds. Therefore, we floor the result of getting
5700 // the OS time.
5702}
5703
5704// static
5706 Address smi_index) {
5707 // Called through CallCFunction.
5709 DisallowHandleAllocation no_handles;
5710 DisallowJavascriptExecution no_js(isolate);
5711
5712 Tagged<Object> object(raw_object);
5713 Tagged<Smi> index(smi_index);
5714 return Cast<JSDate>(object)
5715 ->DoGetField(isolate, static_cast<FieldIndex>(index.value()))
5716 .ptr();
5717}
5718
5720 DateCache* date_cache = isolate->date_cache();
5721
5722 if (index < kFirstUncachedField) {
5723 Tagged<Object> stamp = cache_stamp();
5724 if (stamp != date_cache->stamp() && IsSmi(stamp)) {
5725 // Since the stamp is not NaN, the value is also not NaN.
5726 int64_t local_time_ms =
5727 date_cache->ToLocal(static_cast<int64_t>(value()));
5728 SetCachedFields(local_time_ms, date_cache);
5729 }
5730 switch (index) {
5731 case kYear:
5732 return year();
5733 case kMonth:
5734 return month();
5735 case kDay:
5736 return day();
5737 case kWeekday:
5738 return weekday();
5739 case kHour:
5740 return hour();
5741 case kMinute:
5742 return min();
5743 case kSecond:
5744 return sec();
5745 default:
5746 UNREACHABLE();
5747 }
5748 }
5749
5750 if (index >= kFirstUTCField) {
5751 return GetUTCField(index, value(), date_cache);
5752 }
5753
5754 double time = value();
5755 if (std::isnan(time)) return GetReadOnlyRoots().nan_value();
5756
5757 int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
5758 int days = DateCache::DaysFromTime(local_time_ms);
5759
5760 if (index == kDays) return Smi::FromInt(days);
5761
5762 int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
5763 if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
5764 DCHECK_EQ(index, kTimeInDay);
5765 return Smi::FromInt(time_in_day_ms);
5766}
5767
5769 DateCache* date_cache) {
5770 DCHECK_GE(index, kFirstUTCField);
5771
5772 if (std::isnan(value)) return GetReadOnlyRoots().nan_value();
5773
5774 int64_t time_ms = static_cast<int64_t>(value);
5775
5776 if (index == kTimezoneOffset) {
5777 return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
5778 }
5779
5780 int days = DateCache::DaysFromTime(time_ms);
5781
5782 if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
5783
5784 if (index <= kDayUTC) {
5785 int year, month, day;
5786 date_cache->YearMonthDayFromDays(days, &year, &month, &day);
5787 if (index == kYearUTC) return Smi::FromInt(year);
5788 if (index == kMonthUTC) return Smi::FromInt(month);
5789 DCHECK_EQ(index, kDayUTC);
5790 return Smi::FromInt(day);
5791 }
5792
5793 int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
5794 switch (index) {
5795 case kHourUTC:
5796 return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
5797 case kMinuteUTC:
5798 return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
5799 case kSecondUTC:
5800 return Smi::FromInt((time_in_day_ms / 1000) % 60);
5801 case kMillisecondUTC:
5802 return Smi::FromInt(time_in_day_ms % 1000);
5803 case kDaysUTC:
5804 return Smi::FromInt(days);
5805 case kTimeInDayUTC:
5806 return Smi::FromInt(time_in_day_ms);
5807 default:
5808 UNREACHABLE();
5809 }
5810
5811 UNREACHABLE();
5812}
5813
5814// static
5815void JSDate::SetValue(double value) {
5816#ifdef DEBUG
5817 DCHECK(!std::isnan(value));
5818 double clipped_value = value;
5819 DCHECK(DateCache::TryTimeClip(&clipped_value));
5820 DCHECK_EQ(value, clipped_value);
5821#endif
5822 set_value(value);
5824}
5826 set_value(std::numeric_limits<double>::quiet_NaN());
5827
5828 Tagged<HeapNumber> nan = GetReadOnlyRoots().nan_value();
5829 set_cache_stamp(nan, SKIP_WRITE_BARRIER);
5830 set_year(nan, SKIP_WRITE_BARRIER);
5831 set_month(nan, SKIP_WRITE_BARRIER);
5832 set_day(nan, SKIP_WRITE_BARRIER);
5833 set_hour(nan, SKIP_WRITE_BARRIER);
5834 set_min(nan, SKIP_WRITE_BARRIER);
5835 set_sec(nan, SKIP_WRITE_BARRIER);
5836 set_weekday(nan, SKIP_WRITE_BARRIER);
5837}
5838
5839void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
5840 int days = DateCache::DaysFromTime(local_time_ms);
5841 int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
5842 int year, month, day;
5843 date_cache->YearMonthDayFromDays(days, &year, &month, &day);
5844 int weekday = date_cache->Weekday(days);
5845 int hour = time_in_day_ms / (60 * 60 * 1000);
5846 int min = (time_in_day_ms / (60 * 1000)) % 60;
5847 int sec = (time_in_day_ms / 1000) % 60;
5848 set_cache_stamp(date_cache->stamp());
5849 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
5850 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
5851 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
5852 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
5854 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
5855 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
5856}
5857
5858// static
5860 Isolate* isolate, DirectHandle<JSMessageObject> message) {
5861 DCHECK(!message->DidEnsureSourcePositionsAvailable());
5862 Script::InitLineEnds(isolate, direct_handle(message->script(), isolate));
5863 if (message->shared_info() == Smi::FromInt(-1)) {
5864 message->set_shared_info(Smi::zero());
5865 return;
5866 }
5867 DCHECK(IsSharedFunctionInfo(message->shared_info()));
5868 DCHECK_GE(message->bytecode_offset().value(), kFunctionEntryBytecodeOffset);
5869 Handle<SharedFunctionInfo> shared_info(
5870 Cast<SharedFunctionInfo>(message->shared_info()), isolate);
5871 IsCompiledScope is_compiled_scope;
5873 isolate, shared_info, &is_compiled_scope, CreateSourcePositions::kYes);
5875 DCHECK(shared_info->HasBytecodeArray());
5876 int position = shared_info->abstract_code(isolate)->SourcePosition(
5877 isolate, message->bytecode_offset().value());
5878 DCHECK_GE(position, 0);
5879 message->set_start_position(position);
5880 message->set_end_position(position + 1);
5881 message->set_shared_info(Smi::zero());
5882}
5883
5887 if (start_position() == -1) return Message::kNoLineNumberInfo;
5888
5889 DCHECK(script()->has_line_ends());
5890 DirectHandle<Script> the_script(script(), GetIsolate());
5892 if (!script()->GetPositionInfo(start_position(), &info)) {
5894 }
5895 return info.line + 1;
5896}
5897
5901 if (start_position() == -1) return -1;
5902
5903 DCHECK(script()->has_line_ends());
5904 DirectHandle<Script> the_script(script(), GetIsolate());
5906 if (!script()->GetPositionInfo(start_position(), &info)) {
5907 return -1;
5908 }
5909 return info.column; // Note: No '+1' in contrast to GetLineNumber.
5910}
5911
5914 Tagged<Script> script_object = script();
5915 if (script_object->HasValidSource()) {
5916 Tagged<Object> source = script_object->source();
5917 if (IsString(source)) return Cast<String>(source);
5918 }
5919 return ReadOnlyRoots(GetIsolate()).empty_string();
5920}
5921
5923 Isolate* isolate = GetIsolate();
5924
5925#if V8_ENABLE_WEBASSEMBLY
5926 if (script()->type() == Script::Type::kWasm) {
5927 return isolate->factory()->empty_string();
5928 }
5929#endif // V8_ENABLE_WEBASSEMBLY
5931 {
5934 DCHECK(script()->has_line_ends());
5935 if (!script()->GetPositionInfo(start_position(), &info)) {
5936 return isolate->factory()->empty_string();
5937 }
5938 }
5939
5940 Handle<String> src(Cast<String>(script()->source()), isolate);
5941 return isolate->factory()->NewSubString(src, info.line_start, info.line_end);
5942}
5943
5944} // namespace v8::internal
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)
Builtins::Kind kind
Definition builtins.cc:40
PropertyT * getter
V8_INLINE bool IsJust() const
Definition v8-maybe.h:36
V8_INLINE T FromJust() const &
Definition v8-maybe.h:64
V8_INLINE bool IsNothing() const
Definition v8-maybe.h:35
static const int kNoLineNumberInfo
Definition v8-message.h:198
virtual int64_t CurrentClockTimeMilliseconds()
static V8_INLINE bool ApiCheck(bool condition, const char *location, const char *message)
Definition api.h:214
static constexpr U kMax
Definition bit-field.h:44
static constexpr bool is_valid(T value)
Definition bit-field.h:50
static Handle< JSAny > GetComponent(Isolate *isolate, DirectHandle< NativeContext > native_context, DirectHandle< AccessorPair > accessor_pair, AccessorComponent component)
Definition objects.cc:4015
static bool DigestTransitionFeedback(DirectHandle< AllocationSite > site, ElementsKind to_kind)
static V8_WARN_UNUSED_RESULT Maybe< bool > DefineOwnProperty(Isolate *isolate, DirectHandle< AlwaysSharedSpaceJSObject > shared_obj, DirectHandle< Object > key, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
Definition js-struct.cc:63
static V8_WARN_UNUSED_RESULT MaybeHandle< JSFunction > InstantiateFunction(Isolate *isolate, DirectHandle< NativeContext > native_context, DirectHandle< FunctionTemplateInfo > data, MaybeDirectHandle< Name > maybe_name={})
static int TimeInDay(int64_t time_ms, int days)
Definition date.h:62
void YearMonthDayFromDays(int days, int *year, int *month, int *day)
Definition date.cc:77
static const int kInvalidStamp
Definition date.h:41
int64_t ToLocal(int64_t time_ms)
Definition date.h:114
static bool TryTimeClip(double *time)
Definition date.h:70
int Weekday(int days)
Definition date.h:82
static int DaysFromTime(int64_t time_ms)
Definition date.h:55
Tagged< Smi > stamp()
Definition date.h:170
int TimezoneOffset(int64_t time_ms)
Definition date.h:107
static void DeoptimizeDependencyGroups(Isolate *isolate, ObjectT object, DependencyGroups groups)
static V8_EXPORT_PRIVATE Handle< DescriptorArray > Allocate(IsolateT *isolate, int nof_descriptors, int slack, AllocationType allocation=AllocationType::kYoung)
static Descriptor DataField(Isolate *isolate, DirectHandle< Name > key, int field_index, PropertyAttributes attributes, Representation representation)
Definition property.cc:81
static Descriptor AccessorConstant(DirectHandle< Name > key, DirectHandle< Object > foreign, PropertyAttributes attributes)
Definition property.cc:118
V8_INLINE bool is_null() const
Definition handles.h:693
V8_INLINE void SetValue(Tagged< T > new_value)
Definition handles.h:707
static ElementsAccessor * ForKind(ElementsKind elements_kind)
Definition elements.h:29
virtual V8_WARN_UNUSED_RESULT Maybe< bool > Add(DirectHandle< JSObject > object, uint32_t index, DirectHandle< Object > value, PropertyAttributes attributes, uint32_t new_capacity)=0
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > Call(Isolate *isolate, DirectHandle< Object > callable, DirectHandle< Object > receiver, base::Vector< const DirectHandle< Object > > args)
Definition execution.cc:523
Isolate * isolate() const
Definition factory.h:1281
DirectHandle< PropertyArray > NewPropertyArray(int length, AllocationType allocation=AllocationType::kYoung)
Definition factory.cc:413
static FieldIndex ForPropertyIndex(Tagged< Map > map, int index, Representation representation=Representation::Tagged())
static FieldIndex ForDetails(Tagged< Map > map, PropertyDetails details)
static V8_EXPORT_PRIVATE Tagged< FieldType > Any()
Definition field-type.cc:22
static constexpr int kMaxLength
static HandleType< FixedArray > RightTrimOrEmpty(Isolate *isolate, HandleType< FixedArray > array, int new_length)
V8_INLINE bool is_identical_to(const HandleBase &that) const
Definition handles-inl.h:36
static V8_INLINE bool InYoungGeneration(Tagged< Object > object)
static Tagged< Object > SeqCst_CompareAndSwapField(Tagged< Object > expected_value, Tagged< Object > new_value, CompareAndSwapImpl compare_and_swap_impl)
Bootstrapper * bootstrapper()
Definition isolate.h:1178
static V8_WARN_UNUSED_RESULT Maybe< bool > DefineOwnProperty(Isolate *isolate, DirectHandle< JSArray > o, DirectHandle< Object > name, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
Definition objects.cc:3120
static int64_t CurrentTimeValue(Isolate *isolate)
static Address GetField(Isolate *isolate, Address raw_date, Address smi_index)
Tagged< Object > GetUTCField(FieldIndex index, double value, DateCache *date_cache)
void SetValue(double v)
Tagged< Object > DoGetField(Isolate *isolate, FieldIndex index)
void SetCachedFields(int64_t local_time_ms, DateCache *date_cache)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSDate > New(DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target, double tv)
static V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT MaybeHandle< Map > GetDerivedMap(Isolate *isolate, DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target)
static int GetHeaderSize(bool function_has_prototype_slot)
static void InvalidatePropertyCell(DirectHandle< JSGlobalObject > object, DirectHandle< Name > name)
V8_EXPORT_PRIVATE bool IsDetached()
bool DidEnsureSourcePositionsAvailable() const
MessageTemplate type() const
DirectHandle< String > GetSourceLine() const
V8_EXPORT_PRIVATE Tagged< String > GetSource() const
V8_EXPORT_PRIVATE int GetLineNumber() const
static void V8_PRESERVE_MOST V8_EXPORT_PRIVATE InitializeSourcePositions(Isolate *isolate, DirectHandle< JSMessageObject > message)
V8_EXPORT_PRIVATE int GetColumnNumber() const
static V8_WARN_UNUSED_RESULT Maybe< bool > DefineOwnProperty(Isolate *isolate, DirectHandle< JSModuleNamespace > o, DirectHandle< Object > key, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
Definition module.cc:453
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributes(LookupIterator *it)
Definition module.cc:428
static bool UnregisterPrototypeUser(DirectHandle< Map > user, Isolate *isolate)
static V8_EXPORT_PRIVATE DirectHandle< NumberDictionary > NormalizeElements(DirectHandle< JSObject > object)
static bool IsExtensible(Isolate *isolate, DirectHandle< JSObject > object)
Tagged< Object > RawFastPropertyAtCompareAndSwapInternal(FieldIndex index, Tagged< Object > expected, Tagged< Object > value, SeqCstAccessTag tag)
static V8_WARN_UNUSED_RESULT Maybe< bool > PreventExtensionsWithTransition(Isolate *isolate, DirectHandle< JSObject > object, ShouldThrow should_throw)
static V8_WARN_UNUSED_RESULT MaybeHandle< JSAny > GetPropertyWithInterceptor(LookupIterator *it, bool *done)
static void InvalidatePrototypeValidityCell(Tagged< JSGlobalObject > global)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType DefineOwnPropertyIgnoreAttributes(LookupIterator *it, HandleType< T > value, PropertyAttributes attributes, AccessorInfoHandling handling=DONT_FORCE_FIELD, EnforceDefineSemantics semantics=EnforceDefineSemantics::kSet)
void RequireSlowElements(Tagged< NumberDictionary > dictionary)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > DefinePropertyOrElementIgnoreAttributes(DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes=NONE)
static void SetNormalizedElement(DirectHandle< JSObject > object, uint32_t index, DirectHandle< Object > value, PropertyDetails details)
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static V8_EXPORT_PRIVATE void MigrateSlowToFast(DirectHandle< JSObject > object, int unused_property_fields, const char *reason)
static void OptimizeAsPrototype(DirectHandle< JSObject > object, bool enable_setup_mode=true)
static V8_WARN_UNUSED_RESULT Maybe< InterceptorResult > SetPropertyWithInterceptor(LookupIterator *it, Maybe< ShouldThrow > should_throw, DirectHandle< Object > value)
static Handle< JSAny > FastPropertyAt(Isolate *isolate, DirectHandle< JSObject > object, Representation representation, FieldIndex index)
static void ApplyAttributesToDictionary(Isolate *isolate, ReadOnlyRoots roots, DirectHandle< Dictionary > dictionary, const PropertyAttributes attributes)
void JSObjectShortPrint(StringStream *accumulator)
static MaybeDirectHandle< JSObject > NewWithMap(Isolate *isolate, DirectHandle< Map > initial_map, DirectHandle< AllocationSite > site, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
Tagged< JSAny > RawFastPropertyAt(FieldIndex index) const
static void LazyRegisterPrototypeUser(DirectHandle< Map > user, Isolate *isolate)
static void ValidateElements(Tagged< JSObject > object)
static V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT MaybeHandle< JSObject > New(DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target, DirectHandle< AllocationSite > site, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributesWithInterceptor(LookupIterator *it)
static void ForceSetPrototype(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< JSPrototype > proto)
static Handle< Object > DictionaryPropertyAt(Isolate *isolate, DirectHandle< JSObject > object, InternalIndex dict_index)
static V8_WARN_UNUSED_RESULT Maybe< bool > TestIntegrityLevel(Isolate *isolate, DirectHandle< JSObject > object, IntegrityLevel lvl)
static void EnsureCanContainElements(DirectHandle< JSObject > object, TSlot elements, uint32_t count, EnsureElementsMode mode)
static void UpdatePrototypeUserRegistration(DirectHandle< Map > old_map, DirectHandle< Map > new_map, Isolate *isolate)
static Tagged< Map > InvalidatePrototypeChains(Tagged< Map > map)
static V8_WARN_UNUSED_RESULT Maybe< bool > HasRealNamedCallbackProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name)
static void SetImmutableProto(Isolate *isolate, DirectHandle< JSObject > object)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > V8_EXPORT_PRIVATE SetOwnPropertyIgnoreAttributes(DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static V8_WARN_UNUSED_RESULT Maybe< bool > SetPrototype(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Object > value, bool from_javascript, ShouldThrow should_throw)
Tagged< FixedArrayBase > elements(PtrComprCageBase cage_base, AcquireLoadTag tag) const =delete
static V8_WARN_UNUSED_RESULT Maybe< bool > HasRealElementProperty(Isolate *isolate, DirectHandle< JSObject > object, uint32_t index)
static void SetNormalizedProperty(DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyDetails details)
static void NotifyMapChange(DirectHandle< Map > old_map, DirectHandle< Map > new_map, Isolate *isolate)
static V8_EXPORT_PRIVATE void NormalizeProperties(Isolate *isolate, DirectHandle< JSObject > object, PropertyNormalizationMode mode, int expected_additional_properties, bool use_cache, const char *reason)
static V8_WARN_UNUSED_RESULT Maybe< bool > CheckIfCanDefineAsConfigurable(Isolate *isolate, LookupIterator *it, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
static V8_EXPORT_PRIVATE Maybe< bool > AddDataElement(DirectHandle< JSObject > receiver, uint32_t index, DirectHandle< Object > value, PropertyAttributes attributes)
static void PrototypeRegistryCompactionCallback(Tagged< HeapObject > value, int old_index, int new_index)
Tagged< Object > RawFastPropertyAtCompareAndSwap(FieldIndex index, Tagged< Object > expected, Tagged< Object > value, SeqCstAccessTag tag)
static void MakePrototypesFast(DirectHandle< Object > receiver, WhereToStart where_to_start, Isolate *isolate)
static V8_EXPORT_PRIVATE void TransitionElementsKind(DirectHandle< JSObject > object, ElementsKind to_kind)
static void PrintElementsTransition(FILE *file, DirectHandle< JSObject > object, ElementsKind from_kind, DirectHandle< FixedArrayBase > from_elements, ElementsKind to_kind, DirectHandle< FixedArrayBase > to_elements)
static V8_EXPORT_PRIVATE MaybeDirectHandle< Object > DefineOwnAccessorIgnoreAttributes(DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > getter, DirectHandle< Object > setter, PropertyAttributes attributes)
static V8_EXPORT_PRIVATE void MigrateToMap(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Map > new_map, int expected_additional_properties=0)
bool WouldConvertToSlowElements(uint32_t index)
static V8_WARN_UNUSED_RESULT MaybeHandle< JSAny > GetPropertyWithFailedAccessCheck(LookupIterator *it)
static bool IsUnmodifiedApiObject(FullObjectSlot o)
static DirectHandle< Map > GetElementsTransitionMap(DirectHandle< JSObject > object, ElementsKind to_kind)
Tagged< Object > SlowReverseLookup(Tagged< Object > value)
static V8_WARN_UNUSED_RESULT Maybe< InterceptorResult > DeletePropertyWithInterceptor(LookupIterator *it, ShouldThrow should_throw)
static MaybeDirectHandle< Object > ReadFromOptionsBag(DirectHandle< Object > options, DirectHandle< String > option_name, Isolate *isolate)
static V8_WARN_UNUSED_RESULT Maybe< bool > SetPropertyWithFailedAccessCheck(LookupIterator *it, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
static void MigrateInstance(Isolate *isolate, DirectHandle< JSObject > instance)
static bool UpdateAllocationSite(DirectHandle< JSObject > object, ElementsKind to_kind)
static bool TryMigrateInstance(Isolate *isolate, DirectHandle< JSObject > instance)
bool IsDroppableApiObject() const
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > SetAccessor(DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< AccessorInfo > info, PropertyAttributes attributes)
static void AllocateStorageForMap(DirectHandle< JSObject > object, DirectHandle< Map > map)
void PrintInstanceMigration(FILE *file, Tagged< Map > original_map, Tagged< Map > new_map)
static V8_WARN_UNUSED_RESULT Maybe< bool > HasRealNamedProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSObject > ObjectCreate(Isolate *isolate, DirectHandle< JSPrototype > prototype)
static V8_WARN_UNUSED_RESULT Maybe< bool > CreateDataProperty(Isolate *isolate, DirectHandle< JSObject > object, PropertyKey key, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw=Just(kDontThrow))
static V8_WARN_UNUSED_RESULT Maybe< bool > PreventExtensions(Isolate *isolate, DirectHandle< JSObject > object, ShouldThrow should_throw)
static void ReoptimizeIfPrototype(DirectHandle< JSObject > object)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > SetOwnElementIgnoreAttributes(DirectHandle< JSObject > object, size_t index, DirectHandle< Object > value, PropertyAttributes attributes)
static void EnsureWritableFastElements(DirectHandle< JSObject > object)
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributesWithFailedAccessCheck(LookupIterator *it)
static V8_EXPORT_PRIVATE int GetHeaderSize(InstanceType instance_type, bool function_has_prototype_slot=false)
static V8_WARN_UNUSED_RESULT Maybe< bool > HasProperty(Isolate *isolate, DirectHandle< JSProxy > proxy, DirectHandle< Name > name)
Definition objects.cc:2885
static Maybe< bool > SetPrivateSymbol(Isolate *isolate, DirectHandle< JSProxy > proxy, DirectHandle< Symbol > private_name, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
Definition objects.cc:3443
static V8_WARN_UNUSED_RESULT Maybe< bool > GetOwnPropertyDescriptor(Isolate *isolate, DirectHandle< JSProxy > proxy, DirectHandle< Name > name, PropertyDescriptor *desc)
Definition objects.cc:3490
static V8_WARN_UNUSED_RESULT Maybe< bool > SetPrototype(Isolate *isolate, DirectHandle< JSProxy > proxy, DirectHandle< Object > value, bool from_javascript, ShouldThrow should_throw)
Definition objects.cc:4822
static V8_WARN_UNUSED_RESULT Maybe< bool > IsExtensible(DirectHandle< JSProxy > proxy)
Definition objects.cc:3663
static V8_WARN_UNUSED_RESULT Maybe< bool > DeletePropertyOrElement(DirectHandle< JSProxy > proxy, DirectHandle< Name > name, LanguageMode language_mode)
Definition objects.cc:3010
static V8_WARN_UNUSED_RESULT Maybe< bool > PreventExtensions(DirectHandle< JSProxy > proxy, ShouldThrow should_throw)
Definition objects.cc:3617
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributes(LookupIterator *it)
Definition objects.cc:3096
static V8_WARN_UNUSED_RESULT Maybe< bool > DefineOwnProperty(Isolate *isolate, DirectHandle< JSProxy > object, DirectHandle< Object > key, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
Definition objects.cc:3317
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > GetOwnPropertyDescriptor(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Object > key, PropertyDescriptor *desc)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > DeletePropertyOrElement(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name, LanguageMode language_mode=LanguageMode::kSloppy)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > SetPrototype(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Object > value, bool from_javascript, ShouldThrow should_throw)
bool HasProxyInPrototype(Isolate *isolate)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< FixedArray > OwnPropertyKeys(Isolate *isolate, DirectHandle< JSReceiver > object)
static V8_WARN_UNUSED_RESULT Maybe< bool > OrdinaryDefineOwnProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Object > key, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetOwnPropertyAttributes(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name)
static Tagged< Smi > CreateIdentityHash(Isolate *isolate, Tagged< JSReceiver > key)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > DeleteProperty(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name, LanguageMode language_mode=LanguageMode::kSloppy)
static V8_WARN_UNUSED_RESULT Maybe< bool > TestIntegrityLevel(Isolate *isolate, DirectHandle< JSReceiver > object, IntegrityLevel lvl)
static V8_WARN_UNUSED_RESULT Maybe< bool > SetIntegrityLevel(Isolate *isolate, DirectHandle< JSReceiver > object, IntegrityLevel lvl, ShouldThrow should_throw)
V8_EXPORT_PRIVATE Tagged< String > class_name()
static MaybeDirectHandle< NativeContext > GetFunctionRealm(DirectHandle< JSReceiver > receiver)
static V8_WARN_UNUSED_RESULT Maybe< bool > ValidateAndApplyPropertyDescriptor(Isolate *isolate, LookupIterator *it, bool extensible, PropertyDescriptor *desc, PropertyDescriptor *current, Maybe< ShouldThrow > should_throw, DirectHandle< Name > property_name)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > HasOwnProperty(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name)
bool IsCodeLike(Isolate *isolate) const
V8_EXPORT_PRIVATE Tagged< Object > GetIdentityHash()
static V8_WARN_UNUSED_RESULT Maybe< bool > PreventExtensions(Isolate *isolate, DirectHandle< JSReceiver > object, ShouldThrow should_throw)
static V8_WARN_UNUSED_RESULT Maybe< bool > HasInPrototypeChain(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Object > proto)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType ToPrimitive(Isolate *isolate, HandleType< JSReceiver > receiver, ToPrimitiveHint hint=ToPrimitiveHint::kDefault)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< FixedArray > GetOwnValues(Isolate *isolate, DirectHandle< JSReceiver > object, PropertyFilter filter, bool try_fast_path=true)
static V8_WARN_UNUSED_RESULT Maybe< bool > DeleteElement(Isolate *isolate, DirectHandle< JSReceiver > object, uint32_t index, LanguageMode language_mode=LanguageMode::kSloppy)
static V8_WARN_UNUSED_RESULT Maybe< bool > CreateDataProperty(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > key, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
static V8_WARN_UNUSED_RESULT Tagged< Object > DefineProperty(Isolate *isolate, DirectHandle< Object > object, DirectHandle< Object > name, Handle< Object > attributes)
static Handle< Object > GetDataProperty(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name)
static V8_WARN_UNUSED_RESULT Maybe< bool > IsExtensible(Isolate *isolate, DirectHandle< JSReceiver > object)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType OrdinaryToPrimitive(Isolate *isolate, DirectHandle< JSReceiver > receiver, OrdinaryToPrimitiveHint hint)
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributes(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name)
static V8_WARN_UNUSED_RESULT Maybe< bool > IsCompatiblePropertyDescriptor(Isolate *isolate, bool extensible, PropertyDescriptor *desc, PropertyDescriptor *current, DirectHandle< Name > property_name, Maybe< ShouldThrow > should_throw)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(Isolate *isolate, DirectHandle< JSReceiver > receiver, const char *key)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< FixedArray > GetOwnEntries(Isolate *isolate, DirectHandle< JSReceiver > object, PropertyFilter filter, bool try_fast_path=true)
static MaybeDirectHandle< JSFunction > GetConstructor(Isolate *isolate, DirectHandle< JSReceiver > receiver)
static V8_WARN_UNUSED_RESULT Maybe< bool > DefineOwnProperty(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Object > key, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
static void DeleteNormalizedProperty(DirectHandle< JSReceiver > object, InternalIndex entry)
static DirectHandle< String > GetConstructorName(Isolate *isolate, DirectHandle< JSReceiver > receiver)
static V8_WARN_UNUSED_RESULT Maybe< bool > CheckPrivateNameStore(LookupIterator *it, bool is_define)
static V8_WARN_UNUSED_RESULT Maybe< bool > SetOrCopyDataProperties(Isolate *isolate, DirectHandle< JSReceiver > target, DirectHandle< Object > source, PropertiesEnumerationMode mode, base::Vector< DirectHandle< Object > > excluded_properties={}, bool use_set=true)
static V8_EXPORT_PRIVATE MaybeHandle< NativeContext > GetContextForMicrotask(DirectHandle< JSReceiver > receiver)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > HasProperty(LookupIterator *it)
Definition js-objects.cc:98
V8_EXPORT_PRIVATE void SetIdentityHash(int masked_hash)
V8_EXPORT_PRIVATE Tagged< Smi > GetOrCreateIdentityHash(Isolate *isolate)
static V8_WARN_UNUSED_RESULT Maybe< bool > AddPrivateField(LookupIterator *it, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
V8_EXPORT_PRIVATE std::optional< Tagged< NativeContext > > GetCreationContext()
NEVER_READ_ONLY_SPACE void SetProperties(Tagged< HeapObject > properties)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > DefineProperties(Isolate *isolate, DirectHandle< Object > object, DirectHandle< Object > properties)
static V8_WARN_UNUSED_RESULT Maybe< bool > DefineOwnProperty(Isolate *isolate, DirectHandle< JSTypedArray > o, DirectHandle< Object > key, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
static void PrintTop(Isolate *isolate, FILE *file, bool print_args, bool print_line_number)
Definition frames.cc:2562
static MaybeHandle< FixedArray > GetKeys(Isolate *isolate, DirectHandle< JSReceiver > object, KeyCollectionMode mode, PropertyFilter filter, GetKeysConversion keys_conversion=GetKeysConversion::kKeepNumbers, bool is_for_in=false, bool skip_indices=false)
Definition keys.cc:97
DirectHandle< Map > ReconfigureElementsKind(ElementsKind elements_kind)
Handle< Map > ApplyPrototypeTransition(DirectHandle< JSPrototype > prototype)
static bool IsPrototypeChainInvalidated(Tagged< Map > map)
Definition map.cc:2456
static DirectHandle< PrototypeInfo > GetOrCreatePrototypeInfo(DirectHandle< Map > prototype_map, Isolate *isolate)
Definition map.cc:2377
static V8_EXPORT_PRIVATE Handle< Map > TransitionToUpdatePrototype(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype)
Definition map.cc:2506
static DirectHandle< Map > GetObjectCreateMap(Isolate *isolate, DirectHandle< JSPrototype > prototype)
Definition map.cc:903
static Handle< Map > CopyDropDescriptors(Isolate *isolate, DirectHandle< Map > map)
Definition map.cc:1480
static void SetShouldBeFastPrototypeMap(DirectHandle< Map > map, bool value, Isolate *isolate)
Definition map.cc:2408
static Handle< Map > Copy(Isolate *isolate, DirectHandle< Map > map, const char *reason, TransitionKindFlag kind=SPECIAL_TRANSITION)
Definition map.cc:1811
static V8_EXPORT_PRIVATE MaybeHandle< Map > TryUpdate(Isolate *isolate, Handle< Map > map) V8_WARN_UNUSED_RESULT
Definition map.cc:751
static V8_EXPORT_PRIVATE DirectHandle< Map > PrepareForDataProperty(Isolate *isolate, DirectHandle< Map > old_map, InternalIndex descriptor_number, PropertyConstness constness, DirectHandle< Object > value)
Definition map.cc:1975
static constexpr int kPrototypeChainInvalid
Definition map.h:518
static V8_EXPORT_PRIVATE void SetPrototype(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype, bool enable_prototype_setup_mode=true)
Definition map.cc:2467
static V8_EXPORT_PRIVATE Handle< Map > Normalize(Isolate *isolate, DirectHandle< Map > map, ElementsKind new_elements_kind, DirectHandle< JSPrototype > new_prototype, PropertyNormalizationMode mode, bool use_cache, const char *reason)
Definition map.cc:1282
static V8_EXPORT_PRIVATE DirectHandle< Map > Update(Isolate *isolate, DirectHandle< Map > map)
Definition map.cc:839
static V8_EXPORT_PRIVATE Handle< Map > CopyForPreventExtensions(Isolate *isolate, DirectHandle< Map > map, PropertyAttributes attrs_to_add, DirectHandle< Symbol > transition_marker, const char *reason, bool old_map_is_dictionary_elements_kind=false)
Definition map.cc:1852
static DirectHandle< Map > TransitionElementsTo(Isolate *isolate, DirectHandle< Map > map, ElementsKind to_kind)
Definition map.cc:1068
static DirectHandle< Map > TransitionToImmutableProto(Isolate *isolate, DirectHandle< Map > map)
Definition map.cc:1413
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
static const int kInitialCapacity
Definition dictionary.h:250
static V8_WARN_UNUSED_RESULT HandleType< NumberDictionary > Set(Isolate *isolate, HandleType< NumberDictionary > dictionary, uint32_t key, DirectHandle< Object > value, DirectHandle< JSObject > dictionary_holder=DirectHandle< JSObject >::null(), PropertyDetails details=PropertyDetails::Empty())
static V8_WARN_UNUSED_RESULT Maybe< bool > RedefineIncompatibleProperty(Isolate *isolate, DirectHandle< Object > name, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
Definition objects.cc:2597
static bool ToArrayLength(Tagged< Object > obj, uint32_t *index)
static V8_EXPORT_PRIVATE Handle< UnionOf< JSAny, Hole > > NewStorageFor(Isolate *isolate, Handle< UnionOf< JSAny, Hole > > object, Representation representation)
Definition objects.cc:240
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > AddDataProperty(LookupIterator *it, DirectHandle< Object > value, PropertyAttributes attributes, Maybe< ShouldThrow > should_throw, StoreOrigin store_origin, EnforceDefineSemantics semantics=EnforceDefineSemantics::kSet)
Definition objects.cc:2667
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > SetProperty(LookupIterator *it, DirectHandle< Object > value, StoreOrigin store_origin, Maybe< ShouldThrow > should_throw=Nothing< ShouldThrow >())
Definition objects.cc:2439
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetPropertyOrElement(Isolate *isolate, DirectHandle< JSAny > object, DirectHandle< Name > name)
static ElementsKind OptimalElementsKind(Tagged< Object > obj, PtrComprCageBase cage_base)
static V8_WARN_UNUSED_RESULT HandleType< JSReceiver >::MaybeType ToObject(Isolate *isolate, HandleType< T > object, const char *method_name=nullptr)
static bool FilterKey(Tagged< Object > obj, PropertyFilter filter)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType ToPropertyKey(Isolate *isolate, HandleType< T > value)
static double NumberValue(Tagged< Number > obj)
static V8_WARN_UNUSED_RESULT Maybe< bool > SetPropertyWithAccessor(LookupIterator *it, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
Definition objects.cc:1578
static V8_WARN_UNUSED_RESULT Maybe< bool > TransitionAndWriteDataProperty(LookupIterator *it, DirectHandle< Object > value, PropertyAttributes attributes, Maybe< ShouldThrow > should_throw, StoreOrigin store_origin)
Definition objects.cc:2737
static Handle< JSAny > WrapForRead(IsolateT *isolate, Handle< JSAny > object, Representation representation)
Definition objects.cc:257
static V8_EXPORT_PRIVATE bool SameValue(Tagged< Object > obj, Tagged< Object > other)
Definition objects.cc:1706
static V8_EXPORT_PRIVATE bool ToInt32(Tagged< Object > obj, int32_t *value)
Definition objects.cc:1438
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSReceiver > ConvertReceiver(Isolate *isolate, DirectHandle< Object > object)
Definition objects.cc:305
static V8_WARN_UNUSED_RESULT Maybe< bool > CannotCreateProperty(Isolate *isolate, DirectHandle< JSAny > receiver, DirectHandle< Object > name, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
Definition objects.cc:2559
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > GetMethod(Isolate *isolate, DirectHandle< JSReceiver > receiver, DirectHandle< Name > name)
Definition objects.cc:1125
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it, bool is_global_reference=false)
Definition objects.cc:1248
static V8_WARN_UNUSED_RESULT Maybe< bool > SetDataProperty(LookupIterator *it, DirectHandle< Object > value)
Definition objects.cc:2604
static Tagged< AllocationMemento > FindAllocationMemento(Heap *heap, Tagged< Map > map, Tagged< HeapObject > object)
static const int kNoHashSentinel
static Handle< PropertyCell > PrepareForAndSetValue(Isolate *isolate, DirectHandle< GlobalDictionary > dictionary, InternalIndex entry, DirectHandle< Object > value, PropertyDetails details)
Definition objects.cc:6473
static Handle< PropertyCell > InvalidateAndReplaceEntry(Isolate *isolate, DirectHandle< GlobalDictionary > dictionary, InternalIndex entry, PropertyDetails new_details, DirectHandle< Object > new_value)
Definition objects.cc:6408
void set_value(DirectHandle< JSAny > value)
void set_configurable(bool configurable)
static bool IsAccessorDescriptor(PropertyDescriptor *desc)
static bool IsGenericDescriptor(PropertyDescriptor *desc)
static bool ToPropertyDescriptor(Isolate *isolate, Handle< JSAny > obj, PropertyDescriptor *desc)
static bool IsDataDescriptor(PropertyDescriptor *desc)
PropertyAttributes attributes() const
PropertyDetails CopyWithConstness(PropertyConstness constness) const
PropertyLocation location() const
Representation representation() const
PropertyDetails set_index(int index) const
static constexpr PropertyDetails Empty(PropertyCellType cell_type=PropertyCellType::kNoCell)
PropertyConstness constness() const
PropertyDetails CopyAddAttributes(PropertyAttributes new_attributes) const
PropertyDetails set_cell_type(PropertyCellType type) const
V8_WARN_UNUSED_RESULT bool AdvanceFollowingProxies()
Tagged< T > GetCurrent() const
Definition prototype.h:52
static Handle< WeakArrayList > Add(Isolate *isolate, Handle< WeakArrayList > array, DirectHandle< Map > value, int *assigned_index)
Definition objects.cc:3775
static void MarkSlotEmpty(Tagged< WeakArrayList > array, int index)
const char * Mnemonic() const
bool Equals(const Representation &other) const
static constexpr Representation Tagged()
constexpr bool IsDouble() const
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > SetObjectProperty(Isolate *isolate, DirectHandle< JSAny > object, DirectHandle< Object > key, DirectHandle< Object > value, MaybeDirectHandle< JSAny > receiver, StoreOrigin store_origin, Maybe< ShouldThrow > should_throw=Nothing< ShouldThrow >())
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > GetObjectProperty(Isolate *isolate, DirectHandle< JSAny > lookup_start_object, DirectHandle< Object > key, DirectHandle< JSAny > receiver={}, bool *is_found=nullptr)
static void InitLineEnds(Isolate *isolate, DirectHandle< Script > script)
Definition script-inl.h:201
static void EnsureSourcePositionsAvailable(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared_info)
static void EnsureBytecodeArrayAvailable(Isolate *isolate, Handle< SharedFunctionInfo > shared_info, IsCompiledScope *is_compiled_scope, CreateSourcePositions flag=CreateSourcePositions::kNo)
static Handle< String > DebugName(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
static constexpr int ToInt(const Tagged< Object > object)
Definition smi.h:33
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static constexpr Tagged< Smi > zero()
Definition smi.h:99
static constexpr int kMaxValue
Definition smi.h:101
void Add(const char *format)
static bool IsKey(ReadOnlyRoots roots, Tagged< Object > key_candidate)
static HandleType< SwissNameDictionary > Add(IsolateT *isolate, HandleType< SwissNameDictionary > table, DirectHandle< Name > key, DirectHandle< Object > value, PropertyDetails details, InternalIndex *entry_out=nullptr)
static HandleType< SwissNameDictionary > DeleteEntry(Isolate *isolate, HandleType< SwissNameDictionary > table, InternalIndex entry)
V8_INLINE constexpr StorageType ptr() const
V8_INLINE constexpr bool is_null() const
Definition tagged.h:502
static ThreadId Current()
Definition thread-id.h:32
static bool CanHaveMoreTransitions(Isolate *isolate, DirectHandle< Map > map)
Tagged< Map > SearchTransition(Tagged< Name > name, PropertyKind kind, PropertyAttributes attributes)
Tagged< Map > SearchSpecial(Tagged< Symbol > name)
static V8_EXPORT_PRIVATE v8::Platform * GetCurrentPlatform()
Definition v8.cc:282
#define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
Definition globals.h:242
#define V8_DICT_PROPERTY_CONST_TRACKING_BOOL
Definition globals.h:249
Handle< SharedFunctionInfo > info
LineAndColumn current
#define RAB_GSAB_TYPED_ARRAYS(V)
#define TYPED_ARRAYS(V)
#define RETURN_ON_EXCEPTION(isolate, call)
Definition isolate.h:395
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:284
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:291
#define RETURN_FAILURE(isolate, should_throw, call)
Definition isolate.h:398
#define THROW_NEW_ERROR(isolate, call)
Definition isolate.h:307
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
Definition isolate.h:276
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition isolate.h:294
#define MAYBE_RETURN_NULL(call)
Definition isolate.h:413
#define MAYBE_RETURN(call, value)
Definition isolate.h:408
#define RETURN_ON_EXCEPTION_VALUE(isolate, call, value)
Definition isolate.h:340
#define RETURN_VALUE_IF_EXCEPTION_DETECTOR(isolate, detector, value)
Definition isolate.h:232
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
DirectHandle< Object > new_target
Definition execution.cc:75
Isolate * isolate
int32_t offset
TNode< Object > target
TNode< Object > receiver
SharedFunctionInfoRef shared
std::map< const std::string, const std::string > map
#define SWITCH_KIND(Type, type, TYPE, ctype)
#define WRITE_TYPE(TYPE)
double hour
double days
ZoneVector< RpoNumber > & result
int position
Definition liveedit.cc:290
#define LOG(isolate, Call)
Definition log.h:78
InstructionOperand source
int int32_t
Definition unicode.cc:40
V8_INLINE constexpr bool IsPropertyDictionary(InstanceType instance_type)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
PropertiesEnumerationMode
Definition globals.h:2856
@ kEnumerationOrder
Definition globals.h:2859
@ kPropertyAdditionOrder
Definition globals.h:2861
bool TryCast(Tagged< From > value, Tagged< To > *out)
Definition casting.h:77
constexpr int kFunctionEntryBytecodeOffset
Definition globals.h:854
constexpr NullMaybeHandleType kNullMaybeHandle
V8_WARN_UNUSED_RESULT Maybe< bool > FastGetOwnValuesOrEntries(Isolate *isolate, DirectHandle< JSReceiver > receiver, bool get_entries, Handle< FixedArray > *result)
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
@ SKIP_WRITE_BARRIER
Definition objects.h:52
@ UPDATE_WRITE_BARRIER
Definition objects.h:55
bool is_sloppy(LanguageMode language_mode)
Definition globals.h:773
constexpr bool IsHoleyElementsKind(ElementsKind kind)
static DirectHandle< Object > MakeEntryPair(Isolate *isolate, size_t index, DirectHandle< Object > value)
OrdinaryToPrimitiveHint
Definition globals.h:1860
bool IsNumber(Tagged< Object > obj)
ReadOnlyRoots GetReadOnlyRoots()
Definition roots-inl.h:86
void PrintF(const char *format,...)
Definition utils.cc:39
Map::Bits1::HasPrototypeSlotBit Map::Bits1::HasNamedInterceptorBit Map::Bits1::IsUndetectableBit Map::Bits1::IsConstructorBit Map::Bits2::IsImmutablePrototypeBit Map::Bits3::IsDeprecatedBit is_prototype_map
Definition map-inl.h:133
bool IsSealedElementsKind(ElementsKind kind)
Tagged< DescriptorArray >
Definition map-inl.h:52
bool IsCustomElementsReceiverMap(Tagged< Map > map)
Tagged(T object) -> Tagged< T >
constexpr bool IsSmiElementsKind(ElementsKind kind)
V8_INLINE Isolate * GetIsolateFromWritableObject(Tagged< HeapObject > object)
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
V8_INLINE IndirectHandle< T > indirect_handle(DirectHandle< T > handle)
Definition handles.h:757
kInterpreterTrampolineOffset Tagged< HeapObject >
constexpr bool IsObjectElementsKind(ElementsKind kind)
bool IsNonextensibleElementsKind(ElementsKind kind)
@ HOLEY_NONEXTENSIBLE_ELEMENTS
@ SLOW_STRING_WRAPPER_ELEMENTS
@ PACKED_NONEXTENSIBLE_ELEMENTS
@ TERMINAL_FAST_ELEMENTS_KIND
@ SLOW_SLOPPY_ARGUMENTS_ELEMENTS
@ FAST_SLOPPY_ARGUMENTS_ELEMENTS
@ FAST_STRING_WRAPPER_ELEMENTS
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
return Cast< NumberDictionary >(elements(cage_base))
const char * ElementsKindToString(ElementsKind kind)
void Print(Tagged< Object > obj)
Definition objects.h:774
static int HoleyElementsUsage(Tagged< JSObject > object, Tagged< BackingStore > store)
DirectHandle< NumberDictionary > CreateElementDictionary(Isolate *isolate, DirectHandle< JSObject > object)
ShouldThrow GetShouldThrow(Isolate *isolate, Maybe< ShouldThrow > should_throw)
Definition objects.cc:140
bool IsPrimitive(Tagged< Object > obj)
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
bool IsShared(Tagged< Object > obj)
bool IsSloppyArgumentsElementsKind(ElementsKind kind)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES HOLEY_ELEMENTS
bool IsFrozenElementsKind(ElementsKind kind)
void ShortPrint(Tagged< Object > obj, FILE *out)
Definition objects.cc:1865
bool IsJSObjectThatCanBeTrackedAsPrototype(Tagged< Object > obj)
Definition objects-inl.h:96
static const char * NonAPIInstanceTypeToString(InstanceType instance_type)
bool IsFastElementsKind(ElementsKind kind)
Tagged< MaybeWeak< T > > MakeWeak(Tagged< T > value)
Definition tagged.h:893
static ElementsKind BestFittingFastElementsKind(Tagged< JSObject > object)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES DISABLE_ALLOCATION_SITES HOLEY_DOUBLE_ELEMENTS
static const int kMaxNumberOfDescriptors
bool is_strict(LanguageMode language_mode)
Definition globals.h:777
bool IsDictionaryElementsKind(ElementsKind kind)
V8_INLINE constexpr bool IsHeapObject(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:669
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsUniqueName(Tagged< Name > obj)
V8_INLINE PropertyAttributes PropertyAttributesFromInt(int value)
V8_INLINE bool IsWasmObject(T obj, Isolate *=nullptr)
Definition objects.h:725
static bool ShouldConvertToSlowElements(uint32_t used_elements, uint32_t new_capacity)
return value
Definition map-inl.h:893
static bool ShouldConvertToFastElements(Tagged< JSObject > object, Tagged< NumberDictionary > dictionary, uint32_t index, uint32_t *new_capacity)
bool IsTypedArrayOrRabGsabTypedArrayElementsKind(ElementsKind kind)
bool IsStringWrapperElementsKind(ElementsKind kind)
constexpr bool IsDoubleElementsKind(ElementsKind kind)
@ ACCESSOR_GETTER
Definition objects.h:879
@ ACCESSOR_SETTER
Definition objects.h:879
ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind, ElementsKind to_kind)
bool IsTransitionableFastElementsKind(ElementsKind from_kind)
EnforceDefineSemantics
Definition objects.h:116
static bool PrototypeBenefitsFromNormalization(Tagged< JSObject > object)
MaybeDirectHandle< FixedArray > GetOwnValuesOrEntries(Isolate *isolate, DirectHandle< JSReceiver > object, PropertyFilter filter, bool try_fast_path, bool get_entries)
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
@ kStartAtPrototype
Definition globals.h:1714
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset prototype
Definition map-inl.h:69
kInterpreterTrampolineOffset script
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
PropertyNormalizationMode
Definition objects.h:60
@ KEEP_INOBJECT_PROPERTIES
Definition objects.h:62
@ CLEAR_INOBJECT_PROPERTIES
Definition objects.h:61
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
IntegrityLevel
Definition v8-object.h:228
static constexpr ReleaseStoreTag kReleaseStore
Definition globals.h:2910
Local< T > Handle
Maybe< T > Nothing()
Definition v8-maybe.h:112
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
static constexpr RelaxedStoreTag kRelaxedStore
Definition globals.h:2911
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
Intercepted
#define INSTANCE_TYPE_LIST(V)
uint32_t test
#define FATAL(...)
Definition logging.h:47
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_IMPLIES(lhs, rhs)
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define CHECK_NE(lhs, rhs)
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
Symbol method
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype)
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:671