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 = JSReceiver::DefineOwnProperty(
45       isolate, Handle<JSReceiver>::cast(target), name, &desc, kDontThrow);
46   MAYBE_RETURN(result, isolate->heap()->exception());
47   return *isolate->factory()->ToBoolean(result.FromJust());
48 }
49 
50 // ES6 section 26.1.4 Reflect.deleteProperty
BUILTIN(ReflectDeleteProperty)51 BUILTIN(ReflectDeleteProperty) {
52   HandleScope scope(isolate);
53   DCHECK_EQ(3, args.length());
54   Handle<Object> target = args.at(1);
55   Handle<Object> key = args.at(2);
56 
57   if (!target->IsJSReceiver()) {
58     THROW_NEW_ERROR_RETURN_FAILURE(
59         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
60                               isolate->factory()->NewStringFromAsciiChecked(
61                                   "Reflect.deleteProperty")));
62   }
63 
64   Handle<Name> name;
65   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
66                                      Object::ToName(isolate, key));
67 
68   Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
69       Handle<JSReceiver>::cast(target), name, LanguageMode::kSloppy);
70   MAYBE_RETURN(result, isolate->heap()->exception());
71   return *isolate->factory()->ToBoolean(result.FromJust());
72 }
73 
74 // ES6 section 26.1.6 Reflect.get
BUILTIN(ReflectGet)75 BUILTIN(ReflectGet) {
76   HandleScope scope(isolate);
77   Handle<Object> target = args.atOrUndefined(isolate, 1);
78   Handle<Object> key = args.atOrUndefined(isolate, 2);
79   Handle<Object> receiver = args.length() > 3 ? args.at(3) : target;
80 
81   if (!target->IsJSReceiver()) {
82     THROW_NEW_ERROR_RETURN_FAILURE(
83         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
84                               isolate->factory()->NewStringFromAsciiChecked(
85                                   "Reflect.get")));
86   }
87 
88   Handle<Name> name;
89   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
90                                      Object::ToName(isolate, key));
91 
92   RETURN_RESULT_OR_FAILURE(
93       isolate, Object::GetPropertyOrElement(receiver, name,
94                                             Handle<JSReceiver>::cast(target)));
95 }
96 
97 // ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
BUILTIN(ReflectGetOwnPropertyDescriptor)98 BUILTIN(ReflectGetOwnPropertyDescriptor) {
99   HandleScope scope(isolate);
100   DCHECK_EQ(3, args.length());
101   Handle<Object> target = args.at(1);
102   Handle<Object> key = args.at(2);
103 
104   if (!target->IsJSReceiver()) {
105     THROW_NEW_ERROR_RETURN_FAILURE(
106         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
107                               isolate->factory()->NewStringFromAsciiChecked(
108                                   "Reflect.getOwnPropertyDescriptor")));
109   }
110 
111   Handle<Name> name;
112   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
113                                      Object::ToName(isolate, key));
114 
115   PropertyDescriptor desc;
116   Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
117       isolate, Handle<JSReceiver>::cast(target), name, &desc);
118   MAYBE_RETURN(found, isolate->heap()->exception());
119   if (!found.FromJust()) return isolate->heap()->undefined_value();
120   return *desc.ToObject(isolate);
121 }
122 
123 // ES6 section 26.1.8 Reflect.getPrototypeOf
BUILTIN(ReflectGetPrototypeOf)124 BUILTIN(ReflectGetPrototypeOf) {
125   HandleScope scope(isolate);
126   DCHECK_EQ(2, args.length());
127   Handle<Object> target = args.at(1);
128 
129   if (!target->IsJSReceiver()) {
130     THROW_NEW_ERROR_RETURN_FAILURE(
131         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
132                               isolate->factory()->NewStringFromAsciiChecked(
133                                   "Reflect.getPrototypeOf")));
134   }
135   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
136   RETURN_RESULT_OR_FAILURE(isolate,
137                            JSReceiver::GetPrototype(isolate, receiver));
138 }
139 
140 // ES6 section 26.1.10 Reflect.isExtensible
BUILTIN(ReflectIsExtensible)141 BUILTIN(ReflectIsExtensible) {
142   HandleScope scope(isolate);
143   DCHECK_EQ(2, args.length());
144   Handle<Object> target = args.at(1);
145 
146   if (!target->IsJSReceiver()) {
147     THROW_NEW_ERROR_RETURN_FAILURE(
148         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
149                               isolate->factory()->NewStringFromAsciiChecked(
150                                   "Reflect.isExtensible")));
151   }
152 
153   Maybe<bool> result =
154       JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
155   MAYBE_RETURN(result, isolate->heap()->exception());
156   return *isolate->factory()->ToBoolean(result.FromJust());
157 }
158 
159 // ES6 section 26.1.11 Reflect.ownKeys
BUILTIN(ReflectOwnKeys)160 BUILTIN(ReflectOwnKeys) {
161   HandleScope scope(isolate);
162   DCHECK_EQ(2, args.length());
163   Handle<Object> target = args.at(1);
164 
165   if (!target->IsJSReceiver()) {
166     THROW_NEW_ERROR_RETURN_FAILURE(
167         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
168                               isolate->factory()->NewStringFromAsciiChecked(
169                                   "Reflect.ownKeys")));
170   }
171 
172   Handle<FixedArray> keys;
173   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
174       isolate, keys,
175       KeyAccumulator::GetKeys(Handle<JSReceiver>::cast(target),
176                               KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
177                               GetKeysConversion::kConvertToString));
178   return *isolate->factory()->NewJSArrayWithElements(keys);
179 }
180 
181 // ES6 section 26.1.12 Reflect.preventExtensions
BUILTIN(ReflectPreventExtensions)182 BUILTIN(ReflectPreventExtensions) {
183   HandleScope scope(isolate);
184   DCHECK_EQ(2, args.length());
185   Handle<Object> target = args.at(1);
186 
187   if (!target->IsJSReceiver()) {
188     THROW_NEW_ERROR_RETURN_FAILURE(
189         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
190                               isolate->factory()->NewStringFromAsciiChecked(
191                                   "Reflect.preventExtensions")));
192   }
193 
194   Maybe<bool> result = JSReceiver::PreventExtensions(
195       Handle<JSReceiver>::cast(target), kDontThrow);
196   MAYBE_RETURN(result, isolate->heap()->exception());
197   return *isolate->factory()->ToBoolean(result.FromJust());
198 }
199 
200 // ES6 section 26.1.13 Reflect.set
BUILTIN(ReflectSet)201 BUILTIN(ReflectSet) {
202   HandleScope scope(isolate);
203   Handle<Object> target = args.atOrUndefined(isolate, 1);
204   Handle<Object> key = args.atOrUndefined(isolate, 2);
205   Handle<Object> value = args.atOrUndefined(isolate, 3);
206   Handle<Object> receiver = args.length() > 4 ? args.at(4) : target;
207 
208   if (!target->IsJSReceiver()) {
209     THROW_NEW_ERROR_RETURN_FAILURE(
210         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
211                               isolate->factory()->NewStringFromAsciiChecked(
212                                   "Reflect.set")));
213   }
214 
215   Handle<Name> name;
216   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
217                                      Object::ToName(isolate, key));
218 
219   LookupIterator it = LookupIterator::PropertyOrElement(
220       isolate, receiver, name, Handle<JSReceiver>::cast(target));
221   Maybe<bool> result = Object::SetSuperProperty(
222       &it, value, LanguageMode::kSloppy, Object::MAY_BE_STORE_FROM_KEYED);
223   MAYBE_RETURN(result, isolate->heap()->exception());
224   return *isolate->factory()->ToBoolean(result.FromJust());
225 }
226 
227 // ES6 section 26.1.14 Reflect.setPrototypeOf
BUILTIN(ReflectSetPrototypeOf)228 BUILTIN(ReflectSetPrototypeOf) {
229   HandleScope scope(isolate);
230   DCHECK_EQ(3, args.length());
231   Handle<Object> target = args.at(1);
232   Handle<Object> proto = args.at(2);
233 
234   if (!target->IsJSReceiver()) {
235     THROW_NEW_ERROR_RETURN_FAILURE(
236         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
237                               isolate->factory()->NewStringFromAsciiChecked(
238                                   "Reflect.setPrototypeOf")));
239   }
240 
241   if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) {
242     THROW_NEW_ERROR_RETURN_FAILURE(
243         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
244   }
245 
246   Maybe<bool> result = JSReceiver::SetPrototype(
247       Handle<JSReceiver>::cast(target), proto, true, kDontThrow);
248   MAYBE_RETURN(result, isolate->heap()->exception());
249   return *isolate->factory()->ToBoolean(result.FromJust());
250 }
251 
252 }  // namespace internal
253 }  // namespace v8
254