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