Line data Source code
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 :
5 : #include "src/builtins/builtins-utils-inl.h"
6 : #include "src/builtins/builtins.h"
7 : #include "src/code-factory.h"
8 : #include "src/counters.h"
9 : #include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
10 : #include "src/keys.h"
11 : #include "src/lookup.h"
12 : #include "src/message-template.h"
13 : #include "src/objects-inl.h"
14 : #include "src/property-descriptor.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 : // -----------------------------------------------------------------------------
20 : // ES6 section 19.1 Object Objects
21 :
22 : // ES6 section 19.1.3.4 Object.prototype.propertyIsEnumerable ( V )
23 28770 : BUILTIN(ObjectPrototypePropertyIsEnumerable) {
24 : HandleScope scope(isolate);
25 : Handle<JSReceiver> object;
26 : Handle<Name> name;
27 11513 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
28 : isolate, name, Object::ToName(isolate, args.atOrUndefined(isolate, 1)));
29 11669 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
30 : isolate, object, Object::ToObject(isolate, args.receiver()));
31 : Maybe<PropertyAttributes> maybe =
32 5578 : JSReceiver::GetOwnPropertyAttributes(object, name);
33 5792 : if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
34 5620 : if (maybe.FromJust() == ABSENT) return ReadOnlyRoots(isolate).false_value();
35 10216 : return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
36 : }
37 :
38 : // ES6 section 19.1.2.3 Object.defineProperties
39 3635 : BUILTIN(ObjectDefineProperties) {
40 : HandleScope scope(isolate);
41 : DCHECK_EQ(3, args.length());
42 727 : Handle<Object> target = args.at(1);
43 727 : Handle<Object> properties = args.at(2);
44 :
45 1625 : RETURN_RESULT_OR_FAILURE(
46 : isolate, JSReceiver::DefineProperties(isolate, target, properties));
47 : }
48 :
49 : // ES6 section 19.1.2.4 Object.defineProperty
50 572975 : BUILTIN(ObjectDefineProperty) {
51 : HandleScope scope(isolate);
52 : DCHECK_EQ(4, args.length());
53 114595 : Handle<Object> target = args.at(1);
54 114595 : Handle<Object> key = args.at(2);
55 114595 : Handle<Object> attributes = args.at(3);
56 :
57 229190 : return JSReceiver::DefineProperty(isolate, target, key, attributes);
58 : }
59 :
60 : namespace {
61 :
62 : template <AccessorComponent which_accessor>
63 147991 : Object ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
64 : Handle<Object> name, Handle<Object> accessor) {
65 : // 1. Let O be ? ToObject(this value).
66 : Handle<JSReceiver> receiver;
67 295991 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
68 : Object::ToObject(isolate, object));
69 : // 2. If IsCallable(getter) is false, throw a TypeError exception.
70 147982 : if (!accessor->IsCallable()) {
71 : MessageTemplate message =
72 : which_accessor == ACCESSOR_GETTER
73 : ? MessageTemplate::kObjectGetterExpectingFunction
74 : : MessageTemplate::kObjectSetterExpectingFunction;
75 216 : THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
76 : }
77 : // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
78 : // [[Configurable]]: true}.
79 : PropertyDescriptor desc;
80 : if (which_accessor == ACCESSOR_GETTER) {
81 : desc.set_get(accessor);
82 : } else {
83 : DCHECK(which_accessor == ACCESSOR_SETTER);
84 : desc.set_set(accessor);
85 : }
86 : desc.set_enumerable(true);
87 : desc.set_configurable(true);
88 : // 4. Let key be ? ToPropertyKey(P).
89 295748 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
90 : Object::ToPropertyKey(isolate, name));
91 : // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
92 : // To preserve legacy behavior, we ignore errors silently rather than
93 : // throwing an exception.
94 : Maybe<bool> success = JSReceiver::DefineOwnProperty(
95 147874 : isolate, receiver, name, &desc, Just(kThrowOnError));
96 148055 : MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
97 147693 : if (!success.FromJust()) {
98 0 : isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
99 : }
100 : // 6. Return undefined.
101 147693 : return ReadOnlyRoots(isolate).undefined_value();
102 : }
103 :
104 700 : Object ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
105 : Handle<Object> key, AccessorComponent component) {
106 1400 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
107 : Object::ToObject(isolate, object));
108 1400 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
109 : Object::ToPropertyKey(isolate, key));
110 700 : bool success = false;
111 : LookupIterator it = LookupIterator::PropertyOrElement(
112 : isolate, object, key, &success,
113 700 : LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
114 : DCHECK(success);
115 :
116 700 : for (; it.IsFound(); it.Next()) {
117 574 : switch (it.state()) {
118 : case LookupIterator::INTERCEPTOR:
119 : case LookupIterator::NOT_FOUND:
120 : case LookupIterator::TRANSITION:
121 0 : UNREACHABLE();
122 :
123 : case LookupIterator::ACCESS_CHECK:
124 5 : if (it.HasAccess()) continue;
125 5 : isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
126 5 : RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
127 0 : return ReadOnlyRoots(isolate).undefined_value();
128 :
129 : case LookupIterator::JSPROXY: {
130 : PropertyDescriptor desc;
131 : Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
132 288 : isolate, it.GetHolder<JSProxy>(), it.GetName(), &desc);
133 288 : MAYBE_RETURN(found, ReadOnlyRoots(isolate).exception());
134 288 : if (found.FromJust()) {
135 243 : if (component == ACCESSOR_GETTER && desc.has_get()) {
136 : return *desc.get();
137 : }
138 189 : if (component == ACCESSOR_SETTER && desc.has_set()) {
139 : return *desc.set();
140 : }
141 54 : return ReadOnlyRoots(isolate).undefined_value();
142 : }
143 : Handle<Object> prototype;
144 252 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
145 : isolate, prototype, JSProxy::GetPrototype(it.GetHolder<JSProxy>()));
146 126 : if (prototype->IsNull(isolate)) {
147 18 : return ReadOnlyRoots(isolate).undefined_value();
148 : }
149 108 : return ObjectLookupAccessor(isolate, prototype, key, component);
150 : }
151 :
152 : case LookupIterator::INTEGER_INDEXED_EXOTIC:
153 : case LookupIterator::DATA:
154 72 : return ReadOnlyRoots(isolate).undefined_value();
155 :
156 : case LookupIterator::ACCESSOR: {
157 209 : Handle<Object> maybe_pair = it.GetAccessors();
158 209 : if (maybe_pair->IsAccessorPair()) {
159 418 : return *AccessorPair::GetComponent(
160 : isolate, Handle<AccessorPair>::cast(maybe_pair), component);
161 : }
162 : }
163 : }
164 : }
165 :
166 126 : return ReadOnlyRoots(isolate).undefined_value();
167 : }
168 :
169 : } // namespace
170 :
171 : // ES6 B.2.2.2 a.k.a.
172 : // https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
173 682530 : BUILTIN(ObjectDefineGetter) {
174 : HandleScope scope(isolate);
175 136506 : Handle<Object> object = args.at(0); // Receiver.
176 136506 : Handle<Object> name = args.at(1);
177 136506 : Handle<Object> getter = args.at(2);
178 273012 : return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
179 : }
180 :
181 : // ES6 B.2.2.3 a.k.a.
182 : // https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
183 57425 : BUILTIN(ObjectDefineSetter) {
184 : HandleScope scope(isolate);
185 11485 : Handle<Object> object = args.at(0); // Receiver.
186 11485 : Handle<Object> name = args.at(1);
187 11485 : Handle<Object> setter = args.at(2);
188 22970 : return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
189 : }
190 :
191 : // ES6 B.2.2.4 a.k.a.
192 : // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
193 1540 : BUILTIN(ObjectLookupGetter) {
194 : HandleScope scope(isolate);
195 308 : Handle<Object> object = args.at(0);
196 308 : Handle<Object> name = args.at(1);
197 616 : return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
198 : }
199 :
200 : // ES6 B.2.2.5 a.k.a.
201 : // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
202 1420 : BUILTIN(ObjectLookupSetter) {
203 : HandleScope scope(isolate);
204 284 : Handle<Object> object = args.at(0);
205 284 : Handle<Object> name = args.at(1);
206 568 : return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
207 : }
208 :
209 : // ES6 section 19.1.2.5 Object.freeze ( O )
210 494185 : BUILTIN(ObjectFreeze) {
211 : HandleScope scope(isolate);
212 : Handle<Object> object = args.atOrUndefined(isolate, 1);
213 98837 : if (object->IsJSReceiver()) {
214 197622 : MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
215 : FROZEN, kThrowOnError),
216 : ReadOnlyRoots(isolate).exception());
217 : }
218 : return *object;
219 : }
220 :
221 : // ES section 19.1.2.9 Object.getPrototypeOf ( O )
222 1673695 : BUILTIN(ObjectGetPrototypeOf) {
223 : HandleScope scope(isolate);
224 334739 : Handle<Object> object = args.atOrUndefined(isolate, 1);
225 :
226 : Handle<JSReceiver> receiver;
227 669496 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
228 : Object::ToObject(isolate, object));
229 :
230 669451 : RETURN_RESULT_OR_FAILURE(isolate,
231 : JSReceiver::GetPrototype(isolate, receiver));
232 : }
233 :
234 : // ES6 section 19.1.2.21 Object.setPrototypeOf ( O, proto )
235 293605 : BUILTIN(ObjectSetPrototypeOf) {
236 : HandleScope scope(isolate);
237 :
238 : // 1. Let O be ? RequireObjectCoercible(O).
239 : Handle<Object> object = args.atOrUndefined(isolate, 1);
240 58721 : if (object->IsNullOrUndefined(isolate)) {
241 54 : THROW_NEW_ERROR_RETURN_FAILURE(
242 : isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
243 : isolate->factory()->NewStringFromAsciiChecked(
244 : "Object.setPrototypeOf")));
245 : }
246 :
247 : // 2. If Type(proto) is neither Object nor Null, throw a TypeError exception.
248 : Handle<Object> proto = args.atOrUndefined(isolate, 2);
249 117271 : if (!proto->IsNull(isolate) && !proto->IsJSReceiver()) {
250 954 : THROW_NEW_ERROR_RETURN_FAILURE(
251 : isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
252 : }
253 :
254 : // 3. If Type(O) is not Object, return O.
255 58226 : if (!object->IsJSReceiver()) return *object;
256 : Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
257 :
258 : // 4. Let status be ? O.[[SetPrototypeOf]](proto).
259 : // 5. If status is false, throw a TypeError exception.
260 116551 : MAYBE_RETURN(JSReceiver::SetPrototype(receiver, proto, true, kThrowOnError),
261 : ReadOnlyRoots(isolate).exception());
262 :
263 : // 6. Return O.
264 58019 : return *receiver;
265 : }
266 :
267 : // ES6 section B.2.2.1.1 get Object.prototype.__proto__
268 668075 : BUILTIN(ObjectPrototypeGetProto) {
269 : HandleScope scope(isolate);
270 : // 1. Let O be ? ToObject(this value).
271 : Handle<JSReceiver> receiver;
272 267248 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
273 : isolate, receiver, Object::ToObject(isolate, args.receiver()));
274 :
275 : // 2. Return ? O.[[GetPrototypeOf]]().
276 267194 : RETURN_RESULT_OR_FAILURE(isolate,
277 : JSReceiver::GetPrototype(isolate, receiver));
278 : }
279 :
280 : // ES6 section B.2.2.1.2 set Object.prototype.__proto__
281 804380 : BUILTIN(ObjectPrototypeSetProto) {
282 : HandleScope scope(isolate);
283 : // 1. Let O be ? RequireObjectCoercible(this value).
284 : Handle<Object> object = args.receiver();
285 160876 : if (object->IsNullOrUndefined(isolate)) {
286 54 : THROW_NEW_ERROR_RETURN_FAILURE(
287 : isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
288 : isolate->factory()->NewStringFromAsciiChecked(
289 : "set Object.prototype.__proto__")));
290 : }
291 :
292 : // 2. If Type(proto) is neither Object nor Null, return undefined.
293 : Handle<Object> proto = args.at(1);
294 321350 : if (!proto->IsNull(isolate) && !proto->IsJSReceiver()) {
295 29364 : return ReadOnlyRoots(isolate).undefined_value();
296 : }
297 :
298 : // 3. If Type(O) is not Object, return undefined.
299 131539 : if (!object->IsJSReceiver()) return ReadOnlyRoots(isolate).undefined_value();
300 131449 : Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
301 :
302 : // 4. Let status be ? O.[[SetPrototypeOf]](proto).
303 : // 5. If status is false, throw a TypeError exception.
304 262994 : MAYBE_RETURN(JSReceiver::SetPrototype(receiver, proto, true, kThrowOnError),
305 : ReadOnlyRoots(isolate).exception());
306 :
307 : // Return undefined.
308 131353 : return ReadOnlyRoots(isolate).undefined_value();
309 : }
310 :
311 : namespace {
312 :
313 340 : Object GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
314 : PropertyFilter filter) {
315 : HandleScope scope(isolate);
316 340 : Handle<Object> object = args.atOrUndefined(isolate, 1);
317 : Handle<JSReceiver> receiver;
318 680 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
319 : Object::ToObject(isolate, object));
320 : Handle<FixedArray> keys;
321 680 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
322 : isolate, keys,
323 : KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
324 : GetKeysConversion::kConvertToString));
325 340 : return *isolate->factory()->NewJSArrayWithElements(keys);
326 : }
327 :
328 : } // namespace
329 :
330 : // ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
331 680 : BUILTIN(ObjectGetOwnPropertySymbols) {
332 340 : return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
333 : }
334 :
335 : // ES6 section 19.1.2.11 Object.isExtensible ( O )
336 10525 : BUILTIN(ObjectIsExtensible) {
337 : HandleScope scope(isolate);
338 : Handle<Object> object = args.atOrUndefined(isolate, 1);
339 : Maybe<bool> result =
340 : object->IsJSReceiver()
341 : ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
342 2105 : : Just(false);
343 2105 : MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
344 2105 : return isolate->heap()->ToBoolean(result.FromJust());
345 : }
346 :
347 : // ES6 section 19.1.2.12 Object.isFrozen ( O )
348 5425 : BUILTIN(ObjectIsFrozen) {
349 : HandleScope scope(isolate);
350 : Handle<Object> object = args.atOrUndefined(isolate, 1);
351 : Maybe<bool> result = object->IsJSReceiver()
352 : ? JSReceiver::TestIntegrityLevel(
353 : Handle<JSReceiver>::cast(object), FROZEN)
354 1085 : : Just(true);
355 1094 : MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
356 1076 : return isolate->heap()->ToBoolean(result.FromJust());
357 : }
358 :
359 : // ES6 section 19.1.2.13 Object.isSealed ( O )
360 2520 : BUILTIN(ObjectIsSealed) {
361 : HandleScope scope(isolate);
362 : Handle<Object> object = args.atOrUndefined(isolate, 1);
363 : Maybe<bool> result = object->IsJSReceiver()
364 : ? JSReceiver::TestIntegrityLevel(
365 : Handle<JSReceiver>::cast(object), SEALED)
366 504 : : Just(true);
367 522 : MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
368 486 : return isolate->heap()->ToBoolean(result.FromJust());
369 : }
370 :
371 540 : BUILTIN(ObjectGetOwnPropertyDescriptors) {
372 : HandleScope scope(isolate);
373 108 : Handle<Object> object = args.atOrUndefined(isolate, 1);
374 :
375 : Handle<JSReceiver> receiver;
376 243 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
377 : Object::ToObject(isolate, object));
378 :
379 : Handle<FixedArray> keys;
380 171 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
381 : isolate, keys, KeyAccumulator::GetKeys(
382 : receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
383 : GetKeysConversion::kConvertToString));
384 :
385 : Handle<JSObject> descriptors =
386 72 : isolate->factory()->NewJSObject(isolate->object_function());
387 :
388 450 : for (int i = 0; i < keys->length(); ++i) {
389 189 : Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
390 : PropertyDescriptor descriptor;
391 : Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
392 189 : isolate, receiver, key, &descriptor);
393 189 : MAYBE_RETURN(did_get_descriptor, ReadOnlyRoots(isolate).exception());
394 :
395 198 : if (!did_get_descriptor.FromJust()) continue;
396 180 : Handle<Object> from_descriptor = descriptor.ToObject(isolate);
397 :
398 : Maybe<bool> success = JSReceiver::CreateDataProperty(
399 180 : isolate, descriptors, key, from_descriptor, Just(kDontThrow));
400 180 : CHECK(success.FromJust());
401 : }
402 :
403 72 : return *descriptors;
404 : }
405 :
406 : // ES6 section 19.1.2.15 Object.preventExtensions ( O )
407 27245 : BUILTIN(ObjectPreventExtensions) {
408 : HandleScope scope(isolate);
409 : Handle<Object> object = args.atOrUndefined(isolate, 1);
410 5449 : if (object->IsJSReceiver()) {
411 10908 : MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
412 : kThrowOnError),
413 : ReadOnlyRoots(isolate).exception());
414 : }
415 : return *object;
416 : }
417 :
418 : // ES6 section 19.1.2.17 Object.seal ( O )
419 14990 : BUILTIN(ObjectSeal) {
420 : HandleScope scope(isolate);
421 : Handle<Object> object = args.atOrUndefined(isolate, 1);
422 2998 : if (object->IsJSReceiver()) {
423 5963 : MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
424 : SEALED, kThrowOnError),
425 : ReadOnlyRoots(isolate).exception());
426 : }
427 : return *object;
428 : }
429 :
430 : } // namespace internal
431 122036 : } // namespace v8
|