1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:57:35 +00:00

LibJS: Add spec comments to FinalizationRegistryPrototype

This commit is contained in:
Linus Groh 2023-01-27 21:59:17 +00:00
parent 2473940526
commit 6d6ea1fffe
2 changed files with 37 additions and 5 deletions

View file

@ -23,15 +23,25 @@ void FinalizationRegistry::add_finalization_record(Cell& target, Value held_valu
m_records.append({ &target, held_value, unregister_token });
}
// Extracted from FinalizationRegistry.prototype.unregister ( unregisterToken )
bool FinalizationRegistry::remove_by_token(Cell& unregister_token)
{
// 4. Let removed be false.
auto removed = false;
// 5. For each Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell of finalizationRegistry.[[Cells]], do
for (auto it = m_records.begin(); it != m_records.end(); ++it) {
// a. If cell.[[UnregisterToken]] is not empty and SameValue(cell.[[UnregisterToken]], unregisterToken) is true, then
if (it->unregister_token == &unregister_token) {
// i. Remove cell from finalizationRegistry.[[Cells]].
it.remove(m_records);
// ii. Set removed to true.
removed = true;
}
}
// 6. Return removed.
return removed;
}

View file

@ -32,50 +32,72 @@ void FinalizationRegistryPrototype::initialize(Realm& realm)
// @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 callback = vm.argument(0);
// 1. Let finalizationRegistry be the this value.
// 2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]).
auto* finalization_registry = TRY(typed_this_object(vm));
auto callback = vm.argument(0);
// 3. If callback is present and IsCallable(callback) is false, throw a TypeError exception.
if (vm.argument_count() > 0 && !callback.is_function())
return vm.throw_completion<TypeError>(ErrorType::NotAFunction, callback.to_string_without_side_effects());
// IMPLEMENTATION DEFINED: The specification for this function hasn't been updated to accommodate for JobCallback records.
// This just follows how the constructor immediately converts the callback to a JobCallback using HostMakeJobCallback.
// 4. Perform ? CleanupFinalizationRegistry(finalizationRegistry, callback).
TRY(finalization_registry->cleanup(callback.is_undefined() ? Optional<JobCallback> {} : vm.host_make_job_callback(callback.as_function())));
// 5. Return undefined.
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 target = vm.argument(0);
auto held_value = vm.argument(1);
auto unregister_token = vm.argument(2);
// 1. Let finalizationRegistry be the this value.
// 2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]).
auto* finalization_registry = TRY(typed_this_object(vm));
auto target = vm.argument(0);
// 3. If target is not an Object, throw a TypeError exception.
if (!can_be_held_weakly(target))
return vm.throw_completion<TypeError>(ErrorType::CannotBeHeldWeakly, target.to_string_without_side_effects());
auto held_value = vm.argument(1);
// 4. If SameValue(target, heldValue) is true, throw a TypeError exception.
if (same_value(target, held_value))
return vm.throw_completion<TypeError>(ErrorType::FinalizationRegistrySameTargetAndValue);
auto unregister_token = vm.argument(2);
// 5. If unregisterToken is not an Object, then
// a. If unregisterToken is not undefined, throw a TypeError exception.
// b. Set unregisterToken to empty.
if (!can_be_held_weakly(unregister_token) && !unregister_token.is_undefined())
return vm.throw_completion<TypeError>(ErrorType::CannotBeHeldWeakly, unregister_token.to_string_without_side_effects());
// 6. Let cell be the Record { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }.
// 7. Append cell to finalizationRegistry.[[Cells]].
finalization_registry->add_finalization_record(target.as_cell(), held_value, unregister_token.is_undefined() ? nullptr : &unregister_token.as_cell());
// 8. Return undefined.
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 unregister_token = vm.argument(0);
// 1. Let finalizationRegistry be the this value.
// 2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]).
auto* finalization_registry = TRY(typed_this_object(vm));
auto unregister_token = vm.argument(0);
// 3. If unregisterToken is not an Object, throw a TypeError exception.
if (!can_be_held_weakly(unregister_token))
return vm.throw_completion<TypeError>(ErrorType::CannotBeHeldWeakly, unregister_token.to_string_without_side_effects());
// 4-6.
return Value(finalization_registry->remove_by_token(unregister_token.as_cell()));
}