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