Revert "Remove tests based on the $262.gc hook"

This reverts commit d6d37f2f43.
This commit is contained in:
Leo Balter 2019-09-18 13:42:31 -03:00 committed by Rick Waldron
parent 17685735e1
commit 7134634aa4
22 changed files with 1489 additions and 0 deletions

View File

@ -62,6 +62,8 @@ properties of the global scope prior to test execution.
Completion{[[Type]]: throw, [[Value]]: error, [[Target]]: empty}.
5. Let status be ScriptEvaluation(s).
6. Return Completion(status).
- **`gc`** - a function that wraps the host's garbage collection invocation mechanism, if such a capability exists. Must throw an exception if no capability exists. This is necessary for testing the semantics of any feature that relies on garbage collection, e.g. the `WeakRef` API.
- **`global`** - a reference to the global object on which `$262` was initially defined
- **`IsHTMLDDA`** - (present only in implementations that can provide it) an
object that 1) has an [[IsHTMLDDA]] internal slot, and 2) when called with

View File

@ -236,3 +236,4 @@ WeakSet
# object, go here.
IsHTMLDDA
host-gc-required

View File

@ -0,0 +1,58 @@
// 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-group-constructor
description: >
FinalizationGroupCleanupIteratorPrototype @@toStringTag
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
6. Let result be Call(callback, undefined, « iterator »).
...
%FinalizationGroupCleanupIteratorPrototype% [ @@toStringTag ]
The initial value of the @@toStringTag property is the String value "FinalizationGroup Cleanup Iterator".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
includes: [propertyHelper.js]
features: [FinalizationGroup, host-gc-required, Symbol, Symbol.toStringTag]
---*/
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
called += 1;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
fg.cleanupSome(callback);
assert.sameValue(called, 1, 'cleanup successful');
verifyProperty(FinalizationGroupCleanupIteratorPrototype, Symbol.toStringTag, {
value: 'FinalizationGroup Cleanup Iterator',
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,62 @@
// 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-group-constructor
description: >
Throws a TypeError if [[IsFinalizationGroupCleanupJobActive]] is false
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
5. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to true.
6. Let result be Call(callback, undefined, « iterator »).
7. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to false.
...
%FinalizationGroupCleanupIteratorPrototype%.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 [[FinalizationGroup]] internal slot, throw a TypeError exception.
features: [FinalizationGroup, WeakRef, host-gc-required, Symbol]
---*/
var iter;
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
called += 1;
iter = iterator;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
fg.cleanupSome(callback);
// Make sure everything is set
assert.sameValue(called, 1, 'cleanup successful');
assert.sameValue(typeof iter, 'object');
assert.sameValue(Object.getPrototypeOf(iter), FinalizationGroupCleanupIteratorPrototype);
// To the actual assertion
assert.throws(TypeError, function() {
iter.next();
}, 'Iter should fail if not called during the cleanupSome call');

View File

@ -0,0 +1,70 @@
// 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-group-constructor
description: >
FinalizationGroupCleanupIteratorPrototype.next.length property descriptor
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
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: [propertyHelper.js]
features: [FinalizationGroup, host-gc-required, Symbol]
---*/
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
called += 1;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
fg.cleanupSome(callback);
assert.sameValue(called, 1, 'cleanup successful');
assert.sameValue(typeof FinalizationGroupCleanupIteratorPrototype.next, 'function');
var next = FinalizationGroupCleanupIteratorPrototype.next;
verifyProperty(next, 'length', {
value: 0,
enumerable: false,
writable: false,
configurable: true,
});

View File

@ -0,0 +1,83 @@
// 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-group-constructor
description: >
If iterator does not have a [[FinalizationGroup]] internal slot, throw a TypeError exception.
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
6. Let result be Call(callback, undefined, « iterator »).
...
%FinalizationGroupCleanupIteratorPrototype%.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 [[FinalizationGroup]] internal slot, throw a TypeError exception.
features: [FinalizationGroup, WeakRef, host-gc-required, Symbol]
---*/
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var endOfCall = 0;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
called += 1;
// Only the iterator itself will have a [[FinalizationGroup]] internal
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
// It's sensitive the assertions remain inside this function in order to secure
// [[IsFinalizationGroupCleanupJobActive]] is true
assert.sameValue(typeof FinalizationGroupCleanupIteratorPrototype.next, 'function');
var next = FinalizationGroupCleanupIteratorPrototype.next;
assert.throws(TypeError, function() {
next.call({});
}, '{}');
assert.throws(TypeError, function() {
next.call(FinalizationGroup);
}, 'FinalizationGroup');
assert.throws(TypeError, function() {
next.call(FinalizationGroupCleanupIteratorPrototype);
}, 'FinalizationGroupCleanupIteratorPrototype');
assert.throws(TypeError, function() {
next.call(fg);
}, 'FinalizationGroup instance');
var wr = new WeakRef({});
assert.throws(TypeError, function() {
next.call(wr);
}, 'WeakRef instance');
// Abrupt completions are not directly returned.
endOfCall += 1;
}
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
fg.cleanupSome(callback);
assert.sameValue(called, 1, 'cleanup successful');
assert.sameValue(endOfCall, 1, 'Abrupt completions are not directly returned.');

View File

@ -0,0 +1,69 @@
// 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-group-constructor
description: >
FinalizationGroupCleanupIteratorPrototype.next.name property descriptor
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
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: [propertyHelper.js]
features: [FinalizationGroup, host-gc-required, Symbol]
---*/
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
called += 1;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
fg.cleanupSome(callback);
assert.sameValue(called, 1, 'cleanup successful');
assert.sameValue(typeof FinalizationGroupCleanupIteratorPrototype.next, 'function');
var next = FinalizationGroupCleanupIteratorPrototype.next;
verifyProperty(next, 'name', {
value: 'next',
enumerable: false,
writable: false,
configurable: true,
});

View File

@ -0,0 +1,82 @@
// 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-group-constructor
description: >
FinalizationGroupCleanupIteratorPrototype.next() throws if this is not Object
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
6. Let result be Call(callback, undefined, « iterator »).
...
%FinalizationGroupCleanupIteratorPrototype%.next ( )
1. Let iterator be the this value.
2. If Type(iterator) is not Object, throw a TypeError exception.
features: [FinalizationGroup, host-gc-required, Symbol]
---*/
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
called += 1;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
fg.cleanupSome(callback);
assert.sameValue(called, 1, 'cleanup successful');
assert.sameValue(typeof FinalizationGroupCleanupIteratorPrototype.next, 'function');
var next = FinalizationGroupCleanupIteratorPrototype.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');

View File

@ -0,0 +1,61 @@
// 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-group-constructor
description: >
Prop descriptor for FinalizationGroupCleanupIteratorPrototype.next
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
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]
features: [FinalizationGroup, host-gc-required, Symbol]
---*/
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
called += 1;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
fg.cleanupSome(callback);
assert.sameValue(called, 1, 'cleanup successful');
assert.sameValue(typeof FinalizationGroupCleanupIteratorPrototype.next, 'function');
var next = FinalizationGroupCleanupIteratorPrototype.next;
verifyProperty(FinalizationGroupCleanupIteratorPrototype, 'next', {
enumerable: false,
writable: true,
configurable: true,
});

