LCOV - code coverage report
Current view: top level - src/builtins - builtins-object.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 135 138 97.8 %
Date: 2019-04-18 Functions: 42 61 68.9 %

          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

Generated by: LCOV version 1.10