mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-27 14:58:46 +00:00
Note that as of this commit, there aren't any such throwers, and the call site in Heap::allocate will drop exceptions on the floor. This commit only serves to change the declaration of the overrides, make sure they return an empty value, and to propagate OOM errors frm their base initialize invocations.
104 lines
3.8 KiB
C++
104 lines
3.8 KiB
C++
/*
|
|
* Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
|
|
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibJS/Runtime/Array.h>
|
|
#include <LibJS/Runtime/Error.h>
|
|
#include <LibJS/Runtime/GlobalObject.h>
|
|
#include <LibJS/Runtime/ProxyConstructor.h>
|
|
#include <LibJS/Runtime/ProxyObject.h>
|
|
|
|
namespace JS {
|
|
|
|
// 10.5.14 ProxyCreate ( target, handler ), https://tc39.es/ecma262/#sec-proxycreate
|
|
static ThrowCompletionOr<ProxyObject*> proxy_create(VM& vm, Value target, Value handler)
|
|
{
|
|
auto& realm = *vm.current_realm();
|
|
if (!target.is_object())
|
|
return vm.throw_completion<TypeError>(ErrorType::ProxyConstructorBadType, "target", target.to_string_without_side_effects());
|
|
if (!handler.is_object())
|
|
return vm.throw_completion<TypeError>(ErrorType::ProxyConstructorBadType, "handler", handler.to_string_without_side_effects());
|
|
return ProxyObject::create(realm, target.as_object(), handler.as_object()).ptr();
|
|
}
|
|
|
|
ProxyConstructor::ProxyConstructor(Realm& realm)
|
|
: NativeFunction(realm.vm().names.Proxy.as_string(), *realm.intrinsics().function_prototype())
|
|
{
|
|
}
|
|
|
|
ThrowCompletionOr<void> ProxyConstructor::initialize(Realm& realm)
|
|
{
|
|
auto& vm = this->vm();
|
|
MUST_OR_THROW_OOM(NativeFunction::initialize(realm));
|
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
|
define_native_function(realm, vm.names.revocable, revocable, 2, attr);
|
|
|
|
define_direct_property(vm.names.length, Value(2), Attribute::Configurable);
|
|
|
|
return {};
|
|
}
|
|
|
|
// 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler
|
|
ThrowCompletionOr<Value> ProxyConstructor::call()
|
|
{
|
|
auto& vm = this->vm();
|
|
return vm.throw_completion<TypeError>(ErrorType::ConstructorWithoutNew, vm.names.Proxy);
|
|
}
|
|
|
|
// 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler
|
|
ThrowCompletionOr<NonnullGCPtr<Object>> ProxyConstructor::construct(FunctionObject&)
|
|
{
|
|
auto& vm = this->vm();
|
|
return *TRY(proxy_create(vm, vm.argument(0), vm.argument(1)));
|
|
}
|
|
|
|
// 28.2.2.1 Proxy.revocable ( target, handler ), https://tc39.es/ecma262/#sec-proxy.revocable
|
|
JS_DEFINE_NATIVE_FUNCTION(ProxyConstructor::revocable)
|
|
{
|
|
auto& realm = *vm.current_realm();
|
|
|
|
// 1. Let p be ? ProxyCreate(target, handler).
|
|
auto* proxy = TRY(proxy_create(vm, vm.argument(0), vm.argument(1)));
|
|
|
|
// 2. Let revokerClosure be a new Abstract Closure with no parameters that captures nothing and performs the following steps when called:
|
|
auto revoker_closure = [proxy_handle = make_handle(proxy)](auto&) -> ThrowCompletionOr<Value> {
|
|
// a. Let F be the active function object.
|
|
|
|
// b. Let p be F.[[RevocableProxy]].
|
|
auto& proxy = const_cast<ProxyObject&>(*proxy_handle.cell());
|
|
|
|
// c. If p is null, return undefined.
|
|
if (proxy.is_revoked())
|
|
return js_undefined();
|
|
|
|
// d. Set F.[[RevocableProxy]] to null.
|
|
// e. Assert: p is a Proxy object.
|
|
// f. Set p.[[ProxyTarget]] to null.
|
|
// g. Set p.[[ProxyHandler]] to null.
|
|
proxy.revoke();
|
|
|
|
// h. Return undefined.
|
|
return js_undefined();
|
|
};
|
|
|
|
// 3. Let revoker be CreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »).
|
|
// 4. Set revoker.[[RevocableProxy]] to p.
|
|
auto revoker = NativeFunction::create(realm, move(revoker_closure), 0, "");
|
|
|
|
// 5. Let result be OrdinaryObjectCreate(%Object.prototype%).
|
|
auto result = Object::create(realm, realm.intrinsics().object_prototype());
|
|
|
|
// 6. Perform ! CreateDataPropertyOrThrow(result, "proxy", p).
|
|
MUST(result->create_data_property_or_throw(vm.names.proxy, proxy));
|
|
|
|
// 7. Perform ! CreateDataPropertyOrThrow(result, "revoke", revoker).
|
|
MUST(result->create_data_property_or_throw(vm.names.revoke, revoker));
|
|
|
|
// 8. Return result.
|
|
return result;
|
|
}
|
|
|
|
}
|