v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-object.cc
Go to the documentation of this file.
1// Copyright 2016 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
9#include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
10#include "src/objects/keys.h"
11#include "src/objects/lookup.h"
14
15namespace v8 {
16namespace internal {
17
18// -----------------------------------------------------------------------------
19// ES6 section 19.1 Object Objects
20
21// ES6 section 19.1.3.4 Object.prototype.propertyIsEnumerable ( V )
22BUILTIN(ObjectPrototypePropertyIsEnumerable) {
23 HandleScope scope(isolate);
27 isolate, name, Object::ToName(isolate, args.atOrUndefined(isolate, 1)));
29 isolate, object, Object::ToObject(isolate, args.receiver()));
31 JSReceiver::GetOwnPropertyAttributes(isolate, object, name);
32 if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
33 if (maybe.FromJust() == ABSENT) return ReadOnlyRoots(isolate).false_value();
34 return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
35}
36
37// ES6 section 19.1.2.3 Object.defineProperties
38BUILTIN(ObjectDefineProperties) {
39 HandleScope scope(isolate);
40 DCHECK_LE(3, args.length());
41 DirectHandle<Object> target = args.at(1);
42 DirectHandle<Object> properties = args.at(2);
43
45 isolate, JSReceiver::DefineProperties(isolate, target, properties));
46}
47
48// ES6 section 19.1.2.4 Object.defineProperty
49BUILTIN(ObjectDefineProperty) {
50 HandleScope scope(isolate);
51 DCHECK_LE(4, args.length());
52 DirectHandle<Object> target = args.at(1);
54 Handle<Object> attributes = args.at(3);
55
56 return JSReceiver::DefineProperty(isolate, target, key, attributes);
57}
58
59namespace {
60
61template <AccessorComponent which_accessor>
62Tagged<Object> ObjectDefineAccessor(Isolate* isolate,
63 DirectHandle<JSAny> object,
64 DirectHandle<Object> name,
65 DirectHandle<Object> accessor) {
66 // 1. Let O be ? ToObject(this value).
67 DirectHandle<JSReceiver> receiver;
69 Object::ToObject(isolate, object));
70 // 2. If IsCallable(getter) is false, throw a TypeError exception.
71 if (!IsCallable(*accessor)) {
72 MessageTemplate message =
73 which_accessor == ACCESSOR_GETTER
74 ? MessageTemplate::kObjectGetterExpectingFunction
75 : MessageTemplate::kObjectSetterExpectingFunction;
76 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
77 }
78 // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
79 // [[Configurable]]: true}.
80 PropertyDescriptor desc;
81 if (which_accessor == ACCESSOR_GETTER) {
82 desc.set_get(Cast<JSAny>(accessor));
83 } else {
84 DCHECK(which_accessor == ACCESSOR_SETTER);
85 desc.set_set(Cast<JSAny>(accessor));
86 }
87 desc.set_enumerable(true);
88 desc.set_configurable(true);
89 // 4. Let key be ? ToPropertyKey(P).
91 Object::ToPropertyKey(isolate, name));
92 // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
93 // To preserve legacy behavior, we ignore errors silently rather than
94 // throwing an exception.
95 Maybe<bool> success = JSReceiver::DefineOwnProperty(
96 isolate, receiver, name, &desc, Just(kThrowOnError));
97 MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
98 if (!success.FromJust()) {
100 }
101 // 6. Return undefined.
102 return ReadOnlyRoots(isolate).undefined_value();
103}
104
105Tagged<Object> ObjectLookupAccessor(Isolate* isolate,
106 DirectHandle<JSAny> object,
107 DirectHandle<Object> key,
108 AccessorComponent component) {
110 Object::ToObject(isolate, object));
111 // TODO(jkummerow/verwaest): PropertyKey(..., bool*) performs a
112 // functionally equivalent conversion, but handles element indices slightly
113 // differently. Does one of the approaches have a performance advantage?
115 Object::ToPropertyKey(isolate, key));
116 PropertyKey lookup_key(isolate, key);
117 LookupIterator it(isolate, object, lookup_key,
119
120 for (;; it.Next()) {
121 switch (it.state()) {
124 UNREACHABLE();
125
127 if (it.HasAccess()) continue;
128 RETURN_FAILURE_ON_EXCEPTION(isolate, isolate->ReportFailedAccessCheck(
129 it.GetHolder<JSObject>()));
130 UNREACHABLE();
131
133 PropertyDescriptor desc;
134 Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
135 isolate, it.GetHolder<JSProxy>(), it.GetName(), &desc);
136 MAYBE_RETURN(found, ReadOnlyRoots(isolate).exception());
137 if (found.FromJust()) {
138 if (component == ACCESSOR_GETTER && desc.has_get()) {
139 return *desc.get();
140 }
141 if (component == ACCESSOR_SETTER && desc.has_set()) {
142 return *desc.set();
143 }
144 return ReadOnlyRoots(isolate).undefined_value();
145 }
146 DirectHandle<JSPrototype> prototype;
148 isolate, prototype, JSProxy::GetPrototype(it.GetHolder<JSProxy>()));
149 if (IsNull(*prototype, isolate)) {
150 return ReadOnlyRoots(isolate).undefined_value();
151 }
152 return ObjectLookupAccessor(isolate, prototype, key, component);
153 }
155 continue; // Continue to the prototype, if present.
159 return ReadOnlyRoots(isolate).undefined_value();
160
162 DirectHandle<Object> maybe_pair = it.GetAccessors();
163 if (IsAccessorPair(*maybe_pair)) {
164 DirectHandle<NativeContext> holder_realm(
165 it.GetHolder<JSReceiver>()->GetCreationContext().value(),
166 isolate);
168 isolate, holder_realm, Cast<AccessorPair>(maybe_pair), component);
169 }
170 continue;
171 }
172 }
173 UNREACHABLE();
174 }
175}
176
177} // namespace
178
179// ES6 B.2.2.2 a.k.a.
180// https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
181BUILTIN(ObjectDefineGetter) {
182 HandleScope scope(isolate);
183 DirectHandle<JSAny> object = args.at<JSAny>(0); // Receiver.
184 DirectHandle<Object> name = args.at(1);
186 return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
187}
188
189// ES6 B.2.2.3 a.k.a.
190// https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
191BUILTIN(ObjectDefineSetter) {
192 HandleScope scope(isolate);
193 DirectHandle<JSAny> object = args.at<JSAny>(0); // Receiver.
194 DirectHandle<Object> name = args.at(1);
196 return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
197}
198
199// ES6 B.2.2.4 a.k.a.
200// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
201BUILTIN(ObjectLookupGetter) {
202 HandleScope scope(isolate);
203 DirectHandle<JSAny> object = args.at<JSAny>(0);
204 DirectHandle<Object> name = args.at(1);
205 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
206}
207
208// ES6 B.2.2.5 a.k.a.
209// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
210BUILTIN(ObjectLookupSetter) {
211 HandleScope scope(isolate);
212 DirectHandle<JSAny> object = args.at<JSAny>(0);
213 DirectHandle<Object> name = args.at(1);
214 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
215}
216
217// ES6 section 19.1.2.5 Object.freeze ( O )
218BUILTIN(ObjectFreeze) {
219 HandleScope scope(isolate);
220 DirectHandle<Object> object = args.atOrUndefined(isolate, 1);
221 if (IsJSReceiver(*object)) {
223 isolate, Cast<JSReceiver>(object), FROZEN, kThrowOnError),
224 ReadOnlyRoots(isolate).exception());
225 }
226 return *object;
227}
228
229// ES6 section B.2.2.1.1 get Object.prototype.__proto__
230BUILTIN(ObjectPrototypeGetProto) {
231 HandleScope scope(isolate);
232 // 1. Let O be ? ToObject(this value).
235 isolate, receiver, Object::ToObject(isolate, args.receiver()));
236
237 // 2. Return ? O.[[GetPrototypeOf]]().
240}
241
242// ES6 section B.2.2.1.2 set Object.prototype.__proto__
243BUILTIN(ObjectPrototypeSetProto) {
244 HandleScope scope(isolate);
245 // 1. Let O be ? RequireObjectCoercible(this value).
246 DirectHandle<Object> object = args.receiver();
247 if (IsNullOrUndefined(*object, isolate)) {
249 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
250 isolate->factory()->NewStringFromAsciiChecked(
251 "set Object.prototype.__proto__")));
252 }
253
254 // 2. If Type(proto) is neither Object nor Null, return undefined.
255 DirectHandle<Object> proto = args.at(1);
256 if (!IsNull(*proto, isolate) && !IsJSReceiver(*proto)) {
257 return ReadOnlyRoots(isolate).undefined_value();
258 }
259
260 // 3. If Type(O) is not Object, return undefined.
261 if (!IsJSReceiver(*object)) return ReadOnlyRoots(isolate).undefined_value();
263
264 // 4. Let status be ? O.[[SetPrototypeOf]](proto).
265 // 5. If status is false, throw a TypeError exception.
267 JSReceiver::SetPrototype(isolate, receiver, proto, true, kThrowOnError),
268 ReadOnlyRoots(isolate).exception());
269
270 // Return undefined.
271 return ReadOnlyRoots(isolate).undefined_value();
272}
273
274namespace {
275
276Tagged<Object> GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
277 PropertyFilter filter) {
278 HandleScope scope(isolate);
279 DirectHandle<Object> object = args.atOrUndefined(isolate, 1);
280 DirectHandle<JSReceiver> receiver;
282 Object::ToObject(isolate, object));
283 DirectHandle<FixedArray> keys;
285 isolate, keys,
288 return *isolate->factory()->NewJSArrayWithElements(keys);
289}
290
291} // namespace
292
293// ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
294BUILTIN(ObjectGetOwnPropertySymbols) {
295 return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
296}
297
298// ES6 section 19.1.2.12 Object.isFrozen ( O )
299BUILTIN(ObjectIsFrozen) {
300 HandleScope scope(isolate);
301 DirectHandle<Object> object = args.atOrUndefined(isolate, 1);
302 Maybe<bool> result = IsJSReceiver(*object)
304 isolate, Cast<JSReceiver>(object), FROZEN)
305 : Just(true);
306 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
307 return isolate->heap()->ToBoolean(result.FromJust());
308}
309
310// ES6 section 19.1.2.13 Object.isSealed ( O )
311BUILTIN(ObjectIsSealed) {
312 HandleScope scope(isolate);
313 DirectHandle<Object> object = args.atOrUndefined(isolate, 1);
314 Maybe<bool> result = IsJSReceiver(*object)
316 isolate, Cast<JSReceiver>(object), SEALED)
317 : Just(true);
318 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
319 return isolate->heap()->ToBoolean(result.FromJust());
320}
321
322BUILTIN(ObjectGetOwnPropertyDescriptors) {
323 HandleScope scope(isolate);
324 DirectHandle<Object> object = args.atOrUndefined(isolate, 1);
325
328 Object::ToObject(isolate, object));
329
332 isolate, keys,
336
337 DirectHandle<JSObject> descriptors =
338 isolate->factory()->NewJSObject(isolate->object_function());
339
340 for (int i = 0; i < keys->length(); ++i) {
341 DirectHandle<Name> key(Cast<Name>(keys->get(i)), isolate);
342 PropertyDescriptor descriptor;
344 isolate, receiver, key, &descriptor);
345 MAYBE_RETURN(did_get_descriptor, ReadOnlyRoots(isolate).exception());
346
347 if (!did_get_descriptor.FromJust()) continue;
348 DirectHandle<Object> from_descriptor = descriptor.ToObject(isolate);
349
351 isolate, descriptors, key, from_descriptor, Just(kDontThrow));
352 CHECK(success.FromJust());
353 }
354
355 return *descriptors;
356}
357
358// ES6 section 19.1.2.17 Object.seal ( O )
359BUILTIN(ObjectSeal) {
360 HandleScope scope(isolate);
361 DirectHandle<Object> object = args.atOrUndefined(isolate, 1);
362 if (IsJSReceiver(*object)) {
364 isolate, Cast<JSReceiver>(object), SEALED, kThrowOnError),
365 ReadOnlyRoots(isolate).exception());
366 }
367 return *object;
368}
369
370} // namespace internal
371} // namespace v8
#define BUILTIN(name)
PropertyT * getter
@ kDefineGetterOrSetterWouldThrow
Definition v8-isolate.h:503
V8_INLINE T FromJust() const &
Definition v8-maybe.h:64
V8_INLINE bool IsNothing() const
Definition v8-maybe.h:35
static Handle< JSAny > GetComponent(Isolate *isolate, DirectHandle< NativeContext > native_context, DirectHandle< AccessorPair > accessor_pair, AccessorComponent component)
Definition objects.cc:4015
static V8_WARN_UNUSED_RESULT Maybe< bool > GetOwnPropertyDescriptor(Isolate *isolate, DirectHandle< JSProxy > proxy, DirectHandle< Name > name, PropertyDescriptor *desc)
Definition objects.cc:3490
static MaybeDirectHandle< JSPrototype > GetPrototype(DirectHandle< JSProxy > receiver)
Definition objects.cc:1456
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 > SetPrototype(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Object > value, bool from_javascript, ShouldThrow should_throw)
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetOwnPropertyAttributes(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name)
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)
static MaybeDirectHandle< JSPrototype > GetPrototype(Isolate *isolate, DirectHandle< JSReceiver > receiver)
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 V8_WARN_UNUSED_RESULT Maybe< bool > DefineOwnProperty(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Object > key, PropertyDescriptor *desc, Maybe< ShouldThrow > should_throw)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > DefineProperties(Isolate *isolate, DirectHandle< Object > object, DirectHandle< Object > properties)
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
static V8_WARN_UNUSED_RESULT HandleType< JSReceiver >::MaybeType ToObject(Isolate *isolate, HandleType< T > object, const char *method_name=nullptr)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType ToPropertyKey(Isolate *isolate, HandleType< T > value)
static V8_WARN_UNUSED_RESULT HandleType< Name >::MaybeType ToName(Isolate *isolate, HandleType< Object > input)
DirectHandle< JSObject > ToObject(Isolate *isolate)
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:284
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition isolate.h:294
#define RETURN_FAILURE_ON_EXCEPTION(isolate, call)
Definition isolate.h:368
#define MAYBE_RETURN(call, value)
Definition isolate.h:408
#define RETURN_RESULT_OR_FAILURE(isolate, call)
Definition isolate.h:264
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
TNode< Object > receiver
ZoneVector< RpoNumber > & result
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
bool IsNullOrUndefined(Tagged< Object > obj, Isolate *isolate)
@ ACCESSOR_GETTER
Definition objects.h:879
@ ACCESSOR_SETTER
Definition objects.h:879
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset prototype
Definition map-inl.h:69
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
PropertyFilter
Definition v8-object.h:179
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482