Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: src/builtins/builtins-object.cc

Issue 2165593002: [builtins] Move builtins into own files (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove builtins-error.cc from BUILD.gn Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-number.cc ('k') | src/builtins/builtins-proxy.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.h"
6 #include "src/builtins/builtins-utils.h"
7
8 #include "src/code-factory.h"
9 #include "src/property-descriptor.h"
10
11 namespace v8 {
12 namespace internal {
13
14 // -----------------------------------------------------------------------------
15 // ES6 section 19.1 Object Objects
16
17 void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
18 typedef compiler::Node Node;
19 typedef CodeStubAssembler::Label Label;
20 typedef CodeStubAssembler::Variable Variable;
21
22 Node* object = assembler->Parameter(0);
23 Node* key = assembler->Parameter(1);
24 Node* context = assembler->Parameter(4);
25
26 Label call_runtime(assembler), return_true(assembler),
27 return_false(assembler);
28
29 // Smi receivers do not have own properties.
30 Label if_objectisnotsmi(assembler);
31 assembler->Branch(assembler->WordIsSmi(object), &return_false,
32 &if_objectisnotsmi);
33 assembler->Bind(&if_objectisnotsmi);
34
35 Node* map = assembler->LoadMap(object);
36 Node* instance_type = assembler->LoadMapInstanceType(map);
37
38 Variable var_index(assembler, MachineRepresentation::kWord32);
39
40 Label keyisindex(assembler), if_iskeyunique(assembler);
41 assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
42 &call_runtime);
43
44 assembler->Bind(&if_iskeyunique);
45 assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
46 &return_false, &call_runtime);
47
48 assembler->Bind(&keyisindex);
49 assembler->TryLookupElement(object, map, instance_type, var_index.value(),
50 &return_true, &return_false, &call_runtime);
51
52 assembler->Bind(&return_true);
53 assembler->Return(assembler->BooleanConstant(true));
54
55 assembler->Bind(&return_false);
56 assembler->Return(assembler->BooleanConstant(false));
57
58 assembler->Bind(&call_runtime);
59 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
60 context, object, key));
61 }
62
63 namespace {
64
65 MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
66 Handle<Object> next_source) {
67 // Non-empty strings are the only non-JSReceivers that need to be handled
68 // explicitly by Object.assign.
69 if (!next_source->IsJSReceiver()) {
70 return Just(!next_source->IsString() ||
71 String::cast(*next_source)->length() == 0);
72 }
73
74 // If the target is deprecated, the object will be updated on first store. If
75 // the source for that store equals the target, this will invalidate the
76 // cached representation of the source. Preventively upgrade the target.
77 // Do this on each iteration since any property load could cause deprecation.
78 if (to->map()->is_deprecated()) {
79 JSObject::MigrateInstance(Handle<JSObject>::cast(to));
80 }
81
82 Isolate* isolate = to->GetIsolate();
83 Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
84
85 if (!map->IsJSObjectMap()) return Just(false);
86 if (!map->OnlyHasSimpleProperties()) return Just(false);
87
88 Handle<JSObject> from = Handle<JSObject>::cast(next_source);
89 if (from->elements() != isolate->heap()->empty_fixed_array()) {
90 return Just(false);
91 }
92
93 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
94 int length = map->NumberOfOwnDescriptors();
95
96 bool stable = true;
97
98 for (int i = 0; i < length; i++) {
99 Handle<Name> next_key(descriptors->GetKey(i), isolate);
100 Handle<Object> prop_value;
101 // Directly decode from the descriptor array if |from| did not change shape.
102 if (stable) {
103 PropertyDetails details = descriptors->GetDetails(i);
104 if (!details.IsEnumerable()) continue;
105 if (details.kind() == kData) {
106 if (details.location() == kDescriptor) {
107 prop_value = handle(descriptors->GetValue(i), isolate);
108 } else {
109 Representation representation = details.representation();
110 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
111 prop_value = JSObject::FastPropertyAt(from, representation, index);
112 }
113 } else {
114 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
115 isolate, prop_value, JSReceiver::GetProperty(from, next_key),
116 Nothing<bool>());
117 stable = from->map() == *map;
118 }
119 } else {
120 // If the map did change, do a slower lookup. We are still guaranteed that
121 // the object has a simple shape, and that the key is a name.
122 LookupIterator it(from, next_key, from,
123 LookupIterator::OWN_SKIP_INTERCEPTOR);
124 if (!it.IsFound()) continue;
125 DCHECK(it.state() == LookupIterator::DATA ||
126 it.state() == LookupIterator::ACCESSOR);
127 if (!it.IsEnumerable()) continue;
128 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
129 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
130 }
131 LookupIterator it(to, next_key, to);
132 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
133 Maybe<bool> result = Object::SetProperty(
134 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
135 if (result.IsNothing()) return result;
136 if (stable && call_to_js) stable = from->map() == *map;
137 }
138
139 return Just(true);
140 }
141
142 } // namespace
143
144 // ES6 19.1.2.1 Object.assign
145 BUILTIN(ObjectAssign) {
146 HandleScope scope(isolate);
147 Handle<Object> target = args.atOrUndefined(isolate, 1);
148
149 // 1. Let to be ? ToObject(target).
150 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
151 Object::ToObject(isolate, target));
152 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
153 // 2. If only one argument was passed, return to.
154 if (args.length() == 2) return *to;
155 // 3. Let sources be the List of argument values starting with the
156 // second argument.
157 // 4. For each element nextSource of sources, in ascending index order,
158 for (int i = 2; i < args.length(); ++i) {
159 Handle<Object> next_source = args.at<Object>(i);
160 Maybe<bool> fast_assign = FastAssign(to, next_source);
161 if (fast_assign.IsNothing()) return isolate->heap()->exception();
162 if (fast_assign.FromJust()) continue;
163 // 4a. If nextSource is undefined or null, let keys be an empty List.
164 // 4b. Else,
165 // 4b i. Let from be ToObject(nextSource).
166 // Only non-empty strings and JSReceivers have enumerable properties.
167 Handle<JSReceiver> from =
168 Object::ToObject(isolate, next_source).ToHandleChecked();
169 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
170 Handle<FixedArray> keys;
171 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
172 isolate, keys, KeyAccumulator::GetKeys(
173 from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
174 GetKeysConversion::kKeepNumbers));
175 // 4c. Repeat for each element nextKey of keys in List order,
176 for (int j = 0; j < keys->length(); ++j) {
177 Handle<Object> next_key(keys->get(j), isolate);
178 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
179 PropertyDescriptor desc;
180 Maybe<bool> found =
181 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
182 if (found.IsNothing()) return isolate->heap()->exception();
183 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
184 if (found.FromJust() && desc.enumerable()) {
185 // 4c ii 1. Let propValue be ? Get(from, nextKey).
186 Handle<Object> prop_value;
187 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
188 isolate, prop_value,
189 Runtime::GetObjectProperty(isolate, from, next_key));
190 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
191 Handle<Object> status;
192 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
193 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
194 prop_value, STRICT));
195 }
196 }
197 }
198 // 5. Return to.
199 return *to;
200 }
201
202 // ES6 section 19.1.3.4 Object.prototype.propertyIsEnumerable ( V )
203 BUILTIN(ObjectPrototypePropertyIsEnumerable) {
204 HandleScope scope(isolate);
205 Handle<JSReceiver> object;
206 Handle<Name> name;
207 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
208 isolate, name, Object::ToName(isolate, args.atOrUndefined(isolate, 1)));
209 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
210 isolate, object, JSReceiver::ToObject(isolate, args.receiver()));
211 Maybe<PropertyAttributes> maybe =
212 JSReceiver::GetOwnPropertyAttributes(object, name);
213 if (!maybe.IsJust()) return isolate->heap()->exception();
214 if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value();
215 return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
216 }
217
218 namespace { // anonymous namespace for ObjectProtoToString()
219
220 void IsString(CodeStubAssembler* assembler, compiler::Node* object,
221 CodeStubAssembler::Label* if_string,
222 CodeStubAssembler::Label* if_notstring) {
223 typedef compiler::Node Node;
224 typedef CodeStubAssembler::Label Label;
225
226 Label if_notsmi(assembler);
227 assembler->Branch(assembler->WordIsSmi(object), if_notstring, &if_notsmi);
228
229 assembler->Bind(&if_notsmi);
230 {
231 Node* instance_type = assembler->LoadInstanceType(object);
232
233 assembler->Branch(
234 assembler->Int32LessThan(
235 instance_type, assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
236 if_string, if_notstring);
237 }
238 }
239
240 void ReturnToStringFormat(CodeStubAssembler* assembler, compiler::Node* context,
241 compiler::Node* string) {
242 typedef compiler::Node Node;
243
244 Node* lhs = assembler->HeapConstant(
245 assembler->factory()->NewStringFromStaticChars("[object "));
246 Node* rhs = assembler->HeapConstant(
247 assembler->factory()->NewStringFromStaticChars("]"));
248
249 Callable callable = CodeFactory::StringAdd(
250 assembler->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
251
252 assembler->Return(assembler->CallStub(
253 callable, context, assembler->CallStub(callable, context, lhs, string),
254 rhs));
255 }
256
257 void ReturnIfPrimitive(CodeStubAssembler* assembler,
258 compiler::Node* instance_type,
259 CodeStubAssembler::Label* return_string,
260 CodeStubAssembler::Label* return_boolean,
261 CodeStubAssembler::Label* return_number) {
262 assembler->GotoIf(
263 assembler->Int32LessThan(instance_type,
264 assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
265 return_string);
266
267 assembler->GotoIf(assembler->Word32Equal(
268 instance_type, assembler->Int32Constant(ODDBALL_TYPE)),
269 return_boolean);
270
271 assembler->GotoIf(
272 assembler->Word32Equal(instance_type,
273 assembler->Int32Constant(HEAP_NUMBER_TYPE)),
274 return_number);
275 }
276
277 } // namespace
278
279 // ES6 section 19.1.3.6 Object.prototype.toString
280 void Builtins::Generate_ObjectProtoToString(CodeStubAssembler* assembler) {
281 typedef compiler::Node Node;
282 typedef CodeStubAssembler::Label Label;
283 typedef CodeStubAssembler::Variable Variable;
284
285 Label return_undefined(assembler, Label::kDeferred),
286 return_null(assembler, Label::kDeferred),
287 return_arguments(assembler, Label::kDeferred), return_array(assembler),
288 return_api(assembler, Label::kDeferred), return_object(assembler),
289 return_regexp(assembler), return_function(assembler),
290 return_error(assembler), return_date(assembler), return_string(assembler),
291 return_boolean(assembler), return_jsvalue(assembler),
292 return_jsproxy(assembler, Label::kDeferred), return_number(assembler);
293
294 Label if_isproxy(assembler, Label::kDeferred);
295
296 Label checkstringtag(assembler);
297 Label if_tostringtag(assembler), if_notostringtag(assembler);
298
299 Node* receiver = assembler->Parameter(0);
300 Node* context = assembler->Parameter(3);
301
302 assembler->GotoIf(
303 assembler->Word32Equal(receiver, assembler->UndefinedConstant()),
304 &return_undefined);
305
306 assembler->GotoIf(assembler->Word32Equal(receiver, assembler->NullConstant()),
307 &return_null);
308
309 assembler->GotoIf(assembler->WordIsSmi(receiver), &return_number);
310
311 Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
312 ReturnIfPrimitive(assembler, receiver_instance_type, &return_string,
313 &return_boolean, &return_number);
314
315 // for proxies, check IsArray before getting @@toStringTag
316 Variable var_proxy_is_array(assembler, MachineRepresentation::kTagged);
317 var_proxy_is_array.Bind(assembler->BooleanConstant(false));
318
319 assembler->Branch(
320 assembler->Word32Equal(receiver_instance_type,
321 assembler->Int32Constant(JS_PROXY_TYPE)),
322 &if_isproxy, &checkstringtag);
323
324 assembler->Bind(&if_isproxy);
325 {
326 // This can throw
327 var_proxy_is_array.Bind(
328 assembler->CallRuntime(Runtime::kArrayIsArray, context, receiver));
329 assembler->Goto(&checkstringtag);
330 }
331
332 assembler->Bind(&checkstringtag);
333 {
334 Node* to_string_tag_symbol = assembler->HeapConstant(
335 assembler->isolate()->factory()->to_string_tag_symbol());
336
337 GetPropertyStub stub(assembler->isolate());
338 Callable get_property =
339 Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
340 Node* to_string_tag_value = assembler->CallStub(
341 get_property, context, receiver, to_string_tag_symbol);
342
343 IsString(assembler, to_string_tag_value, &if_tostringtag,
344 &if_notostringtag);
345
346 assembler->Bind(&if_tostringtag);
347 ReturnToStringFormat(assembler, context, to_string_tag_value);
348 }
349 assembler->Bind(&if_notostringtag);
350 {
351 size_t const kNumCases = 11;
352 Label* case_labels[kNumCases];
353 int32_t case_values[kNumCases];
354 case_labels[0] = &return_api;
355 case_values[0] = JS_API_OBJECT_TYPE;
356 case_labels[1] = &return_api;
357 case_values[1] = JS_SPECIAL_API_OBJECT_TYPE;
358 case_labels[2] = &return_arguments;
359 case_values[2] = JS_ARGUMENTS_TYPE;
360 case_labels[3] = &return_array;
361 case_values[3] = JS_ARRAY_TYPE;
362 case_labels[4] = &return_function;
363 case_values[4] = JS_BOUND_FUNCTION_TYPE;
364 case_labels[5] = &return_function;
365 case_values[5] = JS_FUNCTION_TYPE;
366 case_labels[6] = &return_error;
367 case_values[6] = JS_ERROR_TYPE;
368 case_labels[7] = &return_date;
369 case_values[7] = JS_DATE_TYPE;
370 case_labels[8] = &return_regexp;
371 case_values[8] = JS_REGEXP_TYPE;
372 case_labels[9] = &return_jsvalue;
373 case_values[9] = JS_VALUE_TYPE;
374 case_labels[10] = &return_jsproxy;
375 case_values[10] = JS_PROXY_TYPE;
376
377 assembler->Switch(receiver_instance_type, &return_object, case_values,
378 case_labels, arraysize(case_values));
379
380 assembler->Bind(&return_undefined);
381 assembler->Return(assembler->HeapConstant(
382 assembler->isolate()->factory()->undefined_to_string()));
383
384 assembler->Bind(&return_null);
385 assembler->Return(assembler->HeapConstant(
386 assembler->isolate()->factory()->null_to_string()));
387
388 assembler->Bind(&return_number);
389 assembler->Return(assembler->HeapConstant(
390 assembler->isolate()->factory()->number_to_string()));
391
392 assembler->Bind(&return_string);
393 assembler->Return(assembler->HeapConstant(
394 assembler->isolate()->factory()->string_to_string()));
395
396 assembler->Bind(&return_boolean);
397 assembler->Return(assembler->HeapConstant(
398 assembler->isolate()->factory()->boolean_to_string()));
399
400 assembler->Bind(&return_arguments);
401 assembler->Return(assembler->HeapConstant(
402 assembler->isolate()->factory()->arguments_to_string()));
403
404 assembler->Bind(&return_array);
405 assembler->Return(assembler->HeapConstant(
406 assembler->isolate()->factory()->array_to_string()));
407
408 assembler->Bind(&return_function);
409 assembler->Return(assembler->HeapConstant(
410 assembler->isolate()->factory()->function_to_string()));
411
412 assembler->Bind(&return_error);
413 assembler->Return(assembler->HeapConstant(
414 assembler->isolate()->factory()->error_to_string()));
415
416 assembler->Bind(&return_date);
417 assembler->Return(assembler->HeapConstant(
418 assembler->isolate()->factory()->date_to_string()));
419
420 assembler->Bind(&return_regexp);
421 assembler->Return(assembler->HeapConstant(
422 assembler->isolate()->factory()->regexp_to_string()));
423
424 assembler->Bind(&return_api);
425 {
426 Node* class_name =
427 assembler->CallRuntime(Runtime::kClassOf, context, receiver);
428 ReturnToStringFormat(assembler, context, class_name);
429 }
430
431 assembler->Bind(&return_jsvalue);
432 {
433 Node* value = assembler->LoadJSValueValue(receiver);
434 assembler->GotoIf(assembler->WordIsSmi(value), &return_number);
435
436 ReturnIfPrimitive(assembler, assembler->LoadInstanceType(value),
437 &return_string, &return_boolean, &return_number);
438 assembler->Goto(&return_object);
439 }
440
441 assembler->Bind(&return_jsproxy);
442 {
443 assembler->GotoIf(assembler->WordEqual(var_proxy_is_array.value(),
444 assembler->BooleanConstant(true)),
445 &return_array);
446
447 Node* map = assembler->LoadMap(receiver);
448
449 // Return object if the proxy {receiver} is not callable.
450 assembler->Branch(
451 assembler->Word32Equal(
452 assembler->Word32And(
453 assembler->LoadMapBitField(map),
454 assembler->Int32Constant(1 << Map::kIsCallable)),
455 assembler->Int32Constant(0)),
456 &return_object, &return_function);
457 }
458
459 // Default
460 assembler->Bind(&return_object);
461 assembler->Return(assembler->HeapConstant(
462 assembler->isolate()->factory()->object_to_string()));
463 }
464 }
465
466 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
467 // TODO(verwaest): Support the common cases with precached map directly in
468 // an Object.create stub.
469 BUILTIN(ObjectCreate) {
470 HandleScope scope(isolate);
471 Handle<Object> prototype = args.atOrUndefined(isolate, 1);
472 if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
473 THROW_NEW_ERROR_RETURN_FAILURE(
474 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
475 }
476
477 // Generate the map with the specified {prototype} based on the Object
478 // function's initial map from the current native context.
479 // TODO(bmeurer): Use a dedicated cache for Object.create; think about
480 // slack tracking for Object.create.
481 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
482 isolate);
483 if (map->prototype() != *prototype) {
484 if (prototype->IsNull(isolate)) {
485 map = isolate->object_with_null_prototype_map();
486 } else if (prototype->IsJSObject()) {
487 Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
488 if (!js_prototype->map()->is_prototype_map()) {
489 JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
490 }
491 Handle<PrototypeInfo> info =
492 Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
493 // TODO(verwaest): Use inobject slack tracking for this map.
494 if (info->HasObjectCreateMap()) {
495 map = handle(info->ObjectCreateMap(), isolate);
496 } else {
497 map = Map::CopyInitialMap(map);
498 Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
499 PrototypeInfo::SetObjectCreateMap(info, map);
500 }
501 } else {
502 map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
503 }
504 }
505
506 // Actually allocate the object.
507 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
508
509 // Define the properties if properties was specified and is not undefined.
510 Handle<Object> properties = args.atOrUndefined(isolate, 2);
511 if (!properties->IsUndefined(isolate)) {
512 RETURN_FAILURE_ON_EXCEPTION(
513 isolate, JSReceiver::DefineProperties(isolate, object, properties));
514 }
515
516 return *object;
517 }
518
519 // ES6 section 19.1.2.3 Object.defineProperties
520 BUILTIN(ObjectDefineProperties) {
521 HandleScope scope(isolate);
522 DCHECK_EQ(3, args.length());
523 Handle<Object> target = args.at<Object>(1);
524 Handle<Object> properties = args.at<Object>(2);
525
526 RETURN_RESULT_OR_FAILURE(
527 isolate, JSReceiver::DefineProperties(isolate, target, properties));
528 }
529
530 // ES6 section 19.1.2.4 Object.defineProperty
531 BUILTIN(ObjectDefineProperty) {
532 HandleScope scope(isolate);
533 DCHECK_EQ(4, args.length());
534 Handle<Object> target = args.at<Object>(1);
535 Handle<Object> key = args.at<Object>(2);
536 Handle<Object> attributes = args.at<Object>(3);
537
538 return JSReceiver::DefineProperty(isolate, target, key, attributes);
539 }
540
541 namespace {
542
543 template <AccessorComponent which_accessor>
544 Object* ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
545 Handle<Object> name, Handle<Object> accessor) {
546 // 1. Let O be ? ToObject(this value).
547 Handle<JSReceiver> receiver;
548 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
549 Object::ConvertReceiver(isolate, object));
550 // 2. If IsCallable(getter) is false, throw a TypeError exception.
551 if (!accessor->IsCallable()) {
552 MessageTemplate::Template message =
553 which_accessor == ACCESSOR_GETTER
554 ? MessageTemplate::kObjectGetterExpectingFunction
555 : MessageTemplate::kObjectSetterExpectingFunction;
556 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
557 }
558 // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
559 // [[Configurable]]: true}.
560 PropertyDescriptor desc;
561 if (which_accessor == ACCESSOR_GETTER) {
562 desc.set_get(accessor);
563 } else {
564 DCHECK(which_accessor == ACCESSOR_SETTER);
565 desc.set_set(accessor);
566 }
567 desc.set_enumerable(true);
568 desc.set_configurable(true);
569 // 4. Let key be ? ToPropertyKey(P).
570 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
571 Object::ToPropertyKey(isolate, name));
572 // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
573 // To preserve legacy behavior, we ignore errors silently rather than
574 // throwing an exception.
575 Maybe<bool> success = JSReceiver::DefineOwnProperty(
576 isolate, receiver, name, &desc, Object::DONT_THROW);
577 MAYBE_RETURN(success, isolate->heap()->exception());
578 if (!success.FromJust()) {
579 isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
580 }
581 // 6. Return undefined.
582 return isolate->heap()->undefined_value();
583 }
584
585 Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
586 Handle<Object> key, AccessorComponent component) {
587 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
588 Object::ConvertReceiver(isolate, object));
589 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
590 Object::ToPropertyKey(isolate, key));
591 bool success = false;
592 LookupIterator it = LookupIterator::PropertyOrElement(
593 isolate, object, key, &success,
594 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
595 DCHECK(success);
596
597 for (; it.IsFound(); it.Next()) {
598 switch (it.state()) {
599 case LookupIterator::INTERCEPTOR:
600 case LookupIterator::NOT_FOUND:
601 case LookupIterator::TRANSITION:
602 UNREACHABLE();
603
604 case LookupIterator::ACCESS_CHECK:
605 if (it.HasAccess()) continue;
606 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
607 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
608 return isolate->heap()->undefined_value();
609
610 case LookupIterator::JSPROXY:
611 return isolate->heap()->undefined_value();
612
613 case LookupIterator::INTEGER_INDEXED_EXOTIC:
614 return isolate->heap()->undefined_value();
615 case LookupIterator::DATA:
616 continue;
617 case LookupIterator::ACCESSOR: {
618 Handle<Object> maybe_pair = it.GetAccessors();
619 if (maybe_pair->IsAccessorPair()) {
620 return *AccessorPair::GetComponent(
621 Handle<AccessorPair>::cast(maybe_pair), component);
622 }
623 }
624 }
625 }
626
627 return isolate->heap()->undefined_value();
628 }
629
630 } // namespace
631
632 // ES6 B.2.2.2 a.k.a.
633 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
634 BUILTIN(ObjectDefineGetter) {
635 HandleScope scope(isolate);
636 Handle<Object> object = args.at<Object>(0); // Receiver.
637 Handle<Object> name = args.at<Object>(1);
638 Handle<Object> getter = args.at<Object>(2);
639 return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
640 }
641
642 // ES6 B.2.2.3 a.k.a.
643 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
644 BUILTIN(ObjectDefineSetter) {
645 HandleScope scope(isolate);
646 Handle<Object> object = args.at<Object>(0); // Receiver.
647 Handle<Object> name = args.at<Object>(1);
648 Handle<Object> setter = args.at<Object>(2);
649 return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
650 }
651
652 // ES6 B.2.2.4 a.k.a.
653 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
654 BUILTIN(ObjectLookupGetter) {
655 HandleScope scope(isolate);
656 Handle<Object> object = args.at<Object>(0);
657 Handle<Object> name = args.at<Object>(1);
658 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
659 }
660
661 // ES6 B.2.2.5 a.k.a.
662 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
663 BUILTIN(ObjectLookupSetter) {
664 HandleScope scope(isolate);
665 Handle<Object> object = args.at<Object>(0);
666 Handle<Object> name = args.at<Object>(1);
667 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
668 }
669
670 // ES6 section 19.1.2.5 Object.freeze ( O )
671 BUILTIN(ObjectFreeze) {
672 HandleScope scope(isolate);
673 Handle<Object> object = args.atOrUndefined(isolate, 1);
674 if (object->IsJSReceiver()) {
675 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
676 FROZEN, Object::THROW_ON_ERROR),
677 isolate->heap()->exception());
678 }
679 return *object;
680 }
681
682 // ES section 19.1.2.9 Object.getPrototypeOf ( O )
683 BUILTIN(ObjectGetPrototypeOf) {
684 HandleScope scope(isolate);
685 Handle<Object> object = args.atOrUndefined(isolate, 1);
686
687 Handle<JSReceiver> receiver;
688 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
689 Object::ToObject(isolate, object));
690
691 RETURN_RESULT_OR_FAILURE(isolate,
692 JSReceiver::GetPrototype(isolate, receiver));
693 }
694
695 // ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
696 BUILTIN(ObjectGetOwnPropertyDescriptor) {
697 HandleScope scope(isolate);
698 // 1. Let obj be ? ToObject(O).
699 Handle<Object> object = args.atOrUndefined(isolate, 1);
700 Handle<JSReceiver> receiver;
701 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
702 Object::ToObject(isolate, object));
703 // 2. Let key be ? ToPropertyKey(P).
704 Handle<Object> property = args.atOrUndefined(isolate, 2);
705 Handle<Name> key;
706 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
707 Object::ToName(isolate, property));
708 // 3. Let desc be ? obj.[[GetOwnProperty]](key).
709 PropertyDescriptor desc;
710 Maybe<bool> found =
711 JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
712 MAYBE_RETURN(found, isolate->heap()->exception());
713 // 4. Return FromPropertyDescriptor(desc).
714 if (!found.FromJust()) return isolate->heap()->undefined_value();
715 return *desc.ToObject(isolate);
716 }
717
718 namespace {
719
720 Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
721 PropertyFilter filter) {
722 HandleScope scope(isolate);
723 Handle<Object> object = args.atOrUndefined(isolate, 1);
724 Handle<JSReceiver> receiver;
725 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
726 Object::ToObject(isolate, object));
727 Handle<FixedArray> keys;
728 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
729 isolate, keys,
730 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
731 GetKeysConversion::kConvertToString));
732 return *isolate->factory()->NewJSArrayWithElements(keys);
733 }
734
735 } // namespace
736
737 // ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
738 BUILTIN(ObjectGetOwnPropertyNames) {
739 return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
740 }
741
742 // ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
743 BUILTIN(ObjectGetOwnPropertySymbols) {
744 return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
745 }
746
747 // ES#sec-object.is Object.is ( value1, value2 )
748 BUILTIN(ObjectIs) {
749 SealHandleScope shs(isolate);
750 DCHECK_EQ(3, args.length());
751 Handle<Object> value1 = args.at<Object>(1);
752 Handle<Object> value2 = args.at<Object>(2);
753 return isolate->heap()->ToBoolean(value1->SameValue(*value2));
754 }
755
756 // ES6 section 19.1.2.11 Object.isExtensible ( O )
757 BUILTIN(ObjectIsExtensible) {
758 HandleScope scope(isolate);
759 Handle<Object> object = args.atOrUndefined(isolate, 1);
760 Maybe<bool> result =
761 object->IsJSReceiver()
762 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
763 : Just(false);
764 MAYBE_RETURN(result, isolate->heap()->exception());
765 return isolate->heap()->ToBoolean(result.FromJust());
766 }
767
768 // ES6 section 19.1.2.12 Object.isFrozen ( O )
769 BUILTIN(ObjectIsFrozen) {
770 HandleScope scope(isolate);
771 Handle<Object> object = args.atOrUndefined(isolate, 1);
772 Maybe<bool> result = object->IsJSReceiver()
773 ? JSReceiver::TestIntegrityLevel(
774 Handle<JSReceiver>::cast(object), FROZEN)
775 : Just(true);
776 MAYBE_RETURN(result, isolate->heap()->exception());
777 return isolate->heap()->ToBoolean(result.FromJust());
778 }
779
780 // ES6 section 19.1.2.13 Object.isSealed ( O )
781 BUILTIN(ObjectIsSealed) {
782 HandleScope scope(isolate);
783 Handle<Object> object = args.atOrUndefined(isolate, 1);
784 Maybe<bool> result = object->IsJSReceiver()
785 ? JSReceiver::TestIntegrityLevel(
786 Handle<JSReceiver>::cast(object), SEALED)
787 : Just(true);
788 MAYBE_RETURN(result, isolate->heap()->exception());
789 return isolate->heap()->ToBoolean(result.FromJust());
790 }
791
792 // ES6 section 19.1.2.14 Object.keys ( O )
793 BUILTIN(ObjectKeys) {
794 HandleScope scope(isolate);
795 Handle<Object> object = args.atOrUndefined(isolate, 1);
796 Handle<JSReceiver> receiver;
797 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
798 Object::ToObject(isolate, object));
799
800 Handle<FixedArray> keys;
801 int enum_length = receiver->map()->EnumLength();
802 if (enum_length != kInvalidEnumCacheSentinel &&
803 JSObject::cast(*receiver)->elements() ==
804 isolate->heap()->empty_fixed_array()) {
805 DCHECK(receiver->IsJSObject());
806 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
807 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
808 DCHECK(!receiver->map()->has_hidden_prototype());
809 DCHECK(JSObject::cast(*receiver)->HasFastProperties());
810 if (enum_length == 0) {
811 keys = isolate->factory()->empty_fixed_array();
812 } else {
813 Handle<FixedArray> cache(
814 receiver->map()->instance_descriptors()->GetEnumCache());
815 keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
816 }
817 } else {
818 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
819 isolate, keys,
820 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
821 ENUMERABLE_STRINGS,
822 GetKeysConversion::kConvertToString));
823 }
824 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
825 }
826
827 BUILTIN(ObjectValues) {
828 HandleScope scope(isolate);
829 Handle<Object> object = args.atOrUndefined(isolate, 1);
830 Handle<JSReceiver> receiver;
831 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
832 Object::ToObject(isolate, object));
833 Handle<FixedArray> values;
834 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
835 isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
836 return *isolate->factory()->NewJSArrayWithElements(values);
837 }
838
839 BUILTIN(ObjectEntries) {
840 HandleScope scope(isolate);
841 Handle<Object> object = args.atOrUndefined(isolate, 1);
842 Handle<JSReceiver> receiver;
843 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
844 Object::ToObject(isolate, object));
845 Handle<FixedArray> entries;
846 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
847 isolate, entries,
848 JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
849 return *isolate->factory()->NewJSArrayWithElements(entries);
850 }
851
852 BUILTIN(ObjectGetOwnPropertyDescriptors) {
853 HandleScope scope(isolate);
854 Handle<Object> object = args.atOrUndefined(isolate, 1);
855
856 Handle<JSReceiver> receiver;
857 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
858 Object::ToObject(isolate, object));
859
860 Handle<FixedArray> keys;
861 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
862 isolate, keys, KeyAccumulator::GetKeys(
863 receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
864 GetKeysConversion::kConvertToString));
865
866 Handle<JSObject> descriptors =
867 isolate->factory()->NewJSObject(isolate->object_function());
868
869 for (int i = 0; i < keys->length(); ++i) {
870 Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
871 PropertyDescriptor descriptor;
872 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
873 isolate, receiver, key, &descriptor);
874 MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
875
876 if (!did_get_descriptor.FromJust()) continue;
877 Handle<Object> from_descriptor = descriptor.ToObject(isolate);
878
879 LookupIterator it = LookupIterator::PropertyOrElement(
880 isolate, descriptors, key, descriptors, LookupIterator::OWN);
881 Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
882 Object::DONT_THROW);
883 CHECK(success.FromJust());
884 }
885
886 return *descriptors;
887 }
888
889 // ES6 section 19.1.2.15 Object.preventExtensions ( O )
890 BUILTIN(ObjectPreventExtensions) {
891 HandleScope scope(isolate);
892 Handle<Object> object = args.atOrUndefined(isolate, 1);
893 if (object->IsJSReceiver()) {
894 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
895 Object::THROW_ON_ERROR),
896 isolate->heap()->exception());
897 }
898 return *object;
899 }
900
901 // ES6 section 19.1.2.17 Object.seal ( O )
902 BUILTIN(ObjectSeal) {
903 HandleScope scope(isolate);
904 Handle<Object> object = args.atOrUndefined(isolate, 1);
905 if (object->IsJSReceiver()) {
906 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
907 SEALED, Object::THROW_ON_ERROR),
908 isolate->heap()->exception());
909 }
910 return *object;
911 }
912
913 } // namespace internal
914 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-number.cc ('k') | src/builtins/builtins-proxy.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698