mirror of
https://github.com/tc39/test262.git
synced 2025-07-29 17:04:31 +02:00
Migrate FinalizationRegistry tests to per-item callback API
This commit is contained in:
parent
4199a3b34b
commit
966fc11862
@ -21,10 +21,10 @@ function asyncGC(...targets) {
|
|||||||
targets = null;
|
targets = null;
|
||||||
|
|
||||||
return Promise.resolve('tick').then(() => asyncGCDeref()).then(() => {
|
return Promise.resolve('tick').then(() => asyncGCDeref()).then(() => {
|
||||||
var names;
|
var names = [];
|
||||||
|
|
||||||
// consume iterator to capture names
|
// consume iterator to capture names
|
||||||
finalizationRegistry.cleanupSome(iter => { names = [...iter]; });
|
finalizationRegistry.cleanupSome(name => { names.push(name); });
|
||||||
|
|
||||||
if (!names || names.length != length) {
|
if (!names || names.length != length) {
|
||||||
throw asyncGC.notCollected;
|
throw asyncGC.notCollected;
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype @@toStringTag
|
|
||||||
info: |
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
1. Let finalizationRegistry be the this value.
|
|
||||||
...
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
...
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
...
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
%FinalizationRegistryCleanupIteratorPrototype% [ @@toStringTag ]
|
|
||||||
|
|
||||||
The initial value of the @@toStringTag property is the String value "FinalizationRegistry Cleanup Iterator".
|
|
||||||
|
|
||||||
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
|
|
||||||
features: [FinalizationRegistry, host-gc-required, Symbol, Symbol.toStringTag]
|
|
||||||
includes: [async-gc.js, propertyHelper.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
assert.sameValue(called, 1, 'cleanup successful');
|
|
||||||
|
|
||||||
verifyProperty(FinalizationRegistryCleanupIteratorPrototype, Symbol.toStringTag, {
|
|
||||||
value: 'FinalizationRegistry Cleanup Iterator',
|
|
||||||
writable: false,
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -1,69 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
Throws a TypeError if [[IsFinalizationRegistryCleanupJobActive]] is false
|
|
||||||
info: |
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
1. Let finalizationRegistry be the this value.
|
|
||||||
...
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
...
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
...
|
|
||||||
5. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to true.
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
7. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to false.
|
|
||||||
...
|
|
||||||
|
|
||||||
%FinalizationRegistryCleanupIteratorPrototype%.next ( )
|
|
||||||
|
|
||||||
1. Let iterator be the this value.
|
|
||||||
2. If Type(iterator) is not Object, throw a TypeError exception.
|
|
||||||
3. If iterator does not have a [[FinalizationRegistry]] internal slot, throw a TypeError exception.
|
|
||||||
features: [FinalizationRegistry, WeakRef, host-gc-required, Symbol]
|
|
||||||
includes: [async-gc.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var iter;
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
iter = iterator;
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target, 'target');
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
// Make sure everything is set
|
|
||||||
assert.sameValue(called, 1, 'cleanup successful');
|
|
||||||
assert.sameValue(typeof iter, 'object');
|
|
||||||
assert.sameValue(Object.getPrototypeOf(iter), FinalizationRegistryCleanupIteratorPrototype);
|
|
||||||
|
|
||||||
// To the actual assertion
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
iter.next();
|
|
||||||
}, 'Iter should fail if not called during the cleanupSome call');
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -1,74 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype.next.length property descriptor
|
|
||||||
info: |
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
1. Let finalizationRegistry be the this value.
|
|
||||||
...
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
...
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
...
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
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: [async-gc.js, propertyHelper.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
features: [FinalizationRegistry, host-gc-required, Symbol]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
assert.sameValue(called, 1, 'cleanup successful');
|
|
||||||
|
|
||||||
assert.sameValue(typeof FinalizationRegistryCleanupIteratorPrototype.next, 'function');
|
|
||||||
|
|
||||||
verifyProperty(FinalizationRegistryCleanupIteratorPrototype.next, 'length', {
|
|
||||||
value: 0,
|
|
||||||
enumerable: false,
|
|
||||||
writable: false,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -1,90 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
If iterator does not have a [[FinalizationRegistry]] internal slot, throw a TypeError exception.
|
|
||||||
info: |
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
1. Let finalizationRegistry be the this value.
|
|
||||||
...
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
...
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
...
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
%FinalizationRegistryCleanupIteratorPrototype%.next ( )
|
|
||||||
|
|
||||||
1. Let iterator be the this value.
|
|
||||||
2. If Type(iterator) is not Object, throw a TypeError exception.
|
|
||||||
3. If iterator does not have a [[FinalizationRegistry]] internal slot, throw a TypeError exception.
|
|
||||||
features: [FinalizationRegistry, WeakRef, host-gc-required, Symbol]
|
|
||||||
includes: [async-gc.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var endOfCall = 0;
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
// Only the iterator itself will have a [[FinalizationRegistry]] internal
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
|
|
||||||
// It's sensitive the assertions remain inside this function in order to secure
|
|
||||||
// [[IsFinalizationRegistryCleanupJobActive]] is true
|
|
||||||
assert.sameValue(typeof FinalizationRegistryCleanupIteratorPrototype.next, 'function');
|
|
||||||
|
|
||||||
var next = FinalizationRegistryCleanupIteratorPrototype.next;
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call({});
|
|
||||||
}, '{}');
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(FinalizationRegistry);
|
|
||||||
}, 'FinalizationRegistry');
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(FinalizationRegistryCleanupIteratorPrototype);
|
|
||||||
}, 'FinalizationRegistryCleanupIteratorPrototype');
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(finalizationRegistry);
|
|
||||||
}, 'FinalizationRegistry instance');
|
|
||||||
|
|
||||||
var wr = new WeakRef({});
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(wr);
|
|
||||||
}, 'WeakRef instance');
|
|
||||||
|
|
||||||
// Abrupt completions are not directly returned.
|
|
||||||
endOfCall += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
assert.sameValue(called, 1, 'cleanup successful');
|
|
||||||
assert.sameValue(endOfCall, 1, 'Abrupt completions are not directly returned.');
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -1,75 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype.next.name property descriptor
|
|
||||||
info: |
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
1. Let finalizationRegistry be the this value.
|
|
||||||
...
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
...
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
...
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
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: [async-gc.js, propertyHelper.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
features: [FinalizationRegistry, host-gc-required, Symbol]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
assert.sameValue(called, 1, 'cleanup successful');
|
|
||||||
|
|
||||||
assert.sameValue(typeof FinalizationRegistryCleanupIteratorPrototype.next, 'function');
|
|
||||||
|
|
||||||
var next = FinalizationRegistryCleanupIteratorPrototype.next;
|
|
||||||
|
|
||||||
verifyProperty(next, 'name', {
|
|
||||||
value: 'next',
|
|
||||||
enumerable: false,
|
|
||||||
writable: false,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -1,89 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype.next() throws if this is not Object
|
|
||||||
info: |
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
1. Let finalizationRegistry be the this value.
|
|
||||||
...
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
...
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
...
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
%FinalizationRegistryCleanupIteratorPrototype%.next ( )
|
|
||||||
|
|
||||||
1. Let iterator be the this value.
|
|
||||||
2. If Type(iterator) is not Object, throw a TypeError exception.
|
|
||||||
features: [FinalizationRegistry, host-gc-required, Symbol]
|
|
||||||
includes: [async-gc.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
assert.sameValue(called, 1, 'cleanup successful');
|
|
||||||
|
|
||||||
assert.sameValue(typeof FinalizationRegistryCleanupIteratorPrototype.next, 'function');
|
|
||||||
|
|
||||||
var next = FinalizationRegistryCleanupIteratorPrototype.next;
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(undefined);
|
|
||||||
}, 'undefined');
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(null);
|
|
||||||
}, 'null');
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(true);
|
|
||||||
}, 'true');
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(false);
|
|
||||||
}, 'false');
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(1);
|
|
||||||
}, '1');
|
|
||||||
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call('string');
|
|
||||||
}, 'string');
|
|
||||||
|
|
||||||
var symbol = Symbol();
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
next.call(symbol);
|
|
||||||
}, 'symbol');
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -1,67 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
Prop descriptor for FinalizationRegistryCleanupIteratorPrototype.next
|
|
||||||
info: |
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
1. Let finalizationRegistry be the this value.
|
|
||||||
...
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
...
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
...
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
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, async-gc.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
features: [FinalizationRegistry, host-gc-required, Symbol]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
assert.sameValue(called, 1, 'cleanup successful');
|
|
||||||
|
|
||||||
assert.sameValue(typeof FinalizationRegistryCleanupIteratorPrototype.next, 'function');
|
|
||||||
|
|
||||||
var next = FinalizationRegistryCleanupIteratorPrototype.next;
|
|
||||||
|
|
||||||
verifyProperty(FinalizationRegistryCleanupIteratorPrototype, 'next', {
|
|
||||||
enumerable: false,
|
|
||||||
writable: true,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -1,91 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
FinalizationRegistryCleanupIterator has a [[Prototype]] internal slot whose value is the intrinsic
|
|
||||||
object %IteratorPrototype%.
|
|
||||||
info: |
|
|
||||||
The %FinalizationRegistryCleanupIteratorPrototype% Object
|
|
||||||
|
|
||||||
- has properties that are inherited by all FinalizationRegistry Cleanup Iterator Objects.
|
|
||||||
- is an ordinary object.
|
|
||||||
- has a [[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%.
|
|
||||||
...
|
|
||||||
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
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 callback is not undefined and IsCallable(callback) is false, throw a TypeError exception.
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
6. Return undefined.
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
2. If CheckForEmptyCells(finalizationRegistry) is false, return.
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
4. If callback is undefined, set callback to finalizationRegistry.[[CleanupCallback]].
|
|
||||||
5. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to true.
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
CheckForEmptyCells ( finalizationRegistry )
|
|
||||||
|
|
||||||
...
|
|
||||||
2. For each cell in finalizationRegistry.[[Cells]], do
|
|
||||||
a. If cell.[[Target]] is empty, then
|
|
||||||
i. Return true.
|
|
||||||
3. Return false.
|
|
||||||
|
|
||||||
CreateFinalizationRegistryCleanupIterator ( finalizationRegistry )
|
|
||||||
|
|
||||||
...
|
|
||||||
4. Let prototype be finalizationRegistry.[[Realm]].[[Intrinsics]].[[%FinalizationRegistryCleanupIteratorPrototype%]].
|
|
||||||
5. Let iterator be ObjectCreate(prototype, « [[FinalizationRegistry]] »).
|
|
||||||
6. Set iterator.[[FinalizationRegistry]] to finalizationRegistry.
|
|
||||||
7. Return iterator.
|
|
||||||
features: [FinalizationRegistry, host-gc-required]
|
|
||||||
includes: [async-gc.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var cleanupCallbackCalled = 0;
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
assert.sameValue(called, 1, 'cleanup successful');
|
|
||||||
|
|
||||||
var proto = Object.getPrototypeOf(FinalizationRegistryCleanupIteratorPrototype);
|
|
||||||
assert.sameValue(
|
|
||||||
proto, IteratorPrototype,
|
|
||||||
'[[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%'
|
|
||||||
);
|
|
||||||
|
|
||||||
assert.sameValue(cleanupCallbackCalled, 0, 'if a callback is given, do not call cleanupCallback');
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -33,10 +33,8 @@ includes: [async-gc.js]
|
|||||||
var cleanupCallback = 0;
|
var cleanupCallback = 0;
|
||||||
var called = 0;
|
var called = 0;
|
||||||
|
|
||||||
// both this cb and the finalizationRegistry callback are not exhausting the iterator to prevent
|
function cb(holding) {
|
||||||
// the target cell from being removed from the finalizationRegistry.[[Cells]].
|
assert.sameValue(holding, 'a');
|
||||||
// More info at %FinalizationRegistryCleanupIteratorPrototype%.next ( )
|
|
||||||
function cb() {
|
|
||||||
called += 1;
|
called += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,14 +52,17 @@ function emptyCells() {
|
|||||||
return prom;
|
return prom;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's add some async ticks, as the cleanupCallback is not meant to interrupt
|
emptyCells()
|
||||||
// synchronous operations.
|
.then(async function() {
|
||||||
async function fn() {
|
|
||||||
await Promise.resolve(1);
|
await Promise.resolve(1);
|
||||||
|
|
||||||
finalizationRegistry.cleanupSome(cb);
|
finalizationRegistry.cleanupSome(cb);
|
||||||
|
|
||||||
|
// cleanupSome will be invoked if there are empty cells left. If the
|
||||||
|
// cleanupCallback already ran, then cb won't be called.
|
||||||
|
let expectedCalled = cleanupCallback === 1 ? 0 : 1;
|
||||||
// This asserts the registered object was emptied in the previous GC.
|
// This asserts the registered object was emptied in the previous GC.
|
||||||
assert.sameValue(called, 1, 'cleanupSome callback for the first time');
|
assert.sameValue(called, expectedCalled, 'cleanupSome callback for the first time');
|
||||||
|
|
||||||
// At this point, we can't assert if cleanupCallback was called, because it's
|
// At this point, we can't assert if cleanupCallback was called, because it's
|
||||||
// optional. Although, we can finally assert it's not gonna be called anymore
|
// optional. Although, we can finally assert it's not gonna be called anymore
|
||||||
@ -71,8 +72,8 @@ async function fn() {
|
|||||||
assert(cleanupCallback >= 0, 'cleanupCallback might be 0');
|
assert(cleanupCallback >= 0, 'cleanupCallback might be 0');
|
||||||
assert(cleanupCallback <= 1, 'cleanupCallback might be 1');
|
assert(cleanupCallback <= 1, 'cleanupCallback might be 1');
|
||||||
|
|
||||||
// Restoring the cleanupCallback variable to 0 will help us asserting the finalizationRegistry
|
// Restoring the cleanupCallback variable to 0 will help us asserting the
|
||||||
// callback is not called again.
|
// finalizationRegistry callback is not called again.
|
||||||
cleanupCallback = 0;
|
cleanupCallback = 0;
|
||||||
|
|
||||||
await $262.gc();
|
await $262.gc();
|
||||||
@ -80,9 +81,7 @@ async function fn() {
|
|||||||
|
|
||||||
finalizationRegistry.cleanupSome(cb);
|
finalizationRegistry.cleanupSome(cb);
|
||||||
|
|
||||||
// This cb is called again because finalizationRegistry still holds an emptied cell, but it's
|
assert.sameValue(called, expectedCalled, 'cleanupSome callback is not called anymore, no empty cells');
|
||||||
// not yet removed from the
|
|
||||||
assert.sameValue(called, 2, 'cleanupSome callback for the second time');
|
|
||||||
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #1');
|
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #1');
|
||||||
|
|
||||||
await $262.gc();
|
await $262.gc();
|
||||||
@ -90,46 +89,9 @@ async function fn() {
|
|||||||
|
|
||||||
finalizationRegistry.cleanupSome(cb);
|
finalizationRegistry.cleanupSome(cb);
|
||||||
|
|
||||||
assert.sameValue(called, 3, 'cleanupSome callback for the third time');
|
assert.sameValue(called, expectedCalled, 'cleanupSome callback is not called again #2');
|
||||||
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #2');
|
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #2');
|
||||||
|
|
||||||
await $262.gc();
|
await $262.gc();
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells()
|
|
||||||
.then(async function() {
|
|
||||||
await fn();// tick
|
|
||||||
await Promise.resolve(4); // tick
|
|
||||||
|
|
||||||
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #3');
|
|
||||||
|
|
||||||
finalizationRegistry.cleanupSome(cb);
|
|
||||||
|
|
||||||
assert.sameValue(called, 4, 'cleanupSome callback for the fourth time');
|
|
||||||
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #4');
|
|
||||||
|
|
||||||
await $262.gc();
|
|
||||||
|
|
||||||
// Now we are exhausting the iterator, so cleanupSome callback will also not be called.
|
|
||||||
finalizationRegistry.cleanupSome(iterator => {
|
|
||||||
var exhausted = [...iterator];
|
|
||||||
assert.sameValue(exhausted.length, 1);
|
|
||||||
assert.sameValue(exhausted[0], 'a');
|
|
||||||
called += 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.sameValue(called, 5, 'cleanupSome callback for the fifth time');
|
|
||||||
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #4');
|
|
||||||
|
|
||||||
await $262.gc();
|
|
||||||
|
|
||||||
await Promise.resolve(5); // tick
|
|
||||||
await await Promise.resolve(6); // more ticks
|
|
||||||
await await await Promise.resolve(7); // even more ticks
|
|
||||||
|
|
||||||
finalizationRegistry.cleanupSome(cb);
|
|
||||||
|
|
||||||
assert.sameValue(called, 5, 'cleanupSome callback is not called anymore, no empty cells');
|
|
||||||
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #5');
|
|
||||||
})
|
})
|
||||||
.then($DONE, resolveAsyncGC);
|
.then($DONE, resolveAsyncGC);
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
The callback function is called with a FinalizationRegistryCleanupIterator
|
|
||||||
info: |
|
|
||||||
The %FinalizationRegistryCleanupIteratorPrototype% Object
|
|
||||||
|
|
||||||
- has properties that are inherited by all FinalizationRegistry Cleanup Iterator Objects.
|
|
||||||
- is an ordinary object.
|
|
||||||
- has a [[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%.
|
|
||||||
...
|
|
||||||
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
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 callback is not undefined and IsCallable(callback) is false, throw a TypeError exception.
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
6. Return undefined.
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
2. If CheckForEmptyCells(finalizationRegistry) is false, return.
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
4. If callback is undefined, set callback to finalizationRegistry.[[CleanupCallback]].
|
|
||||||
5. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to true.
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
CheckForEmptyCells ( finalizationRegistry )
|
|
||||||
|
|
||||||
...
|
|
||||||
2. For each cell in finalizationRegistry.[[Cells]], do
|
|
||||||
a. If cell.[[Target]] is empty, then
|
|
||||||
i. Return true.
|
|
||||||
3. Return false.
|
|
||||||
|
|
||||||
CreateFinalizationRegistryCleanupIterator ( finalizationRegistry )
|
|
||||||
|
|
||||||
...
|
|
||||||
4. Let prototype be finalizationRegistry.[[Realm]].[[Intrinsics]].[[%FinalizationRegistryCleanupIteratorPrototype%]].
|
|
||||||
5. Let iterator be ObjectCreate(prototype, « [[FinalizationRegistry]] »).
|
|
||||||
6. Set iterator.[[FinalizationRegistry]] to finalizationRegistry.
|
|
||||||
7. Return iterator.
|
|
||||||
features: [FinalizationRegistry, host-gc-required]
|
|
||||||
includes: [async-gc.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
var cleanupCallbackCalled = 0;
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {
|
|
||||||
cleanupCallbackCalled += 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
async function register() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
|
|
||||||
target = null;
|
|
||||||
assert.sameValue(called, 0); // never called in sync execution
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
register()
|
|
||||||
.then(function() {
|
|
||||||
// We can't observe if the cleanupCallback was called, but we can make sure cleanupSome won't call it.
|
|
||||||
cleanupCallbackCalled = 0;
|
|
||||||
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
|
|
||||||
assert.sameValue(called, 1);
|
|
||||||
|
|
||||||
var proto = Object.getPrototypeOf(FinalizationRegistryCleanupIteratorPrototype);
|
|
||||||
assert.sameValue(
|
|
||||||
proto, IteratorPrototype,
|
|
||||||
'[[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%'
|
|
||||||
);
|
|
||||||
|
|
||||||
assert.sameValue(cleanupCallbackCalled, 0, 'if a callback is given, do not call cleanupCallback');
|
|
||||||
})
|
|
||||||
.then($DONE, resolveAsyncGC);
|
|
@ -18,9 +18,9 @@ includes: [async-gc.js]
|
|||||||
flags: [async, non-deterministic]
|
flags: [async, non-deterministic]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
var holdingsList;
|
var holdingsList = [];
|
||||||
function cb(iterator) {
|
function cb(holding) {
|
||||||
holdingsList = [...iterator];
|
holdingsList.push(holding);
|
||||||
};
|
};
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
var finalizationRegistry = new FinalizationRegistry(function() {});
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ emptyCells().then(function() {
|
|||||||
var res = finalizationRegistry.unregister(token);
|
var res = finalizationRegistry.unregister(token);
|
||||||
assert.sameValue(res, true, 'unregister target before iterating over it in cleanup');
|
assert.sameValue(res, true, 'unregister target before iterating over it in cleanup');
|
||||||
|
|
||||||
finalizationRegistry.cleanupSome(function cb(iterator) {
|
finalizationRegistry.cleanupSome(function cb(holding) {
|
||||||
called += 1;
|
called += 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
// Copyright (C) 2019 Leo Balter. All rights reserved.
|
|
||||||
// This code is governed by the BSD license found in the LICENSE file.
|
|
||||||
|
|
||||||
/*---
|
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
|
||||||
description: >
|
|
||||||
The cleanup callback function is called with a FinalizationRegistryCleanupIterator
|
|
||||||
info: |
|
|
||||||
The %FinalizationRegistryCleanupIteratorPrototype% Object
|
|
||||||
|
|
||||||
- has properties that are inherited by all FinalizationRegistry Cleanup Iterator Objects.
|
|
||||||
- is an ordinary object.
|
|
||||||
- has a [[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%.
|
|
||||||
...
|
|
||||||
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
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 callback is not undefined and IsCallable(callback) is false, throw a TypeError exception.
|
|
||||||
5. Perform ! CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
6. Return undefined.
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
...
|
|
||||||
2. If CheckForEmptyCells(finalizationRegistry) is false, return.
|
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
|
||||||
4. If callback is undefined, set callback to finalizationRegistry.[[CleanupCallback]].
|
|
||||||
5. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to true.
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
CheckForEmptyCells ( finalizationRegistry )
|
|
||||||
|
|
||||||
...
|
|
||||||
2. For each cell in finalizationRegistry.[[Cells]], do
|
|
||||||
a. If cell.[[Target]] is empty, then
|
|
||||||
i. Return true.
|
|
||||||
3. Return false.
|
|
||||||
|
|
||||||
CreateFinalizationRegistryCleanupIterator ( finalizationRegistry )
|
|
||||||
|
|
||||||
...
|
|
||||||
4. Let prototype be finalizationRegistry.[[Realm]].[[Intrinsics]].[[%FinalizationRegistryCleanupIteratorPrototype%]].
|
|
||||||
5. Let iterator be ObjectCreate(prototype, « [[FinalizationRegistry]] »).
|
|
||||||
6. Set iterator.[[FinalizationRegistry]] to finalizationRegistry.
|
|
||||||
7. Return iterator.
|
|
||||||
features: [FinalizationRegistry, host-gc-required]
|
|
||||||
includes: [async-gc.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
|
|
||||||
var FinalizationRegistryCleanupIteratorPrototype;
|
|
||||||
var called = 0;
|
|
||||||
|
|
||||||
function callback(iterator) {
|
|
||||||
called += 1;
|
|
||||||
|
|
||||||
FinalizationRegistryCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
finalizationRegistry.cleanupSome(callback);
|
|
||||||
assert.sameValue(called, 1);
|
|
||||||
|
|
||||||
var proto = Object.getPrototypeOf(FinalizationRegistryCleanupIteratorPrototype);
|
|
||||||
assert.sameValue(
|
|
||||||
proto, IteratorPrototype,
|
|
||||||
'[[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%'
|
|
||||||
);
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -16,31 +16,26 @@ info: |
|
|||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
||||||
|
|
||||||
...
|
...
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
3. While finalizationRegistry.[[Cells]] contains a Record cell such that cell.[[WeakRefTarget]] is ~empty~, then an implementation may perform the following steps,
|
||||||
...
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
%FinalizationRegistryCleanupIteratorPrototype%.next ( )
|
|
||||||
|
|
||||||
8. If finalizationRegistry.[[Cells]] contains a Record cell such that cell.[[Target]] is empty,
|
|
||||||
a. Choose any such cell.
|
a. Choose any such cell.
|
||||||
b. Remove cell from finalizationRegistry.[[Cells]].
|
b. Remove cell from finalizationRegistry.[[Cells]].
|
||||||
c. Return CreateIterResultObject(cell.[[Holdings]], false).
|
c. Perform ? Call(callback, undefined, << cell.[[HeldValue]] >>).
|
||||||
9. Otherwise, return CreateIterResultObject(undefined, true).
|
...
|
||||||
|
|
||||||
|
|
||||||
features: [FinalizationRegistry, Symbol, host-gc-required]
|
features: [FinalizationRegistry, Symbol, host-gc-required]
|
||||||
includes: [async-gc.js]
|
includes: [async-gc.js]
|
||||||
flags: [async, non-deterministic]
|
flags: [async, non-deterministic]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
function check(value, expectedName) {
|
function check(value, expectedName) {
|
||||||
var holdings;
|
var holdings = [];
|
||||||
var called = 0;
|
var called = 0;
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
var finalizationRegistry = new FinalizationRegistry(function() {});
|
||||||
|
|
||||||
function callback(iterator) {
|
function callback(holding) {
|
||||||
called += 1;
|
called += 1;
|
||||||
holdings = [...iterator];
|
holdings.push(holding);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is internal to avoid conflicts
|
// This is internal to avoid conflicts
|
@ -1,62 +0,0 @@
|
|||||||
// 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.cleanupSome
|
|
||||||
description: Return abrupt completion from CleanupFinalizationRegistry
|
|
||||||
info: |
|
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
|
||||||
|
|
||||||
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 callback is not undefined and IsCallable(callback) is false, throw a TypeError exception.
|
|
||||||
5. Perform ? CleanupFinalizationRegistry(finalizationRegistry, callback).
|
|
||||||
6. Return undefined.
|
|
||||||
|
|
||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
|
||||||
|
|
||||||
4. If callback is undefined, set callback to finalizationRegistry.[[CleanupCallback]].
|
|
||||||
5. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to true.
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
7. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to false.
|
|
||||||
8. If result is an abrupt completion, return result.
|
|
||||||
features: [FinalizationRegistry, arrow-function, async-functions, async-iteration, class, host-gc-required]
|
|
||||||
includes: [async-gc.js]
|
|
||||||
flags: [async, non-deterministic]
|
|
||||||
---*/
|
|
||||||
|
|
||||||
var called = 0;
|
|
||||||
var iterator = false;
|
|
||||||
|
|
||||||
function poisoned(iter) {
|
|
||||||
called += 1;
|
|
||||||
iterator = iter;
|
|
||||||
iter.next(); // Won't throw
|
|
||||||
throw new Test262Error();
|
|
||||||
}
|
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
|
||||||
|
|
||||||
function emptyCells() {
|
|
||||||
var target = {};
|
|
||||||
finalizationRegistry.register(target);
|
|
||||||
|
|
||||||
var prom = asyncGC(target);
|
|
||||||
target = null;
|
|
||||||
|
|
||||||
return prom;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyCells().then(function() {
|
|
||||||
assert.throws(Test262Error, function() {
|
|
||||||
finalizationRegistry.cleanupSome(poisoned);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.sameValue(called, 1);
|
|
||||||
|
|
||||||
assert.sameValue(typeof iterator, 'object');
|
|
||||||
assert.sameValue(typeof iterator.next, 'function');
|
|
||||||
assert.throws(TypeError, function() {
|
|
||||||
iterator.next();
|
|
||||||
}, 'iterator.next throws a TypeError if IsFinalizationRegistryCleanupJobActive is false');
|
|
||||||
}).then($DONE, resolveAsyncGC);
|
|
@ -4,15 +4,10 @@
|
|||||||
/*---
|
/*---
|
||||||
esid: sec-properties-of-the-finalization-registry-constructor
|
esid: sec-properties-of-the-finalization-registry-constructor
|
||||||
description: >
|
description: >
|
||||||
The cleanupSome() method throws if cleanup is currently in progress.
|
The cleanupSome() method can be reentered
|
||||||
info: |
|
info: |
|
||||||
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
|
||||||
|
|
||||||
1. Let finalizationRegistry be the this value.
|
|
||||||
...
|
|
||||||
4. If finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] is true,
|
|
||||||
throw a TypeError exception.
|
|
||||||
|
|
||||||
features: [FinalizationRegistry, host-gc-required]
|
features: [FinalizationRegistry, host-gc-required]
|
||||||
includes: [async-gc.js]
|
includes: [async-gc.js]
|
||||||
flags: [async, non-deterministic]
|
flags: [async, non-deterministic]
|
||||||
@ -22,16 +17,14 @@ var called = 0;
|
|||||||
var endOfCall = 0;
|
var endOfCall = 0;
|
||||||
var finalizationRegistry = new FinalizationRegistry(function() {});
|
var finalizationRegistry = new FinalizationRegistry(function() {});
|
||||||
|
|
||||||
function callback(iterator) {
|
function callback(holding) {
|
||||||
called += 1;
|
called += 1;
|
||||||
|
|
||||||
if (called === 1) {
|
if (called === 1) {
|
||||||
// Atempt to re-enter the callback.
|
// Atempt to re-enter the callback.
|
||||||
var nestedCallbackRan = false;
|
var nestedCallbackRan = false;
|
||||||
assert.throws(TypeError, () => {
|
|
||||||
finalizationRegistry.cleanupSome(() => { nestedCallbackRan = true });
|
finalizationRegistry.cleanupSome(() => { nestedCallbackRan = true });
|
||||||
});
|
assert.sameValue(nestedCallbackRan, true);
|
||||||
assert.sameValue(nestedCallbackRan, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
endOfCall += 1;
|
endOfCall += 1;
|
||||||
@ -39,7 +32,10 @@ function callback(iterator) {
|
|||||||
|
|
||||||
function emptyCells() {
|
function emptyCells() {
|
||||||
var o1 = {};
|
var o1 = {};
|
||||||
|
var o2 = {};
|
||||||
|
// Register more than one objects to test reentrancy.
|
||||||
finalizationRegistry.register(o1, 'holdings 1');
|
finalizationRegistry.register(o1, 'holdings 1');
|
||||||
|
finalizationRegistry.register(o2, 'holdings 2');
|
||||||
|
|
||||||
var prom = asyncGC(o1);
|
var prom = asyncGC(o1);
|
||||||
o1 = null;
|
o1 = null;
|
@ -39,46 +39,28 @@ function emptyCells() {
|
|||||||
return prom;
|
return prom;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tests = [];
|
emptyCells().then(function() {
|
||||||
|
|
||||||
tests.push(emptyCells().then(function() {
|
|
||||||
called = 0;
|
called = 0;
|
||||||
assert.sameValue(finalizationRegistry.cleanupSome(cb), undefined, 'regular callback');
|
assert.sameValue(finalizationRegistry.cleanupSome(cb), undefined, 'regular callback');
|
||||||
assert.sameValue(called, 1);
|
assert.sameValue(called, 1);
|
||||||
}));
|
}).then(emptyCells).then(function() {
|
||||||
|
|
||||||
tests.push(emptyCells().then(function() {
|
|
||||||
called = 0;
|
called = 0;
|
||||||
assert.sameValue(finalizationRegistry.cleanupSome(fn), undefined, 'regular callback, same FG cleanup function');
|
assert.sameValue(finalizationRegistry.cleanupSome(fn), undefined, 'regular callback, same FG cleanup function');
|
||||||
assert.sameValue(called, 1);
|
assert.sameValue(called, 1);
|
||||||
}));
|
}).then(emptyCells).then(function() {
|
||||||
|
|
||||||
tests.push(emptyCells().then(function() {
|
|
||||||
called = 0;
|
called = 0;
|
||||||
assert.sameValue(finalizationRegistry.cleanupSome(), undefined, 'undefined (implicit) callback, defer to FB callback');
|
assert.sameValue(finalizationRegistry.cleanupSome(), undefined, 'undefined (implicit) callback, defer to FB callback');
|
||||||
assert.sameValue(called, 1);
|
assert.sameValue(called, 1);
|
||||||
}));
|
}).then(emptyCells).then(function() {
|
||||||
|
|
||||||
tests.push(emptyCells().then(function() {
|
|
||||||
called = 0;
|
called = 0;
|
||||||
assert.sameValue(finalizationRegistry.cleanupSome(undefined), undefined, 'undefined (explicit) callback, defer to FB callback');
|
assert.sameValue(finalizationRegistry.cleanupSome(undefined), undefined, 'undefined (explicit) callback, defer to FB callback');
|
||||||
assert.sameValue(called, 1);
|
assert.sameValue(called, 1);
|
||||||
}));
|
}).then(emptyCells).then(function() {
|
||||||
|
|
||||||
tests.push(emptyCells().then(function() {
|
|
||||||
assert.sameValue(finalizationRegistry.cleanupSome(() => 1), undefined, 'arrow function');
|
assert.sameValue(finalizationRegistry.cleanupSome(() => 1), undefined, 'arrow function');
|
||||||
}));
|
}).then(emptyCells).then(function() {
|
||||||
|
|
||||||
tests.push(emptyCells().then(function() {
|
|
||||||
assert.sameValue(finalizationRegistry.cleanupSome(async function() {}), undefined, 'async function');
|
assert.sameValue(finalizationRegistry.cleanupSome(async function() {}), undefined, 'async function');
|
||||||
}));
|
}).then(emptyCells).then(function() {
|
||||||
|
|
||||||
tests.push(emptyCells().then(function() {
|
|
||||||
assert.sameValue(finalizationRegistry.cleanupSome(function *() {}), undefined, 'generator');
|
assert.sameValue(finalizationRegistry.cleanupSome(function *() {}), undefined, 'generator');
|
||||||
}));
|
}).then(emptyCells).then(function() {
|
||||||
|
|
||||||
tests.push(emptyCells().then(function() {
|
|
||||||
assert.sameValue(finalizationRegistry.cleanupSome(async function *() {}), undefined, 'async generator');
|
assert.sameValue(finalizationRegistry.cleanupSome(async function *() {}), undefined, 'async generator');
|
||||||
}));
|
}).then($DONE, resolveAsyncGC);
|
||||||
|
|
||||||
Promise.all(tests).then(() => { $DONE(); }, resolveAsyncGC);
|
|
||||||
|
@ -15,18 +15,11 @@ info: |
|
|||||||
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
|
||||||
|
|
||||||
...
|
...
|
||||||
3. Let iterator be ! CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
|
3. While finalizationRegistry.[[Cells]] contains a Record cell such that cell.[[WeakRefTarget]] is ~empty~, then an implementation may perform the following steps,
|
||||||
...
|
|
||||||
6. Let result be Call(callback, undefined, « iterator »).
|
|
||||||
...
|
|
||||||
|
|
||||||
%FinalizationRegistryCleanupIteratorPrototype%.next ( )
|
|
||||||
|
|
||||||
8. If finalizationRegistry.[[Cells]] contains a Record cell such that cell.[[Target]] is empty,
|
|
||||||
a. Choose any such cell.
|
a. Choose any such cell.
|
||||||
b. Remove cell from finalizationRegistry.[[Cells]].
|
b. Remove cell from finalizationRegistry.[[Cells]].
|
||||||
c. Return CreateIterResultObject(cell.[[Holdings]], false).
|
c. Perform ? Call(callback, undefined, << cell.[[HeldValue]] >>).
|
||||||
9. Otherwise, return CreateIterResultObject(undefined, true).
|
...
|
||||||
|
|
||||||
FinalizationRegistry.prototype.unregister ( unregisterToken )
|
FinalizationRegistry.prototype.unregister ( unregisterToken )
|
||||||
|
|
||||||
@ -57,10 +50,10 @@ function emptyCells() {
|
|||||||
|
|
||||||
emptyCells().then(function() {
|
emptyCells().then(function() {
|
||||||
var called = 0;
|
var called = 0;
|
||||||
var holdings;
|
var holdings = [];
|
||||||
finalizationRegistry.cleanupSome(function cb(iterator) {
|
finalizationRegistry.cleanupSome(function cb(holding) {
|
||||||
called += 1;
|
called += 1;
|
||||||
holdings = [...iterator];
|
holdings.push(holding);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.sameValue(called, 1);
|
assert.sameValue(called, 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user