فهرست منبع

LibJS: Add spec comments to FinalizationRegistryPrototype

Linus Groh 2 سال پیش
والد
کامیت
6d6ea1fffe

+ 10 - 0
Userland/Libraries/LibJS/Runtime/FinalizationRegistry.cpp

@@ -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;
 }
 

+ 27 - 5
Userland/Libraries/LibJS/Runtime/FinalizationRegistryPrototype.cpp

@@ -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()));
 }