1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 19:07:34 +00:00

LibJS: Add all of the FinalizationRegistry.prototype methods

More specifically: cleanupSome, register & unregister.

FinalizationRegistery.prototype.cleanupSome is actually still a stage 2
proposal, but since test262 test cases already exist for it, i decided
to go for it :)
This commit is contained in:
Idan Horowitz 2021-06-15 22:21:24 +03:00 committed by Linus Groh
parent de9fa6622a
commit e1b0719435
7 changed files with 174 additions and 0 deletions

View file

@ -75,6 +75,7 @@ namespace JS {
P(ceil) \
P(charAt) \
P(charCodeAt) \
P(cleanupSome) \
P(clear) \
P(clz32) \
P(concat) \
@ -310,6 +311,7 @@ namespace JS {
P(undefined) \
P(unescape) \
P(unicode) \
P(unregister) \
P(unshift) \
P(value) \
P(valueOf) \
@ -321,6 +323,7 @@ struct CommonPropertyNames {
PropertyName catch_ { "catch", PropertyName::StringMayBeNumber::No };
PropertyName delete_ { "delete", PropertyName::StringMayBeNumber::No };
PropertyName for_ { "for", PropertyName::StringMayBeNumber::No };
PropertyName register_ { "register", PropertyName::StringMayBeNumber::No };
PropertyName return_ { "return", PropertyName::StringMayBeNumber::No };
PropertyName throw_ { "throw", PropertyName::StringMayBeNumber::No };
#define __ENUMERATE(x) PropertyName x { #x, PropertyName::StringMayBeNumber::No };

View file

@ -26,6 +26,7 @@
M(DescWriteNonWritable, "Cannot write to non-writable property '{}'") \
M(DetachedArrayBuffer, "ArrayBuffer is detached") \
M(DivisionByZero, "Division by zero") \
M(FinalizationRegistrySameTargetAndValue, "Target and held value must not be the same") \
M(GetCapabilitiesExecutorCalledMultipleTimes, "GetCapabilitiesExecutor was called multiple times") \
M(InOperatorWithObject, "'in' operator must be used on an object") \
M(InstanceOfOperatorBadPrototype, "'prototype' property of {} is not an object") \

View file

@ -17,6 +17,11 @@ void FinalizationRegistryPrototype::initialize(GlobalObject& global_object)
{
auto& vm = this->vm();
Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(vm.names.cleanupSome, cleanup_some, 0, attr);
define_native_function(vm.names.register_, register_, 2, attr);
define_native_function(vm.names.unregister, unregister, 1, attr);
// 26.2.3.4 FinalizationRegistry.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-finalization-registry.prototype-@@tostringtag
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.FinalizationRegistry.as_string()), Attribute::Configurable);
@ -38,4 +43,68 @@ FinalizationRegistry* FinalizationRegistryPrototype::typed_this(VM& vm, GlobalOb
return static_cast<FinalizationRegistry*>(this_object);
}
// @STAGE 2@ FinalizationRegistry.prototype.cleanupSome ( [ callback ] ), https://github.com/tc39/proposal-cleanup-some/blob/master/spec/finalization-registry.html
JS_DEFINE_NATIVE_FUNCTION(FinalizationRegistryPrototype::cleanup_some)
{
auto* finalization_registry = typed_this(vm, global_object);
if (!finalization_registry)
return {};
auto callback = vm.argument(0);
if (vm.argument_count() > 0 && !callback.is_function()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, callback.to_string_without_side_effects());
return {};
}
finalization_registry->cleanup(callback.is_undefined() ? nullptr : &callback.as_function());
return js_undefined();
}
// 26.2.3.2 FinalizationRegistry.prototype.register ( target, heldValue [ , unregisterToken ] ), https://tc39.es/ecma262/#sec-finalization-registry.prototype.register
JS_DEFINE_NATIVE_FUNCTION(FinalizationRegistryPrototype::register_)
{
auto* finalization_registry = typed_this(vm, global_object);
if (!finalization_registry)
return {};
auto target = vm.argument(0);
if (!target.is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects());
return {};
}
auto held_value = vm.argument(1);
if (same_value(target, held_value)) {
vm.throw_exception<TypeError>(global_object, ErrorType::FinalizationRegistrySameTargetAndValue);
return {};
}
auto unregister_token = vm.argument(2);
if (!unregister_token.is_object() && !unregister_token.is_undefined()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, unregister_token.to_string_without_side_effects());
return {};
}
finalization_registry->add_finalization_record(target.as_cell(), held_value, unregister_token.is_undefined() ? nullptr : &unregister_token.as_object());
return js_undefined();
}
// 26.2.3.3 FinalizationRegistry.prototype.unregister ( unregisterToken ), https://tc39.es/ecma262/#sec-finalization-registry.prototype.unregister
JS_DEFINE_NATIVE_FUNCTION(FinalizationRegistryPrototype::unregister)
{
auto* finalization_registry = typed_this(vm, global_object);
if (!finalization_registry)
return {};
auto unregister_token = vm.argument(0);
if (!unregister_token.is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, unregister_token.to_string_without_side_effects());
return {};
}
return Value(finalization_registry->remove_by_token(unregister_token.as_object()));
}
}

View file

@ -20,4 +20,10 @@ public:
private:
static FinalizationRegistry* typed_this(VM&, GlobalObject&);
JS_DECLARE_NATIVE_FUNCTION(cleanup_some);
JS_DECLARE_NATIVE_FUNCTION(register_);
JS_DECLARE_NATIVE_FUNCTION(unregister);
};
}