From ba475cfcf345c67fd1179a11116d6eafb51d4dc3 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Sun, 14 Jun 2020 20:20:00 +0200 Subject: [PATCH 1/3] =?UTF-8?q?[New]=C2=A0`ES2018+`:=20Add=C2=A0`CreateAsy?= =?UTF-8?q?ncFromSyncIterator`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 4 +- 2018/AsyncFromSyncIteratorContinuation.js | 37 +++++ 2018/CreateAsyncFromSyncIterator.js | 183 ++++++++++++++++++++++ 2019/AsyncFromSyncIteratorContinuation.js | 37 +++++ 2019/CreateAsyncFromSyncIterator.js | 183 ++++++++++++++++++++++ es2018.js | 2 + es2019.js | 2 + package.json | 1 + 8 files changed, 448 insertions(+), 1 deletion(-) create mode 100644 2018/AsyncFromSyncIteratorContinuation.js create mode 100644 2018/CreateAsyncFromSyncIterator.js create mode 100644 2019/AsyncFromSyncIteratorContinuation.js create mode 100644 2019/CreateAsyncFromSyncIterator.js diff --git a/.gitattributes b/.gitattributes index 0d00e318..0b8ada0c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -367,10 +367,12 @@ 2019/ArrayCreate.js spackled linguist-generated=true 2019/ArraySetLength.js spackled linguist-generated=true 2019/ArraySpeciesCreate.js spackled linguist-generated=true +2019/AsyncFromSyncIteratorContinuation.js spackled linguist-generated=true 2019/Call.js spackled linguist-generated=true 2019/CanonicalNumericIndexString.js spackled linguist-generated=true 2019/CompletePropertyDescriptor.js spackled linguist-generated=true 2019/CopyDataProperties.js spackled linguist-generated=true +2019/CreateAsyncFromSyncIterator.js spackled linguist-generated=true 2019/CreateDataProperty.js spackled linguist-generated=true 2019/CreateDataPropertyOrThrow.js spackled linguist-generated=true 2019/CreateHTML.js spackled linguist-generated=true @@ -482,4 +484,4 @@ 2019/thisBooleanValue.js spackled linguist-generated=true 2019/thisNumberValue.js spackled linguist-generated=true 2019/thisStringValue.js spackled linguist-generated=true -2019/thisSymbolValue.js spackled linguist-generated=true \ No newline at end of file +2019/thisSymbolValue.js spackled linguist-generated=true diff --git a/2018/AsyncFromSyncIteratorContinuation.js b/2018/AsyncFromSyncIteratorContinuation.js new file mode 100644 index 00000000..3b96c064 --- /dev/null +++ b/2018/AsyncFromSyncIteratorContinuation.js @@ -0,0 +1,37 @@ +'use strict'; + +var GetIntrinsic = require('../GetIntrinsic.js'); +var callBound = require('../helpers/callBound.js'); + +var Call = require('./Call.js'); +var CreateIterResultObject = require('./CreateIterResultObject.js'); +var IteratorComplete = require('./IteratorComplete.js'); +var IteratorValue = require('./IteratorValue.js'); + +var PromiseResolve = require('./PromiseResolve.js'); + +var $Promise = GetIntrinsic('%Promise%', true); +var PerformPromiseThen = callBound('%Promise.prototype.then%', true); + +// https://www.ecma-international.org/ecma-262/9.0/#sec-asyncfromsynciteratorcontinuation + +module.exports = function AsyncFromSyncIteratorContinuation(result, promiseCapability) { + try { + var done = IteratorComplete(result); + var value = IteratorValue(result); + var valueWrapper = PromiseResolve($Promise, value); + + PerformPromiseThen( + valueWrapper, + function onFulfilled(unwrappedValue) { + Call(promiseCapability['[[Resolve]]'], undefined, [ + CreateIterResultObject(unwrappedValue, done) + ]); + }, + promiseCapability['[[Reject]]'] + ); + } catch (error) { + Call(promiseCapability['[[Reject]]'], undefined, [error]); + } + return promiseCapability['[[Promise]]']; +}; diff --git a/2018/CreateAsyncFromSyncIterator.js b/2018/CreateAsyncFromSyncIterator.js new file mode 100644 index 00000000..33d34881 --- /dev/null +++ b/2018/CreateAsyncFromSyncIterator.js @@ -0,0 +1,183 @@ +'use strict'; + +var internalSlot = require('internal-slot'); +var GetIntrinsic = require('../GetIntrinsic.js'); + +var AsyncFromSyncIteratorContinuation = require('./AsyncFromSyncIteratorContinuation.js'); +var Call = require('./Call.js'); +var CreateIterResultObject = require('./CreateIterResultObject.js'); +var CreateMethodProperty = require('./CreateMethodProperty.js'); +var DefinePropertyOrThrow = require('./DefinePropertyOrThrow.js'); +var Get = require('./Get.js'); +var GetMethod = require('./GetMethod.js'); +var IteratorNext = require('./IteratorNext.js'); +var OrdinaryObjectCreate = require('./ObjectCreate.js'); +var Type = require('./Type.js'); + +var $asyncIterator = GetIntrinsic('%Symbol.asyncIterator%', true); +var $toStringTag = GetIntrinsic('%Symbol.toStringTag%', true); +var $TypeError = GetIntrinsic('%TypeError%'); + +// TODO: Use %AsyncIterator.from% once it's in ECMA-262 + +var AsyncIteratorPrototype + = GetIntrinsic('%AsyncIteratorPrototype%', true) + || (function () { + var result = {}; + if ($toStringTag) { + DefinePropertyOrThrow(result, $toStringTag, { + '[[Writable]]': false, + '[[Enumerable]]': false, + '[[Configurable]]': true, + '[[Value]]': 'AsyncIterator' + }); + } + if ($asyncIterator) { + var method = { + '[Symbol.asyncIterator]': function () { + return this; + } + }['[Symbol.asyncIterator]']; + CreateMethodProperty(result, $asyncIterator, method); + } + return result; + }()); + +var AsyncFromSyncIteratorPrototype + = GetIntrinsic('%AsyncFromSyncIteratorPrototype%', true) + // eslint-disable-next-line max-lines-per-function + || (function () { + var $Promise = GetIntrinsic('%Promise%', true); + if (!$Promise) { + return; + } + + // eslint-disable-next-line no-shadow + var AsyncFromSyncIteratorPrototype = OrdinaryObjectCreate(AsyncIteratorPrototype); + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'next', function next(value) { + // eslint-disable-next-line no-invalid-this + var O = this; + var promiseCapability = {}; + promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { + promiseCapability['[[Resolve]]'] = resolve; + promiseCapability['[[Reject]]'] = reject; + }); + + if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('%AsyncFromSyncIteratorPrototype%.next called on invalid receiver') + ]); + return promiseCapability['[[Promise]]']; + } + + var result; + try { + var syncIteratorRecord = internalSlot.get(O, '[[SyncIteratorRecord]]'); + result = IteratorNext(syncIteratorRecord, value); + } catch (error) { + Call(promiseCapability['[[Reject]]'], undefined, [error]); + return promiseCapability['[[Promise]]']; + } + return AsyncFromSyncIteratorContinuation(result, promiseCapability); + }); + + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'return', function (value) { + // eslint-disable-next-line no-invalid-this + var O = this; + var promiseCapability = {}; + promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { + promiseCapability['[[Resolve]]'] = resolve; + promiseCapability['[[Reject]]'] = reject; + }); + + if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('%AsyncFromSyncIteratorPrototype%.return called on invalid receiver') + ]); + return promiseCapability['[[Promise]]']; + } + + var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[SyncIterator]]']; + var result; + try { + var returnMethod = GetMethod(syncIterator, 'return'); + if (returnMethod === undefined) { + var iterResult = CreateIterResultObject(value, true); + Call(promiseCapability['[[Resolve]]'], undefined, [iterResult]); + return promiseCapability['[[Promise]]']; + } + + result = Call(returnMethod, syncIterator, [value]); + if (Type(result) !== 'Object') { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('iterator return must return an object') + ]); + return promiseCapability['[[Promise]]']; + } + } catch (error) { + Call(promiseCapability['[[Reject]]'], undefined, [error]); + return promiseCapability['[[Promise]]']; + } + return AsyncFromSyncIteratorContinuation(result, promiseCapability); + }); + + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'throw', function (value) { + // eslint-disable-next-line no-invalid-this + var O = this; + var promiseCapability = {}; + promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { + promiseCapability['[[Resolve]]'] = resolve; + promiseCapability['[[Reject]]'] = reject; + }); + + if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('%AsyncFromSyncIteratorPrototype%.return called on invalid receiver') + ]); + return promiseCapability['[[Promise]]']; + } + + var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[SyncIterator]]']; + var result; + try { + var throwMethod = GetMethod(syncIterator, 'throw'); + if (throwMethod === undefined) { + var iterResult = CreateIterResultObject(value, true); + Call(promiseCapability['[[Reject]]'], undefined, [iterResult]); + return promiseCapability['[[Promise]]']; + } + + result = Call(throwMethod, syncIterator, [value]); + if (Type(result) !== 'Object') { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('iterator throw must return an object') + ]); + return promiseCapability['[[Promise]]']; + } + } catch (error) { + Call(promiseCapability['[[Reject]]'], undefined, [error]); + return promiseCapability['[[Promise]]']; + } + return AsyncFromSyncIteratorContinuation(result, promiseCapability); + }); + + // eslint-disable-next-line consistent-return + return AsyncFromSyncIteratorPrototype; + }()); + +// https://www.ecma-international.org/ecma-262/9.0/#sec-createasyncfromsynciterator + +module.exports = function CreateAsyncFromSyncIterator(syncIteratorRecord) { + if (!AsyncFromSyncIteratorPrototype) { + throw new SyntaxError('This environment does not support Promises.'); + } + + var asyncIterator = OrdinaryObjectCreate(AsyncFromSyncIteratorPrototype); + internalSlot.set(asyncIterator, '[[SyncIteratorRecord]]', syncIteratorRecord); + var nextMethod = Get(asyncIterator, 'next'); + return { + '[[Iterator]]': asyncIterator, + '[[NextMethod]]': nextMethod, + '[[Done]]': false + }; +}; diff --git a/2019/AsyncFromSyncIteratorContinuation.js b/2019/AsyncFromSyncIteratorContinuation.js new file mode 100644 index 00000000..3b96c064 --- /dev/null +++ b/2019/AsyncFromSyncIteratorContinuation.js @@ -0,0 +1,37 @@ +'use strict'; + +var GetIntrinsic = require('../GetIntrinsic.js'); +var callBound = require('../helpers/callBound.js'); + +var Call = require('./Call.js'); +var CreateIterResultObject = require('./CreateIterResultObject.js'); +var IteratorComplete = require('./IteratorComplete.js'); +var IteratorValue = require('./IteratorValue.js'); + +var PromiseResolve = require('./PromiseResolve.js'); + +var $Promise = GetIntrinsic('%Promise%', true); +var PerformPromiseThen = callBound('%Promise.prototype.then%', true); + +// https://www.ecma-international.org/ecma-262/9.0/#sec-asyncfromsynciteratorcontinuation + +module.exports = function AsyncFromSyncIteratorContinuation(result, promiseCapability) { + try { + var done = IteratorComplete(result); + var value = IteratorValue(result); + var valueWrapper = PromiseResolve($Promise, value); + + PerformPromiseThen( + valueWrapper, + function onFulfilled(unwrappedValue) { + Call(promiseCapability['[[Resolve]]'], undefined, [ + CreateIterResultObject(unwrappedValue, done) + ]); + }, + promiseCapability['[[Reject]]'] + ); + } catch (error) { + Call(promiseCapability['[[Reject]]'], undefined, [error]); + } + return promiseCapability['[[Promise]]']; +}; diff --git a/2019/CreateAsyncFromSyncIterator.js b/2019/CreateAsyncFromSyncIterator.js new file mode 100644 index 00000000..33d34881 --- /dev/null +++ b/2019/CreateAsyncFromSyncIterator.js @@ -0,0 +1,183 @@ +'use strict'; + +var internalSlot = require('internal-slot'); +var GetIntrinsic = require('../GetIntrinsic.js'); + +var AsyncFromSyncIteratorContinuation = require('./AsyncFromSyncIteratorContinuation.js'); +var Call = require('./Call.js'); +var CreateIterResultObject = require('./CreateIterResultObject.js'); +var CreateMethodProperty = require('./CreateMethodProperty.js'); +var DefinePropertyOrThrow = require('./DefinePropertyOrThrow.js'); +var Get = require('./Get.js'); +var GetMethod = require('./GetMethod.js'); +var IteratorNext = require('./IteratorNext.js'); +var OrdinaryObjectCreate = require('./ObjectCreate.js'); +var Type = require('./Type.js'); + +var $asyncIterator = GetIntrinsic('%Symbol.asyncIterator%', true); +var $toStringTag = GetIntrinsic('%Symbol.toStringTag%', true); +var $TypeError = GetIntrinsic('%TypeError%'); + +// TODO: Use %AsyncIterator.from% once it's in ECMA-262 + +var AsyncIteratorPrototype + = GetIntrinsic('%AsyncIteratorPrototype%', true) + || (function () { + var result = {}; + if ($toStringTag) { + DefinePropertyOrThrow(result, $toStringTag, { + '[[Writable]]': false, + '[[Enumerable]]': false, + '[[Configurable]]': true, + '[[Value]]': 'AsyncIterator' + }); + } + if ($asyncIterator) { + var method = { + '[Symbol.asyncIterator]': function () { + return this; + } + }['[Symbol.asyncIterator]']; + CreateMethodProperty(result, $asyncIterator, method); + } + return result; + }()); + +var AsyncFromSyncIteratorPrototype + = GetIntrinsic('%AsyncFromSyncIteratorPrototype%', true) + // eslint-disable-next-line max-lines-per-function + || (function () { + var $Promise = GetIntrinsic('%Promise%', true); + if (!$Promise) { + return; + } + + // eslint-disable-next-line no-shadow + var AsyncFromSyncIteratorPrototype = OrdinaryObjectCreate(AsyncIteratorPrototype); + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'next', function next(value) { + // eslint-disable-next-line no-invalid-this + var O = this; + var promiseCapability = {}; + promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { + promiseCapability['[[Resolve]]'] = resolve; + promiseCapability['[[Reject]]'] = reject; + }); + + if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('%AsyncFromSyncIteratorPrototype%.next called on invalid receiver') + ]); + return promiseCapability['[[Promise]]']; + } + + var result; + try { + var syncIteratorRecord = internalSlot.get(O, '[[SyncIteratorRecord]]'); + result = IteratorNext(syncIteratorRecord, value); + } catch (error) { + Call(promiseCapability['[[Reject]]'], undefined, [error]); + return promiseCapability['[[Promise]]']; + } + return AsyncFromSyncIteratorContinuation(result, promiseCapability); + }); + + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'return', function (value) { + // eslint-disable-next-line no-invalid-this + var O = this; + var promiseCapability = {}; + promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { + promiseCapability['[[Resolve]]'] = resolve; + promiseCapability['[[Reject]]'] = reject; + }); + + if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('%AsyncFromSyncIteratorPrototype%.return called on invalid receiver') + ]); + return promiseCapability['[[Promise]]']; + } + + var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[SyncIterator]]']; + var result; + try { + var returnMethod = GetMethod(syncIterator, 'return'); + if (returnMethod === undefined) { + var iterResult = CreateIterResultObject(value, true); + Call(promiseCapability['[[Resolve]]'], undefined, [iterResult]); + return promiseCapability['[[Promise]]']; + } + + result = Call(returnMethod, syncIterator, [value]); + if (Type(result) !== 'Object') { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('iterator return must return an object') + ]); + return promiseCapability['[[Promise]]']; + } + } catch (error) { + Call(promiseCapability['[[Reject]]'], undefined, [error]); + return promiseCapability['[[Promise]]']; + } + return AsyncFromSyncIteratorContinuation(result, promiseCapability); + }); + + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'throw', function (value) { + // eslint-disable-next-line no-invalid-this + var O = this; + var promiseCapability = {}; + promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { + promiseCapability['[[Resolve]]'] = resolve; + promiseCapability['[[Reject]]'] = reject; + }); + + if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('%AsyncFromSyncIteratorPrototype%.return called on invalid receiver') + ]); + return promiseCapability['[[Promise]]']; + } + + var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[SyncIterator]]']; + var result; + try { + var throwMethod = GetMethod(syncIterator, 'throw'); + if (throwMethod === undefined) { + var iterResult = CreateIterResultObject(value, true); + Call(promiseCapability['[[Reject]]'], undefined, [iterResult]); + return promiseCapability['[[Promise]]']; + } + + result = Call(throwMethod, syncIterator, [value]); + if (Type(result) !== 'Object') { + Call(promiseCapability['[[Reject]]'], undefined, [ + new $TypeError('iterator throw must return an object') + ]); + return promiseCapability['[[Promise]]']; + } + } catch (error) { + Call(promiseCapability['[[Reject]]'], undefined, [error]); + return promiseCapability['[[Promise]]']; + } + return AsyncFromSyncIteratorContinuation(result, promiseCapability); + }); + + // eslint-disable-next-line consistent-return + return AsyncFromSyncIteratorPrototype; + }()); + +// https://www.ecma-international.org/ecma-262/9.0/#sec-createasyncfromsynciterator + +module.exports = function CreateAsyncFromSyncIterator(syncIteratorRecord) { + if (!AsyncFromSyncIteratorPrototype) { + throw new SyntaxError('This environment does not support Promises.'); + } + + var asyncIterator = OrdinaryObjectCreate(AsyncFromSyncIteratorPrototype); + internalSlot.set(asyncIterator, '[[SyncIteratorRecord]]', syncIteratorRecord); + var nextMethod = Get(asyncIterator, 'next'); + return { + '[[Iterator]]': asyncIterator, + '[[NextMethod]]': nextMethod, + '[[Done]]': false + }; +}; diff --git a/es2018.js b/es2018.js index 17f978d3..8e026d99 100644 --- a/es2018.js +++ b/es2018.js @@ -10,10 +10,12 @@ var ES2018 = { ArrayCreate: require('./2018/ArrayCreate'), ArraySetLength: require('./2018/ArraySetLength'), ArraySpeciesCreate: require('./2018/ArraySpeciesCreate'), + AsyncFromSyncIteratorContinuation: require('./2018/AsyncFromSyncIteratorContinuation'), Call: require('./2018/Call'), CanonicalNumericIndexString: require('./2018/CanonicalNumericIndexString'), CompletePropertyDescriptor: require('./2018/CompletePropertyDescriptor'), CopyDataProperties: require('./2018/CopyDataProperties'), + CreateAsyncFromSyncIterator: require('./2018/CreateAsyncFromSyncIterator'), CreateDataProperty: require('./2018/CreateDataProperty'), CreateDataPropertyOrThrow: require('./2018/CreateDataPropertyOrThrow'), CreateHTML: require('./2018/CreateHTML'), diff --git a/es2019.js b/es2019.js index c3dc61f9..bfe09ed0 100644 --- a/es2019.js +++ b/es2019.js @@ -11,10 +11,12 @@ var ES2019 = { ArrayCreate: require('./2019/ArrayCreate'), ArraySetLength: require('./2019/ArraySetLength'), ArraySpeciesCreate: require('./2019/ArraySpeciesCreate'), + AsyncFromSyncIteratorContinuation: require('./2019/AsyncFromSyncIteratorContinuation'), Call: require('./2019/Call'), CanonicalNumericIndexString: require('./2019/CanonicalNumericIndexString'), CompletePropertyDescriptor: require('./2019/CompletePropertyDescriptor'), CopyDataProperties: require('./2019/CopyDataProperties'), + CreateAsyncFromSyncIterator: require('./2019/CreateAsyncFromSyncIterator'), CreateDataProperty: require('./2019/CreateDataProperty'), CreateDataPropertyOrThrow: require('./2019/CreateDataPropertyOrThrow'), CreateHTML: require('./2019/CreateHTML'), diff --git a/package.json b/package.json index ecc76781..a7573fa3 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", "is-callable": "^1.2.0", "is-negative-zero": "^2.0.0", "is-regex": "^1.1.0", From f62b1245e4cb2caca63647e8b6dcdacb1a56f444 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Sun, 14 Jun 2020 20:45:00 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Update=C2=A0`expectedMissing`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2018/AsyncFromSyncIteratorContinuation.js | 2 +- 2019/AsyncFromSyncIteratorContinuation.js | 2 +- test/es2018.js | 1 - test/es2019.js | 2 -- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/2018/AsyncFromSyncIteratorContinuation.js b/2018/AsyncFromSyncIteratorContinuation.js index 3b96c064..aadf749c 100644 --- a/2018/AsyncFromSyncIteratorContinuation.js +++ b/2018/AsyncFromSyncIteratorContinuation.js @@ -13,7 +13,7 @@ var PromiseResolve = require('./PromiseResolve.js'); var $Promise = GetIntrinsic('%Promise%', true); var PerformPromiseThen = callBound('%Promise.prototype.then%', true); -// https://www.ecma-international.org/ecma-262/9.0/#sec-asyncfromsynciteratorcontinuation +// https://www.ecma-international.org/ecma-262/10.0/#sec-asyncfromsynciteratorcontinuation module.exports = function AsyncFromSyncIteratorContinuation(result, promiseCapability) { try { diff --git a/2019/AsyncFromSyncIteratorContinuation.js b/2019/AsyncFromSyncIteratorContinuation.js index 3b96c064..aadf749c 100644 --- a/2019/AsyncFromSyncIteratorContinuation.js +++ b/2019/AsyncFromSyncIteratorContinuation.js @@ -13,7 +13,7 @@ var PromiseResolve = require('./PromiseResolve.js'); var $Promise = GetIntrinsic('%Promise%', true); var PerformPromiseThen = callBound('%Promise.prototype.then%', true); -// https://www.ecma-international.org/ecma-262/9.0/#sec-asyncfromsynciteratorcontinuation +// https://www.ecma-international.org/ecma-262/10.0/#sec-asyncfromsynciteratorcontinuation module.exports = function AsyncFromSyncIteratorContinuation(result, promiseCapability) { try { diff --git a/test/es2018.js b/test/es2018.js index f8c1781e..344f868d 100644 --- a/test/es2018.js +++ b/test/es2018.js @@ -44,7 +44,6 @@ var expectedMissing = [ 'CopyDataBlockBytes', 'CreateArrayFromList', 'CreateArrayIterator', - 'CreateAsyncFromSyncIterator', 'CreateBuiltinFunction', 'CreateByteDataBlock', 'CreateDynamicFunction', diff --git a/test/es2019.js b/test/es2019.js index 4b71dd9e..2aae2204 100644 --- a/test/es2019.js +++ b/test/es2019.js @@ -16,7 +16,6 @@ var expectedMissing = [ 'AllocateSharedArrayBuffer', 'AllocateTypedArray', 'AllocateTypedArrayBuffer', - 'AsyncFromSyncIteratorContinuation', 'AsyncFunctionCreate', 'AsyncFunctionStart', 'AsyncGeneratorEnqueue', @@ -45,7 +44,6 @@ var expectedMissing = [ 'CopyDataBlockBytes', 'CreateArrayFromList', 'CreateArrayIterator', - 'CreateAsyncFromSyncIterator', 'CreateBuiltinFunction', 'CreateByteDataBlock', 'CreateDynamicFunction', From a0eedfa92a39d7aaad51b5ceaa0a664486dad8d3 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Wed, 17 Jun 2020 23:45:00 +0200 Subject: [PATCH 3/3] =?UTF-8?q?Move=C2=A0`AsyncFromSyncIteratorPrototype`?= =?UTF-8?q?=20implementation=C2=A0to=C2=A0`helpers`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 1 - 2018/AsyncFromSyncIteratorContinuation.js | 37 ---- 2018/CreateAsyncFromSyncIterator.js | 171 +--------------- 2019/AsyncFromSyncIteratorContinuation.js | 37 ---- 2019/CreateAsyncFromSyncIterator.js | 171 +--------------- es2018.js | 1 - es2019.js | 1 - helpers/AsyncFromSyncIterator.js | 230 ++++++++++++++++++++++ test/es2019.js | 1 + 9 files changed, 239 insertions(+), 411 deletions(-) delete mode 100644 2018/AsyncFromSyncIteratorContinuation.js delete mode 100644 2019/AsyncFromSyncIteratorContinuation.js create mode 100644 helpers/AsyncFromSyncIterator.js diff --git a/.gitattributes b/.gitattributes index 0b8ada0c..ee5be791 100644 --- a/.gitattributes +++ b/.gitattributes @@ -367,7 +367,6 @@ 2019/ArrayCreate.js spackled linguist-generated=true 2019/ArraySetLength.js spackled linguist-generated=true 2019/ArraySpeciesCreate.js spackled linguist-generated=true -2019/AsyncFromSyncIteratorContinuation.js spackled linguist-generated=true 2019/Call.js spackled linguist-generated=true 2019/CanonicalNumericIndexString.js spackled linguist-generated=true 2019/CompletePropertyDescriptor.js spackled linguist-generated=true diff --git a/2018/AsyncFromSyncIteratorContinuation.js b/2018/AsyncFromSyncIteratorContinuation.js deleted file mode 100644 index aadf749c..00000000 --- a/2018/AsyncFromSyncIteratorContinuation.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -var GetIntrinsic = require('../GetIntrinsic.js'); -var callBound = require('../helpers/callBound.js'); - -var Call = require('./Call.js'); -var CreateIterResultObject = require('./CreateIterResultObject.js'); -var IteratorComplete = require('./IteratorComplete.js'); -var IteratorValue = require('./IteratorValue.js'); - -var PromiseResolve = require('./PromiseResolve.js'); - -var $Promise = GetIntrinsic('%Promise%', true); -var PerformPromiseThen = callBound('%Promise.prototype.then%', true); - -// https://www.ecma-international.org/ecma-262/10.0/#sec-asyncfromsynciteratorcontinuation - -module.exports = function AsyncFromSyncIteratorContinuation(result, promiseCapability) { - try { - var done = IteratorComplete(result); - var value = IteratorValue(result); - var valueWrapper = PromiseResolve($Promise, value); - - PerformPromiseThen( - valueWrapper, - function onFulfilled(unwrappedValue) { - Call(promiseCapability['[[Resolve]]'], undefined, [ - CreateIterResultObject(unwrappedValue, done) - ]); - }, - promiseCapability['[[Reject]]'] - ); - } catch (error) { - Call(promiseCapability['[[Reject]]'], undefined, [error]); - } - return promiseCapability['[[Promise]]']; -}; diff --git a/2018/CreateAsyncFromSyncIterator.js b/2018/CreateAsyncFromSyncIterator.js index 33d34881..ef74a997 100644 --- a/2018/CreateAsyncFromSyncIterator.js +++ b/2018/CreateAsyncFromSyncIterator.js @@ -1,179 +1,16 @@ 'use strict'; -var internalSlot = require('internal-slot'); -var GetIntrinsic = require('../GetIntrinsic.js'); - -var AsyncFromSyncIteratorContinuation = require('./AsyncFromSyncIteratorContinuation.js'); -var Call = require('./Call.js'); -var CreateIterResultObject = require('./CreateIterResultObject.js'); -var CreateMethodProperty = require('./CreateMethodProperty.js'); -var DefinePropertyOrThrow = require('./DefinePropertyOrThrow.js'); -var Get = require('./Get.js'); -var GetMethod = require('./GetMethod.js'); -var IteratorNext = require('./IteratorNext.js'); -var OrdinaryObjectCreate = require('./ObjectCreate.js'); -var Type = require('./Type.js'); - -var $asyncIterator = GetIntrinsic('%Symbol.asyncIterator%', true); -var $toStringTag = GetIntrinsic('%Symbol.toStringTag%', true); -var $TypeError = GetIntrinsic('%TypeError%'); - -// TODO: Use %AsyncIterator.from% once it's in ECMA-262 - -var AsyncIteratorPrototype - = GetIntrinsic('%AsyncIteratorPrototype%', true) - || (function () { - var result = {}; - if ($toStringTag) { - DefinePropertyOrThrow(result, $toStringTag, { - '[[Writable]]': false, - '[[Enumerable]]': false, - '[[Configurable]]': true, - '[[Value]]': 'AsyncIterator' - }); - } - if ($asyncIterator) { - var method = { - '[Symbol.asyncIterator]': function () { - return this; - } - }['[Symbol.asyncIterator]']; - CreateMethodProperty(result, $asyncIterator, method); - } - return result; - }()); - -var AsyncFromSyncIteratorPrototype - = GetIntrinsic('%AsyncFromSyncIteratorPrototype%', true) - // eslint-disable-next-line max-lines-per-function - || (function () { - var $Promise = GetIntrinsic('%Promise%', true); - if (!$Promise) { - return; - } - - // eslint-disable-next-line no-shadow - var AsyncFromSyncIteratorPrototype = OrdinaryObjectCreate(AsyncIteratorPrototype); - CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'next', function next(value) { - // eslint-disable-next-line no-invalid-this - var O = this; - var promiseCapability = {}; - promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { - promiseCapability['[[Resolve]]'] = resolve; - promiseCapability['[[Reject]]'] = reject; - }); - - if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('%AsyncFromSyncIteratorPrototype%.next called on invalid receiver') - ]); - return promiseCapability['[[Promise]]']; - } - - var result; - try { - var syncIteratorRecord = internalSlot.get(O, '[[SyncIteratorRecord]]'); - result = IteratorNext(syncIteratorRecord, value); - } catch (error) { - Call(promiseCapability['[[Reject]]'], undefined, [error]); - return promiseCapability['[[Promise]]']; - } - return AsyncFromSyncIteratorContinuation(result, promiseCapability); - }); - - CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'return', function (value) { - // eslint-disable-next-line no-invalid-this - var O = this; - var promiseCapability = {}; - promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { - promiseCapability['[[Resolve]]'] = resolve; - promiseCapability['[[Reject]]'] = reject; - }); - - if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('%AsyncFromSyncIteratorPrototype%.return called on invalid receiver') - ]); - return promiseCapability['[[Promise]]']; - } - - var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[SyncIterator]]']; - var result; - try { - var returnMethod = GetMethod(syncIterator, 'return'); - if (returnMethod === undefined) { - var iterResult = CreateIterResultObject(value, true); - Call(promiseCapability['[[Resolve]]'], undefined, [iterResult]); - return promiseCapability['[[Promise]]']; - } - - result = Call(returnMethod, syncIterator, [value]); - if (Type(result) !== 'Object') { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('iterator return must return an object') - ]); - return promiseCapability['[[Promise]]']; - } - } catch (error) { - Call(promiseCapability['[[Reject]]'], undefined, [error]); - return promiseCapability['[[Promise]]']; - } - return AsyncFromSyncIteratorContinuation(result, promiseCapability); - }); - - CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'throw', function (value) { - // eslint-disable-next-line no-invalid-this - var O = this; - var promiseCapability = {}; - promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { - promiseCapability['[[Resolve]]'] = resolve; - promiseCapability['[[Reject]]'] = reject; - }); - - if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('%AsyncFromSyncIteratorPrototype%.return called on invalid receiver') - ]); - return promiseCapability['[[Promise]]']; - } - - var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[SyncIterator]]']; - var result; - try { - var throwMethod = GetMethod(syncIterator, 'throw'); - if (throwMethod === undefined) { - var iterResult = CreateIterResultObject(value, true); - Call(promiseCapability['[[Reject]]'], undefined, [iterResult]); - return promiseCapability['[[Promise]]']; - } - - result = Call(throwMethod, syncIterator, [value]); - if (Type(result) !== 'Object') { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('iterator throw must return an object') - ]); - return promiseCapability['[[Promise]]']; - } - } catch (error) { - Call(promiseCapability['[[Reject]]'], undefined, [error]); - return promiseCapability['[[Promise]]']; - } - return AsyncFromSyncIteratorContinuation(result, promiseCapability); - }); - - // eslint-disable-next-line consistent-return - return AsyncFromSyncIteratorPrototype; - }()); +var AsyncFromSyncIterator = require('../helpers/AsyncFromSyncIterator'); +var Get = require('./Get'); // https://www.ecma-international.org/ecma-262/9.0/#sec-createasyncfromsynciterator module.exports = function CreateAsyncFromSyncIterator(syncIteratorRecord) { - if (!AsyncFromSyncIteratorPrototype) { + if (!AsyncFromSyncIterator) { throw new SyntaxError('This environment does not support Promises.'); } - var asyncIterator = OrdinaryObjectCreate(AsyncFromSyncIteratorPrototype); - internalSlot.set(asyncIterator, '[[SyncIteratorRecord]]', syncIteratorRecord); + var asyncIterator = new AsyncFromSyncIterator(syncIteratorRecord); var nextMethod = Get(asyncIterator, 'next'); return { '[[Iterator]]': asyncIterator, diff --git a/2019/AsyncFromSyncIteratorContinuation.js b/2019/AsyncFromSyncIteratorContinuation.js deleted file mode 100644 index aadf749c..00000000 --- a/2019/AsyncFromSyncIteratorContinuation.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -var GetIntrinsic = require('../GetIntrinsic.js'); -var callBound = require('../helpers/callBound.js'); - -var Call = require('./Call.js'); -var CreateIterResultObject = require('./CreateIterResultObject.js'); -var IteratorComplete = require('./IteratorComplete.js'); -var IteratorValue = require('./IteratorValue.js'); - -var PromiseResolve = require('./PromiseResolve.js'); - -var $Promise = GetIntrinsic('%Promise%', true); -var PerformPromiseThen = callBound('%Promise.prototype.then%', true); - -// https://www.ecma-international.org/ecma-262/10.0/#sec-asyncfromsynciteratorcontinuation - -module.exports = function AsyncFromSyncIteratorContinuation(result, promiseCapability) { - try { - var done = IteratorComplete(result); - var value = IteratorValue(result); - var valueWrapper = PromiseResolve($Promise, value); - - PerformPromiseThen( - valueWrapper, - function onFulfilled(unwrappedValue) { - Call(promiseCapability['[[Resolve]]'], undefined, [ - CreateIterResultObject(unwrappedValue, done) - ]); - }, - promiseCapability['[[Reject]]'] - ); - } catch (error) { - Call(promiseCapability['[[Reject]]'], undefined, [error]); - } - return promiseCapability['[[Promise]]']; -}; diff --git a/2019/CreateAsyncFromSyncIterator.js b/2019/CreateAsyncFromSyncIterator.js index 33d34881..ef74a997 100644 --- a/2019/CreateAsyncFromSyncIterator.js +++ b/2019/CreateAsyncFromSyncIterator.js @@ -1,179 +1,16 @@ 'use strict'; -var internalSlot = require('internal-slot'); -var GetIntrinsic = require('../GetIntrinsic.js'); - -var AsyncFromSyncIteratorContinuation = require('./AsyncFromSyncIteratorContinuation.js'); -var Call = require('./Call.js'); -var CreateIterResultObject = require('./CreateIterResultObject.js'); -var CreateMethodProperty = require('./CreateMethodProperty.js'); -var DefinePropertyOrThrow = require('./DefinePropertyOrThrow.js'); -var Get = require('./Get.js'); -var GetMethod = require('./GetMethod.js'); -var IteratorNext = require('./IteratorNext.js'); -var OrdinaryObjectCreate = require('./ObjectCreate.js'); -var Type = require('./Type.js'); - -var $asyncIterator = GetIntrinsic('%Symbol.asyncIterator%', true); -var $toStringTag = GetIntrinsic('%Symbol.toStringTag%', true); -var $TypeError = GetIntrinsic('%TypeError%'); - -// TODO: Use %AsyncIterator.from% once it's in ECMA-262 - -var AsyncIteratorPrototype - = GetIntrinsic('%AsyncIteratorPrototype%', true) - || (function () { - var result = {}; - if ($toStringTag) { - DefinePropertyOrThrow(result, $toStringTag, { - '[[Writable]]': false, - '[[Enumerable]]': false, - '[[Configurable]]': true, - '[[Value]]': 'AsyncIterator' - }); - } - if ($asyncIterator) { - var method = { - '[Symbol.asyncIterator]': function () { - return this; - } - }['[Symbol.asyncIterator]']; - CreateMethodProperty(result, $asyncIterator, method); - } - return result; - }()); - -var AsyncFromSyncIteratorPrototype - = GetIntrinsic('%AsyncFromSyncIteratorPrototype%', true) - // eslint-disable-next-line max-lines-per-function - || (function () { - var $Promise = GetIntrinsic('%Promise%', true); - if (!$Promise) { - return; - } - - // eslint-disable-next-line no-shadow - var AsyncFromSyncIteratorPrototype = OrdinaryObjectCreate(AsyncIteratorPrototype); - CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'next', function next(value) { - // eslint-disable-next-line no-invalid-this - var O = this; - var promiseCapability = {}; - promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { - promiseCapability['[[Resolve]]'] = resolve; - promiseCapability['[[Reject]]'] = reject; - }); - - if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('%AsyncFromSyncIteratorPrototype%.next called on invalid receiver') - ]); - return promiseCapability['[[Promise]]']; - } - - var result; - try { - var syncIteratorRecord = internalSlot.get(O, '[[SyncIteratorRecord]]'); - result = IteratorNext(syncIteratorRecord, value); - } catch (error) { - Call(promiseCapability['[[Reject]]'], undefined, [error]); - return promiseCapability['[[Promise]]']; - } - return AsyncFromSyncIteratorContinuation(result, promiseCapability); - }); - - CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'return', function (value) { - // eslint-disable-next-line no-invalid-this - var O = this; - var promiseCapability = {}; - promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { - promiseCapability['[[Resolve]]'] = resolve; - promiseCapability['[[Reject]]'] = reject; - }); - - if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('%AsyncFromSyncIteratorPrototype%.return called on invalid receiver') - ]); - return promiseCapability['[[Promise]]']; - } - - var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[SyncIterator]]']; - var result; - try { - var returnMethod = GetMethod(syncIterator, 'return'); - if (returnMethod === undefined) { - var iterResult = CreateIterResultObject(value, true); - Call(promiseCapability['[[Resolve]]'], undefined, [iterResult]); - return promiseCapability['[[Promise]]']; - } - - result = Call(returnMethod, syncIterator, [value]); - if (Type(result) !== 'Object') { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('iterator return must return an object') - ]); - return promiseCapability['[[Promise]]']; - } - } catch (error) { - Call(promiseCapability['[[Reject]]'], undefined, [error]); - return promiseCapability['[[Promise]]']; - } - return AsyncFromSyncIteratorContinuation(result, promiseCapability); - }); - - CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'throw', function (value) { - // eslint-disable-next-line no-invalid-this - var O = this; - var promiseCapability = {}; - promiseCapability['[[Promise]]'] = new $Promise(function (resolve, reject) { - promiseCapability['[[Resolve]]'] = resolve; - promiseCapability['[[Reject]]'] = reject; - }); - - if (Type(O) !== 'Object' || !internalSlot.has(O, '[[SyncIteratorRecord]]')) { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('%AsyncFromSyncIteratorPrototype%.return called on invalid receiver') - ]); - return promiseCapability['[[Promise]]']; - } - - var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[SyncIterator]]']; - var result; - try { - var throwMethod = GetMethod(syncIterator, 'throw'); - if (throwMethod === undefined) { - var iterResult = CreateIterResultObject(value, true); - Call(promiseCapability['[[Reject]]'], undefined, [iterResult]); - return promiseCapability['[[Promise]]']; - } - - result = Call(throwMethod, syncIterator, [value]); - if (Type(result) !== 'Object') { - Call(promiseCapability['[[Reject]]'], undefined, [ - new $TypeError('iterator throw must return an object') - ]); - return promiseCapability['[[Promise]]']; - } - } catch (error) { - Call(promiseCapability['[[Reject]]'], undefined, [error]); - return promiseCapability['[[Promise]]']; - } - return AsyncFromSyncIteratorContinuation(result, promiseCapability); - }); - - // eslint-disable-next-line consistent-return - return AsyncFromSyncIteratorPrototype; - }()); +var AsyncFromSyncIterator = require('../helpers/AsyncFromSyncIterator'); +var Get = require('./Get'); // https://www.ecma-international.org/ecma-262/9.0/#sec-createasyncfromsynciterator module.exports = function CreateAsyncFromSyncIterator(syncIteratorRecord) { - if (!AsyncFromSyncIteratorPrototype) { + if (!AsyncFromSyncIterator) { throw new SyntaxError('This environment does not support Promises.'); } - var asyncIterator = OrdinaryObjectCreate(AsyncFromSyncIteratorPrototype); - internalSlot.set(asyncIterator, '[[SyncIteratorRecord]]', syncIteratorRecord); + var asyncIterator = new AsyncFromSyncIterator(syncIteratorRecord); var nextMethod = Get(asyncIterator, 'next'); return { '[[Iterator]]': asyncIterator, diff --git a/es2018.js b/es2018.js index 8e026d99..fc2d3fa9 100644 --- a/es2018.js +++ b/es2018.js @@ -10,7 +10,6 @@ var ES2018 = { ArrayCreate: require('./2018/ArrayCreate'), ArraySetLength: require('./2018/ArraySetLength'), ArraySpeciesCreate: require('./2018/ArraySpeciesCreate'), - AsyncFromSyncIteratorContinuation: require('./2018/AsyncFromSyncIteratorContinuation'), Call: require('./2018/Call'), CanonicalNumericIndexString: require('./2018/CanonicalNumericIndexString'), CompletePropertyDescriptor: require('./2018/CompletePropertyDescriptor'), diff --git a/es2019.js b/es2019.js index bfe09ed0..966cca43 100644 --- a/es2019.js +++ b/es2019.js @@ -11,7 +11,6 @@ var ES2019 = { ArrayCreate: require('./2019/ArrayCreate'), ArraySetLength: require('./2019/ArraySetLength'), ArraySpeciesCreate: require('./2019/ArraySpeciesCreate'), - AsyncFromSyncIteratorContinuation: require('./2019/AsyncFromSyncIteratorContinuation'), Call: require('./2019/Call'), CanonicalNumericIndexString: require('./2019/CanonicalNumericIndexString'), CompletePropertyDescriptor: require('./2019/CompletePropertyDescriptor'), diff --git a/helpers/AsyncFromSyncIterator.js b/helpers/AsyncFromSyncIterator.js new file mode 100644 index 00000000..41a3140c --- /dev/null +++ b/helpers/AsyncFromSyncIterator.js @@ -0,0 +1,230 @@ +'use strict'; + +var internalSlot = require('internal-slot'); +var isCallable = require('is-callable'); + +var callBind = require('./callBind'); +var callBound = require('./callBound'); +var GetIntrinsic = require('../GetIntrinsic'); +var $isNaN = require('./isNaN'); + +var $apply = GetIntrinsic('%Reflect.apply%', true) || callBound('%Function.prototype.apply%'); +var $asyncIterator = GetIntrinsic('%Symbol.asyncIterator%', true); +var $toStringTag = GetIntrinsic('%Symbol.toStringTag%', true); +var $TypeError = GetIntrinsic('%TypeError%'); + +var undefined; + +// TODO: Use %AsyncIterator.from% once it's in ECMA-262 + +/** @type {(o: object, p: string | symbol, Desc: import('es-abstract').PropertyDescriptor) => boolean} */ +var DefineOwnProperty = callBind( + require('./DefineOwnProperty'), + undefined, + function IsDataDescriptor(Desc) { + return !('[[Get]]' in Desc) && !('[[Set]]' in Desc); + }, + GetIntrinsic('%Object.is%', true) || function SameValue(x, y) { + if (x === y) { + // 0 === -0, but they are not identical. + if (x === 0) { + return 1 / x === 1 / y; + } + return true; + } + return $isNaN(x) && $isNaN(y); + }, + function FromPropertyDescriptor(Desc) { + var obj = {}; + if ('[[Value]]' in Desc) { + obj.value = Desc['[[Value]]']; + } + if ('[[Writable]]' in Desc) { + obj.writable = Desc['[[Writable]]']; + } + if ('[[Get]]' in Desc) { + obj.get = Desc['[[Get]]']; + } + if ('[[Set]]' in Desc) { + obj.set = Desc['[[Set]]']; + } + if ('[[Enumerable]]' in Desc) { + obj.enumerable = Desc['[[Enumerable]]']; + } + if ('[[Configurable]]' in Desc) { + obj.configurable = Desc['[[Configurable]]']; + } + return obj; + } +); + +var CreateMethodProperty = function CreateMethodProperty(O, P, V) { + return DefineOwnProperty(O, P, { + '[[Configurable]]': true, + '[[Enumerable]]': false, + '[[Writable]]': true, + '[[Value]]': V + }); +}; + +var isObject = function (target) { + return target !== null && (typeof target === 'object' || typeof target === 'function'); +}; + +var AsyncIteratorPrototype + = GetIntrinsic('%AsyncIteratorPrototype%', true) + || (function () { + var result = {}; + if ($toStringTag) { + DefineOwnProperty(result, $toStringTag, { + '[[Writable]]': false, + '[[Enumerable]]': false, + '[[Configurable]]': true, + '[[Value]]': 'AsyncIterator' + }); + } + if ($asyncIterator) { + CreateMethodProperty( + result, + $asyncIterator, + { + '[Symbol.asyncIterator]': function () { + return this; + } + }['[Symbol.asyncIterator]'] + ); + } + return result; + }()); + +var AsyncFromSyncIteratorPrototype + = GetIntrinsic('%AsyncFromSyncIteratorPrototype%', true) + // eslint-disable-next-line max-lines-per-function + || (function () { + var $Promise = GetIntrinsic('%Promise%', true); + if (!$Promise) { + return; + } + + var PromiseResolve = callBind(GetIntrinsic('%Promise.resolve%')); + var promiseProtoThen = callBound('%Promise.prototype.then%'); + var AsyncFromSyncIteratorContinuation = function AsyncFromSyncIteratorContinuation(result, promiseCapability) { + var done = !!result.done; + var value = result.value; + var valueWrapper = PromiseResolve($Promise, value); + + promiseProtoThen( + valueWrapper, + function onFulfilled(unwrappedValue) { + $apply( + promiseCapability['[[Resolve]]'], + undefined, + [{ value: unwrappedValue, done: done }] + ); + }, + promiseCapability['[[Reject]]'] + ); + }; + + var T = function T() {}; + T.prototype = AsyncIteratorPrototype; + // eslint-disable-next-line no-shadow + var AsyncFromSyncIteratorPrototype = new T(); + + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'next', function next(value) { + // eslint-disable-next-line no-invalid-this + var O = this; + return new Promise(function (resolve, reject) { + internalSlot.assert(O, '[[SyncIteratorRecord]]'); + + var syncIteratorRecord = internalSlot.get(O, '[[SyncIteratorRecord]]'); + var result = $apply( + syncIteratorRecord['[[NextMethod]]'], + syncIteratorRecord['[[Iterator]]'], + [value] + ); + + if (!isObject(result)) { + throw new $TypeError('iterator next must return an object'); + } + + return AsyncFromSyncIteratorContinuation(result, { + '[[Resolve]]': resolve, + '[[Reject]]': reject + }); + }); + }); + + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'return', { + 'return': function (value) { + var O = this; + return new Promise(function (resolve, reject) { + internalSlot.assert(O, '[[SyncIteratorRecord]]'); + + var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[Iterator]]']; + var returnMethod = syncIterator['return']; + if (returnMethod != null) { + if (!isCallable(returnMethod)) { + throw new $TypeError('iterator return is not a function'); + } + + return resolve({ + value: value, + done: true + }); + } + + var result = $apply(returnMethod, syncIterator, [value]); + if (!isObject(result)) { + throw new $TypeError('iterator return must return an object'); + } + + return AsyncFromSyncIteratorContinuation(result, { + '[[Resolve]]': resolve, + '[[Reject]]': reject + }); + }); + } + }['return']); + + CreateMethodProperty(AsyncFromSyncIteratorPrototype, 'throw', { + 'throw': function (value) { + var O = this; + return new Promise(function (resolve, reject) { + internalSlot.assert(O, '[[SyncIteratorRecord]]'); + + var syncIterator = internalSlot.get(O, '[[SyncIteratorRecord]]')['[[Iterator]]']; + var throwMethod = syncIterator['return']; + if (throwMethod != null) { + if (!isCallable(throwMethod)) { + throw new $TypeError('iterator throw is not a function'); + } + throw value; + } + + var result = $apply(throwMethod, syncIterator, [value]); + if (!isObject(result)) { + throw new $TypeError('iterator throw must return an object'); + } + + return AsyncFromSyncIteratorContinuation(result, { + '[[Resolve]]': resolve, + '[[Reject]]': reject + }); + }); + } + }['throw']); + + // eslint-disable-next-line consistent-return + return AsyncFromSyncIteratorPrototype; + }()); + +var AsyncFromSyncIteratorConstructor; +if (AsyncFromSyncIteratorPrototype) { + AsyncFromSyncIteratorConstructor = function AsyncFromSyncIterator(syncIteratorRecord) { + internalSlot.set(this, '[[SyncIteratorRecord]]', syncIteratorRecord); + }; + AsyncFromSyncIteratorConstructor.prototype = AsyncFromSyncIteratorPrototype; +} + +module.exports = AsyncFromSyncIteratorConstructor; diff --git a/test/es2019.js b/test/es2019.js index 2aae2204..aad9d625 100644 --- a/test/es2019.js +++ b/test/es2019.js @@ -16,6 +16,7 @@ var expectedMissing = [ 'AllocateSharedArrayBuffer', 'AllocateTypedArray', 'AllocateTypedArrayBuffer', + 'AsyncFromSyncIteratorContinuation', 'AsyncFunctionCreate', 'AsyncFunctionStart', 'AsyncGeneratorEnqueue',