From e55a6c291595ea0dc1d9c12778b84122d616187a Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Tue, 29 Nov 2022 01:24:13 +0700 Subject: [PATCH 01/18] add new built-ins from the ERM proposal --- README.md | 2 +- packages/core-js-compat/src/data.mjs | 10 ++ .../src/modules-by-versions.mjs | 5 + packages/core-js/full/async-iterator/index.js | 1 + packages/core-js/full/iterator/index.js | 1 + .../internals/disposable-stack-helpers.js | 40 ++++++ ...next.async-disposable-stack.constructor.js | 136 ++++++++++++++++++ .../esnext.async-iterator.async-dispose.js | 26 ++++ .../esnext.disposable-stack.constructor.js | 118 +++++++++++++++ .../modules/esnext.iterator.dispose.js | 17 +++ .../esnext.suppressed-error.constructor.js | 50 +++++++ .../modules/esnext.symbol.async-dispose.js | 2 +- .../core-js/modules/esnext.symbol.dispose.js | 2 +- packages/core-js/proposals/using-statement.js | 7 +- tests/compat/tests.js | 15 ++ 15 files changed, 428 insertions(+), 4 deletions(-) create mode 100644 packages/core-js/internals/disposable-stack-helpers.js create mode 100644 packages/core-js/modules/esnext.async-disposable-stack.constructor.js create mode 100644 packages/core-js/modules/esnext.async-iterator.async-dispose.js create mode 100644 packages/core-js/modules/esnext.disposable-stack.constructor.js create mode 100644 packages/core-js/modules/esnext.iterator.dispose.js create mode 100644 packages/core-js/modules/esnext.suppressed-error.constructor.js diff --git a/README.md b/README.md index 4fcbea36081a..b354bf08e1bb 100644 --- a/README.md +++ b/README.md @@ -2382,7 +2382,7 @@ core-js(-pure)/full/array/is-template-object ```js console.log(Array.isTemplateObject((it => it)`qwe${ 123 }asd`)); // => true ``` -##### [`Symbol.{ asyncDispose, dispose }` for `using` statement](https://github.com/tc39/proposal-using-statement)[⬆](#index) +##### [`Symbol.{ asyncDispose, dispose }` for `using` statement](https://github.com/tc39/proposal-explicit-resource-management)[⬆](#index) Modules [`esnext.symbol.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.dispose.js) and [`esnext.symbol.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.async-dispose.js). ```js class Symbol { diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index 7fabd6ce139d..3b726a29d21c 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -1802,6 +1802,8 @@ export const data = { }, // TODO: Remove from `core-js@4` 'esnext.aggregate-error': null, + 'esnext.suppressed-error.constructor': { + }, 'esnext.array.from-async': { bun: '0.3.0', }, @@ -1858,11 +1860,15 @@ export const data = { deno: '1.27', safari: '16.0', }, + 'esnext.async-disposable-stack.constructor': { + }, 'esnext.async-iterator.constructor': { }, // TODO: Remove from `core-js@4` 'esnext.async-iterator.as-indexed-pairs': { }, + 'esnext.async-iterator.async-dispose': { + }, 'esnext.async-iterator.drop': { }, 'esnext.async-iterator.every': { @@ -1895,6 +1901,8 @@ export const data = { }, 'esnext.composite-symbol': { }, + 'esnext.disposable-stack.constructor': { + }, 'esnext.function.is-callable': { }, 'esnext.function.is-constructor': { @@ -1908,6 +1916,8 @@ export const data = { // TODO: Remove from `core-js@4` 'esnext.iterator.as-indexed-pairs': { }, + 'esnext.iterator.dispose': { + }, 'esnext.iterator.drop': { }, 'esnext.iterator.every': { diff --git a/packages/core-js-compat/src/modules-by-versions.mjs b/packages/core-js-compat/src/modules-by-versions.mjs index 4c9cda9c7043..5e52f0f38518 100644 --- a/packages/core-js-compat/src/modules-by-versions.mjs +++ b/packages/core-js-compat/src/modules-by-versions.mjs @@ -163,6 +163,11 @@ export default { 'web.self', ], 3.27: [ + 'esnext.suppressed-error.constructor', + 'esnext.async-disposable-stack.constructor', + 'esnext.async-iterator.async-dispose', + 'esnext.disposable-stack.constructor', + 'esnext.iterator.dispose', 'esnext.set.difference.v2', 'esnext.set.intersection.v2', 'esnext.set.is-disjoint-from.v2', diff --git a/packages/core-js/full/async-iterator/index.js b/packages/core-js/full/async-iterator/index.js index b56043f4d688..e213c98a98df 100644 --- a/packages/core-js/full/async-iterator/index.js +++ b/packages/core-js/full/async-iterator/index.js @@ -1,4 +1,5 @@ var parent = require('../../actual/async-iterator'); +require('../../modules/esnext.async-iterator.async-dispose'); // TODO: Remove from `core-js@4` require('../../modules/esnext.async-iterator.as-indexed-pairs'); require('../../modules/esnext.async-iterator.indexed'); diff --git a/packages/core-js/full/iterator/index.js b/packages/core-js/full/iterator/index.js index 9a0ebc60e5b8..01c40ce00509 100644 --- a/packages/core-js/full/iterator/index.js +++ b/packages/core-js/full/iterator/index.js @@ -1,4 +1,5 @@ var parent = require('../../actual/iterator'); +require('../../modules/esnext.iterator.dispose'); // TODO: Remove from `core-js@4` require('../../modules/esnext.iterator.as-indexed-pairs'); require('../../modules/esnext.iterator.indexed'); diff --git a/packages/core-js/internals/disposable-stack-helpers.js b/packages/core-js/internals/disposable-stack-helpers.js new file mode 100644 index 000000000000..3f91c8f0753b --- /dev/null +++ b/packages/core-js/internals/disposable-stack-helpers.js @@ -0,0 +1,40 @@ +var uncurryThis = require('../internals/function-uncurry-this'); +var bind = require('../internals/function-bind-context'); +var anObject = require('../internals/an-object'); +var isNullOrUndefined = require('../internals/is-null-or-undefined'); +var getMethod = require('../internals/get-method'); +var wellKnownSymbol = require('../internals/well-known-symbol'); + +var ASYNC_DISPOSE = wellKnownSymbol('asyncDispose'); +var DISPOSE = wellKnownSymbol('dispose'); + +var push = uncurryThis([].push); + +var getDisposeMethod = function (V, hint) { + if (hint == 'async-dispose') { + return getMethod(V, ASYNC_DISPOSE) || getMethod(V, DISPOSE); + } return getMethod(V, DISPOSE); +}; + +var createDisposableResource = function (V, hint, method) { + return bind(method || getDisposeMethod(V, hint), V); +}; + +var addDisposableResource = function (disposable, V, hint, method) { + var resource; + if (!method) { + if (isNullOrUndefined(V)) return; + resource = createDisposableResource(V, hint); + } else if (isNullOrUndefined(V)) { + resource = createDisposableResource(undefined, hint, method); + } else { + resource = createDisposableResource(anObject(V), hint, method); + } + + push(disposable.stack, resource); +}; + +module.exports = { + getDisposeMethod: getDisposeMethod, + addDisposableResource: addDisposableResource +}; diff --git a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js new file mode 100644 index 000000000000..9f05aaa9c33b --- /dev/null +++ b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js @@ -0,0 +1,136 @@ +'use strict'; +// https://github.com/tc39/proposal-observable +var $ = require('../internals/export'); +var DESCRIPTORS = require('../internals/descriptors'); +var getBuiltIn = require('../internals/get-built-in'); +var aCallable = require('../internals/a-callable'); +var anObject = require('../internals/an-object'); +var anInstance = require('../internals/an-instance'); +var isNullOrUndefined = require('../internals/is-null-or-undefined'); +var defineBuiltIn = require('../internals/define-built-in'); +var defineBuiltIns = require('../internals/define-built-ins'); +var defineBuiltInAccessor = require('../internals/define-built-in-accessor'); +var wellKnownSymbol = require('../internals/well-known-symbol'); +var InternalStateModule = require('../internals/internal-state'); +var DisposableStackHelpers = require('../internals/disposable-stack-helpers'); + +var Promise = getBuiltIn('Promise'); +var SuppressedError = getBuiltIn('SuppressedError'); +var $ReferenceError = ReferenceError; + +var ASYNC_DISPOSE = wellKnownSymbol('asyncDispose'); +var TO_STRING_TAG = wellKnownSymbol('toStringTag'); + +var getDisposeMethod = DisposableStackHelpers.getDisposeMethod; +var addDisposableResource = DisposableStackHelpers.addDisposableResource; + +var ASYNC_DISPOSABLE_STACK = 'AsyncDisposableStack'; +var setInternalState = InternalStateModule.set; +var getAsyncDisposableStackInternalState = InternalStateModule.getterFor(ASYNC_DISPOSABLE_STACK); + +var HINT = 'async-dispose'; +var DISPOSED = 'disposed'; +var PENDING = 'pending'; + +var ALREADY_DISPOSED = ASYNC_DISPOSABLE_STACK + ' already disposed'; + +var $AsyncDisposableStack = function AsyncDisposableStack() { + setInternalState(anInstance(this, AsyncDisposableStackPrototype), { + type: ASYNC_DISPOSABLE_STACK, + state: PENDING, + stack: [] + }); + + if (!DESCRIPTORS) this.disposed = false; +}; + +var AsyncDisposableStackPrototype = $AsyncDisposableStack.prototype; + +defineBuiltIns(AsyncDisposableStackPrototype, { + disposeAsync: function disposeAsync() { + var asyncDisposableStack = this; + return new Promise(function (resolve, reject) { + var internalState = getAsyncDisposableStackInternalState(asyncDisposableStack); + if (internalState.state == DISPOSED) return; + internalState.state = DISPOSED; + if (!DESCRIPTORS) asyncDisposableStack.disposed = true; + var stack = internalState.stack; + var length = stack.length; + var i = 0; + var thrown = false; + var suppressed; + + var handleError = function (result) { + if (thrown) { + suppressed = new SuppressedError(result, suppressed); + } else { + thrown = true; + suppressed = result; + } + + loop(); + }; + + var loop = function () { + if (i < length) { + var disposeMethod = stack[i++]; + try { + Promise.resolve(disposeMethod()).then(loop, handleError); + } catch (error) { + handleError(error); + } + } else { + internalState.stack = null; + thrown ? reject(suppressed) : resolve(undefined); + } + }; + + loop(); + }); + }, + use: function use(value) { + var internalState = getAsyncDisposableStackInternalState(this); + if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); + if (!isNullOrUndefined(value)) { + anObject(value); + var method = aCallable(getDisposeMethod(value, HINT)); + addDisposableResource(internalState, value, HINT, method); + } return value; + }, + adopt: function adopt(value, onDispose) { + var internalState = getAsyncDisposableStackInternalState(this); + if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); + aCallable(onDispose); + addDisposableResource(internalState, undefined, HINT, function () { + onDispose(value); + }); + return value; + }, + defer: function defer(onDispose) { + var internalState = getAsyncDisposableStackInternalState(this); + if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); + aCallable(onDispose); + addDisposableResource(internalState, undefined, HINT, onDispose); + }, + move: function move() { + var internalState = getAsyncDisposableStackInternalState(this); + if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); + var newAsyncDisposableStack = new $AsyncDisposableStack(); + getAsyncDisposableStackInternalState(newAsyncDisposableStack).stack = internalState.stack; + return newAsyncDisposableStack; + } +}); + +if (DESCRIPTORS) defineBuiltInAccessor(AsyncDisposableStackPrototype, 'disposed', { + configurable: true, + get: function disposed() { + return getAsyncDisposableStackInternalState(this).state == DISPOSED; + } +}); + +defineBuiltIn(AsyncDisposableStackPrototype, ASYNC_DISPOSE, AsyncDisposableStackPrototype.disposeAsync, { name: 'disposeAsync' }); +defineBuiltIn(AsyncDisposableStackPrototype, TO_STRING_TAG, ASYNC_DISPOSABLE_STACK, { nonWritable: true }); + +$({ global: true, constructor: true, forced: true }, { + AsyncDisposableStack: $AsyncDisposableStack +}); diff --git a/packages/core-js/modules/esnext.async-iterator.async-dispose.js b/packages/core-js/modules/esnext.async-iterator.async-dispose.js new file mode 100644 index 000000000000..43416996e2cb --- /dev/null +++ b/packages/core-js/modules/esnext.async-iterator.async-dispose.js @@ -0,0 +1,26 @@ +'use strict'; +// https://github.com/tc39/proposal-explicit-resource-management +var call = require('../internals/function-call'); +var defineBuiltIn = require('../internals/define-built-in'); +var getBuiltIn = require('../internals/get-built-in'); +var getMethod = require('../internals/get-method'); +var hasOwn = require('../internals/has-own-property'); +var wellKnownSymbol = require('../internals/well-known-symbol'); +var AsyncIteratorPrototype = require('../internals/async-iterator-prototype'); + +var ASYNC_DISPOSE = wellKnownSymbol('asyncDispose'); +var Promise = getBuiltIn('Promise'); + +if (!hasOwn(AsyncIteratorPrototype, ASYNC_DISPOSE)) { + defineBuiltIn(AsyncIteratorPrototype, ASYNC_DISPOSE, function () { + var O = this; + return new Promise(function (resolve, reject) { + var $return = getMethod(O, 'return'); + if ($return) { + Promise.resolve(call($return, O)).then(function () { + resolve(undefined); + }, reject); + } else resolve(undefined); + }); + }); +} diff --git a/packages/core-js/modules/esnext.disposable-stack.constructor.js b/packages/core-js/modules/esnext.disposable-stack.constructor.js new file mode 100644 index 000000000000..1f2beb2281de --- /dev/null +++ b/packages/core-js/modules/esnext.disposable-stack.constructor.js @@ -0,0 +1,118 @@ +'use strict'; +// https://github.com/tc39/proposal-observable +var $ = require('../internals/export'); +var DESCRIPTORS = require('../internals/descriptors'); +var getBuiltIn = require('../internals/get-built-in'); +var aCallable = require('../internals/a-callable'); +var anObject = require('../internals/an-object'); +var anInstance = require('../internals/an-instance'); +var isNullOrUndefined = require('../internals/is-null-or-undefined'); +var defineBuiltIn = require('../internals/define-built-in'); +var defineBuiltIns = require('../internals/define-built-ins'); +var defineBuiltInAccessor = require('../internals/define-built-in-accessor'); +var wellKnownSymbol = require('../internals/well-known-symbol'); +var InternalStateModule = require('../internals/internal-state'); +var DisposableStackHelpers = require('../internals/disposable-stack-helpers'); + +var SuppressedError = getBuiltIn('SuppressedError'); +var $ReferenceError = ReferenceError; + +var DISPOSE = wellKnownSymbol('dispose'); +var TO_STRING_TAG = wellKnownSymbol('toStringTag'); + +var getDisposeMethod = DisposableStackHelpers.getDisposeMethod; +var addDisposableResource = DisposableStackHelpers.addDisposableResource; + +var DISPOSABLE_STACK = 'DisposableStack'; +var setInternalState = InternalStateModule.set; +var getDisposableStackInternalState = InternalStateModule.getterFor(DISPOSABLE_STACK); + +var HINT = 'sync-dispose'; +var DISPOSED = 'disposed'; +var PENDING = 'pending'; + +var ALREADY_DISPOSED = DISPOSABLE_STACK + ' already disposed'; + +var $DisposableStack = function DisposableStack() { + setInternalState(anInstance(this, DisposableStackPrototype), { + type: DISPOSABLE_STACK, + state: PENDING, + stack: [] + }); + + if (!DESCRIPTORS) this.disposed = false; +}; + +var DisposableStackPrototype = $DisposableStack.prototype; + +defineBuiltIns(DisposableStackPrototype, { + dispose: function dispose() { + var internalState = getDisposableStackInternalState(this); + if (internalState.state == DISPOSED) return; + internalState.state = DISPOSED; + if (!DESCRIPTORS) this.disposed = true; + var stack = internalState.stack; + var thrown = false; + var suppressed; + for (var i = 0, length = stack.length; i < length; i++) { + var disposeMethod = stack[i]; + try { + disposeMethod(); + } catch (errorResult) { + if (thrown) { + suppressed = new SuppressedError(errorResult, suppressed); + } else { + thrown = true; + suppressed = errorResult; + } + } + } + internalState.stack = null; + if (thrown) throw suppressed; + }, + use: function use(value) { + var internalState = getDisposableStackInternalState(this); + if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); + if (!isNullOrUndefined(value)) { + anObject(value); + var method = aCallable(getDisposeMethod(value, HINT)); + addDisposableResource(internalState, value, HINT, method); + } return value; + }, + adopt: function adopt(value, onDispose) { + var internalState = getDisposableStackInternalState(this); + if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); + aCallable(onDispose); + addDisposableResource(internalState, undefined, HINT, function () { + onDispose(value); + }); + return value; + }, + defer: function defer(onDispose) { + var internalState = getDisposableStackInternalState(this); + if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); + aCallable(onDispose); + addDisposableResource(internalState, undefined, HINT, onDispose); + }, + move: function move() { + var internalState = getDisposableStackInternalState(this); + if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); + var newDisposableStack = new $DisposableStack(); + getDisposableStackInternalState(newDisposableStack).stack = internalState.stack; + return newDisposableStack; + } +}); + +if (DESCRIPTORS) defineBuiltInAccessor(DisposableStackPrototype, 'disposed', { + configurable: true, + get: function disposed() { + return getDisposableStackInternalState(this).state == DISPOSED; + } +}); + +defineBuiltIn(DisposableStackPrototype, DISPOSE, DisposableStackPrototype.dispose, { name: 'dispose' }); +defineBuiltIn(DisposableStackPrototype, TO_STRING_TAG, DISPOSABLE_STACK, { nonWritable: true }); + +$({ global: true, constructor: true, forced: true }, { + DisposableStack: $DisposableStack +}); diff --git a/packages/core-js/modules/esnext.iterator.dispose.js b/packages/core-js/modules/esnext.iterator.dispose.js new file mode 100644 index 000000000000..ac463eebc9d0 --- /dev/null +++ b/packages/core-js/modules/esnext.iterator.dispose.js @@ -0,0 +1,17 @@ +'use strict'; +// https://github.com/tc39/proposal-explicit-resource-management +var call = require('../internals/function-call'); +var defineBuiltIn = require('../internals/define-built-in'); +var getMethod = require('../internals/get-method'); +var hasOwn = require('../internals/has-own-property'); +var wellKnownSymbol = require('../internals/well-known-symbol'); +var IteratorPrototype = require('../internals/iterators-core').IteratorPrototype; + +var DISPOSE = wellKnownSymbol('dispose'); + +if (!hasOwn(IteratorPrototype, DISPOSE)) { + defineBuiltIn(IteratorPrototype, DISPOSE, function () { + var $return = getMethod(this, 'return'); + if ($return) call($return, this); + }); +} diff --git a/packages/core-js/modules/esnext.suppressed-error.constructor.js b/packages/core-js/modules/esnext.suppressed-error.constructor.js new file mode 100644 index 000000000000..d4d44dcf2647 --- /dev/null +++ b/packages/core-js/modules/esnext.suppressed-error.constructor.js @@ -0,0 +1,50 @@ +'use strict'; +var $ = require('../internals/export'); +var isPrototypeOf = require('../internals/object-is-prototype-of'); +var getPrototypeOf = require('../internals/object-get-prototype-of'); +var setPrototypeOf = require('../internals/object-set-prototype-of'); +var copyConstructorProperties = require('../internals/copy-constructor-properties'); +var create = require('../internals/object-create'); +var createNonEnumerableProperty = require('../internals/create-non-enumerable-property'); +var createPropertyDescriptor = require('../internals/create-property-descriptor'); +var clearErrorStack = require('../internals/error-stack-clear'); +var installErrorCause = require('../internals/install-error-cause'); +var normalizeStringArgument = require('../internals/normalize-string-argument'); +var wellKnownSymbol = require('../internals/well-known-symbol'); +var ERROR_STACK_INSTALLABLE = require('../internals/error-stack-installable'); + +var TO_STRING_TAG = wellKnownSymbol('toStringTag'); +var $Error = Error; + +var $SuppressedError = function SuppressedError(error, suppressed, message /* , options */) { + var options = arguments.length > 2 ? arguments[2] : undefined; + var isInstance = isPrototypeOf(SuppressedErrorPrototype, this); + var that; + if (setPrototypeOf) { + that = setPrototypeOf($Error(), isInstance ? getPrototypeOf(this) : SuppressedErrorPrototype); + } else { + that = isInstance ? this : create(SuppressedErrorPrototype); + createNonEnumerableProperty(that, TO_STRING_TAG, 'Error'); + } + if (message !== undefined) createNonEnumerableProperty(that, 'message', normalizeStringArgument(message)); + if (ERROR_STACK_INSTALLABLE) createNonEnumerableProperty(that, 'stack', clearErrorStack(that.stack, 1)); + installErrorCause(that, options); + createNonEnumerableProperty(that, 'error', error); + createNonEnumerableProperty(that, 'suppressed', suppressed); + return that; +}; + +if (setPrototypeOf) setPrototypeOf($SuppressedError, $Error); +else copyConstructorProperties($SuppressedError, $Error, { name: true }); + +var SuppressedErrorPrototype = $SuppressedError.prototype = create($Error.prototype, { + constructor: createPropertyDescriptor(1, $SuppressedError), + message: createPropertyDescriptor(1, ''), + name: createPropertyDescriptor(1, 'SuppressedError') +}); + +// `SuppressedError` constructor +// https://github.com/tc39/proposal-explicit-resource-management +$({ global: true, constructor: true, arity: 3 }, { + SuppressedError: $SuppressedError +}); diff --git a/packages/core-js/modules/esnext.symbol.async-dispose.js b/packages/core-js/modules/esnext.symbol.async-dispose.js index c38839d284c8..5c092ceb22be 100644 --- a/packages/core-js/modules/esnext.symbol.async-dispose.js +++ b/packages/core-js/modules/esnext.symbol.async-dispose.js @@ -1,5 +1,5 @@ var defineWellKnownSymbol = require('../internals/well-known-symbol-define'); // `Symbol.asyncDispose` well-known symbol -// https://github.com/tc39/proposal-using-statement +// https://github.com/tc39/proposal-explicit-resource-management defineWellKnownSymbol('asyncDispose'); diff --git a/packages/core-js/modules/esnext.symbol.dispose.js b/packages/core-js/modules/esnext.symbol.dispose.js index 8ea9d8fb8585..13ddbd1ea380 100644 --- a/packages/core-js/modules/esnext.symbol.dispose.js +++ b/packages/core-js/modules/esnext.symbol.dispose.js @@ -1,5 +1,5 @@ var defineWellKnownSymbol = require('../internals/well-known-symbol-define'); // `Symbol.dispose` well-known symbol -// https://github.com/tc39/proposal-using-statement +// https://github.com/tc39/proposal-explicit-resource-management defineWellKnownSymbol('dispose'); diff --git a/packages/core-js/proposals/using-statement.js b/packages/core-js/proposals/using-statement.js index 2ac3df7fc201..9b6d130af48e 100644 --- a/packages/core-js/proposals/using-statement.js +++ b/packages/core-js/proposals/using-statement.js @@ -1,3 +1,8 @@ -// https://github.com/tc39/proposal-using-statement +// https://github.com/tc39/proposal-explicit-resource-management +require('../modules/esnext.suppressed-error.constructor'); +require('../modules/esnext.async-disposable-stack.constructor'); +require('../modules/esnext.async-iterator.async-dispose'); +require('../modules/esnext.disposable-stack.constructor'); +require('../modules/esnext.iterator.dispose'); require('../modules/esnext.symbol.async-dispose'); require('../modules/esnext.symbol.dispose'); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 8139caf39e31..ea40d36156bb 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1392,6 +1392,9 @@ GLOBAL.tests = { && set.add({}) == set && set[Symbol.toStringTag]; }], + 'esnext.suppressed-error.constructor': function () { + return typeof SuppressedError == 'function'; + }, 'esnext.array.from-async': function () { return Array.fromAsync; }, @@ -1432,9 +1435,15 @@ GLOBAL.tests = { 'esnext.array.with': function () { return []['with']; }, + 'esnext.async-disposable-stack.constructor': function () { + return typeof AsyncDisposableStack == 'function'; + }, 'esnext.async-iterator.constructor': function () { return typeof AsyncIterator == 'function'; }, + 'esnext.async-iterator.async-dispose': function () { + return AsyncIterator.prototype[Symbol.asyncDispose]; + }, 'esnext.async-iterator.drop': function () { return AsyncIterator.prototype.drop; }, @@ -1483,6 +1492,9 @@ GLOBAL.tests = { 'esnext.composite-symbol': function () { return compositeSymbol; }, + 'esnext.disposable-stack.constructor': function () { + return typeof DisposableStack == 'function'; + }, 'esnext.function.is-callable': function () { return Function.isCallable; }, @@ -1500,6 +1512,9 @@ GLOBAL.tests = { && Iterator.prototype === Object.getPrototypeOf(Object.getPrototypeOf([].values())); } }, + 'esnext.iterator.dispose': function () { + return Iterator.prototype[Symbol.dispose]; + }, 'esnext.iterator.drop': function () { return Iterator.prototype.drop; }, From 401fa820a7d5f20cede7ff1652480e389d30603c Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Tue, 29 Nov 2022 03:41:15 +0700 Subject: [PATCH 02/18] add some entries --- .../full/async-disposable-stack/constructor.js | 8 ++++++++ packages/core-js/full/async-disposable-stack/index.js | 8 ++++++++ packages/core-js/full/async-iterator/async-dispose.js | 3 +++ packages/core-js/full/disposable-stack/constructor.js | 7 +++++++ packages/core-js/full/disposable-stack/index.js | 7 +++++++ packages/core-js/full/iterator/dispose.js | 1 + packages/core-js/full/suppressed-error.js | 5 +++++ tests/entries/unit.mjs | 11 +++++++++-- 8 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 packages/core-js/full/async-disposable-stack/constructor.js create mode 100644 packages/core-js/full/async-disposable-stack/index.js create mode 100644 packages/core-js/full/async-iterator/async-dispose.js create mode 100644 packages/core-js/full/disposable-stack/constructor.js create mode 100644 packages/core-js/full/disposable-stack/index.js create mode 100644 packages/core-js/full/iterator/dispose.js create mode 100644 packages/core-js/full/suppressed-error.js diff --git a/packages/core-js/full/async-disposable-stack/constructor.js b/packages/core-js/full/async-disposable-stack/constructor.js new file mode 100644 index 000000000000..ae44f521b344 --- /dev/null +++ b/packages/core-js/full/async-disposable-stack/constructor.js @@ -0,0 +1,8 @@ +require('../../modules/es.error.cause'); +require('../../modules/es.object.to-string'); +require('../../modules/es.promise'); +require('../../modules/esnext.suppressed-error.constructor'); +require('../../modules/esnext.async-disposable-stack.constructor'); +var path = require('../../internals/path'); + +module.exports = path.AsyncDisposableStack; diff --git a/packages/core-js/full/async-disposable-stack/index.js b/packages/core-js/full/async-disposable-stack/index.js new file mode 100644 index 000000000000..ae44f521b344 --- /dev/null +++ b/packages/core-js/full/async-disposable-stack/index.js @@ -0,0 +1,8 @@ +require('../../modules/es.error.cause'); +require('../../modules/es.object.to-string'); +require('../../modules/es.promise'); +require('../../modules/esnext.suppressed-error.constructor'); +require('../../modules/esnext.async-disposable-stack.constructor'); +var path = require('../../internals/path'); + +module.exports = path.AsyncDisposableStack; diff --git a/packages/core-js/full/async-iterator/async-dispose.js b/packages/core-js/full/async-iterator/async-dispose.js new file mode 100644 index 000000000000..da1a182c9ec5 --- /dev/null +++ b/packages/core-js/full/async-iterator/async-dispose.js @@ -0,0 +1,3 @@ +require('../../modules/es.object.to-string'); +require('../../modules/es.promise'); +require('../../modules/esnext.async-iterator.async-dispose'); diff --git a/packages/core-js/full/disposable-stack/constructor.js b/packages/core-js/full/disposable-stack/constructor.js new file mode 100644 index 000000000000..90c1292cd8d4 --- /dev/null +++ b/packages/core-js/full/disposable-stack/constructor.js @@ -0,0 +1,7 @@ +require('../../modules/es.error.cause'); +require('../../modules/es.object.to-string'); +require('../../modules/esnext.suppressed-error.constructor'); +require('../../modules/esnext.disposable-stack.constructor'); +var path = require('../../internals/path'); + +module.exports = path.DisposableStack; diff --git a/packages/core-js/full/disposable-stack/index.js b/packages/core-js/full/disposable-stack/index.js new file mode 100644 index 000000000000..90c1292cd8d4 --- /dev/null +++ b/packages/core-js/full/disposable-stack/index.js @@ -0,0 +1,7 @@ +require('../../modules/es.error.cause'); +require('../../modules/es.object.to-string'); +require('../../modules/esnext.suppressed-error.constructor'); +require('../../modules/esnext.disposable-stack.constructor'); +var path = require('../../internals/path'); + +module.exports = path.DisposableStack; diff --git a/packages/core-js/full/iterator/dispose.js b/packages/core-js/full/iterator/dispose.js new file mode 100644 index 000000000000..bf3b517d9677 --- /dev/null +++ b/packages/core-js/full/iterator/dispose.js @@ -0,0 +1 @@ +require('../../modules/esnext.iterator.dispose'); diff --git a/packages/core-js/full/suppressed-error.js b/packages/core-js/full/suppressed-error.js new file mode 100644 index 000000000000..0f41bdef653f --- /dev/null +++ b/packages/core-js/full/suppressed-error.js @@ -0,0 +1,5 @@ +require('../modules/es.error.cause'); +require('../modules/esnext.suppressed-error.constructor'); +var path = require('../internals/path'); + +module.exports = path.SuppressedError; diff --git a/tests/entries/unit.mjs b/tests/entries/unit.mjs index 663fb6e7a0bb..e61055fa5bce 100644 --- a/tests/entries/unit.mjs +++ b/tests/entries/unit.mjs @@ -803,8 +803,6 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(load(NS, 'string/cooked')`a${ 1 }b` === 'a1b'); ok('next' in load(NS, 'string/code-points')('a')); ok('next' in load(NS, 'string/virtual/code-points').call('a')); - ok(load(NS, 'symbol/async-dispose')); - ok(load(NS, 'symbol/dispose')); ok(load(NS, 'symbol/matcher')); ok(load(NS, 'symbol/metadata')); ok(load(NS, 'symbol/metadata-key')); @@ -820,6 +818,15 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(load(NS, 'weak-set/delete-all')(new WeakSet(), [], {}) === false); ok(load(NS, 'weak-set/from')([{}, []]) instanceof WeakSet); ok(load(NS, 'weak-set/of')({}, []) instanceof WeakSet); + ok(load(NS, 'symbol/async-dispose')); + ok(load(NS, 'symbol/dispose')); + ok(new (load(NS, 'suppressed-error'))(1, 2).suppressed === 2); + load(NS, 'async-iterator/async-dispose'); + load(NS, 'iterator/dispose'); + ok(typeof load(NS, 'async-disposable-stack') == 'function'); + ok(typeof load(NS, 'async-disposable-stack/constructor') == 'function'); + ok(typeof load(NS, 'disposable-stack') == 'function'); + ok(typeof load(NS, 'disposable-stack/constructor') == 'function'); const instanceCodePoints = load(NS, 'instance/code-points'); ok(typeof instanceCodePoints == 'function'); From 8a9b2d179802ff4e3bcf89a0699581a6761f4d6a Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Tue, 29 Nov 2022 11:57:38 +0700 Subject: [PATCH 03/18] reverse --- .../modules/esnext.async-disposable-stack.constructor.js | 7 +++---- .../core-js/modules/esnext.disposable-stack.constructor.js | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js index 9f05aaa9c33b..e8371ae147ad 100644 --- a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js +++ b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js @@ -55,8 +55,7 @@ defineBuiltIns(AsyncDisposableStackPrototype, { internalState.state = DISPOSED; if (!DESCRIPTORS) asyncDisposableStack.disposed = true; var stack = internalState.stack; - var length = stack.length; - var i = 0; + var i = stack.length; var thrown = false; var suppressed; @@ -72,8 +71,8 @@ defineBuiltIns(AsyncDisposableStackPrototype, { }; var loop = function () { - if (i < length) { - var disposeMethod = stack[i++]; + if (i) { + var disposeMethod = stack[--i]; try { Promise.resolve(disposeMethod()).then(loop, handleError); } catch (error) { diff --git a/packages/core-js/modules/esnext.disposable-stack.constructor.js b/packages/core-js/modules/esnext.disposable-stack.constructor.js index 1f2beb2281de..52c5b9363644 100644 --- a/packages/core-js/modules/esnext.disposable-stack.constructor.js +++ b/packages/core-js/modules/esnext.disposable-stack.constructor.js @@ -52,10 +52,11 @@ defineBuiltIns(DisposableStackPrototype, { internalState.state = DISPOSED; if (!DESCRIPTORS) this.disposed = true; var stack = internalState.stack; + var i = stack.length; var thrown = false; var suppressed; - for (var i = 0, length = stack.length; i < length; i++) { - var disposeMethod = stack[i]; + while (i) { + var disposeMethod = stack[--i]; try { disposeMethod(); } catch (errorResult) { From 0e72edee0e2d0f64ecd794f7fbb443dd24d416c3 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 30 Nov 2022 01:57:08 +0700 Subject: [PATCH 04/18] add some tests --- .../esnext.suppressed-error.constructor.js | 2 +- tests/eslint/eslint.config.js | 3 ++ .../esnext.suppressed-error.constructor.js | 47 ++++++++++++++++++ .../esnext.suppressed-error.constructor.js | 49 +++++++++++++++++++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 tests/unit-global/esnext.suppressed-error.constructor.js create mode 100644 tests/unit-pure/esnext.suppressed-error.constructor.js diff --git a/packages/core-js/modules/esnext.suppressed-error.constructor.js b/packages/core-js/modules/esnext.suppressed-error.constructor.js index d4d44dcf2647..809e070bc9c1 100644 --- a/packages/core-js/modules/esnext.suppressed-error.constructor.js +++ b/packages/core-js/modules/esnext.suppressed-error.constructor.js @@ -17,7 +17,7 @@ var TO_STRING_TAG = wellKnownSymbol('toStringTag'); var $Error = Error; var $SuppressedError = function SuppressedError(error, suppressed, message /* , options */) { - var options = arguments.length > 2 ? arguments[2] : undefined; + var options = arguments.length > 3 ? arguments[3] : undefined; var isInstance = isPrototypeOf(SuppressedErrorPrototype, this); var that; if (setPrototypeOf) { diff --git a/tests/eslint/eslint.config.js b/tests/eslint/eslint.config.js index d1db2f2d4c28..ebe7b54a4c19 100644 --- a/tests/eslint/eslint.config.js +++ b/tests/eslint/eslint.config.js @@ -1136,9 +1136,12 @@ const json = { }; const globalsESNext = { + AsyncDisposableStack: READONLY, AsyncIterator: READONLY, + DisposableStack: READONLY, Iterator: READONLY, Observable: READONLY, + SuppressedError: READONLY, compositeKey: READONLY, compositeSymbol: READONLY, }; diff --git a/tests/unit-global/esnext.suppressed-error.constructor.js b/tests/unit-global/esnext.suppressed-error.constructor.js new file mode 100644 index 000000000000..a1d62f87a3b0 --- /dev/null +++ b/tests/unit-global/esnext.suppressed-error.constructor.js @@ -0,0 +1,47 @@ +QUnit.test('SuppressedError', assert => { + assert.isFunction(SuppressedError); + assert.arity(SuppressedError, 3); + assert.name(SuppressedError, 'SuppressedError'); + assert.looksNative(SuppressedError); + assert.true(new SuppressedError() instanceof SuppressedError); + assert.true(new SuppressedError() instanceof Error); + assert.true(SuppressedError() instanceof SuppressedError); + assert.true(SuppressedError() instanceof Error); + + assert.same(SuppressedError().error, undefined); + assert.same(SuppressedError().suppressed, undefined); + assert.same(SuppressedError().message, ''); + assert.same(SuppressedError().cause, undefined); + assert.false('cause' in SuppressedError()); + assert.same(SuppressedError().name, 'SuppressedError'); + + assert.same(new SuppressedError().error, undefined); + assert.same(new SuppressedError().suppressed, undefined); + assert.same(new SuppressedError().message, ''); + assert.same(new SuppressedError().cause, undefined); + assert.false('cause' in new SuppressedError()); + assert.same(new SuppressedError().name, 'SuppressedError'); + + const error1 = SuppressedError(1, 2, 3, { cause: 4 }); + + assert.same(error1.error, 1); + assert.same(error1.suppressed, 2); + assert.same(error1.message, '3'); + assert.same(error1.cause, 4); + assert.same(error1.name, 'SuppressedError'); + + const error2 = new SuppressedError(1, 2, 3, { cause: 4 }); + + assert.same(error2.error, 1); + assert.same(error2.suppressed, 2); + assert.same(error2.message, '3'); + assert.same(error2.cause, 4); + assert.same(error2.name, 'SuppressedError'); + + assert.throws(() => SuppressedError(1, 2, Symbol()), 'throws on symbol as a message'); + assert.same(({}).toString.call(SuppressedError()), '[object Error]', 'Object#toString'); + + assert.same(SuppressedError.prototype.constructor, SuppressedError, 'prototype constructor'); + // eslint-disable-next-line no-prototype-builtins -- safe + assert.false(SuppressedError.prototype.hasOwnProperty('cause'), 'prototype has not cause'); +}); diff --git a/tests/unit-pure/esnext.suppressed-error.constructor.js b/tests/unit-pure/esnext.suppressed-error.constructor.js new file mode 100644 index 000000000000..8a94375aa98a --- /dev/null +++ b/tests/unit-pure/esnext.suppressed-error.constructor.js @@ -0,0 +1,49 @@ +import SuppressedError from 'core-js-pure/full/suppressed-error'; +import Symbol from 'core-js-pure/es/symbol'; +import toString from 'core-js-pure/es/object/to-string'; + +QUnit.test('SuppressedError', assert => { + assert.isFunction(SuppressedError); + assert.arity(SuppressedError, 3); + assert.name(SuppressedError, 'SuppressedError'); + assert.true(new SuppressedError() instanceof SuppressedError); + assert.true(new SuppressedError() instanceof Error); + assert.true(SuppressedError() instanceof SuppressedError); + assert.true(SuppressedError() instanceof Error); + + assert.same(SuppressedError().error, undefined); + assert.same(SuppressedError().suppressed, undefined); + assert.same(SuppressedError().message, ''); + assert.same(SuppressedError().cause, undefined); + assert.false('cause' in SuppressedError()); + assert.same(SuppressedError().name, 'SuppressedError'); + + assert.same(new SuppressedError().error, undefined); + assert.same(new SuppressedError().suppressed, undefined); + assert.same(new SuppressedError().message, ''); + assert.same(new SuppressedError().cause, undefined); + assert.false('cause' in new SuppressedError()); + assert.same(new SuppressedError().name, 'SuppressedError'); + + const error1 = SuppressedError(1, 2, 3, { cause: 4 }); + + assert.same(error1.error, 1); + assert.same(error1.suppressed, 2); + assert.same(error1.message, '3'); + assert.same(error1.cause, 4); + assert.same(error1.name, 'SuppressedError'); + + const error2 = new SuppressedError(1, 2, 3, { cause: 4 }); + + assert.same(error2.error, 1); + assert.same(error2.suppressed, 2); + assert.same(error2.message, '3'); + assert.same(error2.cause, 4); + assert.same(error2.name, 'SuppressedError'); + + assert.throws(() => SuppressedError(1, 2, Symbol()), 'throws on symbol as a message'); + assert.same(toString(SuppressedError()), '[object Error]', 'Object#toString'); + + // eslint-disable-next-line no-prototype-builtins -- safe + assert.false(SuppressedError.prototype.hasOwnProperty('cause'), 'prototype has not cause'); +}); From 58121830cdac9cef1a7c9036b4033de86cd2eb9e Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 30 Nov 2022 05:09:04 +0700 Subject: [PATCH 05/18] add some tests --- .../esnext.async-iterator.async-dispose.js | 26 ++++++++++++++++++ tests/unit-global/esnext.iterator.dispose.js | 20 ++++++++++++++ .../esnext.async-iterator.async-dispose.js | 27 +++++++++++++++++++ tests/unit-pure/esnext.iterator.dispose.js | 21 +++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 tests/unit-global/esnext.async-iterator.async-dispose.js create mode 100644 tests/unit-global/esnext.iterator.dispose.js create mode 100644 tests/unit-pure/esnext.async-iterator.async-dispose.js create mode 100644 tests/unit-pure/esnext.iterator.dispose.js diff --git a/tests/unit-global/esnext.async-iterator.async-dispose.js b/tests/unit-global/esnext.async-iterator.async-dispose.js new file mode 100644 index 000000000000..0885f06fc3d3 --- /dev/null +++ b/tests/unit-global/esnext.async-iterator.async-dispose.js @@ -0,0 +1,26 @@ +const { create } = Object; + +QUnit.test('AsyncIterator#@@asyncDispose', assert => { + assert.expect(7); + + const asyncDispose = AsyncIterator.prototype[Symbol.asyncDispose]; + assert.isFunction(asyncDispose); + assert.arity(asyncDispose, 0); + assert.looksNative(asyncDispose); + + create(AsyncIterator.prototype)[Symbol.asyncDispose]().then(result => { + assert.same(result, undefined); + }); + + let called = false; + const iterator2 = create(AsyncIterator.prototype); + iterator2.return = function () { + called = true; + assert.same(this, iterator2); + return 7; + }; + iterator2[Symbol.asyncDispose]().then(result => { + assert.same(result, undefined); + assert.true(called); + }); +}); diff --git a/tests/unit-global/esnext.iterator.dispose.js b/tests/unit-global/esnext.iterator.dispose.js new file mode 100644 index 000000000000..ebafc338f61a --- /dev/null +++ b/tests/unit-global/esnext.iterator.dispose.js @@ -0,0 +1,20 @@ +const { create } = Object; + +QUnit.test('Iterator#@@dispose', assert => { + const dispose = Iterator.prototype[Symbol.dispose]; + assert.isFunction(dispose); + assert.arity(dispose, 0); + assert.looksNative(dispose); + + assert.same(create(Iterator.prototype)[Symbol.dispose](), undefined); + + let called = false; + const iterator2 = create(Iterator.prototype); + iterator2.return = function () { + called = true; + assert.same(this, iterator2); + return 7; + }; + assert.same(iterator2[Symbol.dispose](), undefined); + assert.true(called); +}); diff --git a/tests/unit-pure/esnext.async-iterator.async-dispose.js b/tests/unit-pure/esnext.async-iterator.async-dispose.js new file mode 100644 index 000000000000..dad705dfe81f --- /dev/null +++ b/tests/unit-pure/esnext.async-iterator.async-dispose.js @@ -0,0 +1,27 @@ +import AsyncIterator from 'core-js-pure/full/async-iterator'; +import Symbol from 'core-js-pure/full/symbol'; +import create from 'core-js-pure/es/object/create'; + +QUnit.test('AsyncIterator#@@asyncDispose', assert => { + assert.expect(6); + + const asyncDispose = AsyncIterator.prototype[Symbol.asyncDispose]; + assert.isFunction(asyncDispose); + assert.arity(asyncDispose, 0); + + create(AsyncIterator.prototype)[Symbol.asyncDispose]().then(result => { + assert.same(result, undefined); + }); + + let called = false; + const iterator2 = create(AsyncIterator.prototype); + iterator2.return = function () { + called = true; + assert.same(this, iterator2); + return 7; + }; + iterator2[Symbol.asyncDispose]().then(result => { + assert.same(result, undefined); + assert.true(called); + }); +}); diff --git a/tests/unit-pure/esnext.iterator.dispose.js b/tests/unit-pure/esnext.iterator.dispose.js new file mode 100644 index 000000000000..71914573166c --- /dev/null +++ b/tests/unit-pure/esnext.iterator.dispose.js @@ -0,0 +1,21 @@ +import Iterator from 'core-js-pure/full/iterator'; +import Symbol from 'core-js-pure/full/symbol'; +import create from 'core-js-pure/es/object/create'; + +QUnit.test('Iterator#@@dispose', assert => { + const dispose = Iterator.prototype[Symbol.dispose]; + assert.isFunction(dispose); + assert.arity(dispose, 0); + + assert.same(create(Iterator.prototype)[Symbol.dispose](), undefined); + + let called = false; + const iterator2 = create(Iterator.prototype); + iterator2.return = function () { + called = true; + assert.same(this, iterator2); + return 7; + }; + assert.same(iterator2[Symbol.dispose](), undefined); + assert.true(called); +}); From 13674079d21ad060ff15cc351e8acf9272a6a153 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 30 Nov 2022 07:00:23 +0700 Subject: [PATCH 06/18] rename proposal --- README.md | 6 +++--- .../core-js/proposals/explicit-resource-management.js | 8 ++++++++ packages/core-js/proposals/using-statement.js | 9 ++------- packages/core-js/stage/2.js | 8 ++++---- tests/entries/unit.mjs | 1 + 5 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 packages/core-js/proposals/explicit-resource-management.js diff --git a/README.md b/README.md index b354bf08e1bb..0f0f2a9bf3a8 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ queueMicrotask(() => console.log('called as microtask')); - [Stage 2 proposals](#stage-2-proposals) - [`Map.prototype.emplace`](#mapprototypeemplace) - [`Array.isTemplateObject`](#arrayistemplateobject) - - [`Symbol.{ asyncDispose, dispose }` for `using` statement](#symbol-asyncdispose-dispose--for-using-statement) + - [Explicit resource management](#explicit-resource-management) - [`Symbol.metadataKey` for decorators metadata proposal](#symbolmetadatakey-for-decorators-metadata-proposal) - [Stage 1 proposals](#stage-1-proposals) - [`Observable`](#observable) @@ -2382,7 +2382,7 @@ core-js(-pure)/full/array/is-template-object ```js console.log(Array.isTemplateObject((it => it)`qwe${ 123 }asd`)); // => true ``` -##### [`Symbol.{ asyncDispose, dispose }` for `using` statement](https://github.com/tc39/proposal-explicit-resource-management)[⬆](#index) +##### [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management)[⬆](#index) Modules [`esnext.symbol.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.dispose.js) and [`esnext.symbol.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.async-dispose.js). ```js class Symbol { @@ -2392,7 +2392,7 @@ class Symbol { ``` [*CommonJS entry points:*](#commonjs-api) ```js -core-js/proposals/using-statement +core-js/proposals/explicit-resource-management core-js(-pure)/full/symbol/async-dispose core-js(-pure)/full/symbol/dispose ``` diff --git a/packages/core-js/proposals/explicit-resource-management.js b/packages/core-js/proposals/explicit-resource-management.js new file mode 100644 index 000000000000..9b6d130af48e --- /dev/null +++ b/packages/core-js/proposals/explicit-resource-management.js @@ -0,0 +1,8 @@ +// https://github.com/tc39/proposal-explicit-resource-management +require('../modules/esnext.suppressed-error.constructor'); +require('../modules/esnext.async-disposable-stack.constructor'); +require('../modules/esnext.async-iterator.async-dispose'); +require('../modules/esnext.disposable-stack.constructor'); +require('../modules/esnext.iterator.dispose'); +require('../modules/esnext.symbol.async-dispose'); +require('../modules/esnext.symbol.dispose'); diff --git a/packages/core-js/proposals/using-statement.js b/packages/core-js/proposals/using-statement.js index 9b6d130af48e..bb8113087383 100644 --- a/packages/core-js/proposals/using-statement.js +++ b/packages/core-js/proposals/using-statement.js @@ -1,8 +1,3 @@ +// TODO: Renamed, remove from `core-js@4` // https://github.com/tc39/proposal-explicit-resource-management -require('../modules/esnext.suppressed-error.constructor'); -require('../modules/esnext.async-disposable-stack.constructor'); -require('../modules/esnext.async-iterator.async-dispose'); -require('../modules/esnext.disposable-stack.constructor'); -require('../modules/esnext.iterator.dispose'); -require('../modules/esnext.symbol.async-dispose'); -require('../modules/esnext.symbol.dispose'); +require('./explicit-resource-management'); diff --git a/packages/core-js/stage/2.js b/packages/core-js/stage/2.js index 887a5bfdc63c..0c52a10f4fdc 100644 --- a/packages/core-js/stage/2.js +++ b/packages/core-js/stage/2.js @@ -2,13 +2,13 @@ var parent = require('./3'); require('../proposals/array-is-template-object'); require('../proposals/decorator-metadata'); -// TODO: Obsolete versions, remove from `core-js@4` -require('../proposals/iterator-helpers'); +require('../proposals/explicit-resource-management'); require('../proposals/map-upsert-stage-2'); -require('../proposals/set-methods'); -require('../proposals/using-statement'); // TODO: Obsolete versions, remove from `core-js@4` require('../proposals/array-grouping'); require('../proposals/decorators'); +require('../proposals/iterator-helpers'); +require('../proposals/set-methods'); +require('../proposals/using-statement'); module.exports = parent; diff --git a/tests/entries/unit.mjs b/tests/entries/unit.mjs index e61055fa5bce..d4fc0fe225b3 100644 --- a/tests/entries/unit.mjs +++ b/tests/entries/unit.mjs @@ -881,6 +881,7 @@ for (PATH of ['core-js-pure', 'core-js']) { load('proposals/decorators'); load('proposals/efficient-64-bit-arithmetic'); load('proposals/error-cause'); + load('proposals/explicit-resource-management'); load('proposals/function-is-callable-is-constructor'); load('proposals/function-un-this'); load('proposals/global-this'); From ba2903c00990051b2dcc8fff4b5f1142d2b7cafc Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 30 Nov 2022 07:21:17 +0700 Subject: [PATCH 07/18] add some tests --- ...next.async-disposable-stack.constructor.js | 1 + .../esnext.disposable-stack.constructor.js | 1 + .../esnext.disposable-stack.constructor.js | 178 ++++++++++++++++++ .../esnext.disposable-stack.constructor.js | 176 +++++++++++++++++ 4 files changed, 356 insertions(+) create mode 100644 tests/unit-global/esnext.disposable-stack.constructor.js create mode 100644 tests/unit-pure/esnext.disposable-stack.constructor.js diff --git a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js index e8371ae147ad..31999d66404a 100644 --- a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js +++ b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js @@ -116,6 +116,7 @@ defineBuiltIns(AsyncDisposableStackPrototype, { if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); var newAsyncDisposableStack = new $AsyncDisposableStack(); getAsyncDisposableStackInternalState(newAsyncDisposableStack).stack = internalState.stack; + internalState.stack = []; return newAsyncDisposableStack; } }); diff --git a/packages/core-js/modules/esnext.disposable-stack.constructor.js b/packages/core-js/modules/esnext.disposable-stack.constructor.js index 52c5b9363644..4ee38d35df83 100644 --- a/packages/core-js/modules/esnext.disposable-stack.constructor.js +++ b/packages/core-js/modules/esnext.disposable-stack.constructor.js @@ -100,6 +100,7 @@ defineBuiltIns(DisposableStackPrototype, { if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED); var newDisposableStack = new $DisposableStack(); getDisposableStackInternalState(newDisposableStack).stack = internalState.stack; + internalState.stack = []; return newDisposableStack; } }); diff --git a/tests/unit-global/esnext.disposable-stack.constructor.js b/tests/unit-global/esnext.disposable-stack.constructor.js new file mode 100644 index 000000000000..938553ec8793 --- /dev/null +++ b/tests/unit-global/esnext.disposable-stack.constructor.js @@ -0,0 +1,178 @@ +import { STRICT } from '../helpers/constants'; + +QUnit.test('DisposableStack constructor', assert => { + assert.isFunction(DisposableStack); + assert.arity(DisposableStack, 0); + assert.name(DisposableStack, 'DisposableStack'); + assert.looksNative(DisposableStack); + + assert.throws(() => DisposableStack(), 'throws w/o `new`'); + assert.true(new DisposableStack() instanceof DisposableStack); + + assert.same(DisposableStack.prototype.constructor, DisposableStack); +}); + +QUnit.test('DisposableStack#dispose', assert => { + assert.isFunction(DisposableStack.prototype.dispose); + assert.arity(DisposableStack.prototype.dispose, 0); + assert.name(DisposableStack.prototype.dispose, 'dispose'); + assert.looksNative(DisposableStack.prototype.dispose); + assert.nonEnumerable(DisposableStack.prototype, 'dispose'); +}); + +QUnit.test('DisposableStack#use', assert => { + assert.isFunction(DisposableStack.prototype.use); + assert.arity(DisposableStack.prototype.use, 1); + assert.name(DisposableStack.prototype.use, 'use'); + assert.looksNative(DisposableStack.prototype.use); + assert.nonEnumerable(DisposableStack.prototype, 'use'); + + let result = ''; + const stack1 = new DisposableStack(); + const resource = { + [Symbol.dispose]() { + result += '1'; + assert.same(this, resource); + assert.same(arguments.length, 0); + }, + }; + + assert.same(stack1.use(resource), resource); + assert.same(stack1.dispose(), undefined); + assert.same(result, '1'); +}); + +QUnit.test('DisposableStack#adopt', assert => { + assert.isFunction(DisposableStack.prototype.adopt); + assert.arity(DisposableStack.prototype.adopt, 2); + assert.name(DisposableStack.prototype.adopt, 'adopt'); + assert.looksNative(DisposableStack.prototype.adopt); + assert.nonEnumerable(DisposableStack.prototype, 'adopt'); + + let result = ''; + const stack = new DisposableStack(); + const resource = {}; + + assert.same(stack.adopt(resource, function (arg) { + result += '1'; + if (STRICT) assert.same(this, undefined); + assert.same(arguments.length, 1); + assert.same(arg, resource); + }), resource); + + assert.same(stack.dispose(), undefined); + assert.same(result, '1'); +}); + +QUnit.test('DisposableStack#defer', assert => { + assert.isFunction(DisposableStack.prototype.defer); + assert.arity(DisposableStack.prototype.defer, 1); + assert.name(DisposableStack.prototype.defer, 'defer'); + assert.looksNative(DisposableStack.prototype.defer); + assert.nonEnumerable(DisposableStack.prototype, 'defer'); + + let result = ''; + const stack = new DisposableStack(); + + assert.same(stack.defer(function () { + result += '1'; + if (STRICT) assert.same(this, undefined); + assert.same(arguments.length, 0); + }), undefined); + + assert.same(stack.dispose(), undefined); + assert.same(result, '1'); +}); + +QUnit.test('DisposableStack#move', assert => { + assert.isFunction(DisposableStack.prototype.move); + assert.arity(DisposableStack.prototype.move, 0); + assert.name(DisposableStack.prototype.move, 'move'); + assert.looksNative(DisposableStack.prototype.move); + assert.nonEnumerable(DisposableStack.prototype, 'move'); + + let result = ''; + const stack1 = new DisposableStack(); + + stack1.defer(() => result += '2'); + stack1.defer(() => result += '1'); + + const stack2 = stack1.move(); + + assert.false(stack1.disposed); + + stack1.dispose(); + + assert.same(result, ''); + + assert.true(stack1.disposed); + + stack2.dispose(); + + assert.same(result, '12'); +}); + +QUnit.test('DisposableStack#@@dispose', assert => { + assert.same(DisposableStack.prototype[Symbol.dispose], DisposableStack.prototype.dispose); +}); + +QUnit.test('DisposableStack', assert => { + let result1 = ''; + const stack1 = new DisposableStack(); + + stack1.use({ [Symbol.dispose]: () => result1 += '6' }); + stack1.adopt({}, () => result1 += '5'); + stack1.defer(() => result1 += '4'); + stack1.use({ [Symbol.dispose]: () => result1 += '3' }); + stack1.adopt({}, () => result1 += '2'); + stack1.defer(() => result1 += '1'); + + assert.false(stack1.disposed); + assert.same(stack1.dispose(), undefined); + assert.same(result1, '123456'); + assert.true(stack1.disposed); + assert.same(stack1.dispose(), undefined); + + let result2 = ''; + const stack2 = new DisposableStack(); + let error2; + + stack2.use({ [Symbol.dispose]: () => result2 += '6' }); + stack2.adopt({}, () => { throw Error(5); }); + stack2.defer(() => result2 += '4'); + stack2.use({ [Symbol.dispose]: () => result2 += '3' }); + stack2.adopt({}, () => result2 += '2'); + stack2.defer(() => result2 += '1'); + + try { + stack2.dispose(); + } catch (error2$) { + error2 = error2$; + } + + assert.same(result2, '12346'); + assert.true(error2 instanceof Error); + assert.same(error2.message, '5'); + + let result3 = ''; + const stack3 = new DisposableStack(); + let error3; + + stack3.use({ [Symbol.dispose]: () => result3 += '6' }); + stack3.adopt({}, () => { throw Error(5); }); + stack3.defer(() => result3 += '4'); + stack3.use({ [Symbol.dispose]: () => { throw Error(3); } }); + stack3.adopt({}, () => result3 += '2'); + stack3.defer(() => result3 += '1'); + + try { + stack3.dispose(); + } catch (error3$) { + error3 = error3$; + } + + assert.same(result3, '1246'); + assert.true(error3 instanceof SuppressedError); + assert.same(error3.error.message, '5'); + assert.same(error3.suppressed.message, '3'); +}); diff --git a/tests/unit-pure/esnext.disposable-stack.constructor.js b/tests/unit-pure/esnext.disposable-stack.constructor.js new file mode 100644 index 000000000000..1ab85dae158f --- /dev/null +++ b/tests/unit-pure/esnext.disposable-stack.constructor.js @@ -0,0 +1,176 @@ +import { STRICT } from '../helpers/constants'; + +import Symbol from 'core-js-pure/full/symbol'; +import DisposableStack from 'core-js-pure/full/disposable-stack'; +import SuppressedError from 'core-js-pure/full/suppressed-error'; + +QUnit.test('DisposableStack constructor', assert => { + assert.isFunction(DisposableStack); + assert.arity(DisposableStack, 0); + assert.name(DisposableStack, 'DisposableStack'); + + assert.throws(() => DisposableStack(), 'throws w/o `new`'); + assert.true(new DisposableStack() instanceof DisposableStack); + + assert.same(DisposableStack.prototype.constructor, DisposableStack); +}); + +QUnit.test('DisposableStack#dispose', assert => { + assert.isFunction(DisposableStack.prototype.dispose); + assert.arity(DisposableStack.prototype.dispose, 0); + assert.name(DisposableStack.prototype.dispose, 'dispose'); + assert.nonEnumerable(DisposableStack.prototype, 'dispose'); +}); + +QUnit.test('DisposableStack#use', assert => { + assert.isFunction(DisposableStack.prototype.use); + assert.arity(DisposableStack.prototype.use, 1); + assert.name(DisposableStack.prototype.use, 'use'); + assert.nonEnumerable(DisposableStack.prototype, 'use'); + + let result = ''; + const stack1 = new DisposableStack(); + const resource = { + [Symbol.dispose]() { + result += '1'; + assert.same(this, resource); + assert.same(arguments.length, 0); + }, + }; + + assert.same(stack1.use(resource), resource); + assert.same(stack1.dispose(), undefined); + assert.same(result, '1'); +}); + +QUnit.test('DisposableStack#adopt', assert => { + assert.isFunction(DisposableStack.prototype.adopt); + assert.arity(DisposableStack.prototype.adopt, 2); + assert.name(DisposableStack.prototype.adopt, 'adopt'); + assert.nonEnumerable(DisposableStack.prototype, 'adopt'); + + let result = ''; + const stack = new DisposableStack(); + const resource = {}; + + assert.same(stack.adopt(resource, function (arg) { + result += '1'; + if (STRICT) assert.same(this, undefined); + assert.same(arguments.length, 1); + assert.same(arg, resource); + }), resource); + + assert.same(stack.dispose(), undefined); + assert.same(result, '1'); +}); + +QUnit.test('DisposableStack#defer', assert => { + assert.isFunction(DisposableStack.prototype.defer); + assert.arity(DisposableStack.prototype.defer, 1); + assert.name(DisposableStack.prototype.defer, 'defer'); + assert.nonEnumerable(DisposableStack.prototype, 'defer'); + + let result = ''; + const stack = new DisposableStack(); + + assert.same(stack.defer(function () { + result += '1'; + if (STRICT) assert.same(this, undefined); + assert.same(arguments.length, 0); + }), undefined); + + assert.same(stack.dispose(), undefined); + assert.same(result, '1'); +}); + +QUnit.test('DisposableStack#move', assert => { + assert.isFunction(DisposableStack.prototype.move); + assert.arity(DisposableStack.prototype.move, 0); + assert.name(DisposableStack.prototype.move, 'move'); + assert.nonEnumerable(DisposableStack.prototype, 'move'); + + let result = ''; + const stack1 = new DisposableStack(); + + stack1.defer(() => result += '2'); + stack1.defer(() => result += '1'); + + const stack2 = stack1.move(); + + assert.false(stack1.disposed); + + stack1.dispose(); + + assert.same(result, ''); + + assert.true(stack1.disposed); + + stack2.dispose(); + + assert.same(result, '12'); +}); + +QUnit.test('DisposableStack#@@dispose', assert => { + assert.same(DisposableStack.prototype[Symbol.dispose], DisposableStack.prototype.dispose); +}); + +QUnit.test('DisposableStack', assert => { + let result1 = ''; + const stack1 = new DisposableStack(); + + stack1.use({ [Symbol.dispose]: () => result1 += '6' }); + stack1.adopt({}, () => result1 += '5'); + stack1.defer(() => result1 += '4'); + stack1.use({ [Symbol.dispose]: () => result1 += '3' }); + stack1.adopt({}, () => result1 += '2'); + stack1.defer(() => result1 += '1'); + + assert.false(stack1.disposed); + assert.same(stack1.dispose(), undefined); + assert.same(result1, '123456'); + assert.true(stack1.disposed); + assert.same(stack1.dispose(), undefined); + + let result2 = ''; + const stack2 = new DisposableStack(); + let error2; + + stack2.use({ [Symbol.dispose]: () => result2 += '6' }); + stack2.adopt({}, () => { throw Error(5); }); + stack2.defer(() => result2 += '4'); + stack2.use({ [Symbol.dispose]: () => result2 += '3' }); + stack2.adopt({}, () => result2 += '2'); + stack2.defer(() => result2 += '1'); + + try { + stack2.dispose(); + } catch (error2$) { + error2 = error2$; + } + + assert.same(result2, '12346'); + assert.true(error2 instanceof Error); + assert.same(error2.message, '5'); + + let result3 = ''; + const stack3 = new DisposableStack(); + let error3; + + stack3.use({ [Symbol.dispose]: () => result3 += '6' }); + stack3.adopt({}, () => { throw Error(5); }); + stack3.defer(() => result3 += '4'); + stack3.use({ [Symbol.dispose]: () => { throw Error(3); } }); + stack3.adopt({}, () => result3 += '2'); + stack3.defer(() => result3 += '1'); + + try { + stack3.dispose(); + } catch (error3$) { + error3 = error3$; + } + + assert.same(result3, '1246'); + assert.true(error3 instanceof SuppressedError); + assert.same(error3.error.message, '5'); + assert.same(error3.suppressed.message, '3'); +}); From 53cca1ec66b9fc2c2391ebfb52db8ce1f7124850 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 30 Nov 2022 08:47:42 +0700 Subject: [PATCH 08/18] add some tests --- ...next.async-disposable-stack.constructor.js | 2 +- ...next.async-disposable-stack.constructor.js | 188 ++++++++++++++++++ .../esnext.async-iterator.async-dispose.js | 27 ++- .../esnext.disposable-stack.constructor.js | 14 +- ...next.async-disposable-stack.constructor.js | 187 +++++++++++++++++ .../esnext.async-iterator.async-dispose.js | 27 ++- .../esnext.disposable-stack.constructor.js | 6 +- 7 files changed, 412 insertions(+), 39 deletions(-) create mode 100644 tests/unit-global/esnext.async-disposable-stack.constructor.js create mode 100644 tests/unit-pure/esnext.async-disposable-stack.constructor.js diff --git a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js index 31999d66404a..dad6caad96b2 100644 --- a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js +++ b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js @@ -51,7 +51,7 @@ defineBuiltIns(AsyncDisposableStackPrototype, { var asyncDisposableStack = this; return new Promise(function (resolve, reject) { var internalState = getAsyncDisposableStackInternalState(asyncDisposableStack); - if (internalState.state == DISPOSED) return; + if (internalState.state == DISPOSED) return resolve(undefined); internalState.state = DISPOSED; if (!DESCRIPTORS) asyncDisposableStack.disposed = true; var stack = internalState.stack; diff --git a/tests/unit-global/esnext.async-disposable-stack.constructor.js b/tests/unit-global/esnext.async-disposable-stack.constructor.js new file mode 100644 index 000000000000..54423029d8d3 --- /dev/null +++ b/tests/unit-global/esnext.async-disposable-stack.constructor.js @@ -0,0 +1,188 @@ +import { STRICT } from '../helpers/constants'; + +QUnit.test('AsyncDisposableStack constructor', assert => { + assert.isFunction(AsyncDisposableStack); + assert.arity(AsyncDisposableStack, 0); + assert.name(AsyncDisposableStack, 'AsyncDisposableStack'); + assert.looksNative(AsyncDisposableStack); + + assert.throws(() => AsyncDisposableStack(), 'throws w/o `new`'); + assert.true(new AsyncDisposableStack() instanceof AsyncDisposableStack); + + assert.same(AsyncDisposableStack.prototype.constructor, AsyncDisposableStack); +}); + +QUnit.test('AsyncDisposableStack#disposeAsync', assert => { + assert.isFunction(AsyncDisposableStack.prototype.disposeAsync); + assert.arity(AsyncDisposableStack.prototype.disposeAsync, 0); + assert.name(AsyncDisposableStack.prototype.disposeAsync, 'disposeAsync'); + assert.looksNative(AsyncDisposableStack.prototype.disposeAsync); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'disposeAsync'); +}); + +QUnit.test('AsyncDisposableStack#use', assert => { + assert.isFunction(AsyncDisposableStack.prototype.use); + assert.arity(AsyncDisposableStack.prototype.use, 1); + assert.name(AsyncDisposableStack.prototype.use, 'use'); + assert.looksNative(AsyncDisposableStack.prototype.use); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'use'); + + let result = ''; + const stack = new AsyncDisposableStack(); + const resource = { + [Symbol.asyncDispose]() { + result += '1'; + assert.same(this, resource); + assert.same(arguments.length, 0); + }, + }; + + assert.same(stack.use(resource), resource); + + return stack.disposeAsync().then(it => { + assert.same(it, undefined); + assert.same(result, '1'); + }); +}); + +QUnit.test('AsyncDisposableStack#adopt', assert => { + assert.isFunction(AsyncDisposableStack.prototype.adopt); + assert.arity(AsyncDisposableStack.prototype.adopt, 2); + assert.name(AsyncDisposableStack.prototype.adopt, 'adopt'); + assert.looksNative(AsyncDisposableStack.prototype.adopt); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'adopt'); + + let result = ''; + const stack = new AsyncDisposableStack(); + const resource = {}; + + assert.same(stack.adopt(resource, function (arg) { + result += '1'; + if (STRICT) assert.same(this, undefined); + assert.same(arguments.length, 1); + assert.same(arg, resource); + }), resource); + + return stack.disposeAsync().then(it => { + assert.same(it, undefined); + assert.same(result, '1'); + }); +}); + +QUnit.test('AsyncDisposableStack#defer', assert => { + assert.isFunction(AsyncDisposableStack.prototype.defer); + assert.arity(AsyncDisposableStack.prototype.defer, 1); + assert.name(AsyncDisposableStack.prototype.defer, 'defer'); + assert.looksNative(AsyncDisposableStack.prototype.defer); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'defer'); + + let result = ''; + const stack = new AsyncDisposableStack(); + + assert.same(stack.defer(function () { + result += '1'; + if (STRICT) assert.same(this, undefined); + assert.same(arguments.length, 0); + }), undefined); + + return stack.disposeAsync().then(it => { + assert.same(it, undefined); + assert.same(result, '1'); + }); +}); + +QUnit.test('AsyncDisposableStack#move', assert => { + assert.isFunction(AsyncDisposableStack.prototype.move); + assert.arity(AsyncDisposableStack.prototype.move, 0); + assert.name(AsyncDisposableStack.prototype.move, 'move'); + assert.looksNative(AsyncDisposableStack.prototype.move); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'move'); + + let result = ''; + const stack1 = new AsyncDisposableStack(); + + stack1.defer(() => result += '2'); + stack1.defer(() => result += '1'); + + const stack2 = stack1.move(); + + assert.false(stack1.disposed); + + return stack1.disposeAsync().then(() => { + assert.same(result, ''); + + assert.true(stack1.disposed); + + return stack2.disposeAsync(); + }).then(() => { + assert.same(result, '12'); + }); +}); + +QUnit.test('AsyncDisposableStack#@@asyncDispose', assert => { + assert.same(AsyncDisposableStack.prototype[Symbol.asyncDispose], AsyncDisposableStack.prototype.disposeAsync); +}); + +QUnit.test('AsyncDisposableStack#1', assert => { + let result = ''; + const stack = new AsyncDisposableStack(); + + stack.use({ [Symbol.asyncDispose]: () => result += '6' }); + stack.adopt({}, () => result += '5'); + stack.defer(() => result += '4'); + stack.use({ [Symbol.asyncDispose]: () => Promise.resolve(result += '3') }); + stack.adopt({}, () => Promise.resolve(result += '2')); + stack.defer(() => Promise.resolve(result += '1')); + + assert.false(stack.disposed); + + return stack.disposeAsync().then(it => { + assert.same(it, undefined); + assert.same(result, '123456'); + assert.true(stack.disposed); + return stack.disposeAsync(); + }).then(it => { + assert.same(it, undefined); + }); +}); + +QUnit.test('AsyncDisposableStack#2', assert => { + let result = ''; + const stack = new AsyncDisposableStack(); + + stack.use({ [Symbol.asyncDispose]: () => result += '6' }); + stack.adopt({}, () => { throw Error(5); }); + stack.defer(() => result += '4'); + stack.use({ [Symbol.asyncDispose]: () => Promise.resolve(result += '3') }); + stack.adopt({}, () => Promise.resolve(result += '2')); + stack.defer(() => Promise.resolve(result += '1')); + + return stack.disposeAsync().then(() => { + assert.avoid(); + }, error => { + assert.same(result, '12346'); + assert.true(error instanceof Error); + assert.same(error.message, '5'); + }); +}); + +QUnit.test('AsyncDisposableStack#3', assert => { + let result = ''; + const stack = new AsyncDisposableStack(); + + stack.use({ [Symbol.asyncDispose]: () => result += '6' }); + stack.adopt({}, () => { throw Error(5); }); + stack.defer(() => result += '4'); + stack.use({ [Symbol.asyncDispose]: () => Promise.reject(Error(3)) }); + stack.adopt({}, () => Promise.resolve(result += '2')); + stack.defer(() => Promise.resolve(result += '1')); + + return stack.disposeAsync().then(() => { + assert.avoid(); + }, error => { + assert.same(result, '1246'); + assert.true(error instanceof SuppressedError); + assert.same(error.error.message, '5'); + assert.same(error.suppressed.message, '3'); + }); +}); diff --git a/tests/unit-global/esnext.async-iterator.async-dispose.js b/tests/unit-global/esnext.async-iterator.async-dispose.js index 0885f06fc3d3..a785baba31bc 100644 --- a/tests/unit-global/esnext.async-iterator.async-dispose.js +++ b/tests/unit-global/esnext.async-iterator.async-dispose.js @@ -1,26 +1,25 @@ const { create } = Object; QUnit.test('AsyncIterator#@@asyncDispose', assert => { - assert.expect(7); - const asyncDispose = AsyncIterator.prototype[Symbol.asyncDispose]; assert.isFunction(asyncDispose); assert.arity(asyncDispose, 0); assert.looksNative(asyncDispose); - create(AsyncIterator.prototype)[Symbol.asyncDispose]().then(result => { + return create(AsyncIterator.prototype)[Symbol.asyncDispose]().then(result => { assert.same(result, undefined); - }); + }).then(() => { + let called = false; + const iterator2 = create(AsyncIterator.prototype); + iterator2.return = function () { + called = true; + assert.same(this, iterator2); + return 7; + }; - let called = false; - const iterator2 = create(AsyncIterator.prototype); - iterator2.return = function () { - called = true; - assert.same(this, iterator2); - return 7; - }; - iterator2[Symbol.asyncDispose]().then(result => { - assert.same(result, undefined); - assert.true(called); + return iterator2[Symbol.asyncDispose]().then(result => { + assert.same(result, undefined); + assert.true(called); + }); }); }); diff --git a/tests/unit-global/esnext.disposable-stack.constructor.js b/tests/unit-global/esnext.disposable-stack.constructor.js index 938553ec8793..0bdd67c71436 100644 --- a/tests/unit-global/esnext.disposable-stack.constructor.js +++ b/tests/unit-global/esnext.disposable-stack.constructor.js @@ -92,20 +92,20 @@ QUnit.test('DisposableStack#move', assert => { assert.nonEnumerable(DisposableStack.prototype, 'move'); let result = ''; - const stack1 = new DisposableStack(); + const stack = new DisposableStack(); - stack1.defer(() => result += '2'); - stack1.defer(() => result += '1'); + stack.defer(() => result += '2'); + stack.defer(() => result += '1'); - const stack2 = stack1.move(); + const stack2 = stack.move(); - assert.false(stack1.disposed); + assert.false(stack.disposed); - stack1.dispose(); + stack.dispose(); assert.same(result, ''); - assert.true(stack1.disposed); + assert.true(stack.disposed); stack2.dispose(); diff --git a/tests/unit-pure/esnext.async-disposable-stack.constructor.js b/tests/unit-pure/esnext.async-disposable-stack.constructor.js new file mode 100644 index 000000000000..5bf0ab02aeae --- /dev/null +++ b/tests/unit-pure/esnext.async-disposable-stack.constructor.js @@ -0,0 +1,187 @@ +import { STRICT } from '../helpers/constants'; + +import Promise from 'core-js-pure/es/promise'; +import Symbol from 'core-js-pure/full/symbol'; +import AsyncDisposableStack from 'core-js-pure/full/async-disposable-stack'; +import SuppressedError from 'core-js-pure/full/suppressed-error'; + +QUnit.test('AsyncDisposableStack constructor', assert => { + assert.isFunction(AsyncDisposableStack); + assert.arity(AsyncDisposableStack, 0); + assert.name(AsyncDisposableStack, 'AsyncDisposableStack'); + + assert.throws(() => AsyncDisposableStack(), 'throws w/o `new`'); + assert.true(new AsyncDisposableStack() instanceof AsyncDisposableStack); + + assert.same(AsyncDisposableStack.prototype.constructor, AsyncDisposableStack); +}); + +QUnit.test('AsyncDisposableStack#disposeAsync', assert => { + assert.isFunction(AsyncDisposableStack.prototype.disposeAsync); + assert.arity(AsyncDisposableStack.prototype.disposeAsync, 0); + assert.name(AsyncDisposableStack.prototype.disposeAsync, 'disposeAsync'); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'disposeAsync'); +}); + +QUnit.test('AsyncDisposableStack#use', assert => { + assert.isFunction(AsyncDisposableStack.prototype.use); + assert.arity(AsyncDisposableStack.prototype.use, 1); + assert.name(AsyncDisposableStack.prototype.use, 'use'); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'use'); + + let result = ''; + const stack = new AsyncDisposableStack(); + const resource = { + [Symbol.asyncDispose]() { + result += '1'; + assert.same(this, resource); + assert.same(arguments.length, 0); + }, + }; + + assert.same(stack.use(resource), resource); + + return stack.disposeAsync().then(it => { + assert.same(it, undefined); + assert.same(result, '1'); + }); +}); + +QUnit.test('AsyncDisposableStack#adopt', assert => { + assert.isFunction(AsyncDisposableStack.prototype.adopt); + assert.arity(AsyncDisposableStack.prototype.adopt, 2); + assert.name(AsyncDisposableStack.prototype.adopt, 'adopt'); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'adopt'); + + let result = ''; + const stack = new AsyncDisposableStack(); + const resource = {}; + + assert.same(stack.adopt(resource, function (arg) { + result += '1'; + if (STRICT) assert.same(this, undefined); + assert.same(arguments.length, 1); + assert.same(arg, resource); + }), resource); + + return stack.disposeAsync().then(it => { + assert.same(it, undefined); + assert.same(result, '1'); + }); +}); + +QUnit.test('AsyncDisposableStack#defer', assert => { + assert.isFunction(AsyncDisposableStack.prototype.defer); + assert.arity(AsyncDisposableStack.prototype.defer, 1); + assert.name(AsyncDisposableStack.prototype.defer, 'defer'); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'defer'); + + let result = ''; + const stack = new AsyncDisposableStack(); + + assert.same(stack.defer(function () { + result += '1'; + if (STRICT) assert.same(this, undefined); + assert.same(arguments.length, 0); + }), undefined); + + return stack.disposeAsync().then(it => { + assert.same(it, undefined); + assert.same(result, '1'); + }); +}); + +QUnit.test('AsyncDisposableStack#move', assert => { + assert.isFunction(AsyncDisposableStack.prototype.move); + assert.arity(AsyncDisposableStack.prototype.move, 0); + assert.name(AsyncDisposableStack.prototype.move, 'move'); + assert.nonEnumerable(AsyncDisposableStack.prototype, 'move'); + + let result = ''; + const stack1 = new AsyncDisposableStack(); + + stack1.defer(() => result += '2'); + stack1.defer(() => result += '1'); + + const stack2 = stack1.move(); + + assert.false(stack1.disposed); + + return stack1.disposeAsync().then(() => { + assert.same(result, ''); + + assert.true(stack1.disposed); + + return stack2.disposeAsync(); + }).then(() => { + assert.same(result, '12'); + }); +}); + +QUnit.test('AsyncDisposableStack#@@asyncDispose', assert => { + assert.same(AsyncDisposableStack.prototype[Symbol.asyncDispose], AsyncDisposableStack.prototype.disposeAsync); +}); + +QUnit.test('AsyncDisposableStack#1', assert => { + let result = ''; + const stack = new AsyncDisposableStack(); + + stack.use({ [Symbol.asyncDispose]: () => result += '6' }); + stack.adopt({}, () => result += '5'); + stack.defer(() => result += '4'); + stack.use({ [Symbol.asyncDispose]: () => Promise.resolve(result += '3') }); + stack.adopt({}, () => Promise.resolve(result += '2')); + stack.defer(() => Promise.resolve(result += '1')); + + assert.false(stack.disposed); + + return stack.disposeAsync().then(it => { + assert.same(it, undefined); + assert.same(result, '123456'); + assert.true(stack.disposed); + return stack.disposeAsync(); + }).then(it => { + assert.same(it, undefined); + }); +}); + +QUnit.test('AsyncDisposableStack#2', assert => { + let result = ''; + const stack = new AsyncDisposableStack(); + + stack.use({ [Symbol.asyncDispose]: () => result += '6' }); + stack.adopt({}, () => { throw Error(5); }); + stack.defer(() => result += '4'); + stack.use({ [Symbol.asyncDispose]: () => Promise.resolve(result += '3') }); + stack.adopt({}, () => Promise.resolve(result += '2')); + stack.defer(() => Promise.resolve(result += '1')); + + return stack.disposeAsync().then(() => { + assert.avoid(); + }, error => { + assert.same(result, '12346'); + assert.true(error instanceof Error); + assert.same(error.message, '5'); + }); +}); + +QUnit.test('AsyncDisposableStack#3', assert => { + let result = ''; + const stack = new AsyncDisposableStack(); + + stack.use({ [Symbol.asyncDispose]: () => result += '6' }); + stack.adopt({}, () => { throw Error(5); }); + stack.defer(() => result += '4'); + stack.use({ [Symbol.asyncDispose]: () => Promise.reject(Error(3)) }); + stack.adopt({}, () => Promise.resolve(result += '2')); + stack.defer(() => Promise.resolve(result += '1')); + + return stack.disposeAsync().then(() => { + assert.avoid(); + }, error => { + assert.same(result, '1246'); + assert.true(error instanceof SuppressedError); + assert.same(error.error.message, '5'); + assert.same(error.suppressed.message, '3'); + }); +}); diff --git a/tests/unit-pure/esnext.async-iterator.async-dispose.js b/tests/unit-pure/esnext.async-iterator.async-dispose.js index dad705dfe81f..edf5e29cc394 100644 --- a/tests/unit-pure/esnext.async-iterator.async-dispose.js +++ b/tests/unit-pure/esnext.async-iterator.async-dispose.js @@ -3,25 +3,24 @@ import Symbol from 'core-js-pure/full/symbol'; import create from 'core-js-pure/es/object/create'; QUnit.test('AsyncIterator#@@asyncDispose', assert => { - assert.expect(6); - const asyncDispose = AsyncIterator.prototype[Symbol.asyncDispose]; assert.isFunction(asyncDispose); assert.arity(asyncDispose, 0); - create(AsyncIterator.prototype)[Symbol.asyncDispose]().then(result => { + return create(AsyncIterator.prototype)[Symbol.asyncDispose]().then(result => { assert.same(result, undefined); - }); + }).then(() => { + let called = false; + const iterator2 = create(AsyncIterator.prototype); + iterator2.return = function () { + called = true; + assert.same(this, iterator2); + return 7; + }; - let called = false; - const iterator2 = create(AsyncIterator.prototype); - iterator2.return = function () { - called = true; - assert.same(this, iterator2); - return 7; - }; - iterator2[Symbol.asyncDispose]().then(result => { - assert.same(result, undefined); - assert.true(called); + return iterator2[Symbol.asyncDispose]().then(result => { + assert.same(result, undefined); + assert.true(called); + }); }); }); diff --git a/tests/unit-pure/esnext.disposable-stack.constructor.js b/tests/unit-pure/esnext.disposable-stack.constructor.js index 1ab85dae158f..4cdc0aed3a02 100644 --- a/tests/unit-pure/esnext.disposable-stack.constructor.js +++ b/tests/unit-pure/esnext.disposable-stack.constructor.js @@ -29,7 +29,7 @@ QUnit.test('DisposableStack#use', assert => { assert.nonEnumerable(DisposableStack.prototype, 'use'); let result = ''; - const stack1 = new DisposableStack(); + const stack = new DisposableStack(); const resource = { [Symbol.dispose]() { result += '1'; @@ -38,8 +38,8 @@ QUnit.test('DisposableStack#use', assert => { }, }; - assert.same(stack1.use(resource), resource); - assert.same(stack1.dispose(), undefined); + assert.same(stack.use(resource), resource); + assert.same(stack.dispose(), undefined); assert.same(result, '1'); }); From edb7871b2bd806620ccf1ccfeeb2fa451f6c0eb3 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 30 Nov 2022 09:06:09 +0700 Subject: [PATCH 09/18] add some tests --- .../unit-global/esnext.async-disposable-stack.constructor.js | 4 ++++ tests/unit-global/esnext.disposable-stack.constructor.js | 4 ++++ tests/unit-pure/esnext.async-disposable-stack.constructor.js | 4 ++++ tests/unit-pure/esnext.disposable-stack.constructor.js | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/tests/unit-global/esnext.async-disposable-stack.constructor.js b/tests/unit-global/esnext.async-disposable-stack.constructor.js index 54423029d8d3..d6f0aaa99af3 100644 --- a/tests/unit-global/esnext.async-disposable-stack.constructor.js +++ b/tests/unit-global/esnext.async-disposable-stack.constructor.js @@ -123,6 +123,10 @@ QUnit.test('AsyncDisposableStack#@@asyncDispose', assert => { assert.same(AsyncDisposableStack.prototype[Symbol.asyncDispose], AsyncDisposableStack.prototype.disposeAsync); }); +QUnit.test('AsyncDisposableStack#@@toStringTag', assert => { + assert.same(AsyncDisposableStack.prototype[Symbol.toStringTag], 'AsyncDisposableStack', '@@toStringTag'); +}); + QUnit.test('AsyncDisposableStack#1', assert => { let result = ''; const stack = new AsyncDisposableStack(); diff --git a/tests/unit-global/esnext.disposable-stack.constructor.js b/tests/unit-global/esnext.disposable-stack.constructor.js index 0bdd67c71436..055e64bd9aa0 100644 --- a/tests/unit-global/esnext.disposable-stack.constructor.js +++ b/tests/unit-global/esnext.disposable-stack.constructor.js @@ -116,6 +116,10 @@ QUnit.test('DisposableStack#@@dispose', assert => { assert.same(DisposableStack.prototype[Symbol.dispose], DisposableStack.prototype.dispose); }); +QUnit.test('DisposableStack#@@toStringTag', assert => { + assert.same(DisposableStack.prototype[Symbol.toStringTag], 'DisposableStack', '@@toStringTag'); +}); + QUnit.test('DisposableStack', assert => { let result1 = ''; const stack1 = new DisposableStack(); diff --git a/tests/unit-pure/esnext.async-disposable-stack.constructor.js b/tests/unit-pure/esnext.async-disposable-stack.constructor.js index 5bf0ab02aeae..c8f3f09d350c 100644 --- a/tests/unit-pure/esnext.async-disposable-stack.constructor.js +++ b/tests/unit-pure/esnext.async-disposable-stack.constructor.js @@ -122,6 +122,10 @@ QUnit.test('AsyncDisposableStack#@@asyncDispose', assert => { assert.same(AsyncDisposableStack.prototype[Symbol.asyncDispose], AsyncDisposableStack.prototype.disposeAsync); }); +QUnit.test('AsyncDisposableStack#@@toStringTag', assert => { + assert.same(AsyncDisposableStack.prototype[Symbol.toStringTag], 'AsyncDisposableStack', '@@toStringTag'); +}); + QUnit.test('AsyncDisposableStack#1', assert => { let result = ''; const stack = new AsyncDisposableStack(); diff --git a/tests/unit-pure/esnext.disposable-stack.constructor.js b/tests/unit-pure/esnext.disposable-stack.constructor.js index 4cdc0aed3a02..8b28f01bd515 100644 --- a/tests/unit-pure/esnext.disposable-stack.constructor.js +++ b/tests/unit-pure/esnext.disposable-stack.constructor.js @@ -114,6 +114,10 @@ QUnit.test('DisposableStack#@@dispose', assert => { assert.same(DisposableStack.prototype[Symbol.dispose], DisposableStack.prototype.dispose); }); +QUnit.test('DisposableStack#@@toStringTag', assert => { + assert.same(DisposableStack.prototype[Symbol.toStringTag], 'DisposableStack', '@@toStringTag'); +}); + QUnit.test('DisposableStack', assert => { let result1 = ''; const stack1 = new DisposableStack(); From b40a87bc3b9e6cab56b2c9fd08c5121433b66229 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 30 Nov 2022 09:18:44 +0700 Subject: [PATCH 10/18] test `@@dispose` on `%ArrayIteratorPrototype%` --- tests/compat/tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compat/tests.js b/tests/compat/tests.js index ea40d36156bb..be729084442a 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1513,7 +1513,7 @@ GLOBAL.tests = { } }, 'esnext.iterator.dispose': function () { - return Iterator.prototype[Symbol.dispose]; + return [].keys()[Symbol.dispose]; }, 'esnext.iterator.drop': function () { return Iterator.prototype.drop; From cdfc1a4742c0230af837aa69041439dced73fa30 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 1 Dec 2022 01:33:53 +0700 Subject: [PATCH 11/18] add to changelog --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55785be8e8c7..775710fe9bd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,26 @@ - `String.prototype.toWellFormed` - Moved to Stage 3, [November 2022 TC39 meeting](https://github.com/babel/proposals/issues/85#issuecomment-1332180862) - Added `/actual/` entries, disabled unconditional forced replacement +- [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management) stage 2 proposal + - Renamed from "`using` statement" + - In addition to already present well-known symbols `@@dispose` and `@@asyncDispose`, added new built-ins: + - `AsyncDisposableStack` + - `AsyncDisposableStack.prototype.disposeAsync` + - `AsyncDisposableStack.prototype.use` + - `AsyncDisposableStack.prototype.adopt` + - `AsyncDisposableStack.prototype.defer` + - `AsyncDisposableStack.prototype.move` + - `AsyncDisposableStack.prototype[@@asyncDispose]` + - `DisposableStack` + - `DisposableStack.prototype.dispose` + - `DisposableStack.prototype.use` + - `DisposableStack.prototype.adopt` + - `DisposableStack.prototype.defer` + - `DisposableStack.prototype.move` + - `DisposableStack.prototype[@@dispose]` + - `SuppressedError` + - `Iterator.prototype[@@dispose]` + - `AsyncIterator.prototype[@@asyncDispose]` - [Compat data targets](/packages/core-js-compat#targets-option) improvements: - [React Native from 0.70 shipped with Hermes as the default engine.](https://reactnative.dev/blog/2022/07/08/hermes-as-the-default) However, bundled Hermes versions differ from standalone Hermes releases. So added **`react-native`** target for React Native with bundled Hermes. - [According to the documentation](https://developer.oculus.com/documentation/web/browser-intro/), Oculus Browser was renamed to Meta Quest Browser, so `oculus` target was renamed to **`quest`**. From 7e91a7695898595d3aa5574b01b115e4a857d4d3 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 1 Dec 2022 01:57:34 +0700 Subject: [PATCH 12/18] update docs --- CHANGELOG.md | 2 +- README.md | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 775710fe9bd3..7c58bdf4e036 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ - `String.prototype.toWellFormed` - Moved to Stage 3, [November 2022 TC39 meeting](https://github.com/babel/proposals/issues/85#issuecomment-1332180862) - Added `/actual/` entries, disabled unconditional forced replacement -- [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management) stage 2 proposal +- [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management) stage 2 proposal: - Renamed from "`using` statement" - In addition to already present well-known symbols `@@dispose` and `@@asyncDispose`, added new built-ins: - `AsyncDisposableStack` diff --git a/README.md b/README.md index 0f0f2a9bf3a8..ff294e2c882b 100644 --- a/README.md +++ b/README.md @@ -593,10 +593,11 @@ class [ constructor(message: string, { cause: any }): %Error%; } -class AggregateError { - constructor(errors: Iterable, message: string, { cause: any }): AggregateError; +class AggregateError extends Error { + constructor(errors: Iterable, message?: string, { cause: any }?): AggregateError; errors: Array; message: string; + cause: any; } class Error { @@ -2383,18 +2384,59 @@ core-js(-pure)/full/array/is-template-object console.log(Array.isTemplateObject((it => it)`qwe${ 123 }asd`)); // => true ``` ##### [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management)[⬆](#index) -Modules [`esnext.symbol.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.dispose.js) and [`esnext.symbol.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.async-dispose.js). +Modules [`esnext.symbol.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.dispose.js), [`esnext.symbol.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.async-dispose.js), [`esnext.async-disposable-stack.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.async-disposable-stack.constructor.js), [`esnext.disposable-stack.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.disposable-stack.constructor.js), [`esnext.suppressed-error.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.suppressed-error.constructor.js), [`esnext.iterator.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.iterator.dispose.js), [`esnext.async-iterator.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.async-iterator.async-dispose.js). ```js class Symbol { static asyncDispose: @@asyncDispose; static dispose: @@dispose; } + +class AsyncDisposableStack { + constructor(): AsyncDisposableStack; + disposeAsync(): Promise; + use(value: AsyncDisposable | Disposable): value; + adopt(value: object, onDispose: Function): value; + defer(onDispose: Function): undefined; + @@asyncDispose(): Promise; + @@toStringTag(): 'AsyncDisposableStack'; +} + +class DisposableStack { + constructor(): DisposableStack; + dispose(): undefined; + use(value: Disposable): value; + adopt(value: object, onDispose: Function): value; + defer(onDispose: Function): undefined; + @@dispose(): undefined; + @@toStringTag(): 'DisposableStack'; +} + +class SuppressedError extends Error { + constructor(error: any, suppressed: any, message?: string, { cause: any }?): SuppressedError; + error: any; + suppressed: any; + message: string; + cause: any; +} + +class AsyncIterator { + @@asyncDispose(): Promise; +} + +class Iterator { + @@dispose(): undefined; +} ``` [*CommonJS entry points:*](#commonjs-api) ```js core-js/proposals/explicit-resource-management core-js(-pure)/full/symbol/async-dispose core-js(-pure)/full/symbol/dispose +core-js(-pure)/full/async-disposable-stack +core-js(-pure)/full/disposable-stack +core-js(-pure)/full/suppressed-error +core-js(-pure)/full/async-iterator/async-dispose +core-js(-pure)/full/iterator/dispose ``` ##### [`Symbol.metadataKey` for decorators metadata proposal](https://github.com/tc39/proposal-decorator-metadata)[⬆](#index) Module [`esnext.symbol.metadata-key`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.metadata-key.js). From 7377cd6b2af34fdbf0668a57ad7fb72935978162 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 1 Dec 2022 02:07:13 +0700 Subject: [PATCH 13/18] update docs --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ff294e2c882b..fc6d63a1cdb7 100644 --- a/README.md +++ b/README.md @@ -2384,6 +2384,8 @@ core-js(-pure)/full/array/is-template-object console.log(Array.isTemplateObject((it => it)`qwe${ 123 }asd`)); // => true ``` ##### [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management)[⬆](#index) +Note: **This is only built-ins for this proposal, `using` syntax support requires transpiler support.** + Modules [`esnext.symbol.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.dispose.js), [`esnext.symbol.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.async-dispose.js), [`esnext.async-disposable-stack.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.async-disposable-stack.constructor.js), [`esnext.disposable-stack.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.disposable-stack.constructor.js), [`esnext.suppressed-error.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.suppressed-error.constructor.js), [`esnext.iterator.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.iterator.dispose.js), [`esnext.async-iterator.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.async-iterator.async-dispose.js). ```js class Symbol { @@ -2398,7 +2400,7 @@ class AsyncDisposableStack { adopt(value: object, onDispose: Function): value; defer(onDispose: Function): undefined; @@asyncDispose(): Promise; - @@toStringTag(): 'AsyncDisposableStack'; + @@toStringTag: 'AsyncDisposableStack'; } class DisposableStack { @@ -2408,7 +2410,7 @@ class DisposableStack { adopt(value: object, onDispose: Function): value; defer(onDispose: Function): undefined; @@dispose(): undefined; - @@toStringTag(): 'DisposableStack'; + @@toStringTag: 'DisposableStack'; } class SuppressedError extends Error { From a96dd5ffb9e04c22894d81c39bc838a579820d41 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Fri, 2 Dec 2022 11:55:04 +0700 Subject: [PATCH 14/18] split to sync and async versions, move sync version to stage 3 --- README.md | 75 +++++++++++-------- ...next.async-disposable-stack.constructor.js | 2 +- .../esnext.async-iterator.async-dispose.js | 2 +- .../esnext.disposable-stack.constructor.js | 2 +- .../modules/esnext.symbol.async-dispose.js | 2 +- .../async-explicit-resource-management.js | 5 ++ .../proposals/explicit-resource-management.js | 3 - packages/core-js/proposals/using-statement.js | 3 +- packages/core-js/stage/2.js | 2 +- packages/core-js/stage/3.js | 1 + tests/entries/unit.mjs | 1 + 11 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 packages/core-js/proposals/async-explicit-resource-management.js diff --git a/README.md b/README.md index fc6d63a1cdb7..f0bba4b0952a 100644 --- a/README.md +++ b/README.md @@ -130,11 +130,12 @@ queueMicrotask(() => console.log('called as microtask')); - [`Array` grouping](#array-grouping) - [Change `Array` by copy](#change-array-by-copy) - [New `Set` methods](#new-set-methods) + - [Explicit resource management](#explicit-resource-management) - [Well-formed unicode strings](#well-formed-unicode-strings) - [Stage 2 proposals](#stage-2-proposals) - [`Map.prototype.emplace`](#mapprototypeemplace) - [`Array.isTemplateObject`](#arrayistemplateobject) - - [Explicit resource management](#explicit-resource-management) + - [Async explicit resource management](#async-explicit-resource-management) - [`Symbol.metadataKey` for decorators metadata proposal](#symbolmetadatakey-for-decorators-metadata-proposal) - [Stage 1 proposals](#stage-1-proposals) - [`Observable`](#observable) @@ -2312,6 +2313,45 @@ new Set([1, 2, 3]).isDisjointFrom(new Set([4, 5, 6])); // => true new Set([1, 2, 3]).isSubsetOf(new Set([5, 4, 3, 2, 1])); // => true new Set([5, 4, 3, 2, 1]).isSupersetOf(new Set([1, 2, 3])); // => true ``` +##### [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management)[⬆](#index) +Note: **This is only built-ins for this proposal, `using` syntax support requires transpiler support.** + +Modules [`esnext.symbol.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.dispose.js), [`esnext.disposable-stack.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.disposable-stack.constructor.js), [`esnext.suppressed-error.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.suppressed-error.constructor.js), [`esnext.iterator.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.iterator.dispose.js). +```js +class Symbol { + static dispose: @@dispose; +} + +class DisposableStack { + constructor(): DisposableStack; + dispose(): undefined; + use(value: Disposable): value; + adopt(value: object, onDispose: Function): value; + defer(onDispose: Function): undefined; + @@dispose(): undefined; + @@toStringTag: 'DisposableStack'; +} + +class SuppressedError extends Error { + constructor(error: any, suppressed: any, message?: string, { cause: any }?): SuppressedError; + error: any; + suppressed: any; + message: string; + cause: any; +} + +class Iterator { + @@dispose(): undefined; +} +``` +[*CommonJS entry points:*](#commonjs-api) +```js +core-js/proposals/explicit-resource-management +core-js(-pure)/full/symbol/dispose +core-js(-pure)/full/disposable-stack +core-js(-pure)/full/suppressed-error +core-js(-pure)/full/iterator/dispose +``` ##### [Well-formed unicode strings](https://github.com/tc39/proposal-is-usv-string)[⬆](#index) Modules [`esnext.string.is-well-formed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.string.is-well-formed.js) and [`esnext.string.to-well-formed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.string.to-well-formed.js) ```js @@ -2383,14 +2423,13 @@ core-js(-pure)/full/array/is-template-object ```js console.log(Array.isTemplateObject((it => it)`qwe${ 123 }asd`)); // => true ``` -##### [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management)[⬆](#index) +##### [Async Explicit Resource Management](https://github.com/tc39/proposal-async-explicit-resource-management)[⬆](#index) Note: **This is only built-ins for this proposal, `using` syntax support requires transpiler support.** -Modules [`esnext.symbol.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.dispose.js), [`esnext.symbol.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.async-dispose.js), [`esnext.async-disposable-stack.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.async-disposable-stack.constructor.js), [`esnext.disposable-stack.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.disposable-stack.constructor.js), [`esnext.suppressed-error.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.suppressed-error.constructor.js), [`esnext.iterator.dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.iterator.dispose.js), [`esnext.async-iterator.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.async-iterator.async-dispose.js). +Modules [`esnext.symbol.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.async-dispose.js), [`esnext.async-disposable-stack.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.async-disposable-stack.constructor.js), [`esnext.async-iterator.async-dispose`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.async-iterator.async-dispose.js). ```js class Symbol { static asyncDispose: @@asyncDispose; - static dispose: @@dispose; } class AsyncDisposableStack { @@ -2403,42 +2442,16 @@ class AsyncDisposableStack { @@toStringTag: 'AsyncDisposableStack'; } -class DisposableStack { - constructor(): DisposableStack; - dispose(): undefined; - use(value: Disposable): value; - adopt(value: object, onDispose: Function): value; - defer(onDispose: Function): undefined; - @@dispose(): undefined; - @@toStringTag: 'DisposableStack'; -} - -class SuppressedError extends Error { - constructor(error: any, suppressed: any, message?: string, { cause: any }?): SuppressedError; - error: any; - suppressed: any; - message: string; - cause: any; -} - class AsyncIterator { @@asyncDispose(): Promise; } - -class Iterator { - @@dispose(): undefined; -} ``` [*CommonJS entry points:*](#commonjs-api) ```js -core-js/proposals/explicit-resource-management +core-js/proposals/async-explicit-resource-management core-js(-pure)/full/symbol/async-dispose -core-js(-pure)/full/symbol/dispose core-js(-pure)/full/async-disposable-stack -core-js(-pure)/full/disposable-stack -core-js(-pure)/full/suppressed-error core-js(-pure)/full/async-iterator/async-dispose -core-js(-pure)/full/iterator/dispose ``` ##### [`Symbol.metadataKey` for decorators metadata proposal](https://github.com/tc39/proposal-decorator-metadata)[⬆](#index) Module [`esnext.symbol.metadata-key`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.metadata-key.js). diff --git a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js index dad6caad96b2..5d985fbe74e4 100644 --- a/packages/core-js/modules/esnext.async-disposable-stack.constructor.js +++ b/packages/core-js/modules/esnext.async-disposable-stack.constructor.js @@ -1,5 +1,5 @@ 'use strict'; -// https://github.com/tc39/proposal-observable +// https://github.com/tc39/proposal-async-explicit-resource-management var $ = require('../internals/export'); var DESCRIPTORS = require('../internals/descriptors'); var getBuiltIn = require('../internals/get-built-in'); diff --git a/packages/core-js/modules/esnext.async-iterator.async-dispose.js b/packages/core-js/modules/esnext.async-iterator.async-dispose.js index 43416996e2cb..d6c1cd1cb02e 100644 --- a/packages/core-js/modules/esnext.async-iterator.async-dispose.js +++ b/packages/core-js/modules/esnext.async-iterator.async-dispose.js @@ -1,5 +1,5 @@ 'use strict'; -// https://github.com/tc39/proposal-explicit-resource-management +// https://github.com/tc39/proposal-async-explicit-resource-management var call = require('../internals/function-call'); var defineBuiltIn = require('../internals/define-built-in'); var getBuiltIn = require('../internals/get-built-in'); diff --git a/packages/core-js/modules/esnext.disposable-stack.constructor.js b/packages/core-js/modules/esnext.disposable-stack.constructor.js index 4ee38d35df83..e8d2ea6a8c1c 100644 --- a/packages/core-js/modules/esnext.disposable-stack.constructor.js +++ b/packages/core-js/modules/esnext.disposable-stack.constructor.js @@ -1,5 +1,5 @@ 'use strict'; -// https://github.com/tc39/proposal-observable +// https://github.com/tc39/proposal-explicit-resource-management var $ = require('../internals/export'); var DESCRIPTORS = require('../internals/descriptors'); var getBuiltIn = require('../internals/get-built-in'); diff --git a/packages/core-js/modules/esnext.symbol.async-dispose.js b/packages/core-js/modules/esnext.symbol.async-dispose.js index 5c092ceb22be..d108d76319f4 100644 --- a/packages/core-js/modules/esnext.symbol.async-dispose.js +++ b/packages/core-js/modules/esnext.symbol.async-dispose.js @@ -1,5 +1,5 @@ var defineWellKnownSymbol = require('../internals/well-known-symbol-define'); // `Symbol.asyncDispose` well-known symbol -// https://github.com/tc39/proposal-explicit-resource-management +// https://github.com/tc39/proposal-async-explicit-resource-management defineWellKnownSymbol('asyncDispose'); diff --git a/packages/core-js/proposals/async-explicit-resource-management.js b/packages/core-js/proposals/async-explicit-resource-management.js new file mode 100644 index 000000000000..3dd08cc7e7ff --- /dev/null +++ b/packages/core-js/proposals/async-explicit-resource-management.js @@ -0,0 +1,5 @@ +// https://github.com/tc39/proposal-async-explicit-resource-management +require('../modules/esnext.suppressed-error.constructor'); +require('../modules/esnext.async-disposable-stack.constructor'); +require('../modules/esnext.async-iterator.async-dispose'); +require('../modules/esnext.symbol.async-dispose'); diff --git a/packages/core-js/proposals/explicit-resource-management.js b/packages/core-js/proposals/explicit-resource-management.js index 9b6d130af48e..ade8ecdd91a6 100644 --- a/packages/core-js/proposals/explicit-resource-management.js +++ b/packages/core-js/proposals/explicit-resource-management.js @@ -1,8 +1,5 @@ // https://github.com/tc39/proposal-explicit-resource-management require('../modules/esnext.suppressed-error.constructor'); -require('../modules/esnext.async-disposable-stack.constructor'); -require('../modules/esnext.async-iterator.async-dispose'); require('../modules/esnext.disposable-stack.constructor'); require('../modules/esnext.iterator.dispose'); -require('../modules/esnext.symbol.async-dispose'); require('../modules/esnext.symbol.dispose'); diff --git a/packages/core-js/proposals/using-statement.js b/packages/core-js/proposals/using-statement.js index bb8113087383..b236f1768213 100644 --- a/packages/core-js/proposals/using-statement.js +++ b/packages/core-js/proposals/using-statement.js @@ -1,3 +1,4 @@ // TODO: Renamed, remove from `core-js@4` // https://github.com/tc39/proposal-explicit-resource-management -require('./explicit-resource-management'); +require('../modules/esnext.symbol.async-dispose'); +require('../modules/esnext.symbol.dispose'); diff --git a/packages/core-js/stage/2.js b/packages/core-js/stage/2.js index 0c52a10f4fdc..2919b2f14887 100644 --- a/packages/core-js/stage/2.js +++ b/packages/core-js/stage/2.js @@ -1,8 +1,8 @@ var parent = require('./3'); require('../proposals/array-is-template-object'); +require('../proposals/async-explicit-resource-management'); require('../proposals/decorator-metadata'); -require('../proposals/explicit-resource-management'); require('../proposals/map-upsert-stage-2'); // TODO: Obsolete versions, remove from `core-js@4` require('../proposals/array-grouping'); diff --git a/packages/core-js/stage/3.js b/packages/core-js/stage/3.js index be4945b4e737..bd00ae57c478 100644 --- a/packages/core-js/stage/3.js +++ b/packages/core-js/stage/3.js @@ -3,6 +3,7 @@ var parent = require('./4'); require('../proposals/array-from-async-stage-2'); require('../proposals/array-grouping-stage-3-2'); require('../proposals/change-array-by-copy'); +require('../proposals/explicit-resource-management'); require('../proposals/iterator-helpers-stage-3'); require('../proposals/set-methods-v2'); require('../proposals/well-formed-unicode-strings'); diff --git a/tests/entries/unit.mjs b/tests/entries/unit.mjs index d4fc0fe225b3..bcb851501a40 100644 --- a/tests/entries/unit.mjs +++ b/tests/entries/unit.mjs @@ -873,6 +873,7 @@ for (PATH of ['core-js-pure', 'core-js']) { load('proposals/array-is-template-object'); load('proposals/array-last'); load('proposals/array-unique'); + load('proposals/async-explicit-resource-management'); load('proposals/async-iteration'); load('proposals/change-array-by-copy'); load('proposals/collection-methods'); From c0d4f4181c523dd44e18b38f159a554c4dd9deb4 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Fri, 2 Dec 2022 12:27:49 +0700 Subject: [PATCH 15/18] add `/actual/` entries, disable forced replacing for stage 3 features --- .../core-js/actual/disposable-stack/constructor.js | 7 +++++++ packages/core-js/actual/disposable-stack/index.js | 7 +++++++ packages/core-js/actual/iterator/dispose.js | 1 + packages/core-js/actual/iterator/index.js | 1 + packages/core-js/actual/suppressed-error.js | 5 +++++ packages/core-js/actual/symbol/dispose.js | 4 ++++ packages/core-js/actual/symbol/index.js | 2 ++ packages/core-js/full/async-iterator/indexed.js | 1 + packages/core-js/full/disposable-stack/constructor.js | 8 ++------ packages/core-js/full/disposable-stack/index.js | 8 ++------ packages/core-js/full/iterator/dispose.js | 4 +++- packages/core-js/full/iterator/index.js | 1 - packages/core-js/full/iterator/indexed.js | 1 + packages/core-js/full/suppressed-error.js | 6 ++---- packages/core-js/full/symbol/dispose.js | 5 ++--- packages/core-js/full/symbol/index.js | 1 - .../modules/esnext.disposable-stack.constructor.js | 2 +- tests/entries/unit.mjs | 10 +++++----- 18 files changed, 46 insertions(+), 28 deletions(-) create mode 100644 packages/core-js/actual/disposable-stack/constructor.js create mode 100644 packages/core-js/actual/disposable-stack/index.js create mode 100644 packages/core-js/actual/iterator/dispose.js create mode 100644 packages/core-js/actual/suppressed-error.js create mode 100644 packages/core-js/actual/symbol/dispose.js diff --git a/packages/core-js/actual/disposable-stack/constructor.js b/packages/core-js/actual/disposable-stack/constructor.js new file mode 100644 index 000000000000..90c1292cd8d4 --- /dev/null +++ b/packages/core-js/actual/disposable-stack/constructor.js @@ -0,0 +1,7 @@ +require('../../modules/es.error.cause'); +require('../../modules/es.object.to-string'); +require('../../modules/esnext.suppressed-error.constructor'); +require('../../modules/esnext.disposable-stack.constructor'); +var path = require('../../internals/path'); + +module.exports = path.DisposableStack; diff --git a/packages/core-js/actual/disposable-stack/index.js b/packages/core-js/actual/disposable-stack/index.js new file mode 100644 index 000000000000..90c1292cd8d4 --- /dev/null +++ b/packages/core-js/actual/disposable-stack/index.js @@ -0,0 +1,7 @@ +require('../../modules/es.error.cause'); +require('../../modules/es.object.to-string'); +require('../../modules/esnext.suppressed-error.constructor'); +require('../../modules/esnext.disposable-stack.constructor'); +var path = require('../../internals/path'); + +module.exports = path.DisposableStack; diff --git a/packages/core-js/actual/iterator/dispose.js b/packages/core-js/actual/iterator/dispose.js new file mode 100644 index 000000000000..bf3b517d9677 --- /dev/null +++ b/packages/core-js/actual/iterator/dispose.js @@ -0,0 +1 @@ +require('../../modules/esnext.iterator.dispose'); diff --git a/packages/core-js/actual/iterator/index.js b/packages/core-js/actual/iterator/index.js index 0c3281124d17..fa70861c22cc 100644 --- a/packages/core-js/actual/iterator/index.js +++ b/packages/core-js/actual/iterator/index.js @@ -3,6 +3,7 @@ require('../../modules/es.object.to-string'); require('../../modules/es.promise'); require('../../modules/es.string.iterator'); require('../../modules/esnext.iterator.constructor'); +require('../../modules/esnext.iterator.dispose'); require('../../modules/esnext.iterator.drop'); require('../../modules/esnext.iterator.every'); require('../../modules/esnext.iterator.filter'); diff --git a/packages/core-js/actual/suppressed-error.js b/packages/core-js/actual/suppressed-error.js new file mode 100644 index 000000000000..0f41bdef653f --- /dev/null +++ b/packages/core-js/actual/suppressed-error.js @@ -0,0 +1,5 @@ +require('../modules/es.error.cause'); +require('../modules/esnext.suppressed-error.constructor'); +var path = require('../internals/path'); + +module.exports = path.SuppressedError; diff --git a/packages/core-js/actual/symbol/dispose.js b/packages/core-js/actual/symbol/dispose.js new file mode 100644 index 000000000000..71a4d5044347 --- /dev/null +++ b/packages/core-js/actual/symbol/dispose.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.symbol.dispose'); +var WrappedWellKnownSymbolModule = require('../../internals/well-known-symbol-wrapped'); + +module.exports = WrappedWellKnownSymbolModule.f('dispose'); diff --git a/packages/core-js/actual/symbol/index.js b/packages/core-js/actual/symbol/index.js index 5eeb6fbc6a61..92842b61a8ef 100644 --- a/packages/core-js/actual/symbol/index.js +++ b/packages/core-js/actual/symbol/index.js @@ -1,3 +1,5 @@ var parent = require('../../stable/symbol'); +require('../../modules/esnext.symbol.dispose'); + module.exports = parent; diff --git a/packages/core-js/full/async-iterator/indexed.js b/packages/core-js/full/async-iterator/indexed.js index 2686c40d504a..1fec52caba8a 100644 --- a/packages/core-js/full/async-iterator/indexed.js +++ b/packages/core-js/full/async-iterator/indexed.js @@ -1,3 +1,4 @@ +// TODO: Remove from `core-js@4` require('../../modules/es.object.to-string'); require('../../modules/es.promise'); require('../../modules/esnext.async-iterator.constructor'); diff --git a/packages/core-js/full/disposable-stack/constructor.js b/packages/core-js/full/disposable-stack/constructor.js index 90c1292cd8d4..7ec52460bbb2 100644 --- a/packages/core-js/full/disposable-stack/constructor.js +++ b/packages/core-js/full/disposable-stack/constructor.js @@ -1,7 +1,3 @@ -require('../../modules/es.error.cause'); -require('../../modules/es.object.to-string'); -require('../../modules/esnext.suppressed-error.constructor'); -require('../../modules/esnext.disposable-stack.constructor'); -var path = require('../../internals/path'); +var parent = require('../../actual/disposable-stack/constructor'); -module.exports = path.DisposableStack; +module.exports = parent; diff --git a/packages/core-js/full/disposable-stack/index.js b/packages/core-js/full/disposable-stack/index.js index 90c1292cd8d4..7ada28b9e474 100644 --- a/packages/core-js/full/disposable-stack/index.js +++ b/packages/core-js/full/disposable-stack/index.js @@ -1,7 +1,3 @@ -require('../../modules/es.error.cause'); -require('../../modules/es.object.to-string'); -require('../../modules/esnext.suppressed-error.constructor'); -require('../../modules/esnext.disposable-stack.constructor'); -var path = require('../../internals/path'); +var parent = require('../../actual/disposable-stack'); -module.exports = path.DisposableStack; +module.exports = parent; diff --git a/packages/core-js/full/iterator/dispose.js b/packages/core-js/full/iterator/dispose.js index bf3b517d9677..46438105e607 100644 --- a/packages/core-js/full/iterator/dispose.js +++ b/packages/core-js/full/iterator/dispose.js @@ -1 +1,3 @@ -require('../../modules/esnext.iterator.dispose'); +var parent = require('../../actual/iterator/dispose'); + +module.exports = parent; diff --git a/packages/core-js/full/iterator/index.js b/packages/core-js/full/iterator/index.js index 01c40ce00509..9a0ebc60e5b8 100644 --- a/packages/core-js/full/iterator/index.js +++ b/packages/core-js/full/iterator/index.js @@ -1,5 +1,4 @@ var parent = require('../../actual/iterator'); -require('../../modules/esnext.iterator.dispose'); // TODO: Remove from `core-js@4` require('../../modules/esnext.iterator.as-indexed-pairs'); require('../../modules/esnext.iterator.indexed'); diff --git a/packages/core-js/full/iterator/indexed.js b/packages/core-js/full/iterator/indexed.js index 133712fff554..4d7df998ca10 100644 --- a/packages/core-js/full/iterator/indexed.js +++ b/packages/core-js/full/iterator/indexed.js @@ -1,3 +1,4 @@ +// TODO: Remove from `core-js@4` require('../../modules/es.object.to-string'); require('../../modules/esnext.iterator.constructor'); require('../../modules/esnext.iterator.indexed'); diff --git a/packages/core-js/full/suppressed-error.js b/packages/core-js/full/suppressed-error.js index 0f41bdef653f..da67d8242fec 100644 --- a/packages/core-js/full/suppressed-error.js +++ b/packages/core-js/full/suppressed-error.js @@ -1,5 +1,3 @@ -require('../modules/es.error.cause'); -require('../modules/esnext.suppressed-error.constructor'); -var path = require('../internals/path'); +var parent = require('../actual/suppressed-error'); -module.exports = path.SuppressedError; +module.exports = parent; diff --git a/packages/core-js/full/symbol/dispose.js b/packages/core-js/full/symbol/dispose.js index 71a4d5044347..188e06930300 100644 --- a/packages/core-js/full/symbol/dispose.js +++ b/packages/core-js/full/symbol/dispose.js @@ -1,4 +1,3 @@ -require('../../modules/esnext.symbol.dispose'); -var WrappedWellKnownSymbolModule = require('../../internals/well-known-symbol-wrapped'); +var parent = require('../../actual/symbol/dispose'); -module.exports = WrappedWellKnownSymbolModule.f('dispose'); +module.exports = parent; diff --git a/packages/core-js/full/symbol/index.js b/packages/core-js/full/symbol/index.js index 5dbbfb6a480a..19cf18008474 100644 --- a/packages/core-js/full/symbol/index.js +++ b/packages/core-js/full/symbol/index.js @@ -1,6 +1,5 @@ var parent = require('../../actual/symbol'); require('../../modules/esnext.symbol.async-dispose'); -require('../../modules/esnext.symbol.dispose'); require('../../modules/esnext.symbol.matcher'); require('../../modules/esnext.symbol.metadata-key'); require('../../modules/esnext.symbol.observable'); diff --git a/packages/core-js/modules/esnext.disposable-stack.constructor.js b/packages/core-js/modules/esnext.disposable-stack.constructor.js index e8d2ea6a8c1c..0c6eb7dda4b1 100644 --- a/packages/core-js/modules/esnext.disposable-stack.constructor.js +++ b/packages/core-js/modules/esnext.disposable-stack.constructor.js @@ -115,6 +115,6 @@ if (DESCRIPTORS) defineBuiltInAccessor(DisposableStackPrototype, 'disposed', { defineBuiltIn(DisposableStackPrototype, DISPOSE, DisposableStackPrototype.dispose, { name: 'dispose' }); defineBuiltIn(DisposableStackPrototype, TO_STRING_TAG, DISPOSABLE_STACK, { nonWritable: true }); -$({ global: true, constructor: true, forced: true }, { +$({ global: true, constructor: true }, { DisposableStack: $DisposableStack }); diff --git a/tests/entries/unit.mjs b/tests/entries/unit.mjs index bcb851501a40..019bee4719aa 100644 --- a/tests/entries/unit.mjs +++ b/tests/entries/unit.mjs @@ -652,6 +652,11 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(load(NS, 'string/virtual/is-well-formed').call('a')); ok(load(NS, 'string/to-well-formed')('a') === 'a'); ok(load(NS, 'string/virtual/to-well-formed').call('a') === 'a'); + ok(load(NS, 'symbol/dispose')); + ok(new (load(NS, 'suppressed-error'))(1, 2).suppressed === 2); + ok(typeof load(NS, 'disposable-stack') == 'function'); + ok(typeof load(NS, 'disposable-stack/constructor') == 'function'); + load(NS, 'iterator/dispose'); const instanceGroup = load(NS, 'instance/group'); ok(typeof instanceGroup == 'function'); @@ -819,14 +824,9 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(load(NS, 'weak-set/from')([{}, []]) instanceof WeakSet); ok(load(NS, 'weak-set/of')({}, []) instanceof WeakSet); ok(load(NS, 'symbol/async-dispose')); - ok(load(NS, 'symbol/dispose')); - ok(new (load(NS, 'suppressed-error'))(1, 2).suppressed === 2); load(NS, 'async-iterator/async-dispose'); - load(NS, 'iterator/dispose'); ok(typeof load(NS, 'async-disposable-stack') == 'function'); ok(typeof load(NS, 'async-disposable-stack/constructor') == 'function'); - ok(typeof load(NS, 'disposable-stack') == 'function'); - ok(typeof load(NS, 'disposable-stack/constructor') == 'function'); const instanceCodePoints = load(NS, 'instance/code-points'); ok(typeof instanceCodePoints == 'function'); From 3395221920b8967b1606589316cf5aa0955613b2 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Fri, 2 Dec 2022 12:28:03 +0700 Subject: [PATCH 16/18] update the changelog --- CHANGELOG.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c58bdf4e036..e873f932d2eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,12 @@ - `AsyncDisposableStack.prototype.defer` - `AsyncDisposableStack.prototype.move` - `AsyncDisposableStack.prototype[@@asyncDispose]` +- [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management) stage 3 and [Async explicit resource management](https://github.com/tc39/proposal-async-explicit-resource-management) stage 2 proposals: + - Renamed from "`using` statement" and [splitted into 2 (sync and async) proposals](https://github.com/tc39/proposal-explicit-resource-management/pull/131) + - In addition to already present well-known symbols, added new built-ins: + - `Symbol.dispose` + - `Symbol.asyncDispose` + - `SuppressedError` - `DisposableStack` - `DisposableStack.prototype.dispose` - `DisposableStack.prototype.use` @@ -76,9 +82,17 @@ - `DisposableStack.prototype.defer` - `DisposableStack.prototype.move` - `DisposableStack.prototype[@@dispose]` - - `SuppressedError` + - `AsyncDisposableStack` + - `AsyncDisposableStack.prototype.disposeAsync` + - `AsyncDisposableStack.prototype.use` + - `AsyncDisposableStack.prototype.adopt` + - `AsyncDisposableStack.prototype.defer` + - `AsyncDisposableStack.prototype.move` + - `AsyncDisposableStack.prototype[@@asyncDispose]` - `Iterator.prototype[@@dispose]` - `AsyncIterator.prototype[@@asyncDispose]` + - Sync version of this proposal moved to Stage 3, [November 2022 TC39 meeting](https://github.com/babel/proposals/issues/85#issuecomment-1333747094) + - Added `/actual/` namespace entries for stage 3 proposal - [Compat data targets](/packages/core-js-compat#targets-option) improvements: - [React Native from 0.70 shipped with Hermes as the default engine.](https://reactnative.dev/blog/2022/07/08/hermes-as-the-default) However, bundled Hermes versions differ from standalone Hermes releases. So added **`react-native`** target for React Native with bundled Hermes. - [According to the documentation](https://developer.oculus.com/documentation/web/browser-intro/), Oculus Browser was renamed to Meta Quest Browser, so `oculus` target was renamed to **`quest`**. From 1f8adf57f37c5367c0686f186dcab468d153e426 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Mon, 5 Dec 2022 02:06:57 +0700 Subject: [PATCH 17/18] test minimal available namespaces --- tests/unit-pure/esnext.disposable-stack.constructor.js | 6 +++--- tests/unit-pure/esnext.iterator.dispose.js | 2 +- tests/unit-pure/esnext.suppressed-error.constructor.js | 2 +- tests/unit-pure/esnext.symbol.dispose.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unit-pure/esnext.disposable-stack.constructor.js b/tests/unit-pure/esnext.disposable-stack.constructor.js index 8b28f01bd515..c9f215b33850 100644 --- a/tests/unit-pure/esnext.disposable-stack.constructor.js +++ b/tests/unit-pure/esnext.disposable-stack.constructor.js @@ -1,8 +1,8 @@ import { STRICT } from '../helpers/constants'; -import Symbol from 'core-js-pure/full/symbol'; -import DisposableStack from 'core-js-pure/full/disposable-stack'; -import SuppressedError from 'core-js-pure/full/suppressed-error'; +import Symbol from 'core-js-pure/actual/symbol'; +import DisposableStack from 'core-js-pure/actual/disposable-stack'; +import SuppressedError from 'core-js-pure/actual/suppressed-error'; QUnit.test('DisposableStack constructor', assert => { assert.isFunction(DisposableStack); diff --git a/tests/unit-pure/esnext.iterator.dispose.js b/tests/unit-pure/esnext.iterator.dispose.js index 71914573166c..9f224fdeb0b6 100644 --- a/tests/unit-pure/esnext.iterator.dispose.js +++ b/tests/unit-pure/esnext.iterator.dispose.js @@ -1,5 +1,5 @@ import Iterator from 'core-js-pure/full/iterator'; -import Symbol from 'core-js-pure/full/symbol'; +import Symbol from 'core-js-pure/actual/symbol'; import create from 'core-js-pure/es/object/create'; QUnit.test('Iterator#@@dispose', assert => { diff --git a/tests/unit-pure/esnext.suppressed-error.constructor.js b/tests/unit-pure/esnext.suppressed-error.constructor.js index 8a94375aa98a..8f03d519e509 100644 --- a/tests/unit-pure/esnext.suppressed-error.constructor.js +++ b/tests/unit-pure/esnext.suppressed-error.constructor.js @@ -1,4 +1,4 @@ -import SuppressedError from 'core-js-pure/full/suppressed-error'; +import SuppressedError from 'core-js-pure/actual/suppressed-error'; import Symbol from 'core-js-pure/es/symbol'; import toString from 'core-js-pure/es/object/to-string'; diff --git a/tests/unit-pure/esnext.symbol.dispose.js b/tests/unit-pure/esnext.symbol.dispose.js index 12cb13730c05..e9bb124b3ff9 100644 --- a/tests/unit-pure/esnext.symbol.dispose.js +++ b/tests/unit-pure/esnext.symbol.dispose.js @@ -1,4 +1,4 @@ -import Symbol from 'core-js-pure/full/symbol'; +import Symbol from 'core-js-pure/actual/symbol'; QUnit.test('Symbol.dispose', assert => { assert.true('dispose' in Symbol, 'Symbol.dispose available'); From 6b6b9c3e5ba025674e48fa4624d6c81bf4010260 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Sun, 11 Dec 2022 16:15:34 +0700 Subject: [PATCH 18/18] fix rebasing issue --- CHANGELOG.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e873f932d2eb..20beb4961305 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,17 +59,7 @@ - `String.prototype.toWellFormed` - Moved to Stage 3, [November 2022 TC39 meeting](https://github.com/babel/proposals/issues/85#issuecomment-1332180862) - Added `/actual/` entries, disabled unconditional forced replacement -- [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management) stage 2 proposal: - - Renamed from "`using` statement" - - In addition to already present well-known symbols `@@dispose` and `@@asyncDispose`, added new built-ins: - - `AsyncDisposableStack` - - `AsyncDisposableStack.prototype.disposeAsync` - - `AsyncDisposableStack.prototype.use` - - `AsyncDisposableStack.prototype.adopt` - - `AsyncDisposableStack.prototype.defer` - - `AsyncDisposableStack.prototype.move` - - `AsyncDisposableStack.prototype[@@asyncDispose]` -- [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management) stage 3 and [Async explicit resource management](https://github.com/tc39/proposal-async-explicit-resource-management) stage 2 proposals: +- [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management) Stage 3 and [Async explicit resource management](https://github.com/tc39/proposal-async-explicit-resource-management) Stage 2 proposals: - Renamed from "`using` statement" and [splitted into 2 (sync and async) proposals](https://github.com/tc39/proposal-explicit-resource-management/pull/131) - In addition to already present well-known symbols, added new built-ins: - `Symbol.dispose` @@ -92,7 +82,7 @@ - `Iterator.prototype[@@dispose]` - `AsyncIterator.prototype[@@asyncDispose]` - Sync version of this proposal moved to Stage 3, [November 2022 TC39 meeting](https://github.com/babel/proposals/issues/85#issuecomment-1333747094) - - Added `/actual/` namespace entries for stage 3 proposal + - Added `/actual/` namespace entries for Stage 3 proposal - [Compat data targets](/packages/core-js-compat#targets-option) improvements: - [React Native from 0.70 shipped with Hermes as the default engine.](https://reactnative.dev/blog/2022/07/08/hermes-as-the-default) However, bundled Hermes versions differ from standalone Hermes releases. So added **`react-native`** target for React Native with bundled Hermes. - [According to the documentation](https://developer.oculus.com/documentation/web/browser-intro/), Oculus Browser was renamed to Meta Quest Browser, so `oculus` target was renamed to **`quest`**.