async-to-gen
Advanced tools
Comparing version 1.0.1 to 1.0.2
148
index.js
@@ -61,4 +61,3 @@ var babylon = require('babylon'); | ||
var asyncHelper = | ||
'function __async(f){' + | ||
'var g=f();' + | ||
'function __async(g){' + | ||
'return new Promise(function(s,j){' + | ||
@@ -93,3 +92,3 @@ 'function c(a,x){' + | ||
ArrowFunctionExpression: { | ||
enter: enterFunction, | ||
enter: enterArrowFunction, | ||
leave: leaveArrowFunction | ||
@@ -130,2 +129,5 @@ }, | ||
} | ||
}, | ||
MemberExpression: { | ||
leave: leaveMemberExpression | ||
} | ||
@@ -143,17 +145,50 @@ }; | ||
var idx = findTokenIndex(ast.tokens, node.start); | ||
if (node.static) { | ||
while (ast.tokens[idx].value !== 'async') { | ||
idx++; | ||
} | ||
editor.remove(ast.tokens[idx].start, ast.tokens[idx + 1].start); | ||
editor.insertLeft(node.body.start + 1, 'return __async(function*(){'); | ||
editor.insertRight(node.body.end - 1, node.referencesThis ? '}.bind(this))' : '})'); | ||
var argNames = []; | ||
var argValues = []; | ||
if (node.referencesThis) { | ||
argValues.push('this'); | ||
} | ||
if (node.referencesSuper) { | ||
argNames.push('$uper'); | ||
argValues.push('p=>super[p]'); | ||
} | ||
if (node.referencesSuperEq) { | ||
argNames.push('$uperEq'); | ||
argValues.push('(p,v)=>(super[p]=v)'); | ||
} | ||
editor.insertLeft( | ||
node.body.start + 1, | ||
'return __async(function*(' + argNames.join(',') + '){' | ||
); | ||
editor.insertRight( | ||
node.body.end - 1, | ||
(node.referencesThis ? '}.call(' : '}(') + argValues.join(',') + '))' | ||
); | ||
} | ||
} | ||
function enterArrowFunction(editor, node, ast) { | ||
if (node.async) { | ||
ast.scope.push(node); | ||
} | ||
} | ||
function leaveArrowFunction(editor, node, ast) { | ||
ast.scope.pop(); | ||
if (node.referencesThis) { | ||
ast.scope[ast.scope.length - 1].referencesThis = true; | ||
} | ||
if (node.async) { | ||
ast.scope.pop(); | ||
if (node.referencesThis) { | ||
ast.scope[ast.scope.length - 1].referencesThis = true; | ||
} | ||
if (node.referencesSuper) { | ||
ast.scope[ast.scope.length - 1].referencesSuper = true; | ||
} | ||
if (node.referencesSuperEq) { | ||
ast.scope[ast.scope.length - 1].referencesSuperEq = true; | ||
} | ||
ast.isEdited = true; | ||
@@ -163,8 +198,11 @@ editor.remove(node.start, node.start + 6); | ||
editor.overwrite(node.body.start, node.body.start + 1, '__async(function*(){'); | ||
editor.overwrite(node.body.end - 1, node.body.end, node.referencesThis ? '}.bind(this))' : '})'); | ||
editor.overwrite(node.body.end - 1, node.body.end, node.referencesThis ? '}.call(this))' : '}())'); | ||
} else { | ||
var idx = findTokenIndex(ast.tokens, node.body.start); | ||
editor.insertRight(ast.tokens[idx - 1].end, '__async(function*(){'); | ||
var idx = findTokenIndex(ast.tokens, node.body.start) - 1; | ||
while (ast.tokens[idx].type.label !== '=>') { | ||
idx--; | ||
} | ||
editor.insertRight(ast.tokens[idx].end, '__async(function*(){'); | ||
editor.insertLeft(node.body.start, 'return '); | ||
editor.insertRight(node.body.end, node.referencesThis ? '}.bind(this))' : '})'); | ||
editor.insertRight(node.body.end, node.referencesThis ? '}.call(this))' : '}())'); | ||
} | ||
@@ -174,2 +212,56 @@ } | ||
function leaveMemberExpression(editor, node, ast, stack) { | ||
// Only transform super member expressions. | ||
if (node.object.type !== 'Super') return; | ||
// Only within transformed async function scopes. | ||
var envRecord = ast.scope[ast.scope.length - 1]; | ||
if (!envRecord.async) return; | ||
var contextNode = stack.parent; | ||
// Do not transform delete unary expressions. | ||
if (contextNode.operator === 'delete') return; | ||
// Convert member property to function argument | ||
var idx = findTokenIndex(ast.tokens, node.object.end); | ||
while (ast.tokens[idx].type.label !== (node.computed ? '[' : '.')) { | ||
idx++; | ||
} | ||
editor.remove(ast.tokens[idx].start, ast.tokens[idx].end); | ||
if (node.computed) { | ||
editor.remove(node.end - 1, node.end); | ||
} else { | ||
editor.insertRight(node.property.start, '"'); | ||
editor.insertLeft(node.property.end, '"'); | ||
} | ||
// super.prop = value | ||
if (contextNode.type === 'AssignmentExpression' && contextNode.left === node) { | ||
envRecord.referencesSuperEq = true; | ||
editor.overwrite(node.object.start, node.object.end, '$uperEq('); | ||
editor.insertRight(contextNode.end, ')') | ||
var idx = findTokenIndex(ast.tokens, node.end); | ||
while (ast.tokens[idx].type.label !== '=') { | ||
idx++; | ||
} | ||
editor.overwrite(ast.tokens[idx].start, ast.tokens[idx].end, ','); | ||
} else { | ||
envRecord.referencesSuper = true; | ||
editor.overwrite(node.object.start, node.object.end, '$uper('); | ||
editor.insertRight(node.end, ')'); | ||
// Ensure super.prop() use the current this binding. | ||
if (contextNode.type === 'CallExpression') { | ||
envRecord.referencesThis = true; | ||
var idx = findTokenIndex(ast.tokens, node.end); | ||
while (ast.tokens[idx].type.label !== '(') { | ||
idx++; | ||
} | ||
editor.overwrite(ast.tokens[idx].start, ast.tokens[idx].end, contextNode.arguments.length ? '.call(this,' : '.call(this'); | ||
} | ||
} | ||
} | ||
// Given the AST output of babylon parse, walk through in a depth-first order, | ||
@@ -179,4 +271,4 @@ // calling methods on the given visitor, providing editor as the first argument. | ||
var stack; | ||
var parent; | ||
var keys = []; | ||
var parent = ast; | ||
var keys = ['program']; | ||
var index = -1; | ||
@@ -190,11 +282,15 @@ | ||
index = stack.index; | ||
stack = stack.prev; | ||
var node = parent ? parent[keys[index]] : ast.program; | ||
var node = parent[keys[index]]; | ||
if (node.type) { | ||
var visitFn = visitor[node.type] && visitor[node.type].leave; | ||
visitFn && visitFn(editor, node, ast); | ||
visitFn && visitFn(editor, node, ast, stack); | ||
} | ||
stack = stack.prev; | ||
} else { | ||
var node = parent ? parent[keys[index]] : ast.program; | ||
if (node && typeof node === 'object') { | ||
var node = parent[keys[index]]; | ||
if (node && typeof node === 'object' && (node.type || node.length && node[0].type)) { | ||
stack = { parent: parent, keys: keys, index: index, prev: stack }; | ||
parent = node; | ||
keys = Object.keys(node); | ||
index = -1; | ||
if (node.type) { | ||
@@ -206,10 +302,4 @@ if (sourceMap) { | ||
var visitFn = visitor[node.type] && visitor[node.type].enter; | ||
if (visitFn && visitFn(editor, node, ast) === false) { | ||
continue; | ||
} | ||
visitFn && visitFn(editor, node, ast, stack); | ||
} | ||
stack = { parent: parent, keys: keys, index: index, prev: stack }; | ||
parent = node; | ||
keys = Object.keys(node); | ||
index = -1; | ||
} | ||
@@ -237,2 +327,4 @@ } | ||
} | ||
return ptr; | ||
} |
{ | ||
"name": "async-to-gen", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "Transform async functions to generator functions with speed and simplicity.", | ||
@@ -5,0 +5,0 @@ "author": "Lee Byron <lee@leebyron.com> (http://leebyron.com/)", |
@@ -83,2 +83,7 @@ async-to-gen | ||
## Use in Build Systems: | ||
**Rollup**: [`rollup-plugin-async`](https://github.com/leebyron/rollup-plugin-async) | ||
## Common Usage | ||
@@ -143,3 +148,3 @@ | ||
It also includes a very small (227 byte) conversion function at the bottom of the file. | ||
It also includes a very small (217 byte) conversion function at the bottom of the file. | ||
@@ -146,0 +151,0 @@ **Before:** |
@@ -0,5 +1,7 @@ | ||
"use strict" | ||
// async function statement | ||
function foo() {return __async(function*(){ | ||
return yield x | ||
})} | ||
}())} | ||
@@ -9,3 +11,3 @@ // async function expression | ||
yield x | ||
})} | ||
}())} | ||
@@ -15,7 +17,7 @@ // async arrow functions with body | ||
yield 42 | ||
}) | ||
}()) | ||
// async arrow functions with expression | ||
var arrow2 = () =>__async(function*(){ | ||
return yield 42}); | ||
return yield 42}()); | ||
@@ -26,3 +28,3 @@ // async obj member function | ||
yield this.x | ||
}.bind(this))} | ||
}.call(this))} | ||
} | ||
@@ -34,3 +36,3 @@ | ||
yield this.x | ||
}.bind(this))} | ||
}.call(this))} | ||
} | ||
@@ -42,12 +44,82 @@ | ||
yield this.x | ||
}.bind(this))} | ||
}.call(this))} | ||
} | ||
// arrow function referencing this within function | ||
// normal function referencing this | ||
function normalThis() { | ||
return this; | ||
} | ||
// async function referencing this | ||
function asyncThis() {return __async(function*(){ | ||
return this; | ||
}.call(this))} | ||
// async arrow function referencing this | ||
var fn = () =>__async(function*(){ | ||
return this}.call(this)); | ||
var fn2 = /**/ /**/ ( /**/ ) /**/ =>__async(function*(){ /**/ | ||
/**/ return this}.call(this)) /**/ ; | ||
// async arrow function referencing this within async function | ||
function within1() {return __async(function*(){ | ||
function within2() {return __async(function*(){ | ||
return yield (() =>__async(function*(){ return yield this}.bind(this))) | ||
}.bind(this))} | ||
})} | ||
return yield (() =>__async(function*(){ return yield this}.call(this))) | ||
}.call(this))} | ||
}())} | ||
function __async(f){var g=f();return new Promise(function(s,j){function c(a,x){try{var r=g[x?"throw":"next"](a)}catch(e){return j(e)}return r.done?s(r.value):Promise.resolve(r.value).then(c,d)}function d(e){return c(e,1)}c()})} | ||
// async arrow function referencing this within normal function | ||
function within1() { | ||
function within2() { | ||
return () =>__async(function*(){ | ||
return this}.call(this)) | ||
} | ||
} | ||
// normal arrow function referencing this within async function | ||
function within1() { | ||
function within2() {return __async(function*(){ | ||
return () => this | ||
}.call(this))} | ||
} | ||
// normal arrow function referencing this deep within async function | ||
function within1() {return __async(function*(){ | ||
function within2() { | ||
return () => this | ||
} | ||
}())} | ||
// async arrow inside normal arrow inside async function | ||
function within1() {return __async(function*(){ | ||
() => () =>__async(function*(){ return this}.call(this)) | ||
}.call(this))} | ||
class SuperDuper extends BaseClass { | ||
constructor(arg) { | ||
super(arg) | ||
} | ||
barAsync() {return __async(function*($uper,$uperEq){ | ||
const arg = $uper("arg").call(this) | ||
$uperEq("arg" , $uper("arg").call(this)) | ||
$uperEq( /*a*/ /*b*/ "arg" /*c*/ , /*d*/ $uper( /*e*/ /*f*/ "arg")) /*g*/ | ||
$uperEq( /*a*/ /*b*/ arg /*c*/ /*d*/ , /*e*/ $uper( /*f*/ /*g*/ arg /*h*/ )) /*i*/ | ||
const arg = $uper('arg') | ||
$uperEq('arg' , arg) | ||
delete super.arg | ||
return $uper(arg).call(this,arg) | ||
delete super.arg | ||
return $uper("barAsync").call(this,arg) | ||
}.call(this,p=>super[p],(p,v)=>(super[p]=v)))} | ||
bazAsync() {return __async(function*($uper,$uperEq){ | ||
$uperEq('arg' , $uper('arg')) | ||
}(p=>super[p],(p,v)=>(super[p]=v)))} | ||
} | ||
function __async(g){return new Promise(function(s,j){function c(a,x){try{var r=g[x?"throw":"next"](a)}catch(e){return j(e)}return r.done?s(r.value):Promise.resolve(r.value).then(c,d)}function d(e){return c(e,1)}c()})} |
@@ -0,1 +1,3 @@ | ||
"use strict" | ||
// async function statement | ||
@@ -41,3 +43,20 @@ async function foo() { | ||
// arrow function referencing this within function | ||
// normal function referencing this | ||
function normalThis() { | ||
return this; | ||
} | ||
// async function referencing this | ||
async function asyncThis() { | ||
return this; | ||
} | ||
// async arrow function referencing this | ||
var fn = async () => | ||
this; | ||
var fn2 = /**/ async /**/ ( /**/ ) /**/ => /**/ | ||
/**/ this /**/ ; | ||
// async arrow function referencing this within async function | ||
async function within1() { | ||
@@ -48,1 +67,54 @@ async function within2() { | ||
} | ||
// async arrow function referencing this within normal function | ||
function within1() { | ||
function within2() { | ||
return async () => | ||
this | ||
} | ||
} | ||
// normal arrow function referencing this within async function | ||
function within1() { | ||
async function within2() { | ||
return () => this | ||
} | ||
} | ||
// normal arrow function referencing this deep within async function | ||
async function within1() { | ||
function within2() { | ||
return () => this | ||
} | ||
} | ||
// async arrow inside normal arrow inside async function | ||
async function within1() { | ||
() => async () => this | ||
} | ||
class SuperDuper extends BaseClass { | ||
constructor(arg) { | ||
super(arg) | ||
} | ||
async barAsync() { | ||
const arg = super.arg() | ||
super.arg = super.arg() | ||
super /*a*/ . /*b*/ arg /*c*/ = /*d*/ super /*e*/ . /*f*/ arg /*g*/ | ||
super /*a*/ [ /*b*/ arg /*c*/ ] /*d*/ = /*e*/ super /*f*/ [ /*g*/ arg /*h*/ ] /*i*/ | ||
const arg = super['arg'] | ||
super['arg'] = arg | ||
delete super.arg | ||
return super[arg](arg) | ||
delete super.arg | ||
return super.barAsync(arg) | ||
} | ||
async bazAsync() { | ||
super['arg'] = super['arg'] | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
29280
507
166