summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister')
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/custom-this.js50
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/length.js35
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/name.js34
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/not-a-constructor.js36
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/prop-desc.js27
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/this-does-not-have-internal-cells-throws.js51
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/this-not-object-throws.js52
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/throws-when-unregisterToken-cannot-be-held-weakly.js47
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-object-cell.js64
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-object-token.js57
-rw-r--r--js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-symbol-token.js64
13 files changed, 517 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/browser.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/browser.js
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/custom-this.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/custom-this.js
new file mode 100644
index 0000000000..ac7157940e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/custom-this.js
@@ -0,0 +1,50 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2019 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: Return values applying custom this
+info: |
+ FinalizationRegistry.prototype.unregister ( unregisterToken )
+
+ 1. Let finalizationRegistry be the this value.
+ 2. If Type(finalizationRegistry) is not Object, throw a TypeError exception.
+ 3. If finalizationRegistry does not have a [[Cells]] internal slot, throw a TypeError exception.
+ 4. If Type(unregisterToken) is not Object, throw a TypeError exception.
+ 5. Let removed be false.
+ 6. For each Record { [[Target]], [[Holdings]], [[UnregisterToken]] } cell that is an element of finalizationRegistry.[[Cells]], do
+ a. If SameValue(cell.[[UnregisterToken]], unregisterToken) is true, then
+ i. Remove cell from finalizationRegistry.[[Cells]].
+ ii. Set removed to true.
+ 7. Return removed.
+features: [FinalizationRegistry]
+---*/
+
+var fn = function() {};
+var unregister = FinalizationRegistry.prototype.unregister;
+var finalizationRegistry = new FinalizationRegistry(fn);
+
+var target1 = {};
+var target2 = {};
+var target3 = {};
+var token1 = {};
+var token2 = {};
+
+assert.sameValue(unregister.call(finalizationRegistry, token1), false, 'unregistering token1 from empty finalizationRegistry');
+assert.sameValue(unregister.call(finalizationRegistry, token2), false, 'unregistering token2 from empty finalizationRegistry');
+
+finalizationRegistry.register(target1, undefined, token1);
+finalizationRegistry.register(target2, undefined, token2);
+finalizationRegistry.register(target3, undefined, token2);
+
+assert.sameValue(unregister.call(finalizationRegistry, target1), false, 'own target does not work on unregister, #1');
+assert.sameValue(unregister.call(finalizationRegistry, target2), false, 'own target does not work on unregister, #2');
+assert.sameValue(unregister.call(finalizationRegistry, target3), false, 'own target does not work on unregister, #3');
+
+assert.sameValue(unregister.call(finalizationRegistry, token1), true, 'unregistering token1 from finalizationRegistry');
+assert.sameValue(unregister.call(finalizationRegistry, token1), false, 'unregistering token1 again from finalizationRegistry');
+assert.sameValue(unregister.call(finalizationRegistry, token2), true, 'unregistering token2 to remove target2 and target3');
+assert.sameValue(unregister.call(finalizationRegistry, token2), false, 'unregistering token2 from empty finalizationRegistry');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/length.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/length.js
new file mode 100644
index 0000000000..72d6570581
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/length.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2019 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: FinalizationRegistry.prototype.unregister.length property descriptor
+info: |
+ FinalizationRegistry.prototype.unregister ( unregisterToken )
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in function object, including constructors, has a length
+ property whose value is an integer. Unless otherwise specified, this
+ value is equal to the largest number of named arguments shown in the
+ subclause headings for the function description. Optional parameters
+ (which are indicated with brackets: [ ]) or rest parameters (which
+ are shown using the form «...name») are not included in the default
+ argument count.
+
+ Unless otherwise specified, the length property of a built-in
+ function object has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [FinalizationRegistry]
+---*/
+
+verifyProperty(FinalizationRegistry.prototype.unregister, 'length', {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/name.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/name.js
new file mode 100644
index 0000000000..3b92b98d58
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/name.js
@@ -0,0 +1,34 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2019 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: FinalizationRegistry.prototype.unregister.name property descriptor
+info: |
+ FinalizationRegistry.prototype.unregister.name value and property descriptor
+
+ 17 ECMAScript Standard Built-in Objects
+
+ Every built-in function object, including constructors, that is not
+ identified as an anonymous function has a name property whose value
+ is a String. Unless otherwise specified, this value is the name that
+ is given to the function in this specification. For functions that
+ are specified as properties of objects, the name value is the
+ property name string used to access the function. [...]
+
+ Unless otherwise specified, the name property of a built-in function
+ object, if it exists, has the attributes { [[Writable]]: false,
+ [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [FinalizationRegistry]
+---*/
+
+verifyProperty(FinalizationRegistry.prototype.unregister, 'name', {
+ value: 'unregister',
+ writable: false,
+ enumerable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/not-a-constructor.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/not-a-constructor.js
new file mode 100644
index 0000000000..ea51595556
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/not-a-constructor.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2020 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-ecmascript-standard-built-in-objects
+description: >
+ FinalizationRegistry.prototype.unregister does not implement [[Construct]], is not new-able
+info: |
+ ECMAScript Function Objects
+
+ Built-in function objects that are not identified as constructors do not
+ implement the [[Construct]] internal method unless otherwise specified in
+ the description of a particular function.
+
+ sec-evaluatenew
+
+ ...
+ 7. If IsConstructor(constructor) is false, throw a TypeError exception.
+ ...
+includes: [isConstructor.js]
+features: [Reflect.construct, FinalizationRegistry, arrow-function]
+---*/
+
+assert.sameValue(
+ isConstructor(FinalizationRegistry.prototype.unregister),
+ false,
+ 'isConstructor(FinalizationRegistry.prototype.unregister) must return false'
+);
+
+assert.throws(TypeError, () => {
+ let fr = new FinalizationRegistry(() => {}); let token = {}; fr.register(token); new fr.unregister(token);
+}, '`let fr = new FinalizationRegistry(() => {}); let token = {}; fr.register(token); new fr.unregister(token)` throws TypeError');
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/prop-desc.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/prop-desc.js
new file mode 100644
index 0000000000..0e4aa0564c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/prop-desc.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2019 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: >
+ Property descriptor of FinalizationRegistry.prototype.unregister
+info: |
+ 17 ECMAScript Standard Built-in Objects:
+
+ Every other data property described in clauses 18 through 26 and in Annex B.2
+ has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+ [[Configurable]]: true } unless otherwise specified.
+includes: [propertyHelper.js]
+features: [FinalizationRegistry]
+---*/
+
+assert.sameValue(typeof FinalizationRegistry.prototype.unregister, 'function');
+
+verifyProperty(FinalizationRegistry.prototype, 'unregister', {
+ enumerable: false,
+ writable: true,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/shell.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/shell.js
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/this-does-not-have-internal-cells-throws.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/this-does-not-have-internal-cells-throws.js
new file mode 100644
index 0000000000..a10e58c01d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/this-does-not-have-internal-cells-throws.js
@@ -0,0 +1,51 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')||!this.hasOwnProperty('WeakRef')) -- FinalizationRegistry,WeakRef is not enabled unconditionally
+// Copyright (C) 2019 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: Throws a TypeError if this does not have a [[Cells]] internal slot
+info: |
+ FinalizationRegistry.prototype.unregister ( unregisterToken )
+
+ 1. Let finalizationRegistry be the this value.
+ 2. If Type(finalizationRegistry) is not Object, throw a TypeError exception.
+ 3. If finalizationRegistry does not have a [[Cells]] internal slot, throw a TypeError exception.
+ 4. If Type(unregisterToken) is not Object, throw a TypeError exception.
+ ...
+features: [WeakSet, WeakMap, FinalizationRegistry, WeakRef]
+---*/
+
+assert.sameValue(typeof FinalizationRegistry.prototype.unregister, 'function');
+
+var unregister = FinalizationRegistry.prototype.unregister;
+var token = {};
+
+assert.throws(TypeError, function() {
+ unregister.call({ ['[[Cells]]']: {} }, token);
+}, 'Ordinary object without [[Cells]]');
+
+assert.throws(TypeError, function() {
+ unregister.call(WeakRef.prototype, token);
+}, 'WeakRef.prototype does not have a [[Cells]] internal slot');
+
+assert.throws(TypeError, function() {
+ unregister.call(WeakRef, token);
+}, 'WeakRef does not have a [[Cells]] internal slot');
+
+var wr = new WeakRef({});
+assert.throws(TypeError, function() {
+ unregister.call(wr, token);
+}, 'WeakRef instance');
+
+var wm = new WeakMap();
+assert.throws(TypeError, function() {
+ unregister.call(wm, token);
+}, 'WeakMap instance');
+
+var ws = new WeakSet();
+assert.throws(TypeError, function() {
+ unregister.call(ws, token);
+}, 'WeakSet instance');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/this-not-object-throws.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/this-not-object-throws.js
new file mode 100644
index 0000000000..7cb536cb9c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/this-not-object-throws.js
@@ -0,0 +1,52 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2019 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: Throws a TypeError if this is not an Object
+info: |
+ FinalizationRegistry.prototype.unregister ( unregisterToken )
+
+ 1. Let finalizationRegistry be the this value.
+ 2. If Type(finalizationRegistry) is not Object, throw a TypeError exception.
+ 3. If finalizationRegistry does not have a [[Cells]] internal slot, throw a TypeError exception.
+ 4. If Type(unregisterToken) is not Object, throw a TypeError exception.
+ ...
+features: [FinalizationRegistry]
+---*/
+
+assert.sameValue(typeof FinalizationRegistry.prototype.unregister, 'function');
+
+var unregister = FinalizationRegistry.prototype.unregister;
+
+assert.throws(TypeError, function() {
+ unregister.call(undefined, {});
+}, 'undefined');
+
+assert.throws(TypeError, function() {
+ unregister.call(null, {});
+}, 'null');
+
+assert.throws(TypeError, function() {
+ unregister.call(true, {});
+}, 'true');
+
+assert.throws(TypeError, function() {
+ unregister.call(false, {});
+}, 'false');
+
+assert.throws(TypeError, function() {
+ unregister.call(1, {});
+}, 'number');
+
+assert.throws(TypeError, function() {
+ unregister.call('object', {});
+}, 'string');
+
+var s = Symbol();
+assert.throws(TypeError, function() {
+ unregister.call(s, {});
+}, 'symbol');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/throws-when-unregisterToken-cannot-be-held-weakly.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/throws-when-unregisterToken-cannot-be-held-weakly.js
new file mode 100644
index 0000000000..403b569d5a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/throws-when-unregisterToken-cannot-be-held-weakly.js
@@ -0,0 +1,47 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2019 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: Throws a TypeError if unregisterToken cannot be held weakly
+info: |
+ FinalizationRegistry.prototype.unregister ( _unregisterToken_ )
+ 3. If CanBeHeldWeakly(_unregisterToken_) is *false*, throw a *TypeError* exception.
+features: [FinalizationRegistry]
+---*/
+
+assert.sameValue(typeof FinalizationRegistry.prototype.unregister, 'function');
+
+var finalizationRegistry = new FinalizationRegistry(function() {});
+
+assert.throws(TypeError, function() {
+ finalizationRegistry.unregister(undefined);
+}, 'undefined');
+
+assert.throws(TypeError, function() {
+ finalizationRegistry.unregister(null);
+}, 'null');
+
+assert.throws(TypeError, function() {
+ finalizationRegistry.unregister(true);
+}, 'true');
+
+assert.throws(TypeError, function() {
+ finalizationRegistry.unregister(false);
+}, 'false');
+
+assert.throws(TypeError, function() {
+ finalizationRegistry.unregister(1);
+}, 'number');
+
+assert.throws(TypeError, function() {
+ finalizationRegistry.unregister('object');
+}, 'string');
+
+var s = Symbol.for('registered symbol');
+assert.throws(TypeError, function() {
+ finalizationRegistry.unregister(s);
+}, 'registered symbol');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-object-cell.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-object-cell.js
new file mode 100644
index 0000000000..da74a59287
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-object-cell.js
@@ -0,0 +1,64 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) async -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2019 Mathieu Hofman. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: >
+ Cannot unregister a cell referring to an Object that has been cleaned up
+info: |
+ FinalizationRegistry.prototype.cleanupSome ( [ _callback_ ] )
+ 4. Perform ? CleanupFinalizationRegistry(_finalizationRegistry_, _callback_).
+
+ CleanupFinalizationRegistry ( _finalizationRegistry_ ):
+ 3. While _finalizationRegistry_.[[Cells]] contains a Record _cell_ such that
+ _cell_.[[WeakRefTarget]] is ~empty~, then an implementation may perform the
+ following steps:
+ a. Choose any such _cell_.
+ b. Remove _cell_ from _finalizationRegistry_.[[Cells]].
+ c. Perform ? HostCallJobCallback(_callback_, *undefined*,
+ « _cell_.[[HeldValue]] »).
+
+ FinalizationRegistry.prototype.unregister ( _unregisterToken_ )
+ 4. Let _removed_ be *false*.
+ 5. For each Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] }
+ _cell_ of _finalizationRegistry_.[[Cells]], do
+ a. If _cell_.[[UnregisterToken]] is not ~empty~ and
+ SameValue(_cell_.[[UnregisterToken]], _unregisterToken_) is *true*, then
+ i. Remove _cell_ from _finalizationRegistry_.[[Cells]].
+ ii. Set _removed_ to *true*.
+ 6. Return _removed_.
+features: [FinalizationRegistry.prototype.cleanupSome, FinalizationRegistry, host-gc-required]
+includes: [async-gc.js]
+flags: [async, non-deterministic]
+---*/
+
+var value = 'target!';
+var token = {};
+var finalizationRegistry = new FinalizationRegistry(function() {});
+
+function emptyCells() {
+ var target = {};
+ finalizationRegistry.register(target, value, token);
+
+ var prom = asyncGC(target);
+ target = null;
+
+ return prom;
+}
+
+emptyCells().then(function() {
+ var called = 0;
+ var holdings = [];
+ finalizationRegistry.cleanupSome(function cb(holding) {
+ called += 1;
+ holdings.push(holding);
+ });
+
+ assert.sameValue(called, 1);
+ assert.sameValue(holdings.length, 1);
+ assert.sameValue(holdings[0], value);
+
+ var res = finalizationRegistry.unregister(token);
+ assert.sameValue(res, false, 'unregister after iterating over it in cleanup');
+}).then($DONE, resolveAsyncGC);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-object-token.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-object-token.js
new file mode 100644
index 0000000000..0dd685e4b8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-object-token.js
@@ -0,0 +1,57 @@
+// |reftest| skip-if(!this.hasOwnProperty('FinalizationRegistry')) -- FinalizationRegistry is not enabled unconditionally
+// Copyright (C) 2019 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: >
+ Return boolean values indicating unregistering of values with Object token
+info: |
+ FinalizationRegistry.prototype.unregister ( _unregisterToken_ )
+ 4. Let _removed_ be *false*.
+ 5. For each Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] }
+ _cell_ of _finalizationRegistry_.[[Cells]], do
+ a. If _cell_.[[UnregisterToken]] is not ~empty~ and
+ SameValue(_cell_.[[UnregisterToken]], _unregisterToken_) is *true*, then
+ i. Remove _cell_ from _finalizationRegistry_.[[Cells]].
+ ii. Set _removed_ to *true*.
+ 6. Return _removed_.
+features: [FinalizationRegistry]
+---*/
+
+var fn = function() {};
+var finalizationRegistry = new FinalizationRegistry(fn);
+
+var target1 = {};
+var target2 = {};
+var target3 = {};
+var token1 = {};
+var token2 = {};
+
+assert.sameValue(finalizationRegistry.unregister(token1), false, 'unregistering token1 from empty finalizationRegistry');
+assert.sameValue(finalizationRegistry.unregister(token2), false, 'unregistering token2 from empty finalizationRegistry');
+
+finalizationRegistry.register(target1, undefined, token1);
+finalizationRegistry.register(target1, undefined, token1); // Repeat registering un purpose
+finalizationRegistry.register(target2, undefined, token2);
+finalizationRegistry.register(target3, undefined, token2);
+
+assert.sameValue(finalizationRegistry.unregister(target1), false, 'own target does not work on unregister, #1');
+assert.sameValue(finalizationRegistry.unregister(target2), false, 'own target does not work on unregister, #2');
+assert.sameValue(finalizationRegistry.unregister(target3), false, 'own target does not work on unregister, #3');
+
+assert.sameValue(finalizationRegistry.unregister(token1), true, 'unregistering token1 from finalizationRegistry');
+assert.sameValue(finalizationRegistry.unregister(token1), false, 'unregistering token1 again from finalizationRegistry');
+assert.sameValue(finalizationRegistry.unregister(token2), true, 'unregistering token2 to remove target2 and target3');
+assert.sameValue(finalizationRegistry.unregister(token2), false, 'unregistering token2 from empty finalizationRegistry');
+
+// Notice these assertions take advantage of adding targets previously added with a token,
+// but now they got no token so it won't be used to remove them.
+finalizationRegistry.register(target1, token1); // holdings, not unregisterToken
+finalizationRegistry.register(target2, token2); // holdings, not unregisterToken
+finalizationRegistry.register(target3);
+
+assert.sameValue(finalizationRegistry.unregister(token1), false, 'nothing to remove without a set unregisterToken #1');
+assert.sameValue(finalizationRegistry.unregister(token2), false, 'nothing to remove without a set unregisterToken #2');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-symbol-token.js b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-symbol-token.js
new file mode 100644
index 0000000000..f343ff3712
--- /dev/null
+++ b/js/src/tests/test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-symbol-token.js
@@ -0,0 +1,64 @@
+// |reftest| shell-option(--enable-symbols-as-weakmap-keys) skip-if(release_or_beta||!this.hasOwnProperty('FinalizationRegistry')||!xulRuntime.shell) -- symbols-as-weakmap-keys is not released yet, FinalizationRegistry is not enabled unconditionally, requires shell-options
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-finalization-registry.prototype.unregister
+description: >
+ Return boolean values indicating unregistering of values with Symbol token
+info: |
+ FinalizationRegistry.prototype.unregister ( _unregisterToken_ )
+ 4. Let _removed_ be *false*.
+ 5. For each Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] }
+ _cell_ of _finalizationRegistry_.[[Cells]], do
+ a. If _cell_.[[UnregisterToken]] is not ~empty~ and
+ SameValue(_cell_.[[UnregisterToken]], _unregisterToken_) is *true*, then
+ i. Remove _cell_ from _finalizationRegistry_.[[Cells]].
+ ii. Set _removed_ to *true*.
+ 6. Return _removed_.
+features: [FinalizationRegistry, Symbol, symbols-as-weakmap-keys]
+---*/
+
+var fn = function() {};
+var reg = new FinalizationRegistry(fn);
+
+var target1 = {};
+var target2 = {};
+var target3 = {};
+var token = Symbol('unregister');
+
+assert.sameValue(reg.unregister(token), false, 'unregistering regular symbol from empty registry');
+assert.sameValue(reg.unregister(Symbol.hasInstance), false, 'unregistering well-known symbol from empty registry');
+
+reg.register(target1, undefined, token);
+reg.register(target1, undefined, token); // Repeat registering on purpose
+reg.register(target2, undefined, Symbol.hasInstance);
+reg.register(target3, undefined, Symbol.hasInstance);
+
+assert.sameValue(reg.unregister(token), true, 'unregistering regular symbol from finalization registry');
+assert.sameValue(reg.unregister(token), false, 'unregistering regular symbol again from finalization registry');
+assert.sameValue(
+ reg.unregister(Symbol.hasInstance),
+ true,
+ 'unregistering well-known symbol to remove target2 and target3'
+);
+assert.sameValue(
+ reg.unregister(Symbol.hasInstance),
+ false,
+ 'unregistering well-known again from finalization registry'
+);
+
+// Notice these assertions take advantage of adding targets previously added
+// with a token, but now they have no token so it won't be used to remove them.
+reg.register(target1, token); // heldValue, not unregisterToken
+reg.register(target2, Symbol.hasInstance); // heldValue, not unregisterToken
+reg.register(target3);
+
+assert.sameValue(reg.unregister(token), false, 'nothing to remove with regular symbol unregister token');
+assert.sameValue(
+ reg.unregister(Symbol.hasInstance),
+ false,
+ 'nothing to remove with well-known symbol unregister token'
+);
+
+reportCompare(0, 0);