async-to-gen
Advanced tools
Comparing version 1.1.5 to 1.2.0
84
index.js
@@ -29,2 +29,3 @@ var babylon = require('babylon'); | ||
editor.containsAsyncGen = false; | ||
editor.containsForAwaitOf = false; | ||
@@ -52,5 +53,10 @@ // Cheap trick for files that don't actually contain async functions | ||
editor.isEdited = Boolean(ast.containsAsync || ast.containsAsyncGen); | ||
editor.isEdited = Boolean( | ||
ast.containsAsync || | ||
ast.containsAsyncGen || | ||
ast.containsForAwaitOf | ||
); | ||
editor.containsAsync = Boolean(ast.containsAsync); | ||
editor.containsAsyncGen = Boolean(ast.containsAsyncGen); | ||
editor.containsForAwaitOf = Boolean(ast.containsForAwaitOf); | ||
@@ -115,8 +121,7 @@ return editor; | ||
'}' + | ||
'Symbol&&(' + | ||
'Symbol.iterator&&(I[Symbol.iterator]=t),' + | ||
'Symbol.asyncIterator&&(I[Symbol.asyncIterator]=t));' + | ||
'function t(){' + | ||
'I[Symbol?' + | ||
'Symbol.asyncIterator||(Symbol.asyncIterator=Symbol()):' + | ||
'"@@asyncIterator"]=function (){' + | ||
'return this' + | ||
'}' + | ||
'};' + | ||
'function a(t,v){' + | ||
@@ -151,2 +156,19 @@ 'return new Promise(function(s,j){' + | ||
/** | ||
* A helper function which provides an async iterator from an async iterable. | ||
* | ||
* Automatically included at the end of files containing for-await-of loops, but | ||
* also exported from this module for other uses. | ||
* See ./async-node for an example of another usage. | ||
*/ | ||
var asyncIteratorHelper = | ||
'function __asyncIterator(o){' + | ||
'var i=o[Symbol&&Symbol.asyncIterator||"@@asyncIterator"]||' + | ||
'o[Symbol&&Symbol.iterator||"@@iterator"];' + | ||
'if(!i)throw new TypeError("Object is not AsyncIterable.");' + | ||
'return i.call(o)' + | ||
'}'; | ||
module.exports.asyncIteratorHelper = asyncIteratorHelper; | ||
// A collection of methods for each AST type names which contain async functions to | ||
@@ -190,2 +212,5 @@ // be transformed. | ||
} | ||
if (ast.containsForAwaitOf) { | ||
editor.append('\n' + asyncIteratorHelper + '\n'); | ||
} | ||
} | ||
@@ -440,2 +465,5 @@ } | ||
function leaveForAwait(editor, node, ast) { | ||
ast.containsForAwaitOf = true; | ||
// Remove 'await' | ||
var envRecord = currentScope(ast); | ||
@@ -448,13 +476,41 @@ var idx = findTokenIndex(ast.tokens, node.start) + 1; | ||
var tmpName = '$await' + (ast.scope.length - 1); | ||
// Remove 'of' | ||
idx = findTokenIndex(ast.tokens, node.right.start) - 1; | ||
while (ast.tokens[idx].value !== 'of') { | ||
idx--; | ||
} | ||
editor.remove(ast.tokens[idx].start, ast.tokens[idx + 1].start); | ||
// Convert for-await-of to typical for loop that operates on the async iterable | ||
// interface and properly closes iterators on completion. | ||
var iter = '$i' + (ast.scope.length - 1); | ||
var step = '$s' + (ast.scope.length - 1); | ||
var error = '$e' + (ast.scope.length - 1); | ||
var left = step + '=null,' + iter + '=__asyncIterator('; | ||
var right = ');' + step + '=' + toYield(iter + '.next()', ast) + ',!' + step + '.done;'; | ||
var head = 'var ' + iter + ',' + step + ',' + error + ';try{'; | ||
var tail = | ||
'}catch(e){' + | ||
error + '=e' + | ||
'}finally{' + | ||
'try{' + | ||
'!' + step + '.done&&' + iter + '.return&&(' + toYield(iter + '.return()', ast) + ')' + | ||
'}finally{' + | ||
'if(' + error + ')throw ' + error + | ||
'}' + | ||
'}'; | ||
editor.insertRight(node.start, head); | ||
editor.move(node.left.start, node.left.end, node.body.start + 1); | ||
editor.insertLeft( | ||
node.left.end, | ||
envRecord.generator ? | ||
'=yield{__await:' + tmpName + '};' : | ||
'=yield ' + tmpName + ';' | ||
); | ||
editor.insertLeft(node.left.start, 'let ' + tmpName); | ||
editor.insertLeft(node.left.end, '=' + step + '.value;'); | ||
editor.insertLeft(node.left.start, left); | ||
editor.insertRight(node.right.end, right); | ||
editor.insertLeft(node.end, tail); | ||
} | ||
function toYield(expr, ast) { | ||
var envRecord = currentScope(ast); | ||
return envRecord.generator ? 'yield{__await:' + expr + '}' : 'yield ' + expr; | ||
} | ||
function currentScope(ast) { | ||
@@ -461,0 +517,0 @@ return ast.scope[ast.scope.length - 1]; |
{ | ||
"name": "async-to-gen", | ||
"version": "1.1.5", | ||
"version": "1.2.0", | ||
"description": "Transform async functions to generator functions with speed and simplicity.", | ||
@@ -41,5 +41,5 @@ "author": "Lee Byron <lee@leebyron.com> (http://leebyron.com/)", | ||
"dependencies": { | ||
"babylon": "^6.11.4", | ||
"babylon": "^6.14.0", | ||
"magic-string": "^0.16.0" | ||
} | ||
} |
@@ -235,3 +235,3 @@ async-to-gen | ||
Or use `for-await` loops within another async function: | ||
Or use `for-await-of` loops within another async function: | ||
@@ -246,4 +246,4 @@ ```js | ||
NOTE: The behavior of `for-await` loops using this tool is not identical to the | ||
proposed spec addition. Where the proposed spec's `for-await` expects a | ||
NOTE: The behavior of `for-await-of` loops using this tool is not identical to the | ||
proposed spec addition. Where the proposed spec's `for-await-of` expects a | ||
`Symbol.asyncIterator` method for the iterated source, this tool expects | ||
@@ -250,0 +250,0 @@ `Symbol.iterator` instead since it transforms it to a `for-of` loop. |
Sorry, the diff of this file is not supported yet
37711
519
Updatedbabylon@^6.14.0