• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
BUILTIN(ReflectDefineProperty)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
BUILTIN(ReflectDeleteProperty)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
BUILTIN(ReflectGet)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
BUILTIN(ReflectGetOwnPropertyDescriptor)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
BUILTIN(ReflectGetPrototypeOf)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
BUILTIN(ReflectHas)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
BUILTIN(ReflectIsExtensible)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
BUILTIN(ReflectOwnKeys)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
BUILTIN(ReflectPreventExtensions)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
BUILTIN(ReflectSet)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
BUILTIN(ReflectSetPrototypeOf)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