Line data Source code
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-proxy-gen.h"
6 : #include "src/builtins/builtins-utils-gen.h"
7 : #include "src/builtins/builtins-utils.h"
8 : #include "src/builtins/builtins.h"
9 :
10 : #include "src/counters.h"
11 : #include "src/objects-inl.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
17 93 : TF_BUILTIN(ProxyConstructor, CodeStubAssembler) {
18 : Node* context = Parameter(Descriptor::kContext);
19 31 : ThrowTypeError(context, MessageTemplate::kConstructorNotFunction, "Proxy");
20 31 : }
21 :
22 62 : void ProxiesCodeStubAssembler::GotoIfRevokedProxy(Node* object,
23 : Label* if_proxy_revoked) {
24 62 : Label proxy_not_revoked(this);
25 124 : GotoIfNot(IsJSProxy(object), &proxy_not_revoked);
26 : Branch(IsJSReceiver(LoadObjectField(object, JSProxy::kHandlerOffset)),
27 124 : &proxy_not_revoked, if_proxy_revoked);
28 62 : BIND(&proxy_not_revoked);
29 62 : }
30 :
31 31 : Node* ProxiesCodeStubAssembler::AllocateProxy(Node* target, Node* handler,
32 : Node* context) {
33 31 : VARIABLE(map, MachineRepresentation::kTagged);
34 :
35 31 : Label callable_target(this), constructor_target(this), none_target(this),
36 31 : create_proxy(this);
37 :
38 62 : Node* nativeContext = LoadNativeContext(context);
39 :
40 62 : Branch(IsCallable(target), &callable_target, &none_target);
41 :
42 31 : BIND(&callable_target);
43 : {
44 : // Every object that is a constructor is implicitly callable
45 : // so it's okay to nest this check here
46 62 : GotoIf(IsConstructor(target), &constructor_target);
47 : map.Bind(
48 62 : LoadContextElement(nativeContext, Context::PROXY_CALLABLE_MAP_INDEX));
49 31 : Goto(&create_proxy);
50 : }
51 31 : BIND(&constructor_target);
52 : {
53 : map.Bind(LoadContextElement(nativeContext,
54 62 : Context::PROXY_CONSTRUCTOR_MAP_INDEX));
55 31 : Goto(&create_proxy);
56 : }
57 31 : BIND(&none_target);
58 : {
59 62 : map.Bind(LoadContextElement(nativeContext, Context::PROXY_MAP_INDEX));
60 31 : Goto(&create_proxy);
61 : }
62 :
63 31 : BIND(&create_proxy);
64 31 : Node* proxy = Allocate(JSProxy::kSize);
65 31 : StoreMapNoWriteBarrier(proxy, map.value());
66 : StoreObjectFieldRoot(proxy, JSProxy::kPropertiesOrHashOffset,
67 31 : Heap::kEmptyPropertyDictionaryRootIndex);
68 31 : StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kTargetOffset, target);
69 31 : StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHandlerOffset, handler);
70 : StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHashOffset,
71 62 : UndefinedConstant());
72 :
73 31 : return proxy;
74 : }
75 :
76 62 : Node* ProxiesCodeStubAssembler::AllocateJSArrayForCodeStubArguments(
77 : Node* context, CodeStubArguments& args, Node* argc, ParameterMode mode) {
78 124 : Node* native_context = LoadNativeContext(context);
79 124 : Node* array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
80 : Node* argc_smi = ParameterToTagged(argc, mode);
81 :
82 : Node* array = AllocateJSArray(PACKED_ELEMENTS, array_map, argc, argc_smi,
83 62 : nullptr, mode);
84 124 : Node* elements = LoadElements(array);
85 :
86 124 : VARIABLE(index, MachineType::PointerRepresentation(),
87 : IntPtrConstant(FixedArrayBase::kHeaderSize - kHeapObjectTag));
88 62 : VariableList list({&index}, zone());
89 62 : args.ForEach(list, [=, &index](Node* arg) {
90 : StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, index.value(),
91 62 : arg);
92 62 : Increment(&index, kPointerSize);
93 186 : });
94 62 : return array;
95 : }
96 :
97 : // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
98 155 : TF_BUILTIN(ProxyConstructor_ConstructStub, ProxiesCodeStubAssembler) {
99 : int const kTargetArg = 0;
100 : int const kHandlerArg = 1;
101 :
102 : Node* argc =
103 62 : ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
104 31 : CodeStubArguments args(this, argc);
105 :
106 62 : Node* target = args.GetOptionalArgumentValue(kTargetArg);
107 62 : Node* handler = args.GetOptionalArgumentValue(kHandlerArg);
108 : Node* context = Parameter(BuiltinDescriptor::kContext);
109 :
110 : Label throw_proxy_non_object(this, Label::kDeferred),
111 31 : throw_proxy_handler_or_target_revoked(this, Label::kDeferred),
112 31 : return_create_proxy(this);
113 :
114 62 : GotoIf(TaggedIsSmi(target), &throw_proxy_non_object);
115 62 : GotoIfNot(IsJSReceiver(target), &throw_proxy_non_object);
116 31 : GotoIfRevokedProxy(target, &throw_proxy_handler_or_target_revoked);
117 :
118 62 : GotoIf(TaggedIsSmi(handler), &throw_proxy_non_object);
119 62 : GotoIfNot(IsJSReceiver(handler), &throw_proxy_non_object);
120 31 : GotoIfRevokedProxy(handler, &throw_proxy_handler_or_target_revoked);
121 :
122 31 : args.PopAndReturn(AllocateProxy(target, handler, context));
123 :
124 31 : BIND(&throw_proxy_non_object);
125 31 : ThrowTypeError(context, MessageTemplate::kProxyNonObject);
126 :
127 31 : BIND(&throw_proxy_handler_or_target_revoked);
128 62 : ThrowTypeError(context, MessageTemplate::kProxyHandlerOrTargetRevoked);
129 31 : }
130 :
131 155 : TF_BUILTIN(CallProxy, ProxiesCodeStubAssembler) {
132 : Node* argc = Parameter(Descriptor::kActualArgumentsCount);
133 62 : Node* argc_ptr = ChangeInt32ToIntPtr(argc);
134 : Node* proxy = Parameter(Descriptor::kFunction);
135 : Node* context = Parameter(Descriptor::kContext);
136 :
137 : CSA_ASSERT(this, IsJSProxy(proxy));
138 : CSA_ASSERT(this, IsCallable(proxy));
139 :
140 : Label throw_proxy_handler_revoked(this, Label::kDeferred),
141 31 : trap_undefined(this);
142 :
143 : // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
144 31 : Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
145 :
146 : // 2. If handler is null, throw a TypeError exception.
147 : CSA_ASSERT(this, IsNullOrJSReceiver(handler));
148 62 : GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
149 :
150 : // 3. Assert: Type(handler) is Object.
151 : CSA_ASSERT(this, IsJSReceiver(handler));
152 :
153 : // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
154 : Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
155 :
156 : // 5. Let trap be ? GetMethod(handler, "apply").
157 : // 6. If trap is undefined, then
158 31 : Handle<Name> trap_name = factory()->apply_string();
159 31 : Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
160 :
161 : CodeStubArguments args(this, argc_ptr);
162 62 : Node* receiver = args.GetReceiver();
163 :
164 : // 7. Let argArray be CreateArrayFromList(argumentsList).
165 : Node* array = AllocateJSArrayForCodeStubArguments(context, args, argc_ptr,
166 31 : INTPTR_PARAMETERS);
167 :
168 : // 8. Return Call(trap, handler, «target, thisArgument, argArray»).
169 : Node* result = CallJS(CodeFactory::Call(isolate()), context, trap, handler,
170 62 : target, receiver, array);
171 31 : args.PopAndReturn(result);
172 :
173 31 : BIND(&trap_undefined);
174 : {
175 : // 6.a. Return Call(target, thisArgument, argumentsList).
176 62 : TailCallStub(CodeFactory::Call(isolate()), context, target, argc);
177 : }
178 :
179 31 : BIND(&throw_proxy_handler_revoked);
180 62 : { ThrowTypeError(context, MessageTemplate::kProxyRevoked, "apply"); }
181 31 : }
182 :
183 155 : TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) {
184 : Node* argc = Parameter(Descriptor::kActualArgumentsCount);
185 62 : Node* argc_ptr = ChangeInt32ToIntPtr(argc);
186 : Node* proxy = Parameter(Descriptor::kFunction);
187 : Node* new_target = Parameter(Descriptor::kNewTarget);
188 : Node* context = Parameter(Descriptor::kContext);
189 :
190 : CSA_ASSERT(this, IsJSProxy(proxy));
191 : CSA_ASSERT(this, IsCallable(proxy));
192 :
193 : Label throw_proxy_handler_revoked(this, Label::kDeferred),
194 31 : trap_undefined(this), not_an_object(this, Label::kDeferred);
195 :
196 : // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
197 31 : Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
198 :
199 : // 2. If handler is null, throw a TypeError exception.
200 : CSA_ASSERT(this, IsNullOrJSReceiver(handler));
201 62 : GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
202 :
203 : // 3. Assert: Type(handler) is Object.
204 : CSA_ASSERT(this, IsJSReceiver(handler));
205 :
206 : // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
207 : Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
208 :
209 : // 5. Let trap be ? GetMethod(handler, "construct").
210 : // 6. If trap is undefined, then
211 31 : Handle<Name> trap_name = factory()->construct_string();
212 31 : Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
213 :
214 : CodeStubArguments args(this, argc_ptr);
215 :
216 : // 7. Let argArray be CreateArrayFromList(argumentsList).
217 : Node* array = AllocateJSArrayForCodeStubArguments(context, args, argc_ptr,
218 31 : INTPTR_PARAMETERS);
219 :
220 : // 8. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »).
221 : Node* new_obj = CallJS(CodeFactory::Call(isolate()), context, trap, handler,
222 62 : target, array, new_target);
223 :
224 : // 9. If Type(newObj) is not Object, throw a TypeError exception.
225 62 : GotoIf(TaggedIsSmi(new_obj), ¬_an_object);
226 62 : GotoIfNot(IsJSReceiver(new_obj), ¬_an_object);
227 :
228 : // 10. Return newObj.
229 31 : args.PopAndReturn(new_obj);
230 :
231 31 : BIND(¬_an_object);
232 : {
233 31 : ThrowTypeError(context, MessageTemplate::kProxyConstructNonObject, new_obj);
234 : }
235 :
236 31 : BIND(&trap_undefined);
237 : {
238 : // 6.a. Assert: target has a [[Construct]] internal method.
239 : CSA_ASSERT(this, IsConstructor(target));
240 :
241 : // 6.b. Return ? Construct(target, argumentsList, newTarget).
242 : TailCallStub(CodeFactory::Construct(isolate()), context, target, new_target,
243 62 : argc);
244 : }
245 :
246 31 : BIND(&throw_proxy_handler_revoked);
247 62 : { ThrowTypeError(context, MessageTemplate::kProxyRevoked, "construct"); }
248 31 : }
249 :
250 124 : TF_BUILTIN(ProxyHasProperty, ProxiesCodeStubAssembler) {
251 : Node* context = Parameter(Descriptor::kContext);
252 : Node* proxy = Parameter(Descriptor::kProxy);
253 : Node* name = Parameter(Descriptor::kName);
254 :
255 : CSA_ASSERT(this, IsJSProxy(proxy));
256 :
257 : // 1. Assert: IsPropertyKey(P) is true.
258 : CSA_ASSERT(this, IsName(name));
259 : CSA_ASSERT(this, Word32Equal(IsPrivateSymbol(name), Int32Constant(0)));
260 :
261 : Label throw_proxy_handler_revoked(this, Label::kDeferred),
262 31 : trap_undefined(this),
263 31 : if_try_get_own_property_bailout(this, Label::kDeferred),
264 31 : trap_not_callable(this, Label::kDeferred), return_true(this),
265 31 : return_false(this), check_target_desc(this);
266 :
267 : // 2. Let handler be O.[[ProxyHandler]].
268 31 : Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
269 :
270 : // 3. If handler is null, throw a TypeError exception.
271 : // 4. Assert: Type(handler) is Object.
272 62 : GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
273 :
274 : // 5. Let target be O.[[ProxyTarget]].
275 : Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
276 :
277 : // 6. Let trap be ? GetMethod(handler, "has").
278 : // 7. If trap is undefined, then (see 7.a below).
279 31 : Handle<Name> trap_name = factory()->has_string();
280 31 : Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
281 :
282 62 : GotoIf(TaggedIsSmi(trap), &trap_not_callable);
283 62 : GotoIfNot(IsCallable(trap), &trap_not_callable);
284 :
285 : // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, P
286 : // »)).
287 : BranchIfToBooleanIsTrue(CallJS(CodeFactory::Call(isolate()), context, trap,
288 : handler, target, name),
289 62 : &return_true, &check_target_desc);
290 :
291 31 : BIND(&check_target_desc);
292 : {
293 : // 9. If booleanTrapResult is false, then (see 9.a. in CheckHasTrapResult).
294 : CheckHasTrapResult(context, target, proxy, name, &return_false,
295 31 : &if_try_get_own_property_bailout);
296 : }
297 :
298 31 : BIND(&if_try_get_own_property_bailout);
299 : {
300 : CallRuntime(Runtime::kCheckProxyHasTrap, context, name, target);
301 62 : Return(FalseConstant());
302 : }
303 :
304 31 : BIND(&trap_undefined);
305 : {
306 : // 7.a. Return ? target.[[HasProperty]](P).
307 : TailCallStub(Builtins::CallableFor(isolate(), Builtins::kHasProperty),
308 62 : context, name, target);
309 : }
310 :
311 31 : BIND(&return_false);
312 62 : Return(FalseConstant());
313 :
314 31 : BIND(&return_true);
315 62 : Return(TrueConstant());
316 :
317 31 : BIND(&throw_proxy_handler_revoked);
318 31 : ThrowTypeError(context, MessageTemplate::kProxyRevoked, "has");
319 :
320 31 : BIND(&trap_not_callable);
321 : ThrowTypeError(context, MessageTemplate::kPropertyNotFunction, trap,
322 93 : StringConstant("has"), proxy);
323 31 : }
324 :
325 124 : TF_BUILTIN(ProxyGetProperty, ProxiesCodeStubAssembler) {
326 : Node* context = Parameter(Descriptor::kContext);
327 : Node* proxy = Parameter(Descriptor::kProxy);
328 : Node* name = Parameter(Descriptor::kName);
329 : Node* receiver = Parameter(Descriptor::kReceiverValue);
330 :
331 : CSA_ASSERT(this, IsJSProxy(proxy));
332 :
333 : // 1. Assert: IsPropertyKey(P) is true.
334 : CSA_ASSERT(this, TaggedIsNotSmi(name));
335 : CSA_ASSERT(this, IsName(name));
336 : CSA_ASSERT(this, Word32Equal(IsPrivateSymbol(name), Int32Constant(0)));
337 :
338 : Label throw_proxy_handler_revoked(this, Label::kDeferred),
339 31 : trap_undefined(this);
340 :
341 : // 2. Let handler be O.[[ProxyHandler]].
342 31 : Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
343 :
344 : // 3. If handler is null, throw a TypeError exception.
345 62 : GotoIf(IsNull(handler), &throw_proxy_handler_revoked);
346 :
347 : // 4. Assert: Type(handler) is Object.
348 : CSA_ASSERT(this, IsJSReceiver(handler));
349 :
350 : // 5. Let target be O.[[ProxyTarget]].
351 : Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
352 :
353 : // 6. Let trap be ? GetMethod(handler, "get").
354 : // 7. If trap is undefined, then (see 7.a below).
355 31 : Handle<Name> trap_name = factory()->get_string();
356 31 : Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
357 :
358 : // 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »).
359 : Node* trap_result = CallJS(
360 : CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
361 62 : context, trap, handler, target, name, receiver);
362 :
363 : // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
364 31 : Label return_result(this);
365 : CheckGetSetTrapResult(context, target, proxy, name, trap_result,
366 31 : &return_result, JSProxy::kGet);
367 :
368 31 : BIND(&return_result);
369 : {
370 : // 11. Return trapResult.
371 31 : Return(trap_result);
372 : }
373 :
374 31 : BIND(&trap_undefined);
375 : {
376 : // 7.a. Return ? target.[[Get]](P, Receiver).
377 : // TODO(mslekova): Introduce GetPropertyWithReceiver stub
378 : Return(CallRuntime(Runtime::kGetPropertyWithReceiver, context, target, name,
379 31 : receiver));
380 : }
381 :
382 31 : BIND(&throw_proxy_handler_revoked);
383 62 : ThrowTypeError(context, MessageTemplate::kProxyRevoked, "get");
384 31 : }
385 :
386 124 : TF_BUILTIN(ProxySetProperty, ProxiesCodeStubAssembler) {
387 : Node* context = Parameter(Descriptor::kContext);
388 : Node* proxy = Parameter(Descriptor::kProxy);
389 : Node* name = Parameter(Descriptor::kName);
390 : Node* value = Parameter(Descriptor::kValue);
391 : Node* receiver = Parameter(Descriptor::kReceiverValue);
392 : Node* language_mode = Parameter(Descriptor::kLanguageMode);
393 :
394 : CSA_ASSERT(this, IsJSProxy(proxy));
395 :
396 : // 1. Assert: IsPropertyKey(P) is true.
397 : CSA_ASSERT(this, TaggedIsNotSmi(name));
398 : CSA_ASSERT(this, IsName(name));
399 :
400 : Label throw_proxy_handler_revoked(this, Label::kDeferred),
401 31 : trap_undefined(this), failure(this, Label::kDeferred),
402 31 : continue_checks(this), success(this),
403 31 : private_symbol(this, Label::kDeferred);
404 :
405 62 : GotoIf(IsPrivateSymbol(name), &private_symbol);
406 :
407 : // 2. Let handler be O.[[ProxyHandler]].
408 : Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
409 :
410 : // 3. If handler is null, throw a TypeError exception.
411 62 : GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
412 :
413 : // 4. Assert: Type(handler) is Object.
414 : CSA_ASSERT(this, IsJSReceiver(handler));
415 :
416 : // 5. Let target be O.[[ProxyTarget]].
417 : Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
418 :
419 : // 6. Let trap be ? GetMethod(handler, "set").
420 : // 7. If trap is undefined, then (see 7.a below).
421 31 : Handle<Name> set_string = factory()->set_string();
422 31 : Node* trap = GetMethod(context, handler, set_string, &trap_undefined);
423 :
424 : // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler,
425 : // « target, P, V, Receiver »)).
426 : // 9. If booleanTrapResult is false, return false.
427 : BranchIfToBooleanIsTrue(
428 : CallJS(CodeFactory::Call(isolate(),
429 : ConvertReceiverMode::kNotNullOrUndefined),
430 : context, trap, handler, target, name, value, receiver),
431 62 : &continue_checks, &failure);
432 :
433 31 : BIND(&continue_checks);
434 : {
435 : // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
436 : Label return_result(this);
437 : CheckGetSetTrapResult(context, target, proxy, name, value, &success,
438 31 : JSProxy::kSet);
439 : }
440 :
441 31 : BIND(&failure);
442 : {
443 : Label if_throw(this, Label::kDeferred);
444 : Branch(SmiEqual(language_mode,
445 : SmiConstant(Smi::FromEnum(LanguageMode::kStrict))),
446 93 : &if_throw, &success);
447 :
448 31 : BIND(&if_throw);
449 : ThrowTypeError(context, MessageTemplate::kProxyTrapReturnedFalsishFor,
450 31 : HeapConstant(set_string), name);
451 : }
452 :
453 : // 12. Return true.
454 31 : BIND(&success);
455 31 : Return(value);
456 :
457 31 : BIND(&private_symbol);
458 : {
459 31 : Label failure(this), throw_error(this, Label::kDeferred);
460 :
461 : Branch(SmiEqual(language_mode,
462 : SmiConstant(Smi::FromEnum(LanguageMode::kStrict))),
463 93 : &throw_error, &failure);
464 :
465 31 : BIND(&failure);
466 62 : Return(UndefinedConstant());
467 :
468 31 : BIND(&throw_error);
469 62 : ThrowTypeError(context, MessageTemplate::kProxyPrivate);
470 : }
471 :
472 31 : BIND(&trap_undefined);
473 : {
474 : // 7.a. Return ? target.[[Set]](P, V, Receiver).
475 : CallRuntime(Runtime::kSetPropertyWithReceiver, context, target, name, value,
476 : receiver, language_mode);
477 31 : Return(value);
478 : }
479 :
480 31 : BIND(&throw_proxy_handler_revoked);
481 62 : ThrowTypeError(context, MessageTemplate::kProxyRevoked, "set");
482 31 : }
483 :
484 62 : void ProxiesCodeStubAssembler::CheckGetSetTrapResult(
485 : Node* context, Node* target, Node* proxy, Node* name, Node* trap_result,
486 : Label* check_passed, JSProxy::AccessKind access_kind) {
487 124 : Node* map = LoadMap(target);
488 62 : VARIABLE(var_value, MachineRepresentation::kTagged);
489 124 : VARIABLE(var_details, MachineRepresentation::kWord32);
490 124 : VARIABLE(var_raw_value, MachineRepresentation::kTagged);
491 :
492 62 : Label if_found_value(this), check_in_runtime(this, Label::kDeferred);
493 :
494 124 : Node* instance_type = LoadInstanceType(target);
495 : TryGetOwnProperty(context, target, target, map, instance_type, name,
496 : &if_found_value, &var_value, &var_details, &var_raw_value,
497 62 : check_passed, &check_in_runtime);
498 :
499 62 : BIND(&if_found_value);
500 : {
501 : Label throw_non_configurable_data(this, Label::kDeferred),
502 62 : throw_non_configurable_accessor(this, Label::kDeferred),
503 62 : check_accessor(this), check_data(this);
504 :
505 : // If targetDesc is not undefined and targetDesc.[[Configurable]] is
506 : // false, then:
507 : GotoIfNot(IsSetWord32(var_details.value(),
508 124 : PropertyDetails::kAttributesDontDeleteMask),
509 124 : check_passed);
510 :
511 : // If IsDataDescriptor(targetDesc) is true and
512 : // targetDesc.[[Writable]] is false, then:
513 62 : BranchIfAccessorPair(var_raw_value.value(), &check_accessor, &check_data);
514 :
515 62 : BIND(&check_data);
516 : {
517 : Node* read_only = IsSetWord32(var_details.value(),
518 186 : PropertyDetails::kAttributesReadOnlyMask);
519 62 : GotoIfNot(read_only, check_passed);
520 :
521 : // If SameValue(trapResult, targetDesc.[[Value]]) is false,
522 : // throw a TypeError exception.
523 : BranchIfSameValue(trap_result, var_value.value(), check_passed,
524 62 : &throw_non_configurable_data);
525 : }
526 :
527 62 : BIND(&check_accessor);
528 : {
529 62 : Node* accessor_pair = var_raw_value.value();
530 :
531 62 : if (access_kind == JSProxy::kGet) {
532 : Label continue_check(this, Label::kDeferred);
533 : // 10.b. If IsAccessorDescriptor(targetDesc) is true and
534 : // targetDesc.[[Get]] is undefined, then:
535 : Node* getter =
536 : LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
537 : // Here we check for null as well because if the getter was never
538 : // defined it's set as null.
539 62 : GotoIf(IsUndefined(getter), &continue_check);
540 62 : GotoIf(IsNull(getter), &continue_check);
541 31 : Goto(check_passed);
542 :
543 : // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
544 31 : BIND(&continue_check);
545 62 : GotoIfNot(IsUndefined(trap_result), &throw_non_configurable_accessor);
546 : } else {
547 : // 11.b.i. If targetDesc.[[Set]] is undefined, throw a TypeError
548 : // exception.
549 : Node* setter =
550 : LoadObjectField(accessor_pair, AccessorPair::kSetterOffset);
551 62 : GotoIf(IsUndefined(setter), &throw_non_configurable_accessor);
552 62 : GotoIf(IsNull(setter), &throw_non_configurable_accessor);
553 : }
554 62 : Goto(check_passed);
555 : }
556 :
557 62 : BIND(&check_in_runtime);
558 : {
559 : CallRuntime(Runtime::kCheckProxyGetSetTrapResult, context, name, target,
560 62 : trap_result, SmiConstant(access_kind));
561 62 : Return(trap_result);
562 : }
563 :
564 62 : BIND(&throw_non_configurable_data);
565 : {
566 : ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableData,
567 62 : name, var_value.value(), trap_result);
568 : }
569 :
570 62 : BIND(&throw_non_configurable_accessor);
571 : {
572 : ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableAccessor,
573 62 : name, trap_result);
574 62 : }
575 62 : }
576 62 : }
577 :
578 31 : void ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target,
579 : Node* proxy, Node* name,
580 : Label* check_passed,
581 : Label* if_bailout) {
582 62 : Node* target_map = LoadMap(target);
583 31 : VARIABLE(var_value, MachineRepresentation::kTagged);
584 62 : VARIABLE(var_details, MachineRepresentation::kWord32);
585 62 : VARIABLE(var_raw_value, MachineRepresentation::kTagged);
586 :
587 31 : Label if_found_value(this, Label::kDeferred),
588 31 : throw_non_configurable(this, Label::kDeferred),
589 31 : throw_non_extensible(this, Label::kDeferred);
590 :
591 : // 9.a. Let targetDesc be ? target.[[GetOwnProperty]](P).
592 62 : Node* instance_type = LoadInstanceType(target);
593 : TryGetOwnProperty(context, target, target, target_map, instance_type, name,
594 : &if_found_value, &var_value, &var_details, &var_raw_value,
595 31 : check_passed, if_bailout);
596 :
597 : // 9.b. If targetDesc is not undefined, then (see 9.b.i. below).
598 31 : BIND(&if_found_value);
599 : {
600 : // 9.b.i. If targetDesc.[[Configurable]] is false, throw a TypeError
601 : // exception.
602 : Node* non_configurable = IsSetWord32(
603 93 : var_details.value(), PropertyDetails::kAttributesDontDeleteMask);
604 31 : GotoIf(non_configurable, &throw_non_configurable);
605 :
606 : // 9.b.ii. Let extensibleTarget be ? IsExtensible(target).
607 31 : Node* target_extensible = IsExtensibleMap(target_map);
608 :
609 : // 9.b.iii. If extensibleTarget is false, throw a TypeError exception.
610 31 : GotoIfNot(target_extensible, &throw_non_extensible);
611 31 : Goto(check_passed);
612 : }
613 :
614 31 : BIND(&throw_non_configurable);
615 31 : { ThrowTypeError(context, MessageTemplate::kProxyHasNonConfigurable, name); }
616 :
617 31 : BIND(&throw_non_extensible);
618 62 : { ThrowTypeError(context, MessageTemplate::kProxyHasNonExtensible, name); }
619 31 : }
620 :
621 : } // namespace internal
622 : } // namespace v8
|