diff --git a/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/Symbol.toStringTag.js b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/Symbol.toStringTag.js new file mode 100644 index 0000000000..c3f687ca20 --- /dev/null +++ b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/Symbol.toStringTag.js @@ -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 +}); diff --git a/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-job-not-active-throws.js b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-job-not-active-throws.js new file mode 100644 index 0000000000..a482b83848 --- /dev/null +++ b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-job-not-active-throws.js @@ -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'); diff --git a/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-length.js b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-length.js new file mode 100644 index 0000000000..d8c9df9722 --- /dev/null +++ b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-length.js @@ -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, +}); diff --git a/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-missing-internal-throws.js b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-missing-internal-throws.js new file mode 100644 index 0000000000..184a38b41a --- /dev/null +++ b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-missing-internal-throws.js @@ -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.'); diff --git a/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-name.js b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-name.js new file mode 100644 index 0000000000..0522715b75 --- /dev/null +++ b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-name.js @@ -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, +}); diff --git a/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-not-object-throws.js b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-not-object-throws.js new file mode 100644 index 0000000000..169d02834c --- /dev/null +++ b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-not-object-throws.js @@ -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'); diff --git a/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-prop-desc.js b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-prop-desc.js new file mode 100644 index 0000000000..e8663aaec6 --- /dev/null +++ b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/next-prop-desc.js @@ -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, +}); diff --git a/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/proto.js b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/proto.js new file mode 100644 index 0000000000..5b48918f91 --- /dev/null +++ b/test/built-ins/FinalizationGroup/FinalizationGroupCleanupIteratorPrototype/proto.js @@ -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'); diff --git a/test/built-ins/FinalizationGroup/prototype/cleanupSome/callback-iterator-proto.js b/test/built-ins/FinalizationGroup/prototype/cleanupSome/callback-iterator-proto.js new file mode 100644 index 0000000000..cd593cb6cf --- /dev/null +++ b/test/built-ins/FinalizationGroup/prototype/cleanupSome/callback-iterator-proto.js @@ -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'); diff --git a/test/built-ins/FinalizationGroup/prototype/cleanupSome/cleanupcallback-iterator-proto.js b/test/built-ins/FinalizationGroup/prototype/cleanupSome/cleanupcallback-iterator-proto.js new file mode 100644 index 0000000000..5adc6e4700 --- /dev/null +++ b/test/built-ins/FinalizationGroup/prototype/cleanupSome/cleanupcallback-iterator-proto.js @@ -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%' +); + diff --git a/test/built-ins/FinalizationGroup/prototype/cleanupSome/iterator-dynamic.js b/test/built-ins/FinalizationGroup/prototype/cleanupSome/iterator-dynamic.js new file mode 100644 index 0000000000..f930c7aed9 --- /dev/null +++ b/test/built-ins/FinalizationGroup/prototype/cleanupSome/iterator-dynamic.js @@ -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'); diff --git a/test/built-ins/FinalizationGroup/prototype/cleanupSome/iterator-holdings-multiple-values.js b/test/built-ins/FinalizationGroup/prototype/cleanupSome/iterator-holdings-multiple-values.js new file mode 100644 index 0000000000..db2ac9e5c5 --- /dev/null +++ b/test/built-ins/FinalizationGroup/prototype/cleanupSome/iterator-holdings-multiple-values.js @@ -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'); diff --git a/test/built-ins/FinalizationGroup/prototype/cleanupSome/return-undefined-with-gc.js b/test/built-ins/FinalizationGroup/prototype/cleanupSome/return-undefined-with-gc.js new file mode 100644 index 0000000000..07011ef06e --- /dev/null +++ b/test/built-ins/FinalizationGroup/prototype/cleanupSome/return-undefined-with-gc.js @@ -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-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 poisoned = function() { throw new Test262Error(); }; +var fg = new FinalizationGroup(fn); + +function emptyCells(custom) { + called = 0; + if (!custom) { + custom = fg; + } + (function() { + var o = {}; + custom.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(poisoned), undefined, 'poisoned'); + +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'); + +var poisonedFg = new FinalizationGroup(poisoned); + +emptyCells(poisonedFg); +assert.sameValue(poisonedFg.cleanupSome(cb), undefined, 'regular callback on poisoned FG cleanup callback'); + +emptyCells(poisonedFg); +assert.sameValue(poisonedFg.cleanupSome(poisoned), undefined, 'poisoned callback on poisoned FG cleanup callback');