Home | History | Annotate | Download | only in builtins
      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/counters.h"
      9 #include "src/keys.h"
     10 #include "src/lookup.h"
     11 #include "src/objects-inl.h"
     12 #include "src/property-descriptor.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 
     17 // -----------------------------------------------------------------------------
     18 // ES6 section 26.1 The Reflect Object
     19 
     20 // ES6 section 26.1.3 Reflect.defineProperty
     21 BUILTIN(ReflectDefineProperty) {
     22   HandleScope scope(isolate);
     23   DCHECK_EQ(4, args.length());
     24   Handle<Object> target = args.at(1);
     25   Handle<Object> key = args.at(2);
     26   Handle<Object> attributes = args.at(3);
     27 
     28   if (!target->IsJSReceiver()) {
     29     THROW_NEW_ERROR_RETURN_FAILURE(
     30         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
     31                               isolate->factory()->NewStringFromAsciiChecked(
     32                                   "Reflect.defineProperty")));
     33   }
     34 
     35   Handle<Name> name;
     36   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
     37                                      Object::ToName(isolate, key));
     38 
     39   PropertyDescriptor desc;
     40   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
     41     return isolate->heap()->exception();
     42   }
     43 
     44   Maybe<bool> result =
     45       JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
     46                                     name, &desc, Object::DONT_THROW);
     47   MAYBE_RETURN(result, isolate->heap()->exception());
     48   return *isolate->factory()->ToBoolean(result.FromJust());
     49 }
     50 
     51 // ES6 section 26.1.4 Reflect.deleteProperty
     52 BUILTIN(ReflectDeleteProperty) {
     53   HandleScope scope(isolate);
     54   DCHECK_EQ(3, args.length());
     55   Handle<Object> target = args.at(1);
     56   Handle<Object> key = args.at(2);
     57 
     58   if (!target->IsJSReceiver()) {
     59     THROW_NEW_ERROR_RETURN_FAILURE(
     60         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
     61                               isolate->factory()->NewStringFromAsciiChecked(
     62                                   "Reflect.deleteProperty")));
     63   }
     64 
     65   Handle<Name> name;
     66   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
     67                                      Object::ToName(isolate, key));
     68 
     69   Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
     70       Handle<JSReceiver>::cast(target), name, SLOPPY);
     71   MAYBE_RETURN(result, isolate->heap()->exception());
     72   return *isolate->factory()->ToBoolean(result.FromJust());
     73 }
     74 
     75 // ES6 section 26.1.6 Reflect.get
     76 BUILTIN(ReflectGet) {
     77   HandleScope scope(isolate);
     78   Handle<Object> target = args.atOrUndefined(isolate, 1);
     79   Handle<Object> key = args.atOrUndefined(isolate, 2);
     80   Handle<Object> receiver = args.length() > 3 ? args.at(3) : target;
     81 
     82   if (!target->IsJSReceiver()) {
     83     THROW_NEW_ERROR_RETURN_FAILURE(
     84         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
     85                               isolate->factory()->NewStringFromAsciiChecked(
     86                                   "Reflect.get")));
     87   }
     88 
     89   Handle<Name> name;
     90   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
     91                                      Object::ToName(isolate, key));
     92 
     93   RETURN_RESULT_OR_FAILURE(
     94       isolate, Object::GetPropertyOrElement(receiver, name,
     95                                             Handle<JSReceiver>::cast(target)));
     96 }
     97 
     98 // ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
     99 BUILTIN(ReflectGetOwnPropertyDescriptor) {
    100   HandleScope scope(isolate);
    101   DCHECK_EQ(3, args.length());
    102   Handle<Object> target = args.at(1);
    103   Handle<Object> key = args.at(2);
    104 
    105   if (!target->IsJSReceiver()) {
    106     THROW_NEW_ERROR_RETURN_FAILURE(
    107         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
    108                               isolate->factory()->NewStringFromAsciiChecked(
    109                                   "Reflect.getOwnPropertyDescriptor")));
    110   }
    111 
    112   Handle<Name> name;
    113   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
    114                                      Object::ToName(isolate, key));
    115 
    116   PropertyDescriptor desc;
    117   Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
    118       isolate, Handle<JSReceiver>::cast(target), name, &desc);
    119   MAYBE_RETURN(found, isolate->heap()->exception());
    120   if (!found.FromJust()) return isolate->heap()->undefined_value();
    121   return *desc.ToObject(isolate);
    122 }
    123 
    124 // ES6 section 26.1.8 Reflect.getPrototypeOf
    125 BUILTIN(ReflectGetPrototypeOf) {
    126   HandleScope scope(isolate);
    127   DCHECK_EQ(2, args.length());
    128   Handle<Object> target = args.at(1);
    129 
    130   if (!target->IsJSReceiver()) {
    131     THROW_NEW_ERROR_RETURN_FAILURE(
    132         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
    133                               isolate->factory()->NewStringFromAsciiChecked(
    134                                   "Reflect.getPrototypeOf")));
    135   }
    136   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
    137   RETURN_RESULT_OR_FAILURE(isolate,
    138                            JSReceiver::GetPrototype(isolate, receiver));
    139 }
    140 
    141 // ES6 section 26.1.9 Reflect.has
    142 BUILTIN(ReflectHas) {
    143   HandleScope scope(isolate);
    144   DCHECK_EQ(3, args.length());
    145   Handle<Object> target = args.at(1);
    146   Handle<Object> key = args.at(2);
    147 
    148   if (!target->IsJSReceiver()) {
    149     THROW_NEW_ERROR_RETURN_FAILURE(
    150         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
    151                               isolate->factory()->NewStringFromAsciiChecked(
    152                                   "Reflect.has")));
    153   }
    154 
    155   Handle<Name> name;
    156   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
    157                                      Object::ToName(isolate, key));
    158 
    159   Maybe<bool> result =
    160       JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
    161   return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
    162                          : isolate->heap()->exception();
    163 }
    164 
    165 // ES6 section 26.1.10 Reflect.isExtensible
    166 BUILTIN(ReflectIsExtensible) {
    167   HandleScope scope(isolate);
    168   DCHECK_EQ(2, args.length());
    169   Handle<Object> target = args.at(1);
    170 
    171   if (!target->IsJSReceiver()) {
    172     THROW_NEW_ERROR_RETURN_FAILURE(
    173         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
    174                               isolate->factory()->NewStringFromAsciiChecked(
    175                                   "Reflect.isExtensible")));
    176   }
    177 
    178   Maybe<bool> result =
    179       JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
    180   MAYBE_RETURN(result, isolate->heap()->exception());
    181   return *isolate->factory()->ToBoolean(result.FromJust());
    182 }
    183 
    184 // ES6 section 26.1.11 Reflect.ownKeys
    185 BUILTIN(ReflectOwnKeys) {
    186   HandleScope scope(isolate);
    187   DCHECK_EQ(2, args.length());
    188   Handle<Object> target = args.at(1);
    189 
    190   if (!target->IsJSReceiver()) {
    191     THROW_NEW_ERROR_RETURN_FAILURE(
    192         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
    193                               isolate->factory()->NewStringFromAsciiChecked(
    194                                   "Reflect.ownKeys")));
    195   }
    196 
    197   Handle<FixedArray> keys;
    198   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    199       isolate, keys,
    200       KeyAccumulator::GetKeys(Handle<JSReceiver>::cast(target),
    201                               KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
    202                               GetKeysConversion::kConvertToString));
    203   return *isolate->factory()->NewJSArrayWithElements(keys);
    204 }
    205 
    206 // ES6 section 26.1.12 Reflect.preventExtensions
    207 BUILTIN(ReflectPreventExtensions) {
    208   HandleScope scope(isolate);
    209   DCHECK_EQ(2, args.length());
    210   Handle<Object> target = args.at(1);
    211 
    212   if (!target->IsJSReceiver()) {
    213     THROW_NEW_ERROR_RETURN_FAILURE(
    214         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
    215                               isolate->factory()->NewStringFromAsciiChecked(
    216                                   "Reflect.preventExtensions")));
    217   }
    218 
    219   Maybe<bool> result = JSReceiver::PreventExtensions(
    220       Handle<JSReceiver>::cast(target), Object::DONT_THROW);
    221   MAYBE_RETURN(result, isolate->heap()->exception());
    222   return *isolate->factory()->ToBoolean(result.FromJust());
    223 }
    224 
    225 // ES6 section 26.1.13 Reflect.set
    226 BUILTIN(ReflectSet) {
    227   HandleScope scope(isolate);
    228   Handle<Object> target = args.atOrUndefined(isolate, 1);
    229   Handle<Object> key = args.atOrUndefined(isolate, 2);
    230   Handle<Object> value = args.atOrUndefined(isolate, 3);
    231   Handle<Object> receiver = args.length() > 4 ? args.at(4) : target;
    232 
    233   if (!target->IsJSReceiver()) {
    234     THROW_NEW_ERROR_RETURN_FAILURE(
    235         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
    236                               isolate->factory()->NewStringFromAsciiChecked(
    237                                   "Reflect.set")));
    238   }
    239 
    240   Handle<Name> name;
    241   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
    242                                      Object::ToName(isolate, key));
    243 
    244   LookupIterator it = LookupIterator::PropertyOrElement(
    245       isolate, receiver, name, Handle<JSReceiver>::cast(target));
    246   Maybe<bool> result = Object::SetSuperProperty(
    247       &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
    248   MAYBE_RETURN(result, isolate->heap()->exception());
    249   return *isolate->factory()->ToBoolean(result.FromJust());
    250 }
    251 
    252 // ES6 section 26.1.14 Reflect.setPrototypeOf
    253 BUILTIN(ReflectSetPrototypeOf) {
    254   HandleScope scope(isolate);
    255   DCHECK_EQ(3, args.length());
    256   Handle<Object> target = args.at(1);
    257   Handle<Object> proto = args.at(2);
    258 
    259   if (!target->IsJSReceiver()) {
    260     THROW_NEW_ERROR_RETURN_FAILURE(
    261         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
    262                               isolate->factory()->NewStringFromAsciiChecked(
    263                                   "Reflect.setPrototypeOf")));
    264   }
    265 
    266   if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) {
    267     THROW_NEW_ERROR_RETURN_FAILURE(
    268         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
    269   }
    270 
    271   Maybe<bool> result = JSReceiver::SetPrototype(
    272       Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
    273   MAYBE_RETURN(result, isolate->heap()->exception());
    274   return *isolate->factory()->ToBoolean(result.FromJust());
    275 }
    276 
    277 }  // namespace internal
    278 }  // namespace v8
    279