• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 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
7namespace proxy {
8
9extern transitioning runtime
10SetPropertyWithReceiver(implicit context: Context)(
11    Object, Name, Object, Object): void;
12
13transitioning macro CallThrowTypeErrorIfStrict(implicit context: Context)(
14    message: constexpr MessageTemplate): void {
15  ThrowTypeErrorIfStrict(SmiConstant(message), Null, Null);
16}
17
18// ES #sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
19// https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
20transitioning builtin
21ProxySetProperty(implicit context: Context)(
22    proxy: JSProxy, name: PropertyKey|PrivateSymbol, value: JSAny,
23    receiverValue: JSAny): JSAny {
24  // 1. Assert: IsPropertyKey(P) is true.
25  dcheck(TaggedIsNotSmi(name));
26  dcheck(Is<Name>(name));
27
28  let key: PropertyKey;
29  typeswitch (name) {
30    case (PrivateSymbol): {
31      CallThrowTypeErrorIfStrict(MessageTemplate::kProxyPrivate);
32      return Undefined;
33    }
34    case (name: PropertyKey): {
35      key = name;
36    }
37  }
38
39  try {
40    // 2. Let handler be O.[[ProxyHandler]].
41    // 3. If handler is null, throw a TypeError exception.
42    // 4. Assert: Type(handler) is Object.
43    dcheck(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
44    const handler =
45        Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
46
47    // 5. Let target be O.[[ProxyTarget]].
48    const target = UnsafeCast<JSReceiver>(proxy.target);
49
50    // 6. Let trap be ? GetMethod(handler, "set").
51    // 7. If trap is undefined, then (see 7.a below).
52    const trap: Callable = GetMethod(handler, 'set')
53        otherwise goto TrapUndefined(target);
54
55    // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler,
56    // « target, P, V, Receiver »)).
57    // 9. If booleanTrapResult is false, return false.
58    // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
59    // 11. If targetDesc is not undefined and targetDesc.[[Configurable]] is
60    // false, then
61    //    a. If IsDataDescriptor(targetDesc) is true and
62    //    targetDesc.[[Writable]] is false, then
63    //      i. If SameValue(V, targetDesc.[[Value]]) is false, throw a
64    //      TypeError exception.
65    //    b. If IsAccessorDescriptor(targetDesc) is true, then
66    //      i. If targetDesc.[[Set]] is undefined, throw a TypeError
67    //      exception.
68    // 12. Return true.
69    const trapResult =
70        Call(context, trap, handler, target, key, value, receiverValue);
71    if (ToBoolean(trapResult)) {
72      CheckGetSetTrapResult(target, proxy, name, value, kProxySet);
73      return value;
74    }
75    ThrowTypeErrorIfStrict(
76        SmiConstant(MessageTemplate::kProxyTrapReturnedFalsishFor), 'set',
77        name);
78    return value;
79  } label TrapUndefined(target: Object) {
80    // 7.a. Return ? target.[[Set]](P, V, Receiver).
81    SetPropertyWithReceiver(target, name, value, receiverValue);
82    return value;
83  } label ThrowProxyHandlerRevoked deferred {
84    ThrowTypeError(MessageTemplate::kProxyRevoked, 'set');
85  }
86}
87}
88