From df038ab377acaacb113171ec360dacaf1141faea Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Sat, 26 Dec 2020 15:06:00 +0100 Subject: [PATCH] Implement CreateAsyncFromSyncIterator abstract op --- .../lib/abstract-ops/ecmascript.js | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/reference-implementation/lib/abstract-ops/ecmascript.js b/reference-implementation/lib/abstract-ops/ecmascript.js index d277aa724..edb69dfac 100644 --- a/reference-implementation/lib/abstract-ops/ecmascript.js +++ b/reference-implementation/lib/abstract-ops/ecmascript.js @@ -56,6 +56,23 @@ exports.GetMethod = (V, P) => { return func; }; +exports.CreateAsyncFromSyncIterator = syncIteratorRecord => { + // Instead of re-implementing CreateAsyncFromSyncIterator and %AsyncFromSyncIteratorPrototype%, + // we use yield* inside an async generator function to achieve the same result. + + // Wrap the sync iterator inside a sync iterable, so we can use it with yield*. + const syncIterable = { + [Symbol.iterator]: () => syncIteratorRecord.iterator + }; + // Create an async generator function and immediately invoke it. + const asyncIterator = (async function* () { + return yield* syncIterable; + }()); + // Return as an async iterator record. + const nextMethod = asyncIterator.next; + return { iterator: asyncIterator, nextMethod, done: false }; +}; + exports.GetIterator = (obj, hint = 'sync', method) => { assert(hint === 'sync' || hint === 'async'); if (method === undefined) { @@ -63,8 +80,8 @@ exports.GetIterator = (obj, hint = 'sync', method) => { method = exports.GetMethod(obj, Symbol.asyncIterator); if (method === undefined) { const syncMethod = exports.GetMethod(obj, Symbol.iterator); - const syncIterator = exports.GetIterator(obj, 'sync', syncMethod); - return syncIterator; // TODO sync to async iterator + const syncIteratorRecord = exports.GetIterator(obj, 'sync', syncMethod); + return exports.CreateAsyncFromSyncIterator(syncIteratorRecord); } } else { method = exports.GetMethod(obj, Symbol.iterator);