View File

@ -0,0 +1,84 @@
// 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-group-constructor
description: >
FinalizationGroupCleanupIterator has a [[Prototype]] internal slot whose value is the intrinsic
object %IteratorPrototype%.
info: |
The %FinalizationGroupCleanupIteratorPrototype% Object
- has properties that are inherited by all FinalizationGroup Cleanup Iterator Objects.
- is an ordinary object.
- has a [[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%.
...
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
3. If finalizationGroup 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 ! CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
2. If CheckForEmptyCells(finalizationGroup) is false, return.
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
4. If callback is undefined, set callback to finalizationGroup.[[CleanupCallback]].
5. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to true.
6. Let result be Call(callback, undefined, « iterator »).
...
CheckForEmptyCells ( finalizationGroup )
...
2. For each cell in finalizationGroup.[[Cells]], do
a. If cell.[[Target]] is empty, then
i. Return true.
3. Return false.
CreateFinalizationGroupCleanupIterator ( finalizationGroup )
...
4. Let prototype be finalizationGroup.[[Realm]].[[Intrinsics]].[[%FinalizationGroupCleanupIteratorPrototype%]].
5. Let iterator be ObjectCreate(prototype, « [[FinalizationGroup]] »).
6. Set iterator.[[FinalizationGroup]] to finalizationGroup.
7. Return iterator.
features: [FinalizationGroup, host-gc-required]
---*/
var IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var cleanupCallbackCalled = 0;
function callback(iterator) {
called += 1;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
var fg = new FinalizationGroup(function() {});
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
fg.cleanupSome(callback);
assert.sameValue(called, 1, 'cleanup successful');
var proto = Object.getPrototypeOf(FinalizationGroupCleanupIteratorPrototype);
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');

View File

@ -0,0 +1,135 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-finalization-group-target
description: >
cleanupCallback has only one optional chance to be called for a GC that cleans up
a registered target.
info: |
FinalizationGroup ( cleanupCallback )
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
...
4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception.
5. Perform ? CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
Execution
At any time, if an object obj is not live, an ECMAScript implementation may perform the following steps atomically:
1. For each WeakRef ref such that ref.[[Target]] is obj,
a. Set ref.[[Target]] to empty.
2. For each FinalizationGroup fg such that fg.[[Cells]] contains cell, such that cell.[[Target]] is obj,
a. Set cell.[[Target]] to empty.
b. Optionally, perform ! HostCleanupFinalizationGroup(fg).
features: [FinalizationGroup, async-functions, host-gc-required]
flags: [async]
---*/
var cleanupCallback = 0;
var called = 0;
// both this cb and the fg callback are not exhausting the iterator to prevent
// the target cell from being removed from the finalizationGroup.[[Cells]].
// More info at %FinalizationGroupCleanupIteratorPrototype%.next ( )
function cb() {
called += 1;
}
var fg = new FinalizationGroup(function() {
cleanupCallback += 1;
});
function emptyCells() {
(function() {
var a = {};
fg.register(a, 'a');
})();
// GC is called here
$262.gc();
}
emptyCells();
// Let's add some async ticks, as the cleanupCallback is not meant to interrupt
// synchronous operations.
async function fn() {
await Promise.resolve(1);
fg.cleanupSome(cb);
// This asserts the registered object was emptied in the previous GC.
assert.sameValue(called, 1, 'cleanupSome callback for the first time');
// 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
// for the other executions of the Garbage Collector.
// The chance of having it called only happens right after the
// cell.[[Target]] is set to empty.
assert(cleanupCallback >= 0, 'cleanupCallback might be 0');
assert(cleanupCallback <= 1, 'cleanupCallback might be 1');
// Restoring the cleanupCallback variable to 0 will help us asserting the fg
// callback is not called again.
cleanupCallback = 0;
$262.gc();
await Promise.resolve(2); // tick
fg.cleanupSome(cb);
// This cb is called again because fg still holds an emptied cell, but it's
// 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');
$262.gc();
await Promise.resolve(3); // tick
fg.cleanupSome(cb);
assert.sameValue(called, 3, 'cleanupSome callback for the third time');
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #2');
$262.gc();
}
fn()
.then(async function() { // tick
await Promise.resolve(4); // tick
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #3');
fg.cleanupSome(cb);
assert.sameValue(called, 4, 'cleanupSome callback for the fourth time');
assert.sameValue(cleanupCallback, 0, 'cleanupCallback is not called again #4');
$262.gc();
// Now we are exhausting the iterator, so cleanupSome callback will also not be called.
fg.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');
$262.gc();
await Promise.resolve(5); // tick
await await Promise.resolve(6); // more ticks
await await await Promise.resolve(7); // even more ticks
fg.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, $DONE);

View File

@ -0,0 +1,87 @@
// 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-group-constructor
description: >
The callback function is called with a FinalizationGroupCleanupIterator
info: |
The %FinalizationGroupCleanupIteratorPrototype% Object
- has properties that are inherited by all FinalizationGroup Cleanup Iterator Objects.
- is an ordinary object.
- has a [[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%.
...
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
3. If finalizationGroup 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 ! CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
2. If CheckForEmptyCells(finalizationGroup) is false, return.
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
4. If callback is undefined, set callback to finalizationGroup.[[CleanupCallback]].
5. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to true.
6. Let result be Call(callback, undefined, « iterator »).
...
CheckForEmptyCells ( finalizationGroup )
...
2. For each cell in finalizationGroup.[[Cells]], do
a. If cell.[[Target]] is empty, then
i. Return true.
3. Return false.
CreateFinalizationGroupCleanupIterator ( finalizationGroup )
...
4. Let prototype be finalizationGroup.[[Realm]].[[Intrinsics]].[[%FinalizationGroupCleanupIteratorPrototype%]].
5. Let iterator be ObjectCreate(prototype, « [[FinalizationGroup]] »).
6. Set iterator.[[FinalizationGroup]] to finalizationGroup.
7. Return iterator.
features: [FinalizationGroup, host-gc-required]
---*/
var IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
var cleanupCallbackCalled = 0;
function callback(iterator) {
called += 1;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
var fg = new FinalizationGroup(function() {
cleanupCallbackCalled += 1;
});
(function() {
let o = {};
fg.register(o);
})();
assert.sameValue(called, 0);
$262.gc();
fg.cleanupSome(callback);
assert.sameValue(called, 1);
var proto = Object.getPrototypeOf(FinalizationGroupCleanupIteratorPrototype);
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');

View File

@ -0,0 +1,48 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-finalization-group.prototype.cleanupSome
description: Cleanup might be prevented with a reference usage;
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
3. If finalizationGroup 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 ? CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
features: [FinalizationGroup, host-gc-required]
---*/
var holdingsList;
function cb(iterator) {
holdingsList = [...iterator];
};
var fg = new FinalizationGroup(function() {});
function emptyCells() {
var x;
(function() {
var a = {};
b = {};
x = {};
var y = {};
fg.register(x, 'x');
fg.register(a, 'a');
fg.register(y, y);
fg.register(b, 'b');
var b;
})();
$262.gc();
x; // This is an intentional reference to x, please leave it here, after the GC
}
emptyCells();
fg.cleanupSome(cb);
// The order is per implementation so we can't use compareArray without sorting
assert.sameValue(holdingsList.length, 2);
assert(holdingsList.includes('a'));
assert(holdingsList.includes('b'));

View File

@ -0,0 +1,88 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-finalization-group.prototype.cleanupSome
description: Cleanup might be prevented with an unregister usage
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
3. If finalizationGroup 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 ? CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
FinalizationGroup.prototype.unregister ( unregisterToken )
1. Let removed be false.
2. For each Record { [[Target]], [[Holdings]], [[UnregisterToken]] } cell that is an element of finalizationGroup.[[Cells]], do
a. If SameValue(cell.[[UnregisterToken]], unregisterToken) is true, then
i. Remove cell from finalizationGroup.[[Cells]].
ii. Set removed to true.
3. Return removed.
features: [FinalizationGroup, host-gc-required]
---*/
var holdingsList;
var fg = new FinalizationGroup(function() {});
var unregA = {};
var unregB = {};
var unregC = {};
var unregDE = {}; // Use the same unregister token for D and E
function emptyCells() {
(function() {
var a = {};
var b = {};
var c = {};
var d = {};
var e = {};
fg.register(a, 'a', unregA);
fg.register(b, 'b', unregB);
fg.register(c, 'c', unregC);
fg.register(d, 'd', unregDE);
fg.register(e, 'e', unregDE);
})();
var res = fg.unregister(unregC); // unregister 'c' before GC
assert.sameValue(res, true, 'unregister c before GC');
$262.gc();
}
emptyCells();
var res = fg.unregister(unregDE);
assert.sameValue(res, true, 'unregister d and e after GC');
fg.cleanupSome(function cb(iterator) {
var res = fb.unregister(unregA);
assert.sameValue(res, true, 'unregister a before the iterator is consumed.');
holdingsList = [...iterator];
// It's not possible to verify an unregister during the iterator consumption
// as it's .next() does not have any specific order to follow for each item.
});
assert.sameValue(holdingsList[0], 'b');
assert.sameValue(holdingsList.length, 1);
// Second run
res = fg.unregister(unregB); // let's empty the cells
assert.sameValue(res, true, 'unregister B for cleanup');
holdingsList = undefined;
emptyCells();
fg.cleanupSome(function cb(iterator) {
var res = fb.unregister(unregDE);
assert.sameValue(res, true, 'unregister d and e before the iterator is consumed.');
holdingsList = [...iterator];
});
assert(holdingsList.includes('b'));
assert(holdingsList.includes('a'), 'just like the first run, now without removing a');
assert.sameValue(holdingsList.length, 2);

View File

@ -0,0 +1,82 @@
// 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-group-constructor
description: >
The cleanup callback function is called with a FinalizationGroupCleanupIterator
info: |
The %FinalizationGroupCleanupIteratorPrototype% Object
- has properties that are inherited by all FinalizationGroup Cleanup Iterator Objects.
- is an ordinary object.
- has a [[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%.
...
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
3. If finalizationGroup 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 ! CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
2. If CheckForEmptyCells(finalizationGroup) is false, return.
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
4. If callback is undefined, set callback to finalizationGroup.[[CleanupCallback]].
5. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to true.
6. Let result be Call(callback, undefined, « iterator »).
...
CheckForEmptyCells ( finalizationGroup )
...
2. For each cell in finalizationGroup.[[Cells]], do
a. If cell.[[Target]] is empty, then
i. Return true.
3. Return false.
CreateFinalizationGroupCleanupIterator ( finalizationGroup )
...
4. Let prototype be finalizationGroup.[[Realm]].[[Intrinsics]].[[%FinalizationGroupCleanupIteratorPrototype%]].
5. Let iterator be ObjectCreate(prototype, « [[FinalizationGroup]] »).
6. Set iterator.[[FinalizationGroup]] to finalizationGroup.
7. Return iterator.
features: [FinalizationGroup, host-gc-required]
---*/
var IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
var FinalizationGroupCleanupIteratorPrototype;
var called = 0;
function callback(iterator) {
called += 1;
FinalizationGroupCleanupIteratorPrototype = Object.getPrototypeOf(iterator);
}
var fg = new FinalizationGroup(callback);
(function() {
let o = {};
fg.register(o);
})();
assert.sameValue(called, 0);
$262.gc();
fg.cleanupSome();
assert.sameValue(called, 1);
var proto = Object.getPrototypeOf(FinalizationGroupCleanupIteratorPrototype);
assert.sameValue(
proto, IteratorPrototype,
'[[Prototype]] internal slot whose value is the intrinsic object %IteratorPrototype%'
);

View File

@ -0,0 +1,51 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-finalization-group.prototype.cleanupSome
description: WeakRef deref should not prevent a GC event
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
...
4. If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception.
5. Perform ? CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
WeakRef.prototype.deref ( )
...
4. Let target be the value of weakRef.[[Target]].
5. If target is not empty,
a. Perform ! KeepDuringJob(target).
b. Return target.
6. Return undefined.
features: [FinalizationGroup, WeakRef, host-gc-required]
---*/
var holdingsList;
function cb(iterator) {
holdingsList = [...iterator];
}
var fg = new FinalizationGroup(function() {});
var deref = false;
function emptyCells() {
var wr;
(function() {
var a = {};
wr = new WeakRef(a);
fg.register(a, 'a');
})();
$262.gc();
deref = wr.deref();
}
emptyCells();
fg.cleanupSome(cb);
assert.sameValue(holdingsList.length, 1);
assert.sameValue(holdingsList[0], 'a');
assert.sameValue(deref, undefined, 'deref handles an empty wearRef.[[Target]] returning undefined');

View File

@ -0,0 +1,98 @@
// 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-group-constructor
description: >
The callback iterator is dynamic. Therefore, it can be emptied before iteration
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
6. Let result be Call(callback, undefined, « iterator »).
...
%FinalizationGroupCleanupIteratorPrototype%.next ( )
8. If finalizationGroup.[[Cells]] contains a Record cell such that cell.[[Target]] is empty,
a. Choose any such cell.
b. Remove cell from finalizationGroup.[[Cells]].
c. Return CreateIterResultObject(cell.[[Holdings]], false).
9. Otherwise, return CreateIterResultObject(undefined, true).
features: [FinalizationGroup, host-gc-required, Symbol]
---*/
var called = 0;
var endOfCall = 0;
var first, second, third;
var firstIter, secondIter, thirdIter;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
called += 1;
if (called === 1) {
// Inception!
fg.cleanupSome(callback);
first = iterator.next();
firstIter = iterator;
} else if (called === 2) {
// Double Inception!
fg.cleanupSome(callback);
second = iterator.next();
secondIter = iterator;
} else if (called === 3) {
// Triple Inception!
// But this time we won't try to consume iterator anymore, leave it alone there.
fg.cleanupSome(callback);
third = iterator.next();
thirdIter = iterator;
}
endOfCall += 1;
}
(function() {
var o1 = {};
var o2 = {};
fg.register(o1, 'holdings 1');
fg.register(o2, 'holdings 2');
})();
$262.gc();
fg.cleanupSome(callback);
// Make sure everything is set
assert.sameValue(called, 4, 'cleanup successfully');
assert.sameValue(endOfCall, 4, 'cleanup ended successfully');
assert.notSameValue(firstIter, secondIter, 'callback is not called with the same iterator #1');
assert.notSameValue(firstIter, thirdIter, 'callback is not called with the same iterator #2');
assert.notSameValue(secondIter, thirdIter, 'callback is not called with the same iterator #3');
assert.sameValue(first.value, undefined, 'iterator is already consumed');
assert.sameValue(first.done, true, 'first callback will find no empty Targets');
assert.sameValue(second.done, false, 'second callback will find an empty Target');
assert.sameValue(third.done, false, 'third callback will find an empty Target');
// 8.a. Choose any such cell.
var holdings = [second.value, third.value];
assert(holdings.includes('holdings 1'), 'iterators consume emptied cells #1');
assert(holdings.includes('holdings 2'), 'iterators consume emptied cells #2');

View File

@ -0,0 +1,116 @@
// 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-group-constructor
description: >
Iterates over different type values in holdings
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
...
5. Perform ! CleanupFinalizationGroup(finalizationGroup, callback).
...
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
...
3. Let iterator be ! CreateFinalizationGroupCleanupIterator(finalizationGroup).
...
6. Let result be Call(callback, undefined, « iterator »).
...
%FinalizationGroupCleanupIteratorPrototype%.next ( )
8. If finalizationGroup.[[Cells]] contains a Record cell such that cell.[[Target]] is empty,
a. Choose any such cell.
b. Remove cell from finalizationGroup.[[Cells]].
c. Return CreateIterResultObject(cell.[[Holdings]], false).
9. Otherwise, return CreateIterResultObject(undefined, true).
features: [FinalizationGroup, Symbol, host-gc-required]
includes: [compareArray.js]
---*/
var holdings;
var fg = new FinalizationGroup(function() {});
function callback(iterator) {
holdings = [...iterator];
}
(function() {
var o = {};
fg.register(o);
fg.register(o, undefined);
})();
$262.gc();
fg.cleanupSome(callback);
assert.compareArray(holdings, [undefined, undefined], 'undefined');
(function() {
var o = {};
fg.register(o, null);
})();
$262.gc();
fg.cleanupSome(callback);
assert.compareArray(holdings, [null], 'null');
(function() {
var o = {};
fg.register(o, '');
})();
$262.gc();
fg.cleanupSome(callback);
assert.compareArray(holdings, [''], 'the empty string');
var other = {};
(function() {
var o = {};
fg.register(o, other);
})();
$262.gc();
fg.cleanupSome(callback);
assert.compareArray(holdings, [other], '{}');
(function() {
var o = {};
fg.register(o, 42);
})();
$262.gc();
fg.cleanupSome(callback);
assert.compareArray(holdings, [42], '42');
(function() {
var o = {};
fg.register(o, true);
})();
$262.gc();
fg.cleanupSome(callback);
assert.compareArray(holdings, [true], 'true');
(function() {
var o = {};
fg.register(o, false);
})();
$262.gc();
fg.cleanupSome(callback);
assert.compareArray(holdings, [false], 'false');
var s = Symbol();
(function() {
var o = {};
fg.register(o, s);
})();
$262.gc();
fg.cleanupSome(callback);
assert.compareArray(holdings, [s], 'symbol');

View File

@ -0,0 +1,58 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-finalization-group.prototype.cleanupSome
description: Return abrupt completion from CleanupFinalizationGroup
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
3. If finalizationGroup 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 ? CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
4. If callback is undefined, set callback to finalizationGroup.[[CleanupCallback]].
5. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to true.
6. Let result be Call(callback, undefined, « iterator »).
7. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to false.
8. If result is an abrupt completion, return result.
features: [FinalizationGroup, arrow-function, async-functions, async-iteration, class, host-gc-required]
---*/
var called = 0;
var iterator;
function poisoned(iter) {
iterator = iter;
iter.next(); // Won't throw
throw new Test262Error();
}
var fg = new FinalizationGroup(function() {
called += 1;
});
function emptyCells() {
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
}
emptyCells();
assert.throws(Test262Error, function() {
fg.cleanupSome(poisoned);
});
assert.sameValue(called, 0);
assert.sameValue(typeof iteraror.next, 'function');
assert.throws(TypeError, function() {
iterator.next();
}, 'iterator.next throws a TypeError if IsFinalizationGroupCleanupJobActive is false');

View File

@ -0,0 +1,52 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-finalization-group.prototype.cleanupSome
description: Return abrupt completion from CleanupFinalizationGroup (using CleanupCallback)
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
3. If finalizationGroup 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 ? CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
4. If callback is undefined, set callback to finalizationGroup.[[CleanupCallback]].
5. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to true.
6. Let result be Call(callback, undefined, « iterator »).
7. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to false.
8. If result is an abrupt completion, return result.
features: [FinalizationGroup, arrow-function, async-functions, async-iteration, class, host-gc-required]
---*/
var iterator;
function poisoned(iter) {
iterator = iter;
iter.next(); // Won't throw
throw new Test262Error();
}
var fg = new FinalizationGroup(poisoned);
function emptyCells() {
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
}
emptyCells();
assert.throws(Test262Error, function() {
fg.cleanupSome();
});
assert.sameValue(typeof iteraror.next, 'function');
assert.throws(TypeError, function() {
iterator.next();
}, 'iterator.next throws a TypeError if IsFinalizationGroupCleanupJobActive is false');

View File

@ -0,0 +1,69 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-finalization-group.prototype.cleanupSome
description: Return undefined regardless the result of CleanupFinalizationGroup
info: |
FinalizationGroup.prototype.cleanupSome ( [ callback ] )
1. Let finalizationGroup be the this value.
2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
3. If finalizationGroup 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 ? CleanupFinalizationGroup(finalizationGroup, callback).
6. Return undefined.
features: [FinalizationGroup, arrow-function, async-functions, async-iteration, class, host-gc-required]
---*/
var called;
var fn = function() {
called += 1;
return 39;
};
var cb = function() {
called += 1;
return 42;
};
var fg = new FinalizationGroup(fn);
function emptyCells() {
called = 0;
(function() {
var o = {};
fg.register(o);
})();
$262.gc();
}
emptyCells();
assert.sameValue(fg.cleanupSome(cb), undefined, 'regular callback');
assert.sameValue(called, 1);
emptyCells();
assert.sameValue(fg.cleanupSome(fn), undefined, 'regular callback, same FG cleanup function');
assert.sameValue(called, 1);
emptyCells();
assert.sameValue(fg.cleanupSome(() => 1), undefined, 'arrow function');
emptyCells();
assert.sameValue(fg.cleanupSome(fg.cleanupSome), undefined, 'cleanupSome itself');
emptyCells();
assert.sameValue(fg.cleanupSome(class {}), undefined, 'class expression');
emptyCells();
assert.sameValue(fg.cleanupSome(async function() {}), undefined, 'async function');
emptyCells();
assert.sameValue(fg.cleanupSome(function *() {}), undefined, 'generator');
emptyCells();
assert.sameValue(fg.cleanupSome(async function *() {}), undefined, 'async generator');
emptyCells();
assert.sameValue(fg.cleanupSome(), undefined, 'undefined, implicit');
emptyCells();
assert.sameValue(fg.cleanupSome(undefined), undefined, 'undefined, explicit');

View File

@ -0,0 +1,33 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-weak-ref.prototype.deref
description: WeakRef deref should not prevent a GC event
info: |
WeakRef.prototype.deref ( )
...
4. Let target be the value of weakRef.[[Target]].
5. If target is not empty,
a. Perform ! KeepDuringJob(target).
b. Return target.
6. Return undefined.
features: [WeakRef, host-gc-required]
---*/
var deref = false;
function emptyCells() {
var wr;
(function() {
var a = {};
wr = new WeakRef(a);
})();
$262.gc();
deref = wr.deref();
}
emptyCells();
assert.sameValue(deref, undefined);