| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include 'src/builtins/builtins-proxy-gen.h' |
| |
| namespace proxy { |
| |
| // ES #sec-proxy-object-internal-methods-and-internal-slots-delete-p |
| // https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-delete-p |
| transitioning builtin |
| ProxyDeleteProperty(implicit context: Context)( |
| proxy: JSProxy, name: PropertyKey, languageMode: LanguageModeSmi): JSAny { |
| const kTrapName: constexpr string = 'deleteProperty'; |
| // Handle deeply nested proxy. |
| PerformStackCheck(); |
| // 1. Assert: IsPropertyKey(P) is true. |
| assert(TaggedIsNotSmi(name)); |
| assert(Is<Name>(name)); |
| assert(!IsPrivateSymbol(name)); |
| |
| try { |
| // 2. Let handler be O.[[ProxyHandler]]. |
| // 3. If handler is null, throw a TypeError exception. |
| // 4. Assert: Type(handler) is Object. |
| assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler)); |
| const handler = |
| Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked; |
| |
| // 5. Let target be O.[[ProxyTarget]]. |
| const target = UnsafeCast<JSReceiver>(proxy.target); |
| |
| // 6. Let trap be ? GetMethod(handler, "deleteProperty"). |
| // 7. If trap is undefined, then (see 7.a below). |
| const trap: Callable = GetMethod(handler, kTrapName) |
| otherwise goto TrapUndefined(target); |
| |
| // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, |
| // « target, P »)). |
| const trapResult = Call(context, trap, handler, target, name); |
| |
| // 9. If booleanTrapResult is false, return false. |
| if (!ToBoolean(trapResult)) { |
| const strictValue: LanguageModeSmi = LanguageMode::kStrict; |
| if (languageMode == strictValue) { |
| ThrowTypeError( |
| MessageTemplate::kProxyTrapReturnedFalsishFor, kTrapName, name); |
| } |
| return False; |
| } |
| |
| // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). |
| // 11. If targetDesc is undefined, return true. |
| // 12. If targetDesc.[[Configurable]] is false, throw a TypeError |
| // exception. |
| // 13. Let extensibleTarget be ? IsExtensible(target). |
| // 14. If extensibleTarget is false, throw a TypeError exception. |
| CheckDeleteTrapResult(target, proxy, name); |
| |
| // 15. Return true. |
| return True; |
| } label TrapUndefined(target: JSAny) { |
| // 7.a. Return ? target.[[Delete]](P). |
| return DeleteProperty(target, name, languageMode); |
| } label ThrowProxyHandlerRevoked deferred { |
| ThrowTypeError(MessageTemplate::kProxyRevoked, kTrapName); |
| } |
| } |
| } |