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