jass 0.9.1 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/jass.rb +5 -0
  4. data/lib/jass/compiler.rb +5 -0
  5. data/lib/jass/plugin.rb +2 -1
  6. data/lib/jass/version.rb +1 -1
  7. data/vendor/node_modules/@types/estree/index.d.ts +4 -2
  8. data/vendor/node_modules/@types/estree/package.json +2 -2
  9. data/vendor/node_modules/acorn/bin/_acorn.js +12 -12
  10. data/vendor/node_modules/acorn/bin/run_test262.js +2 -3
  11. data/vendor/node_modules/acorn/bin/test262.whitelist +0 -5
  12. data/vendor/node_modules/acorn/dist/acorn.es.js +76 -68
  13. data/vendor/node_modules/acorn/dist/acorn.js +76 -68
  14. data/vendor/node_modules/acorn/dist/acorn_loose.es.js +42 -30
  15. data/vendor/node_modules/acorn/dist/acorn_loose.js +42 -30
  16. data/vendor/node_modules/acorn/dist/walk.es.js +47 -43
  17. data/vendor/node_modules/acorn/dist/walk.js +47 -43
  18. data/vendor/node_modules/acorn/package.json +9 -5
  19. data/vendor/node_modules/chalk/index.js.flow +93 -0
  20. data/vendor/node_modules/chalk/package.json +8 -3
  21. data/vendor/node_modules/color-convert/conversions.js +36 -29
  22. data/vendor/node_modules/color-convert/package.json +4 -4
  23. data/vendor/node_modules/estree-walker/index.d.ts +17 -0
  24. data/vendor/node_modules/estree-walker/package.json +2 -1
  25. data/vendor/node_modules/fill-range/index.js +2 -2
  26. data/vendor/node_modules/fill-range/package.json +24 -7
  27. data/vendor/node_modules/is-reference/node_modules/@types/estree/index.d.ts +546 -0
  28. data/vendor/node_modules/is-reference/node_modules/@types/estree/package.json +22 -0
  29. data/vendor/node_modules/math-random/browser.js +17 -0
  30. data/vendor/node_modules/math-random/node.js +13 -0
  31. data/vendor/node_modules/math-random/package.json +31 -0
  32. data/vendor/node_modules/math-random/test.js +26 -0
  33. data/vendor/node_modules/nodent-compiler/compiler.js +115 -11
  34. data/vendor/node_modules/nodent-compiler/{lib/output.js → output.js} +0 -0
  35. data/vendor/node_modules/nodent-compiler/package.json +8 -4
  36. data/vendor/node_modules/{nodent-compiler/lib → nodent-transform}/arboriculture.js +1340 -1107
  37. data/vendor/node_modules/nodent-transform/package.json +19 -0
  38. data/vendor/node_modules/path-parse/package.json +1 -1
  39. data/vendor/node_modules/pretty-ms/index.js +2 -1
  40. data/vendor/node_modules/pretty-ms/package.json +2 -3
  41. data/vendor/node_modules/randomatic/index.js +12 -2
  42. data/vendor/node_modules/randomatic/node_modules/is-number/index.js +6 -7
  43. data/vendor/node_modules/randomatic/node_modules/is-number/package.json +9 -16
  44. data/vendor/node_modules/randomatic/node_modules/kind-of/index.js +112 -102
  45. data/vendor/node_modules/randomatic/node_modules/kind-of/package.json +18 -20
  46. data/vendor/node_modules/randomatic/package.json +15 -13
  47. data/vendor/node_modules/repeat-element/index.js +1 -1
  48. data/vendor/node_modules/repeat-element/package.json +27 -22
  49. data/vendor/node_modules/resolve/lib/async.js +20 -17
  50. data/vendor/node_modules/resolve/lib/core.js +2 -2
  51. data/vendor/node_modules/resolve/lib/core.json +4 -1
  52. data/vendor/node_modules/resolve/lib/sync.js +52 -13
  53. data/vendor/node_modules/resolve/package.json +3 -3
  54. data/vendor/node_modules/rollup-plugin-commonjs/dist/rollup-plugin-commonjs.cjs.js +50 -12
  55. data/vendor/node_modules/rollup-plugin-commonjs/dist/rollup-plugin-commonjs.es.js +50 -12
  56. data/vendor/node_modules/rollup-plugin-commonjs/package.json +2 -2
  57. data/vendor/node_modules/rollup-plugin-commonjs/src/index.js +49 -11
  58. data/vendor/node_modules/rollup-plugin-commonjs/src/transform.js +1 -1
  59. data/vendor/node_modules/rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.cjs.js +82 -85
  60. data/vendor/node_modules/rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.es.js +82 -85
  61. data/vendor/node_modules/rollup-plugin-node-resolve/package.json +1 -1
  62. data/vendor/node_modules/rollup-plugin-node-resolve/src/index.js +81 -84
  63. data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.cjs.js +81 -2
  64. data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.es.js +81 -3
  65. data/vendor/node_modules/rollup-pluginutils/package.json +12 -6
  66. data/vendor/node_modules/rollup-pluginutils/src/attachScopes.js +10 -2
  67. data/vendor/node_modules/rollup-pluginutils/src/dataToEsm.js +69 -0
  68. data/vendor/node_modules/rollup-pluginutils/src/index.js +1 -0
  69. data/vendor/node_modules/supports-color/index.js +1 -5
  70. data/vendor/node_modules/supports-color/package.json +51 -51
  71. data/vendor/yarn.lock +65 -70
  72. metadata +16 -21
  73. data/vendor/node_modules/irregular-plurals/irregular-plurals.json +0 -146
  74. data/vendor/node_modules/irregular-plurals/package.json +0 -39
  75. data/vendor/node_modules/nodent-compiler/lib/parser.js +0 -291
  76. data/vendor/node_modules/path-parse/index.min.js +0 -1
  77. data/vendor/node_modules/path-parse/test.min.js +0 -1
  78. data/vendor/node_modules/plur/index.js +0 -20
  79. data/vendor/node_modules/plur/package.json +0 -42
  80. data/vendor/node_modules/randomatic/node_modules/is-number/node_modules/kind-of/index.js +0 -116
  81. data/vendor/node_modules/randomatic/node_modules/is-number/node_modules/kind-of/package.json +0 -90
  82. data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.es6.js +0 -217
  83. data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.es.js +0 -55
  84. data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.es6.js +0 -59
  85. data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.umd.js +0 -65
  86. data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/package.json +0 -33
  87. data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/src/estree-walker.js +0 -49
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@types/estree",
3
+ "version": "0.0.38",
4
+ "description": "TypeScript definitions for ESTree AST specification",
5
+ "license": "MIT",
6
+ "contributors": [
7
+ {
8
+ "name": "RReverser",
9
+ "url": "https://github.com/RReverser",
10
+ "githubUsername": "RReverser"
11
+ }
12
+ ],
13
+ "main": "",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://www.github.com/DefinitelyTyped/DefinitelyTyped.git"
17
+ },
18
+ "scripts": {},
19
+ "dependencies": {},
20
+ "typesPublisherContentHash": "19879f4eaa24d649d1de20d95bf747d91637d037470d47442d96dad57ec9a424",
21
+ "typeScriptVersion": "2.0"
22
+ }
@@ -0,0 +1,17 @@
1
+ module.exports = (function (global) {
2
+ var uint32 = 'Uint32Array' in global
3
+ var crypto = global.crypto || global.msCrypto
4
+ var rando = crypto && typeof crypto.getRandomValues === 'function'
5
+ var good = uint32 && crypto && rando
6
+ if (!good) return Math.random
7
+
8
+ var arr = new Uint32Array(1)
9
+ var max = Math.pow(2, 32)
10
+ function random () {
11
+ crypto.getRandomValues(arr)
12
+ return arr[0] / max
13
+ }
14
+
15
+ random.cryptographic = true
16
+ return random
17
+ })(typeof self !== 'undefined' ? self : window)
@@ -0,0 +1,13 @@
1
+ var crypto = require('crypto')
2
+ var max = Math.pow(2, 32)
3
+
4
+ module.exports = random
5
+ module.exports.cryptographic = true
6
+
7
+ function random () {
8
+ var buf = crypto
9
+ .randomBytes(4)
10
+ .toString('hex')
11
+
12
+ return parseInt(buf, 16) / max
13
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "math-random",
3
+ "version": "1.0.1",
4
+ "description": "a drop-in replacement for Math.random that uses cryptographically secure random number generation, where available",
5
+ "main": "node.js",
6
+ "browser": "browser.js",
7
+ "scripts": {
8
+ "test": "tape test.js"
9
+ },
10
+ "devDependencies": {
11
+ "array-unique": "~0.2.1",
12
+ "tape": "~4.2.2"
13
+ },
14
+ "testling": {
15
+ "files": "test.js"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git@github.com:michaelrhodes/math-random"
20
+ },
21
+ "keywords": [
22
+ "Math.random",
23
+ "crypto.getRandomValues"
24
+ ],
25
+ "author": "Michael Rhodes",
26
+ "license": "MIT",
27
+ "bugs": {
28
+ "url": "https://github.com/michaelrhodes/math-random/issues"
29
+ },
30
+ "homepage": "https://github.com/michaelrhodes/math-random"
31
+ }
@@ -0,0 +1,26 @@
1
+ var test = require('tape')
2
+ var unique = require('array-unique')
3
+ var random = require('./')
4
+
5
+ test('it works', function (assert) {
6
+ var number, l = 1000, cache = []
7
+
8
+ for (var i = 0; i < l; i++) {
9
+ number = random()
10
+ if (number <= 0) {
11
+ assert.fail('a random number was less than or equal to zero')
12
+ assert.end()
13
+ return
14
+ }
15
+ if (number >= 1) {
16
+ assert.fail('a random number was greater than or equal to one')
17
+ assert.end()
18
+ return
19
+ }
20
+ cache.push(number)
21
+ }
22
+
23
+ assert.pass('all ' + l + ' random numbers were greater than zero and less than one')
24
+ assert.equal(cache.length, unique(cache).length, 'all ' + l + ' random numbers were unique')
25
+ assert.end()
26
+ })
@@ -1,6 +1,72 @@
1
- var parser = require('./lib/parser') ;
2
- var treeSurgeon = require('./lib/arboriculture') ;
3
- var outputCode = require('./lib/output') ;
1
+ 'use strict';
2
+
3
+ var acorn = require("acorn");
4
+ var treeSurgeon = require('nodent-transform') ;
5
+ var outputCode = require('./output') ;
6
+
7
+ var alreadyInstalledPlugin = false ;
8
+
9
+ function acornParse(code,config) {
10
+ var comments = [] ;
11
+ var options = {
12
+ ecmaVersion:9,
13
+ allowHashBang:true,
14
+ allowReturnOutsideFunction:true,
15
+ allowImportExportEverywhere:true,
16
+ locations:true,
17
+ onComment:comments
18
+ } ;
19
+
20
+ if (config)
21
+ for (var k in config)
22
+ if (k !== 'noNodentExtensions' && k != 'onParserInstallation')
23
+ options[k] = config[k] ;
24
+
25
+ if (!(config && config.noNodentExtensions) || parseInt(acorn.version) < 4) {
26
+ if (!alreadyInstalledPlugin) {
27
+ if (parseInt(acorn.version) < 4)
28
+ console.warn("Nodent: Warning - noNodentExtensions option requires acorn >=v4.x. Extensions installed.") ;
29
+ require('acorn-es7-plugin')(acorn) ;
30
+ if (config && config.onParserInstallation) config.onParserInstallation(acorn) ;
31
+ alreadyInstalledPlugin = true ;
32
+ }
33
+ options.plugins = options.plugins || {} ;
34
+ options.plugins.asyncawait = {asyncExits:true, awaitAnywhere:true} ;
35
+ }
36
+
37
+ var ast = acorn.parse(code,options) ;
38
+
39
+ // attach comments to the most tightly containing node
40
+ treeSurgeon.treeWalker(ast,function(node,descend,path){
41
+ descend() ;
42
+ while (comments.length && node.loc &&
43
+ (node.loc.start.line >= comments[0].loc.start.line && node.loc.end.line>=comments[0].loc.end.line)) {
44
+ node.$comments = node.$comments||[] ;
45
+ node.$comments.push(comments.shift()) ;
46
+ }
47
+ }) ;
48
+ return ast ;
49
+ }
50
+
51
+ function parse(code) {
52
+ return acornParse(code, {
53
+ noNodentExtensions:true, // The partial parser only ever parses vanilla JS
54
+ locations:false,
55
+ ranges:false,
56
+ onComment:null
57
+ }) ;
58
+ }
59
+
60
+ function printNode(n) {
61
+ if (!n) return '' ;
62
+ if (Array.isArray(n))
63
+ return n.map(printNode).join("|\n");
64
+ try {
65
+ return outputCode(n) ; //+"\t//@"+Object.keys(n).filter(function(k){ return k[0]==='$'}).map(function(k){ return k+":"+n[k] });
66
+ } catch (ex) {
67
+ return ex.message + ": " + (n && n.type);
68
+ }
69
+ } ;
4
70
 
5
71
  /* Utils */
6
72
  function copyObj(a){
@@ -18,7 +84,11 @@ function btoa(str) {
18
84
  if (str instanceof Buffer) {
19
85
  buffer = str;
20
86
  } else {
21
- buffer = new Buffer(str.toString(), 'binary');
87
+ if (Buffer.from) {
88
+ buffer = Buffer.from(str.toString(), 'binary');
89
+ } else {
90
+ buffer = new Buffer(str.toString(), 'binary');
91
+ }
22
92
  }
23
93
 
24
94
  return buffer.toString('base64');
@@ -40,7 +110,11 @@ function compile(code,origFilename,__sourceMapping,opts) {
40
110
  }
41
111
 
42
112
  var pr = this.parse(code,origFilename,null,opts);
43
- this.asynchronize(pr,null,opts,this.log || noLogger) ;
113
+ this.transform(pr,opts,{
114
+ parse: parse, // Parse a JS fragment into an AST
115
+ printNode: printNode, // Print a node as JS source
116
+ logger:this.logger || noLogger // Log a warning
117
+ }) ;
44
118
  this.prettyPrint(pr,opts) ;
45
119
  return pr ;
46
120
  }
@@ -100,9 +174,9 @@ function parseCode(code,origFilename,__sourceMapping,opts) {
100
174
 
101
175
  var r = { origCode:code.toString(), filename:origFilename } ;
102
176
  try {
103
- r.ast = parser.parse(r.origCode, opts && opts.parser) ;
177
+ r.ast = acornParse(r.origCode, opts && opts.parser) ;
104
178
  if (opts.babelTree) {
105
- parser.treeWalker(r.ast,function(node,descend,path){
179
+ treeSurgeon.treeWalker(r.ast,function(node,descend,path){
106
180
  if (node.type==='Literal')
107
181
  path[0].replace(treeSurgeon.babelLiteralNode(node.value)) ;
108
182
  else if (node.type==='Property') {
@@ -135,14 +209,43 @@ NodentCompiler.prototype.isThenable = function(x) { return x && x instanceof Obj
135
209
  NodentCompiler.prototype.compile = compile ;
136
210
  // Exported ; but not to be used lightly!
137
211
  NodentCompiler.prototype.parse = parseCode ;
138
- NodentCompiler.prototype.asynchronize = treeSurgeon.asynchronize ;
139
- NodentCompiler.prototype.printNode = treeSurgeon.printNode ;
140
212
  NodentCompiler.prototype.prettyPrint = prettyPrint ;
141
213
  NodentCompiler.prototype.getDefaultCompileOptions = undefined ;
214
+ NodentCompiler.prototype.transform = treeSurgeon.transform ;
215
+ // asynchronize and printNode were previuosly defined in arboriculture, but they are
216
+ // are now (>3.2.0) pulled up into compiler so arboriculture.transform can be called from other
217
+ // hosts such as babel 7
218
+ NodentCompiler.prototype.asynchronize = function asynchronize(pr, __sourceMapping, opts, logger) {
219
+ try {
220
+ var tree = treeSurgeon.transform(pr, opts, {
221
+ parse: parse, // Parse a JS fragment into an AST
222
+ printNode: printNode, // Print a node as JS source
223
+ logger:logger // Log a warning
224
+ }) ;
225
+ if (opts.babelTree) {
226
+ tree.ast = treeSurgeon.treeWalker(tree.ast, function(node,descend,path){
227
+ if (node.type === 'Literal')
228
+ path[0].replace(treeSurgeon.babelLiteralNode(node.value)) ;
229
+ else
230
+ descend() ;
231
+ }) ;
232
+ }
233
+ return tree ;
234
+ } catch (ex) {
235
+ if (ex instanceof SyntaxError) {
236
+ var l = pr.origCode.substr(ex.pos - ex.loc.column);
237
+ l = l.split("\n")[0];
238
+ ex.message += " (nodent)\n" + l + "\n" + l.replace(/[\S ]/g, "-").substring(0, ex.loc.column) + "^";
239
+ ex.stack = "";
240
+ }
241
+ throw ex;
242
+ }
243
+ } ;
244
+ NodentCompiler.prototype.printNode = printNode ;
142
245
 
143
246
  Object.defineProperty(NodentCompiler.prototype,"Promise",{
144
247
  get:function (){
145
- initOpts.log("Warning: nodent.Promise is deprecated. Use nodent.Thenable instead");
248
+ console.warn("Warning: nodent.Promise is deprecated. Use nodent.Thenable instead");
146
249
  return Thenable;
147
250
  },
148
251
  enumerable:false,
@@ -159,12 +262,13 @@ NodentCompiler.initialCodeGenOpts = {
159
262
  sourcemap:true,
160
263
  engine:false,
161
264
  parser:{sourceType:'script'},
265
+ generatedSymbolPrefix:"$",
162
266
  $return:"$return",
163
267
  $error:"$error",
164
268
  $arguments:"$args",
269
+ $Promise:"Promise",
165
270
  $asyncspawn:"$asyncspawn",
166
271
  $asyncbind:"$asyncbind",
167
- generatedSymbolPrefix:"$",
168
272
  $makeThenable:'$makeThenable'
169
273
  };
170
274
 
@@ -1,15 +1,19 @@
1
1
  {
2
2
  "name": "nodent-compiler",
3
- "version": "3.1.7",
3
+ "version": "3.2.9",
4
4
  "description": "NoDent - Asynchronous Javascript language extensions",
5
5
  "main": "compiler.js",
6
6
  "scripts": {
7
- "test": "node tests/basic.js # Please install 'nodent' and test the compiler fully from there."
7
+ "test": "node tests tests/semantics/*"
8
8
  },
9
9
  "dependencies": {
10
10
  "acorn": ">=2.5.2",
11
- "acorn-es7-plugin": ">=1.1.6",
12
- "source-map": "^0.5.6"
11
+ "acorn-es7-plugin": "^1.1.7",
12
+ "nodent-transform": "^3.2.9",
13
+ "source-map": "^0.5.7"
14
+ },
15
+ "devDependencies": {
16
+ "nodent-runtime": "^3.2.1"
13
17
  },
14
18
  "repository": {
15
19
  "type": "git",
@@ -1,22 +1,8 @@
1
1
  'use strict';
2
-
3
2
  /* We manipulate (abstract syntax) trees */
4
- var parser = require('./parser');
5
- var outputCode = require('./output');
6
3
  /** Helpers **/
7
- /*global.printNode = */function printNode(n) {
8
- if (!n) return '' ;
9
- if (Array.isArray(n))
10
- return n.map(printNode).join("|\n");
11
- try {
12
- return outputCode(n) ; //+"\t//@"+Object.keys(n).filter(function(k){ return k[0]==='$'}).map(function(k){ return k+":"+n[k] });
13
- } catch (ex) {
14
- return ex.message + ": " + (n && n.type);
15
- }
16
- }
17
-
18
4
  function cloneNode(n) {
19
- if (Array.isArray(n))
5
+ if (Array.isArray(n))
20
6
  return n.map(function (n) {
21
7
  return cloneNode(n);
22
8
  });
@@ -29,40 +15,76 @@ function cloneNode(n) {
29
15
 
30
16
  /* Bit of a hack: without having to search for references to this
31
17
  * node, force it to be some replacement node */
32
- var locationInfo = { start:true, end: true, loc: true, range: true } ;
18
+ var locationInfo = {
19
+ start: true,
20
+ end: true,
21
+ loc: true,
22
+ range: true
23
+ };
33
24
  function coerce(node, replace) {
34
- if (node===replace) return ;
25
+ if (node === replace)
26
+ return;
35
27
  node.__proto__ = Object.getPrototypeOf(replace);
36
28
  Object.keys(node).forEach(function (k) {
37
- if (!(k in locationInfo))
29
+ if (!(k in locationInfo))
38
30
  delete node[k];
39
31
  });
40
32
  Object.keys(replace).forEach(function (k) {
41
- if (!(k in node))
33
+ if (!(k in node))
42
34
  node[k] = replace[k];
43
35
  });
44
36
  }
45
37
 
46
- function Nothing(){}
38
+ function Nothing() {}
47
39
 
48
40
  var examinations = {
49
- getScope: function(){ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || (this.node.type === 'ArrowFunctionExpression' && this.node.body.type === 'BlockStatement') ? this.node.body.body : this.node.type === 'Program' ? this.node.body : null},
50
- isScope: function(){ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'Program' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || (this.node.type === 'ArrowFunctionExpression' && this.node.body.type === 'BlockStatement')},
51
- isFunction: function(){ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || this.node.type === 'ArrowFunctionExpression'},
52
- isClass: function(){ return this.node.type === 'ClassDeclaration' || this.node.type === 'ClassExpression'},
53
- isBlockStatement: function(){ return this.node.type==='ClassBody' || this.node.type === 'Program' || this.node.type === 'BlockStatement' ? this.node.body : this.node.type === 'SwitchCase' ? this.node.consequent : false},
54
- isExpressionStatement: function(){ return this.node.type === 'ExpressionStatement'},
55
- isLiteral: function(){ return this.node.type === 'Literal' || this.node.type === 'BooleanLiteral' || this.node.type === 'RegExpLiteral' || this.node.type === 'NumericLiteral' || this.node.type === 'StringLiteral' || this.node.type === 'NullLiteral'},
56
- isDirective: function(){ return this.node.type === 'ExpressionStatement' && (this.node.expression.type === 'StringLiteral' || this.node.expression.type === 'Literal' && typeof this.node.expression.value === 'string')},
57
- isUnaryExpression: function(){ return this.node.type === 'UnaryExpression'},
58
- isAwait: function(){ return this.node.type === 'AwaitExpression' && !this.node.$hidden},
59
- isAsync: function(){ return this.node.async },
60
- isStatement: function(){ return this.node.type.match(/[a-zA-Z]+Declaration/) !== null || this.node.type.match(/[a-zA-Z]+Statement/) !== null},
61
- isExpression: function(){ return this.node.type.match(/[a-zA-Z]+Expression/) !== null},
62
- isLoop: function(){ return this.node.type === 'ForStatement' || this.node.type === 'WhileStatement' || this.node.type === 'DoWhileStatement'}, // Other loops?
63
- isJump: function(){ return this.node.type === 'ReturnStatement' || this.node.type === 'ThrowStatement' || this.node.type === 'BreakStatement' || this.node.type === 'ContinueStatement'},
64
- isES6: function(){
65
- switch (this.node.type) {
41
+ getScope: function () {
42
+ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || this.node.type === 'ArrowFunctionExpression' && this.node.body.type === 'BlockStatement' ? this.node.body.body : this.node.type === 'Program' ? this.node.body : null;
43
+ },
44
+ isScope: function () {
45
+ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'Program' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || this.node.type === 'ArrowFunctionExpression' && this.node.body.type === 'BlockStatement';
46
+ },
47
+ isFunction: function () {
48
+ return this.node.type === 'FunctionDeclaration' || this.node.type === 'FunctionExpression' || this.node.type === 'Function' || this.node.type === 'ObjectMethod' || this.node.type === 'ClassMethod' || this.node.type === 'ArrowFunctionExpression';
49
+ },
50
+ isClass: function () {
51
+ return this.node.type === 'ClassDeclaration' || this.node.type === 'ClassExpression';
52
+ },
53
+ isBlockStatement: function () {
54
+ return this.node.type === 'ClassBody' || this.node.type === 'Program' || this.node.type === 'BlockStatement' ? this.node.body : this.node.type === 'SwitchCase' ? this.node.consequent : false;
55
+ },
56
+ isExpressionStatement: function () {
57
+ return this.node.type === 'ExpressionStatement';
58
+ },
59
+ isLiteral: function () {
60
+ return this.node.type === 'Literal' || this.node.type === 'BooleanLiteral' || this.node.type === 'RegExpLiteral' || this.node.type === 'NumericLiteral' || this.node.type === 'StringLiteral' || this.node.type === 'NullLiteral';
61
+ },
62
+ isDirective: function () {
63
+ return this.node.type === 'ExpressionStatement' && (this.node.expression.type === 'StringLiteral' || this.node.expression.type === 'Literal' && typeof this.node.expression.value === 'string');
64
+ },
65
+ isUnaryExpression: function () {
66
+ return this.node.type === 'UnaryExpression';
67
+ },
68
+ isAwait: function () {
69
+ return this.node.type === 'AwaitExpression' && !this.node.$hidden;
70
+ },
71
+ isAsync: function () {
72
+ return this.node.async;
73
+ },
74
+ isStatement: function () {
75
+ return this.node.type.match(/[a-zA-Z]+Declaration/) !== null || this.node.type.match(/[a-zA-Z]+Statement/) !== null;
76
+ },
77
+ isExpression: function () {
78
+ return this.node.type.match(/[a-zA-Z]+Expression/) !== null;
79
+ },
80
+ isLoop: function () { // Other loops?
81
+ return this.node.type === 'ForStatement' || this.node.type === 'WhileStatement' || this.node.type === 'DoWhileStatement';
82
+ },
83
+ isJump: function () {
84
+ return this.node.type === 'ReturnStatement' || this.node.type === 'ThrowStatement' || this.node.type === 'BreakStatement' || this.node.type === 'ContinueStatement';
85
+ },
86
+ isES6: function () {
87
+ switch (this.node.type) {
66
88
  case 'ExportNamedDeclaration':
67
89
  case 'ExportSpecifier':
68
90
  case 'ExportDefaultDeclaration':
@@ -81,111 +103,36 @@ var examinations = {
81
103
  case 'TemplateLiteral':
82
104
  case 'ClassDeclaration':
83
105
  case 'ClassExpression':
84
- return true ;
85
-
106
+ return true;
86
107
  case 'VariableDeclaration':
87
- return this.node.kind && this.node.kind !== 'var' ;
88
-
108
+ return this.node.kind && this.node.kind === 'let';
89
109
  case 'FunctionDeclaration':
90
110
  case 'FunctionExpression':
91
- return !!this.node.generator;
111
+ return !(!this.node.generator);
92
112
  }
93
- }
113
+ }
94
114
  };
95
-
96
- var NodeExaminer = {} ;
97
- Object.keys(examinations).forEach(function(k){
98
- Object.defineProperty(NodeExaminer,k,{
99
- get:examinations[k]
100
- }) ;
101
- }) ;
102
-
115
+ var NodeExaminer = {};
116
+ Object.keys(examinations).forEach(function (k) {
117
+ Object.defineProperty(NodeExaminer, k, {
118
+ get: examinations[k]
119
+ });
120
+ });
103
121
  function examine(node) {
104
- if (!node)
122
+ if (!node)
105
123
  return {};
106
- NodeExaminer.node = node ;
107
- return NodeExaminer ;
108
- }
109
-
110
- /*
111
- * descendOn = true Enter scopes within scopes
112
- * descendOn = false/undefined/null Do not enter scopes within scopes
113
- * descendOn = function Descend when function(node) is true
114
- */
115
- function contains(ast, fn, descendOn) {
116
- if (!ast)
117
- return null;
118
- if (fn && typeof fn === 'object') {
119
- var keys = Object.keys(fn);
120
- return contains(ast, function (node) {
121
- return keys.every(function (k) {
122
- return node[k] == fn[k];
123
- });
124
- });
125
- }
126
- var n, found = {};
127
- if (Array.isArray(ast)) {
128
- for (var i = 0;i < ast.length; i++)
129
- if (n = contains(ast[i], fn))
130
- return n;
131
- return null;
132
- }
133
-
134
- var subScopes = descendOn ;
135
- if (typeof descendOn !== "function") {
136
- if (descendOn) {
137
- subScopes = function(n) { return true } ;
138
- } else {
139
- subScopes = function(n) { return !examine(n).isScope } ;
140
- }
141
- }
142
-
143
- try {
144
- parser.treeWalker(ast, function (node, descend, path) {
145
- if (fn(node)) {
146
- found.path = path;
147
- throw found;
148
- }
149
- if (node === ast || subScopes(node))
150
- descend();
151
- });
152
- } catch (ex) {
153
- if (ex === found)
154
- return found.path;
155
- throw ex;
156
- }
157
- return null;
158
- }
159
-
160
- function containsAwait(ast) {
161
- return contains(ast, function(n){
162
- return n.type==='AwaitExpression' && !n.$hidden
163
- });
164
- }
165
-
166
- function containsAwaitInBlock(ast) {
167
- return contains(ast, function(n){
168
- return n.type==='AwaitExpression' && !n.$hidden
169
- }, function (n) {
170
- var x = examine(n) ;
171
- return !x.isBlockStatement && !x.isScope
172
- });
173
- }
174
-
175
- function containsThis(ast) {
176
- return contains(ast, {
177
- type: 'ThisExpression'
178
- });
124
+ NodeExaminer.node = node;
125
+ return NodeExaminer;
179
126
  }
180
127
 
181
128
  function babelLiteralNode(value) {
182
- if (value === null)
129
+ if (value === null)
183
130
  return {
184
131
  type: 'NullLiteral',
185
132
  value: null,
186
133
  raw: 'null'
187
134
  };
188
- if (value === true || value === false)
135
+ if (value === true || value === false)
189
136
  return {
190
137
  type: 'BooleanLiteral',
191
138
  value: value,
@@ -202,7 +149,7 @@ function babelLiteralNode(value) {
202
149
  flags: parts[2]
203
150
  };
204
151
  }
205
- if (typeof value === 'number')
152
+ if (typeof value === 'number')
206
153
  return {
207
154
  type: 'NumericLiteral',
208
155
  value: value,
@@ -216,6 +163,8 @@ function babelLiteralNode(value) {
216
163
  }
217
164
 
218
165
  function ident(name, loc) {
166
+ if (!name)
167
+ throw new Error("Illegal Identifier name") ;
219
168
  return {
220
169
  type: 'Identifier',
221
170
  name: name,
@@ -225,70 +174,166 @@ function ident(name, loc) {
225
174
 
226
175
  function idents(s) {
227
176
  var r = {};
228
- for (var k in s)
177
+ for (var k in s)
229
178
  r[k] = typeof s[k] === "string" ? ident(s[k]) : s[k];
230
179
  return r;
231
180
  }
232
181
 
233
- function asynchronize(pr, __sourceMapping, opts, logger) {
182
+ function asynchronize(pr, opts, logger, parsePart, printNode) {
234
183
  var continuations = {};
235
184
  var generatedSymbol = 1;
236
185
  var genIdent = {};
186
+
237
187
  Object.keys(opts).filter(function (k) {
238
188
  return k[0] === '$';
239
189
  }).forEach(function (k) {
240
- genIdent[k.slice(1)] = ident(opts[k]);
190
+ if (opts[k])
191
+ genIdent[k.slice(1)] = ident(opts[k]);
241
192
  });
242
-
193
+ /*
194
+ * descendOn = true Enter scopes within scopes
195
+ * descendOn = false/undefined/null Do not enter scopes within scopes
196
+ * descendOn = function Descend when function(node) is true
197
+ */
198
+ function contains(ast, fn, descendOn) {
199
+ if (!ast)
200
+ return null;
201
+ if (fn && typeof fn === 'object') {
202
+ var keys = Object.keys(fn);
203
+ return contains(ast, function (node) {
204
+ return keys.every(function (k) {
205
+ return node[k] == fn[k];
206
+ });
207
+ });
208
+ }
209
+ var n, found = {};
210
+ if (Array.isArray(ast)) {
211
+ for (var i = 0;i < ast.length; i++)
212
+ if (n = contains(ast[i], fn))
213
+ return n;
214
+ return null;
215
+ }
216
+ var subScopes = descendOn;
217
+ if (typeof descendOn !== "function") {
218
+ if (descendOn) {
219
+ subScopes = function (n) {
220
+ return true;
221
+ };
222
+ } else {
223
+ subScopes = function (n) {
224
+ return !examine(n).isScope;
225
+ };
226
+ }
227
+ }
228
+ try {
229
+ treeWalk(ast, function (node, descend, path) {
230
+ if (fn(node)) {
231
+ found.path = path;
232
+ throw found;
233
+ }
234
+ if (node === ast || subScopes(node))
235
+ descend();
236
+ });
237
+ } catch (ex) {
238
+ if (ex === found)
239
+ return found.path;
240
+ throw ex;
241
+ }
242
+ return null;
243
+ }
244
+
245
+ function containsAwait(ast) {
246
+ return contains(ast, function (n) {
247
+ return n.type === 'AwaitExpression' && !n.$hidden;
248
+ });
249
+ }
250
+
251
+ function containsAwaitInBlock(ast) {
252
+ return contains(ast, function (n) {
253
+ return n.type === 'AwaitExpression' && !n.$hidden;
254
+ }, function (n) {
255
+ var x = examine(n);
256
+ return !x.isBlockStatement && !x.isScope;
257
+ });
258
+ }
259
+
260
+ function containsThis(ast) {
261
+ return contains(ast, {
262
+ type: 'ThisExpression'
263
+ });
264
+ }
265
+
243
266
  /* Generate a prototypical call of the form:
244
267
  * (left).$asyncbind(this,...args)
245
268
  */
246
- function bindAsync(left,arg) {
247
- if (opts.es6target && !left.id && !arg && left.type.indexOf("Function")===0) {
248
- left.type = 'ArrowFunctionExpression' ;
249
- return left ;
269
+ function bindAsync(left, arg) {
270
+ if (opts.es6target && !left.id && !arg && left.type.indexOf("Function") === 0) {
271
+ left.type = 'ArrowFunctionExpression';
272
+ return left;
250
273
  }
251
-
252
274
  if (opts.noRuntime) {
253
275
  if (arg) {
254
276
  if (examine(arg).isLiteral) {
255
- throw new Error("Nodent: 'noRuntime' option only compatible with -promise and -engine modes") ;
277
+ throw new Error("Nodent: 'noRuntime' option only compatible with -promise and -engine modes");
256
278
  }
257
279
  // Add a global synchronous exception handler to (left)
258
- left.body.body = parser.part("try {$:0} catch($2) {return $1($2)}",[cloneNode(left.body),arg,ident('$boundEx')]).body ;
259
- } else if (opts.es6target && !left.id && left.type.indexOf("Function")===0) {
260
- left.type = 'ArrowFunctionExpression' ;
261
- return left ;
280
+ left.body.body = parsePart("try {$:0} catch($2) {return $1($2)}", [cloneNode(left.body),
281
+ arg,ident('$boundEx')]).body;
282
+ } else if (opts.es6target && !left.id && left.type.indexOf("Function") === 0) {
283
+ left.type = 'ArrowFunctionExpression';
284
+ return left;
262
285
  }
263
286
  if (opts.es6target && !left.id) {
264
- left.type = 'ArrowFunctionExpression' ;
287
+ left.type = 'ArrowFunctionExpression';
265
288
  return left;
266
289
  }
267
- return parser.part("$0.bind(this)",[left]).expr;
290
+ if (containsThis(left))
291
+ return parsePart("$0.bind(this)", [left]).expr;
292
+ return left;
268
293
  }
269
-
270
- var params = [{ "type": "ThisExpression" }] ;
271
- if (arg) {
272
- return parser.part("$0.$1(this,$2)",[left,genIdent.asyncbind,arg]).expr;
294
+ var subst = {
295
+ runtime: genIdent.runtime,
296
+ asyncbind: genIdent.asyncbind,
297
+ fn: left,
298
+ arg: arg
299
+ };
300
+ if (opts.$runtime) {
301
+ if (arg) {
302
+ return parsePart("$runtime.$asyncbind.call($fn,this,$arg)", subst).expr;
303
+ } else {
304
+ if (opts.lazyThenables || containsThis(left))
305
+ return parsePart("$runtime.$asyncbind.call($fn,this)", subst).expr;
306
+ return left;
307
+ }
308
+ } else {
309
+ if (arg) {
310
+ return parsePart("$fn.$asyncbind(this,$arg)", subst).expr;
311
+ } else {
312
+ if (opts.lazyThenables || containsThis(left))
313
+ return parsePart("$fn.$asyncbind(this)", subst).expr;
314
+ return left;
315
+ }
273
316
  }
274
- return parser.part("$0.$1(this)",[left,genIdent.asyncbind]).expr;
275
317
  }
276
-
318
+
277
319
  function makeBoundFn(name, body, argnames, binding) {
278
- return parser.part("var $0 = $1",[ident(name),bindAsync({
279
- "type": "FunctionExpression",
280
- "id": null,
281
- "generator": false,
282
- "expression": false,
283
- "params": argnames || [],
284
- "body": Array.isArray(body)?{type:'BlockStatement',body:body}:body
285
- }, binding)]).body[0] ;
320
+ return parsePart("var $0 = $1", [ident(name),bindAsync({
321
+ "type": "FunctionExpression",
322
+ "id": null,
323
+ "generator": false,
324
+ "expression": false,
325
+ "params": argnames || [],
326
+ "body": Array.isArray(body) ? {
327
+ type: 'BlockStatement',
328
+ body: body
329
+ } : body
330
+ }, binding)]).body[0];
286
331
  }
287
-
332
+
288
333
  function where(node) {
289
334
  return pr.filename + (node && node.loc && node.loc.start ? "(" + node.loc.start.line + ":" + node.loc.start.column + ")\t" : "\t");
290
335
  }
291
-
336
+
292
337
  function literal(value) {
293
338
  if (opts.babelTree) {
294
339
  return babelLiteralNode(value);
@@ -300,10 +345,10 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
300
345
  };
301
346
  }
302
347
  }
303
-
348
+
304
349
  function getMemberFunction(node) {
305
- if (!node)
306
- return null ;
350
+ if (!node)
351
+ return null;
307
352
  if (opts.babelTree && (node.type === 'ClassMethod' || node.type === 'ObjectMethod')) {
308
353
  return node;
309
354
  } else if ((!opts.babelTree && node.type === 'MethodDefinition' || node.type === 'Property' && (node.method || node.kind == 'get' || node.kind == 'set')) && examine(node.value).isFunction) {
@@ -311,50 +356,47 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
311
356
  }
312
357
  return null;
313
358
  }
314
-
315
- var assign$Args = parser.part("var $0 = arguments",[genIdent.arguments]).body[0] ;
316
-
359
+
360
+ var assign$Args = parsePart("var $0 = arguments", [genIdent.arguments]).body[0];
317
361
  /* Replace 'arguments' identifiers in a function. Return true if a
318
362
  * replacement has been made and so the symbol opts.$arguments needs
319
363
  * initializing.
320
364
  */
321
- function replaceArguments(ast,nested) {
322
- if (!examine(ast).isFunction)
323
- throw new Error("Can only replace 'arguments' in functions") ;
324
-
365
+ function replaceArguments(ast, nested) {
366
+ if (!examine(ast).isFunction)
367
+ throw new Error("Can only replace 'arguments' in functions");
325
368
  if (!('$usesArguments' in ast)) {
326
- parser.treeWalker(ast, function (node, descend, path) {
369
+ treeWalk(ast, function (node, descend, path) {
327
370
  if (node.type === 'Identifier' && node.name === 'arguments') {
328
371
  // Fix up shorthand properties
329
372
  if (path[0].parent.shorthand) {
330
- path[0].parent.shorthand = false ;
331
- path[0].parent.key = ident('arguments') ;
332
- ast.$usesArguments = true ;
373
+ path[0].parent.shorthand = false;
374
+ path[0].parent.key = ident('arguments');
375
+ ast.$usesArguments = true;
333
376
  }
334
-
335
377
  // Replace identifiers that are not keys
336
- if (path[0].field !== 'key') {
337
- node.name = opts.$arguments;
338
- ast.$usesArguments = true ;
378
+ if (path[0].field !== 'key' && path[0].field !== 'property') {
379
+ node.name = opts.$arguments;
380
+ ast.$usesArguments = true;
339
381
  }
340
382
  } else if (node === ast || !examine(node).isFunction) {
341
- descend();
342
- } else if (node.type==='ArrowFunctionExpression') {
343
- replaceArguments(node) ;
344
- ast.$usesArguments = ast.$usesArguments || node.$usesArguments ;
383
+ descend();
384
+ } else if (node.type === 'ArrowFunctionExpression') {
385
+ replaceArguments(node);
386
+ ast.$usesArguments = ast.$usesArguments || node.$usesArguments;
345
387
  }
346
388
  });
347
- ast.$usesArguments = ast.$usesArguments || false ;
389
+ ast.$usesArguments = ast.$usesArguments || false;
348
390
  }
349
391
  return ast.$usesArguments && ast.type !== 'ArrowFunctionExpression';
350
392
  }
351
-
393
+
352
394
  function generateSymbol(node) {
353
- if (typeof node != 'string')
354
- node = node.type.replace(/Statement|Expression/g,"");
395
+ if (typeof node != 'string')
396
+ node = node.type.replace(/Statement|Expression/g, "");
355
397
  return opts.generatedSymbolPrefix + node + "_" + generatedSymbol++;
356
398
  }
357
-
399
+
358
400
  function setExit(n, sym) {
359
401
  if (n) {
360
402
  n.$exit = idents({
@@ -364,7 +406,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
364
406
  }
365
407
  return n;
366
408
  }
367
-
409
+
368
410
  function getExitNode(path) {
369
411
  for (var n = 0;n < path.length; n++) {
370
412
  if (path[n].self.$exit) {
@@ -376,19 +418,24 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
376
418
  }
377
419
  return null;
378
420
  }
379
-
421
+
380
422
  function getExit(path, parents) {
381
423
  var n = getExitNode(path);
382
- if (n)
424
+ if (n)
383
425
  return n.$exit;
384
426
  if (parents) {
385
- for (var i = 0;i < parents.length; i++)
386
- if (parents[i])
427
+ for (var i = 0;i < parents.length; i++)
428
+ if (parents[i])
387
429
  return idents(parents[i]);
388
430
  }
389
431
  return null;
390
432
  }
391
433
 
434
+
435
+ var looksLikeES6 = opts.es6target || pr.ast.type === 'Program' && pr.ast.sourceType === 'module' || contains(pr.ast, function (n) {
436
+ return examine(n).isES6;
437
+ }, true);
438
+
392
439
  // actually do the transforms
393
440
  if (opts.engine) {
394
441
  // Only Transform extensions:
@@ -398,33 +445,25 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
398
445
  // - get async id(){} / async get id(){}
399
446
  // - super references (in case they are used by async exits - in general they aren't)
400
447
  // Everything else is passed through unmolested to be run by a JS engine such as V8 v5.4
401
- pr.ast = fixSuperReferences(pr.ast,true);
448
+ pr.ast = fixSuperReferences(pr.ast, true);
402
449
  pr.ast = asyncSpawn(pr.ast, opts.engine);
403
450
  pr.ast = exposeCompilerOpts(pr.ast);
404
- cleanCode(pr.ast)
451
+ cleanCode(pr.ast);
405
452
  } else if (opts.generators) {
406
453
  // Transform to generators
407
454
  pr.ast = fixSuperReferences(pr.ast);
408
455
  pr.ast = asyncSpawn(pr.ast);
409
456
  pr.ast = exposeCompilerOpts(pr.ast);
410
- cleanCode(pr.ast)
457
+ cleanCode(pr.ast);
411
458
  } else {
412
459
  // Transform to callbacks, optionally with Promises
413
460
  pr.ast = fixSuperReferences(pr.ast);
414
461
  asyncTransforms(pr.ast);
415
462
  }
416
- if (opts.babelTree) {
417
- parser.treeWalker(pr.ast, function (node, descend, path) {
418
- descend();
419
- if (node.type === 'Literal') {
420
- coerce(node, literal(node.value));
421
- }
422
- });
423
- }
424
463
  return pr;
425
-
464
+
426
465
  function asyncTransforms(ast, awaitFlag) {
427
- var useLazyLoops = !(opts.promises || opts.generators || opts.engine) && opts.lazyThenables ;
466
+ var useLazyLoops = !(opts.promises || opts.generators || opts.engine) && opts.lazyThenables;
428
467
  // Because we create functions (and scopes), we need all declarations before use
429
468
  blockifyArrows(ast);
430
469
  hoistDeclarations(ast);
@@ -436,31 +475,32 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
436
475
  // Loops are asynchronized in an odd way - the loop is turned into a function that is
437
476
  // invoked through tail recursion OR callback. They are like the inner functions of
438
477
  // async functions to allow for completion and throwing
439
- (useLazyLoops?asyncLoops_1:Nothing)(ast);
478
+ (useLazyLoops ? asyncLoops_1 : Nothing)(ast);
440
479
  // Handle the various JS control flow keywords by splitting into continuations that could
441
480
  // be invoked asynchronously
442
481
  mapLogicalOp(ast);
443
482
  mapCondOp(ast);
444
- walkDown(ast, [mapTryCatch,(useLazyLoops?Nothing:mapLoops),mapIfStmt,mapSwitch,mapBlock]);
483
+ walkDown(ast, [mapTryCatch,useLazyLoops ? Nothing : mapLoops,mapIfStmt,mapSwitch,
484
+ mapBlock]);
445
485
  // Map awaits by creating continuations and passing them into the async resolver
446
486
  asyncAwait(ast, awaitFlag);
447
487
  exposeCompilerOpts(ast);
448
488
  // Remove guff generated by transpiling
449
489
  cleanCode(ast);
450
490
  }
451
-
491
+
452
492
  /* Create a 'continuation' - a block of statements that have been hoisted
453
493
  * into a named function so they can be invoked conditionally or asynchronously */
454
494
  function makeContinuation(name, body) {
455
495
  var ctn = {
456
496
  $continuation: true,
457
- type: name?'FunctionDeclaration':'FunctionExpression',
458
- id: name?typeof name==="string"?ident(name):name:undefined,
459
- params: [],
460
- body: {
461
- type: 'BlockStatement',
462
- body: cloneNode(body)
463
- }
497
+ type: name ? 'FunctionDeclaration' : 'FunctionExpression',
498
+ id: name ? typeof name === "string" ? ident(name) : name : undefined,
499
+ params: [],
500
+ body: {
501
+ type: 'BlockStatement',
502
+ body: cloneNode(body)
503
+ }
464
504
  };
465
505
  if (name) {
466
506
  continuations[name] = {
@@ -469,7 +509,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
469
509
  }
470
510
  return ctn;
471
511
  }
472
-
512
+
473
513
  /* Generate an expression AST the immediate invokes the specified async function, e.g.
474
514
  * (await ((async function(){ ...body... })()))
475
515
  */
@@ -487,9 +527,9 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
487
527
  "body": body
488
528
  }
489
529
  }).body.body[0].argument
490
- }
530
+ };
491
531
  }
492
-
532
+
493
533
  /* Used to invoke a 'continuation' - a function that represents
494
534
  * a block of statements lifted out so they can be labelled (as
495
535
  * a function definition) to be invoked via multiple execution
@@ -497,20 +537,23 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
497
537
  * in the original scope of the statements, the continuation function
498
538
  * must also have the correct 'this'.*/
499
539
  function thisCall(name, args) {
500
- if (typeof name === 'string')
540
+ if (typeof name === 'string')
501
541
  name = ident(name);
502
- var n = parser.part("$0.call($1)",[name,[{"type": "ThisExpression"}].concat(args || [])]).expr ;
542
+ var n = parsePart("$0.call($1)", [name,[{
543
+ "type": "ThisExpression"
544
+ }].concat(args || [])]).expr;
503
545
  name.$thisCall = n;
504
546
  n.$thisCallName = name.name;
505
547
  return n;
506
548
  }
507
- function returnThisCall(name,args) {
549
+
550
+ function returnThisCall(name, args) {
508
551
  return {
509
- type:'ReturnStatement',
510
- argument: thisCall(name,args)
511
- }
552
+ type: 'ReturnStatement',
553
+ argument: thisCall(name, args)
554
+ };
512
555
  }
513
-
556
+
514
557
  function deferredFinally(node, expr) {
515
558
  return {
516
559
  "type": "CallExpression",
@@ -518,7 +561,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
518
561
  "arguments": expr ? [expr] : []
519
562
  };
520
563
  }
521
-
564
+
522
565
  /**
523
566
  * returnMapper is an Uglify2 transformer that is used to change statements such as:
524
567
  * return some-expression ;
@@ -536,8 +579,8 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
536
579
  });
537
580
  }
538
581
  var lambdaNesting = 0;
539
- var tryNesting = 0 ;
540
- return parser.treeWalker(n, function (node, descend, path) {
582
+ var tryNesting = 0;
583
+ return treeWalk(n, function (node, descend, path) {
541
584
  if (node.type === 'ReturnStatement' && !node.$mapped) {
542
585
  if (lambdaNesting > 0) {
543
586
  if (!examine(node).isAsync) {
@@ -571,7 +614,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
571
614
  }
572
615
  return;
573
616
  } else if (node.type === 'ThrowStatement') {
574
- var isAsync = examine(node).isAsync ;
617
+ var isAsync = examine(node).isAsync;
575
618
  if (lambdaNesting > 0) {
576
619
  if (!isAsync) {
577
620
  return descend(node);
@@ -579,22 +622,22 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
579
622
  delete node.async;
580
623
  }
581
624
  if (!isAsync && tryNesting) {
582
- descend() ;
625
+ descend();
583
626
  } else {
584
- node.type = 'ReturnStatement';
585
- node.$mapped = true;
586
- node.argument = {
587
- type: 'CallExpression',
588
- callee: getExit(path, [opts]).$error,
589
- arguments: [node.argument]
590
- };
627
+ node.type = 'ReturnStatement';
628
+ node.$mapped = true;
629
+ node.argument = {
630
+ type: 'CallExpression',
631
+ callee: getExit(path, [opts]).$error,
632
+ arguments: [node.argument]
633
+ };
591
634
  }
592
635
  return;
593
636
  } else if (node.type === 'TryStatement') {
594
- tryNesting++;
595
- descend(node);
596
- tryNesting--;
597
- return;
637
+ tryNesting++;
638
+ descend(node);
639
+ tryNesting--;
640
+ return;
598
641
  } else if (examine(node).isFunction) {
599
642
  lambdaNesting++;
600
643
  descend(node);
@@ -606,7 +649,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
606
649
  }
607
650
  }, path);
608
651
  }
609
-
652
+
610
653
  /*
611
654
  To implement conditional execution, a?b:c is mapped to
612
655
 
@@ -615,21 +658,22 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
615
658
  Note that 'await (async function(){})()' can be optimized to a Thenable since no args are passed
616
659
  */
617
660
  function mapCondOp(ast, state) {
618
- if (Array.isArray(ast))
661
+ if (Array.isArray(ast))
619
662
  return ast.map(function (n) {
620
663
  return mapCondOp(n, state);
621
664
  });
622
- parser.treeWalker(ast, function (node, descend, path) {
665
+ treeWalk(ast, function (node, descend, path) {
623
666
  descend();
624
667
  if (node.type === 'ConditionalExpression' && (containsAwait(node.alternate) || containsAwait(node.consequent))) {
625
668
  var z = ident(generateSymbol("condOp"));
626
- var xform = internalIIAFE(parser.part("if ($0) return $1 ; return $2",[node.test,node.consequent,node.alternate]).body);
669
+ var xform = internalIIAFE(parsePart("if ($0) return $1 ; return $2", [node.test,
670
+ node.consequent,node.alternate]).body);
627
671
  coerce(node, xform);
628
672
  }
629
673
  }, state);
630
674
  return ast;
631
675
  }
632
-
676
+
633
677
  /*
634
678
  To implement conditional execution, logical operators with an awaited RHS are mapped thus:
635
679
 
@@ -639,56 +683,57 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
639
683
  Note that 'await (async function(){})()' can be optimized to a Thenable since no args are passed
640
684
  */
641
685
  function mapLogicalOp(ast, state) {
642
- if (Array.isArray(ast))
686
+ if (Array.isArray(ast))
643
687
  return ast.map(function (n) {
644
688
  return mapLogicalOp(n, state);
645
689
  });
646
- parser.treeWalker(ast, function (node, descend, path) {
690
+ treeWalk(ast, function (node, descend, path) {
647
691
  descend();
648
692
  if (node.type === 'LogicalExpression' && containsAwait(node.right)) {
649
693
  var codeFrag;
650
694
  var z = ident(generateSymbol("logical" + (node.operator === '&&' ? "And" : "Or")));
651
-
652
695
  if (node.operator === '||') {
653
- codeFrag = "var $0; if (!($0 = $1)) {$0 = $2} return $0" ;
696
+ codeFrag = "var $0; if (!($0 = $1)) {$0 = $2} return $0";
654
697
  } else if (node.operator === '&&') {
655
- codeFrag = "var $0; if ($0 = $1) {$0 = $2} return $0" ;
656
- } else
657
- throw new Error(where(node) + "Illegal logical operator: "+node.operator);
658
-
659
- coerce(node, internalIIAFE(parser.part(codeFrag,[z,node.left, node.right]).body));
698
+ codeFrag = "var $0; if ($0 = $1) {$0 = $2} return $0";
699
+ } else
700
+ throw new Error(where(node) + "Illegal logical operator: " + node.operator);
701
+ coerce(node, internalIIAFE(parsePart(codeFrag, [z,node.left,node.right]).body));
660
702
  }
661
703
  }, state);
662
704
  return ast;
663
705
  }
664
-
706
+
665
707
  function mapBlock(block, path, down) {
666
708
  if (block.type !== "SwitchCase" && examine(block).isBlockStatement) {
667
- var idx = 0 ;
709
+ var idx = 0;
668
710
  while (idx < block.body.length) {
669
- var node = block.body[idx] ;
711
+ var node = block.body[idx];
670
712
  if (node.type !== "SwitchCase" && examine(node).isBlockStatement) {
671
- var blockScoped = containsBlockScopedDeclarations(node.body) ;
713
+ var blockScoped = containsBlockScopedDeclarations(node.body);
672
714
  if (!blockScoped) {
673
- block.body.splice.apply(block.body,[idx,1].concat(node.body));
715
+ block.body.splice.apply(block.body, [idx,1].concat(node.body));
674
716
  } else {
675
717
  if (containsAwaitInBlock(node)) {
676
718
  var symName = generateSymbol(node);
677
719
  var deferredCode = block.body.splice(idx + 1, block.body.length - (idx + 1));
678
720
  if (deferredCode.length) {
679
721
  var ctn = makeContinuation(symName, deferredCode);
680
- delete continuations[symName] ;
722
+ delete continuations[symName];
681
723
  node.body.push(returnThisCall(symName));
682
- block.body.push(ctn) ;
683
- idx++ ;
684
- } else idx++ ;
685
- } else idx++ ;
724
+ block.body.push(ctn);
725
+ idx++;
726
+ } else
727
+ idx++;
728
+ } else
729
+ idx++;
686
730
  }
687
- } else idx++ ;
731
+ } else
732
+ idx++;
688
733
  }
689
734
  }
690
735
  }
691
-
736
+
692
737
  /*
693
738
  * Translate:
694
739
  if (x) { y; } more... ;
@@ -714,12 +759,12 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
714
759
  var call = returnThisCall(symName);
715
760
  synthBlock.body.push(down(makeContinuation(symName, deferredCode)));
716
761
  [ifStmt.consequent,ifStmt.alternate].forEach(function (cond) {
717
- if (!cond)
762
+ if (!cond)
718
763
  return;
719
764
  var blockEnd;
720
- if (!examine(cond).isBlockStatement)
765
+ if (!examine(cond).isBlockStatement)
721
766
  blockEnd = cond;
722
- else
767
+ else
723
768
  blockEnd = cond.body[cond.body.length - 1];
724
769
  if (!(blockEnd && blockEnd.type === 'ReturnStatement')) {
725
770
  if (!(cond.type === 'BlockStatement')) {
@@ -735,7 +780,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
735
780
  });
736
781
  // If both blocks are transformed, the trailing call to $post_if()
737
782
  // can be omitted as it'll be unreachable via a synchronous path
738
- if (!(ifStmt.consequent && ifStmt.alternate && ifStmt.consequent.$deferred && ifStmt.alternate.$deferred))
783
+ if (!(ifStmt.consequent && ifStmt.alternate && ifStmt.consequent.$deferred && ifStmt.alternate.$deferred))
739
784
  synthBlock.body.push(cloneNode(call));
740
785
  }
741
786
  } else {
@@ -743,7 +788,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
743
788
  }
744
789
  }
745
790
  }
746
-
791
+
747
792
  function mapSwitch(switchStmt, path, down) {
748
793
  if (!switchStmt.$switched && switchStmt.type === 'SwitchStatement' && containsAwait(switchStmt.cases)) {
749
794
  switchStmt.$switched = true;
@@ -751,7 +796,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
751
796
  if ('index' in ref) {
752
797
  var j = ref.index + 1;
753
798
  deferredCode = ref.parent[ref.field].splice(j, ref.parent[ref.field].length - j);
754
- if (deferredCode.length && deferredCode[deferredCode.length - 1].type === 'BreakStatement')
799
+ if (deferredCode.length && deferredCode[deferredCode.length - 1].type === 'BreakStatement')
755
800
  ref.parent[ref.field].push(deferredCode.pop());
756
801
  symName = generateSymbol(switchStmt);
757
802
  deferred = returnThisCall(symName);
@@ -766,7 +811,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
766
811
  if (containsAwait(caseStmt.consequent)) {
767
812
  var end = caseStmt.consequent[caseStmt.consequent.length - 1];
768
813
  if (end.type === 'BreakStatement') {
769
- caseStmt.consequent[caseStmt.consequent.length - 1] = cloneNode(deferred) ;
814
+ caseStmt.consequent[caseStmt.consequent.length - 1] = cloneNode(deferred);
770
815
  } else if (end.type === 'ReturnStatement' || end.type === 'ThrowStatement') {} else {
771
816
  // Do nothing - block ends in return or throw
772
817
  logger(where(caseStmt) + "switch-case fall-through not supported - added break. See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification");
@@ -777,27 +822,27 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
777
822
  return true;
778
823
  }
779
824
  }
780
-
825
+
781
826
  function isExitStatement(n) {
782
- return n.type==='ReturnStatement' || n.type==='ThrowStatement'
827
+ return n.type === 'ReturnStatement' || n.type === 'ThrowStatement';
783
828
  }
829
+
784
830
  /* Give unique names to TryCatch blocks */
785
- function labelTryCatch(ast,engineMode) {
786
- parser.treeWalker(ast, function (node, descend, path) {
831
+ function labelTryCatch(ast, engineMode) {
832
+ treeWalk(ast, function (node, descend, path) {
787
833
  if (node.type === 'TryStatement' && !node.$seh) {
788
834
  if (!examine(path[0].parent).isBlockStatement) {
789
- path[0].parent[path[0].field] = {
790
- type:'BlockStatement',
791
- body:[node]
792
- } ;
835
+ path[0].parent[path[0].field] = {
836
+ type: 'BlockStatement',
837
+ body: [node]
838
+ };
793
839
  }
794
840
  // Every try-catch needs a name, so asyncDefine/asyncAwait knows who's handling errors
795
841
  node.$seh = generateSymbol("Try") + "_";
796
- node.$containedAwait = !!containsAwait(node);
797
- node.$finallyExit = node.finalizer && inAsync(path) && !!contains(node.finalizer.body,isExitStatement) ;
798
-
842
+ node.$containedAwait = !(!containsAwait(node));
843
+ node.$finallyExit = node.finalizer && inAsync(path) && !(!contains(node.finalizer.body, isExitStatement));
799
844
  if (node.$containedAwait || node.$finallyExit) {
800
- node.$needsMapping = engineMode? !node.$finallyExit : true ;
845
+ node.$needsMapping = engineMode ? !node.$finallyExit : true;
801
846
  var parent = getExit(path, [opts]);
802
847
  if (node.finalizer && !node.handler) {
803
848
  // We have a finally, but no 'catch'. Create the default catch clause 'catch(_ex) { throw _ex }'
@@ -841,24 +886,24 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
841
886
  });
842
887
  return ast;
843
888
  }
844
-
845
- function afterDirectives(body,nodes) {
846
- for (var i=0; i<body.length; i++) {
847
- if (examine(body[i]).isDirective)
848
- continue ;
849
- body.splice.apply(body,[i,0].concat(nodes)) ;
850
- return ;
889
+
890
+ function afterDirectives(body, nodes) {
891
+ for (var i = 0;i < body.length; i++) {
892
+ if (examine(body[i]).isDirective)
893
+ continue;
894
+ body.splice.apply(body, [i,0].concat(nodes));
895
+ return;
851
896
  }
852
- body.splice.apply(body,[body.length,0].concat(nodes)) ;
897
+ body.splice.apply(body, [body.length,0].concat(nodes));
853
898
  }
854
-
899
+
855
900
  function inAsync(path) {
856
- for (var i=0; i<path.length; i++)
857
- if (examine(path[i].self).isFunction)
858
- return path[i].self.async || path[i].self.$wasAsync ;
859
- return false ;
901
+ for (var i = 0;i < path.length; i++)
902
+ if (examine(path[i].self).isFunction)
903
+ return path[i].self.async || path[i].self.$wasAsync;
904
+ return false;
860
905
  }
861
-
906
+
862
907
  function mapTryCatch(node, path, down) {
863
908
  if (node.$needsMapping) {
864
909
  var continuation, ctnName, catchBody;
@@ -867,11 +912,10 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
867
912
  var i = ref.index + 1;
868
913
  var afterTry = ref.parent[ref.field].splice(i, ref.parent[ref.field].length - i);
869
914
  if (afterTry.length) {
870
- ctnName = node.$seh + "Post";
871
- var afterContinuation = down(makeBoundFn(ctnName, afterTry, [], getExit(path, [opts]).$error));
872
- ref.parent[ref.field].splice(ref.index,0,afterContinuation);
873
- continuation = parser.part("return $0()",
874
- [node.finalizer ? deferredFinally(node, ident(ctnName)) : ident(ctnName)]).body[0] ;
915
+ ctnName = ident(node.$seh + "Post") ;
916
+ var afterContinuation = down(makeBoundFn(ctnName.name, afterTry, [], getExit(path, [opts]).$error));
917
+ ref.parent[ref.field].splice(ref.index, 0, afterContinuation);
918
+ continuation = parsePart("return $0()", [node.finalizer ? deferredFinally(node, ctnName) : ctnName]).body[0];
875
919
  } else if (node.finalizer) {
876
920
  continuation = returnThisCall(deferredFinally(node));
877
921
  }
@@ -887,28 +931,27 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
887
931
  if (node.handler) {
888
932
  var symCatch = ident(node.$seh + "Catch");
889
933
  catchBody = cloneNode(node.handler.body);
934
+ down(catchBody);
890
935
  var catcher = makeBoundFn(symCatch.name, catchBody, [cloneNode(node.handler.param)], node.finalizer ? deferredFinally(node, binding.$error) : binding.$error);
891
936
  node.handler.body.body = [{
892
937
  type: 'CallExpression',
893
938
  callee: symCatch,
894
939
  arguments: [cloneNode(node.handler.param)]
895
940
  }];
896
- ref.parent[ref.field].splice(ref.index,0,catcher) ;
941
+ ref.parent[ref.field].splice(ref.index, 0, catcher);
897
942
  }
898
943
  if (node.finalizer) {
899
- down(node.finalizer) ;
944
+ down(node.finalizer);
900
945
  var finalParams = {
901
- exit:ident(node.$seh + "Exit"),
902
- value:ident(node.$seh + "Value"),
903
- body:cloneNode(node.finalizer.body),
904
- } ;
905
-
906
- var chainFinalize = parser.part(
907
- "(function ($value) { "+
908
- " $:body; "+
909
- " return $exit && ($exit.call(this, $value)); "+
910
- " })",finalParams).expr ;
911
-
946
+ exit: ident(node.$seh + "Exit"),
947
+ value: ident(node.$seh + "Value"),
948
+ body: cloneNode(node.finalizer.body)
949
+ };
950
+ var chainFinalize = parsePart(
951
+ "(function ($value) { " +
952
+ " $:body; " +
953
+ " return $exit && ($exit.call(this, $value)); " +
954
+ "})", finalParams).expr;
912
955
  var finalizer = {
913
956
  type: 'VariableDeclaration',
914
957
  kind: 'var',
@@ -916,41 +959,38 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
916
959
  type: "VariableDeclarator",
917
960
  id: ident(node.$seh + "Finally"),
918
961
  init: bindAsync({
919
- type:'FunctionExpression',
920
- params:[finalParams.exit],
921
- id:null,
922
- body:{
923
- type:'BlockStatement',
924
- body:[{
962
+ type: 'FunctionExpression',
963
+ params: [finalParams.exit],
964
+ id: null,
965
+ body: {
966
+ type: 'BlockStatement',
967
+ body: [{
925
968
  type: 'ReturnStatement',
926
- argument: bindAsync(chainFinalize,binding.$error)
969
+ argument: bindAsync(chainFinalize, binding.$error)
927
970
  }]
928
971
  }
929
972
  })
930
973
  }]
931
- } ;
932
-
933
- afterDirectives(ref.parent[ref.field],[finalizer]);
934
- var callFinally = parser.part("return $0()",
935
- [node.finalizer ? deferredFinally(node, ident(ctnName)) : ident(ctnName)]).body[0] ;
974
+ };
975
+ afterDirectives(ref.parent[ref.field], [finalizer]);
976
+ var callFinally = cloneNode(continuation) ;//parsePart("return $0()", [node.finalizer ? deferredFinally(node, ctnName) : ctnName]).body[0];
936
977
  catchBody.body[catchBody.length - 1] = callFinally;
937
978
  node.block.body[node.block.body.length - 1] = callFinally;
938
979
  delete node.finalizer;
939
980
  }
940
981
  }
941
982
  }
942
-
983
+
943
984
  function walkDown(ast, mappers, state) {
944
985
  var walked = [];
945
-
946
- function closedWalk(ast,state) {
947
- return parser.treeWalker(ast, function (node, descend, path) {
986
+ function closedWalk(ast, state) {
987
+ return treeWalk(ast, function (node, descend, path) {
948
988
  function walkDownSubtree(node) {
949
989
  return closedWalk(node, path);
950
990
  }
951
-
991
+
952
992
  if (walked.indexOf(node) < 0) {
953
- walked.push(node) ;
993
+ walked.push(node);
954
994
  mappers.forEach(function (m) {
955
995
  m(node, path, walkDownSubtree);
956
996
  });
@@ -959,20 +999,20 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
959
999
  return;
960
1000
  }, state);
961
1001
  }
962
-
963
- closedWalk(ast,state)
964
- return ast ;
1002
+
1003
+ closedWalk(ast, state);
1004
+ return ast;
965
1005
  }
966
-
1006
+
967
1007
  function asyncAwait(ast, inAsync, parentCatcher) {
968
- parser.treeWalker(ast, function (node, descend, path) {
1008
+ treeWalk(ast, function (node, descend, path) {
969
1009
  if (node.type == 'IfStatement') {
970
- if (node.consequent.type != 'BlockStatement' && containsAwait(node.consequent))
1010
+ if (node.consequent.type != 'BlockStatement' && containsAwait(node.consequent))
971
1011
  node.consequent = {
972
1012
  type: 'BlockStatement',
973
1013
  body: [node.consequent]
974
1014
  };
975
- if (node.alternate && node.alternate.type != 'BlockStatement' && containsAwait(node.alternate))
1015
+ if (node.alternate && node.alternate.type != 'BlockStatement' && containsAwait(node.alternate))
976
1016
  node.alternate = {
977
1017
  type: 'BlockStatement',
978
1018
  body: [node.alternate]
@@ -989,9 +1029,9 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
989
1029
  });
990
1030
  if (!inAsync || inAsync === "warn") {
991
1031
  var errMsg = where(node) + "'await' used inside non-async function. ";
992
- if (opts.promises)
1032
+ if (opts.promises)
993
1033
  errMsg += "'return' value Promise runtime-specific";
994
- else
1034
+ else
995
1035
  errMsg += "'return' value from await is synchronous";
996
1036
  logger(errMsg + ". See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification");
997
1037
  }
@@ -1013,7 +1053,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1013
1053
  break;
1014
1054
  }
1015
1055
  }
1016
- if (!stmt)
1056
+ if (!stmt)
1017
1057
  throw new Error(where(node) + "Illegal await not contained in a statement");
1018
1058
  var containingExits = getExit(path, [parentCatcher,opts]);
1019
1059
  var i = stmt.index;
@@ -1036,7 +1076,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1036
1076
  }, inAsync, containingExits)
1037
1077
  };
1038
1078
  } else {
1039
- if (callBack.length)
1079
+ if (callBack.length)
1040
1080
  callback = {
1041
1081
  type: 'FunctionExpression',
1042
1082
  params: [cloneNode(result)],
@@ -1059,7 +1099,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1059
1099
  // Wrap the callback statement(s) in a Block and transform them
1060
1100
  if (!returner) {
1061
1101
  if (callback) {
1062
- returner = bindAsync(callback,containingExits.$error) ;
1102
+ returner = bindAsync(callback, containingExits.$error);
1063
1103
  } else {
1064
1104
  returner = {
1065
1105
  type: 'FunctionExpression',
@@ -1075,11 +1115,11 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1075
1115
  expr = {
1076
1116
  type: 'CallExpression',
1077
1117
  arguments: [expr],
1078
- callee: (opts.promises || opts.generators)?{
1118
+ callee: opts.promises || opts.generators ? {
1079
1119
  type: 'MemberExpression',
1080
- object: ident('Promise'),
1120
+ object: genIdent.Promise,
1081
1121
  property: ident('resolve')
1082
- }:{
1122
+ } : {
1083
1123
  // ES7 makeThenable
1084
1124
  type: 'MemberExpression',
1085
1125
  object: ident('Object'),
@@ -1107,30 +1147,28 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1107
1147
  });
1108
1148
  return ast;
1109
1149
  }
1110
-
1150
+
1111
1151
  // Transform a for..in into it's iterative equivalent
1112
1152
  function transformForIn(node, path) {
1113
- var label = node.$label ;
1114
- delete node.$label ;
1115
-
1116
- var idx = ident(generateSymbol("idx"))
1153
+ var label = node.$label;
1154
+ delete node.$label;
1155
+ var idx = ident(generateSymbol("idx"));
1117
1156
  var inArray = ident(generateSymbol("in"));
1118
- var declVars = parser.part("var $0,$1 = [];for ($0 in $2) $1.push($0)",[idx,inArray,node.right]).body ;
1119
- var loop = parser.part("for ($0; $1.length;){ $2 = $1.shift(); $:3 ; }",[
1120
- node.left,
1121
- inArray,
1122
- node.left.type === 'VariableDeclaration' ? node.left.declarations[0].id : node.left,
1123
- node.body]).body[0] ;
1124
- loop.$label = label ;
1125
- for (var b=0; b<path.length; b++) {
1157
+ var declVars = parsePart("var $0,$1 = [];for ($0 in $2) $1.push($0)", [idx,
1158
+ inArray,node.right]).body;
1159
+ var loop = parsePart("for ($0; $1.length;){ $2 = $1.shift(); $:3 ; }", [node.left,
1160
+ inArray,node.left.type === 'VariableDeclaration' ? node.left.declarations[0].id : node.left,
1161
+ node.body]).body[0];
1162
+ loop.$label = label;
1163
+ for (var b = 0;b < path.length; b++) {
1126
1164
  if (examine(path[b].parent).isBlockStatement) {
1127
- path[b].parent[path[b].field].splice(path[b].index,0,declVars[0],declVars[1]) ;
1128
- break ;
1165
+ path[b].parent[path[b].field].splice(path[b].index, 0, declVars[0], declVars[1]);
1166
+ break;
1129
1167
  }
1130
1168
  }
1131
- coerce(node,loop) ;
1169
+ coerce(node, loop);
1132
1170
  }
1133
-
1171
+
1134
1172
  // Transform a for..of into it's iterative equivalent
1135
1173
  function iterizeForOf(node, path) {
1136
1174
  if (node.body.type !== 'BlockStatement') {
@@ -1139,22 +1177,23 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1139
1177
  body: [node.body]
1140
1178
  };
1141
1179
  }
1142
- var index, iterator, initIterator = parser.part("[$0[Symbol.iterator]()]",[node.right]).expr;
1143
-
1180
+ var index, iterator, initIterator = parsePart("[$0[Symbol.iterator]()]", [node.right]).expr;
1144
1181
  if (node.left.type === 'VariableDeclaration') {
1145
- if (node.left.kind==='const')
1146
- node.left.kind = 'let' ;
1147
-
1148
- index = node.left.declarations[0].id ;
1149
- var decls = getDeclNames(node.left.declarations[0].id) ;
1182
+ if (node.left.kind === 'const')
1183
+ node.left.kind = 'let';
1184
+ if (node.left.kind === 'let') {
1185
+ node.update = literal(null) ;
1186
+ node.update.$EmptyExpression = true ;
1187
+ }
1188
+ index = node.left.declarations[0].id;
1189
+ var decls = getDeclNames(node.left.declarations[0].id);
1150
1190
  iterator = ident(generateSymbol("iterator_" + decls.join('_')));
1151
-
1152
- node.left.declarations = decls.map(function(name){
1191
+ node.left.declarations = decls.map(function (name) {
1153
1192
  return {
1154
1193
  type: "VariableDeclarator",
1155
1194
  id: ident(name)
1156
- } ;
1157
- }) ;
1195
+ };
1196
+ });
1158
1197
  node.left.declarations.push({
1159
1198
  type: "VariableDeclarator",
1160
1199
  id: iterator,
@@ -1176,282 +1215,276 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1176
1215
  node.init = declaration;
1177
1216
  }
1178
1217
  node.type = 'ForStatement';
1179
- node.test = parser.part("!($0[1] = $0[0].next()).done && (($1 = $0[1].value) || true)",[iterator,index]).expr ;
1218
+ node.test = parsePart("!($0[1] = $0[0].next()).done && (($1 = $0[1].value) || true)", [iterator,
1219
+ index]).expr;
1180
1220
  delete node.left;
1181
1221
  delete node.right;
1182
1222
  }
1183
-
1223
+
1184
1224
  /* Map loops */
1185
1225
  /* As of v3.0.0 loops are asynchronized via a trampoline to prevent stack overflow in big loops with no actionable awaits. */
1186
1226
  function mapLoops(node, path, down) {
1187
- var depth = node.$depth ;
1227
+ var depth = node.$depth;
1188
1228
  if (node.type === 'ForInStatement' && containsAwait(node)) {
1189
- transformForIn(node, path) ;
1229
+ transformForIn(node, path);
1190
1230
  } else if (node.type === 'ForOfStatement' && containsAwait(node)) {
1191
- iterizeForOf(node, path);
1231
+ iterizeForOf(node, path);
1192
1232
  }
1193
-
1194
1233
  // Are we inside a loop that has already been asynchronized and is labelled?
1195
- var inAsyncLoop = path.some(function(p){
1196
- return ('$label' in p.self && p.self.type==='ForStatement' && p.self.$mapped) ;
1197
- }) ;
1198
-
1234
+ var inAsyncLoop = path.some(function (p) {
1235
+ return '$label' in p.self && p.self.type === 'ForStatement' && p.self.$mapped;
1236
+ });
1199
1237
  // Check if the loop contains an await, or a labelled exit if we're inside an async loop
1200
- function mappableLoop(n){
1201
- return (n.type==='AwaitExpression' && !n.$hidden)
1202
- || (inAsyncLoop && (n.type==='BreakStatement'|| n.type==='ContinueStatement') && n.label)
1203
- };
1204
-
1205
- if (!node.$mapped && examine(node).isLoop && contains(node,mappableLoop)) {
1206
- path[0].self.$mapped = true ;
1207
- var p ;
1208
- var mapped = [] ;
1209
- var init = node.init;
1210
- var test = node.test || literal(true);
1211
- var step = node.update;
1212
- var body = node.body;
1213
-
1214
- if (step) {
1215
- step = {
1216
- type:'ExpressionStatement',
1217
- expression: step
1218
- } ;
1219
- }
1220
-
1221
- if (init) {
1222
- if (!examine(init).isStatement) {
1223
- init = {
1224
- type: 'ExpressionStatement',
1225
- expression: init
1226
- };
1227
- }
1228
- mapped.push(init) ;
1229
- }
1230
-
1231
- var ref, label ;
1232
- if (node.$label) {
1233
- label = node.$label.name ;
1234
- ref = path[1] ;
1235
- } else {
1236
- label = generatedSymbol++ ;
1237
- ref = path[0] ;
1238
- }
1239
-
1240
- label = opts.generatedSymbolPrefix + "Loop_" + label;
1241
- var idTrampoline = ident(label + "_trampoline") ;
1242
- var idIter = ident(label) ;
1243
- var idStep = step ? ident(label + "_step") : idIter ;
1244
- var idContinuation = ident(label + "_exit") ;
1245
- var idBounce = ident("q") ;
1246
- var idCatchParam = ident("$exception") ;
1247
- var continuation, deferredCode ;
1248
-
1249
- if ('index' in ref) {
1250
- var idx = ref.index;
1251
- deferredCode = ref.parent[ref.field].splice(idx + 1, ref.parent[ref.field].length - (idx + 1));
1252
- } else {
1253
- deferredCode = [] ;
1254
- }
1255
-
1256
- continuation = makeContinuation(idContinuation, deferredCode) ;
1257
- var returnIter = {
1258
- "type": "ReturnStatement",
1259
- "argument": idIter
1260
- } ;
1261
-
1262
- var returnStep = {
1263
- "type": "ReturnStatement",
1264
- "argument": idStep
1265
- } ;
1266
-
1267
- var returnBreak = {
1268
- type: 'ReturnStatement',
1269
- argument: {
1270
- "type": "ArrayExpression",
1271
- "elements":[literal(1)]
1272
- }
1273
- };
1274
-
1275
- parser.treeWalker(body, function mapExits(n, descend, subpath) {
1276
- if (examine(n).isFunction || examine(n).isLoop) {
1277
- return true;
1278
- } else if (n.type === 'BreakStatement' || n.type === 'ContinueStatement') {
1279
- if (n.label) {
1280
- var labelStack = subpath.filter(function(p){
1281
- return '$label' in p.self
1282
- }).map(function(p,idx){
1283
- return p.self.$label && p.self.$label.name
1284
- }) ;
1285
-
1286
- // Work out how many loops to exit by examining subpath.
1287
- var loops = [] ;
1288
- for (var l=0; l<labelStack.length; l++) {
1289
- if (labelStack[l] === n.label.name) {
1290
- if (n.type === 'BreakStatement')
1291
- loops.push(literal(1)) ;
1292
- subpath[0].replace({
1293
- type: 'ReturnStatement',
1294
- argument: {
1295
- "type": "ArrayExpression",
1296
- "elements":loops.reverse()
1297
- }
1298
- }) ;
1299
- break ;
1300
- }
1301
- loops.push(literal(0)) ;
1302
- }
1303
- } else {
1304
- if (n.type === 'BreakStatement')
1305
- subpath[0].replace(returnBreak) ;
1306
- else // continue;
1307
- subpath[0].replace(returnStep) ;
1308
- }
1309
- } else {
1310
- descend();
1311
- }
1312
- },path) ;
1313
-
1314
- if (body.type === 'BlockStatement')
1315
- body = body.body.slice(0) ;
1316
- else
1317
- body = [body] ;
1318
-
1319
- if (node.type==='DoWhileStatement') {
1320
- body = body.concat({
1321
- "type": "IfStatement",
1322
- "test": {
1323
- type:'UnaryExpression',
1324
- argument:test,
1325
- prefix:true,
1326
- operator:'!'
1327
- },
1328
- "consequent": returnBreak,
1329
- alternate:returnStep
1330
- }) ;
1331
- } else {
1332
- body = [{
1333
- "type": "IfStatement",
1334
- "test": test,
1335
- "consequent": {
1336
- "type": "BlockStatement",
1337
- "body": body.concat(returnStep)
1338
- },
1339
- alternate:returnBreak
1340
- }] ;
1341
- }
1342
-
1343
- if (opts.noRuntime) {
1344
- mapped.push({
1345
- "type": "VariableDeclaration",
1346
- "declarations": [{
1347
- "type": "VariableDeclarator",
1348
- "id": idTrampoline
1349
- }],
1350
- "kind": "var"
1351
- }) ;
1352
- }
1353
- var invokeIterate ;
1354
- var exit = getExit(path, [opts]).$error ;
1355
- if (opts.noRuntime) {
1356
- invokeIterate = parser.part(
1357
- opts.es6target?
1358
- "($idTrampoline = ((q) => { "+
1359
- " $$setMapped: while (q) { "+
1360
- " if (q.then) "+
1361
- (depth===1?
1362
- " return void q.then($idTrampoline, $exit); ":
1363
- " return q.then($idTrampoline, $exit); ")+
1364
- " try { "+
1365
- " if (q.pop) "+
1366
- " if (q.length) "+
1367
- " return q.pop() ? $idContinuation.call(this) : q; "+
1368
- " else "+
1369
- " q = $idStep; "+
1370
- " else "+
1371
- " q = q.call(this) "+
1372
- " } catch (_exception) { "+
1373
- " return $exit(_exception); "+
1374
- " } "+
1375
- " } "+
1376
- "}))($idIter)":
1377
- "($idTrampoline = (function (q) { "+
1378
- " $$setMapped: while (q) { "+
1379
- " if (q.then) "+
1380
- (depth===1?
1381
- " return void q.then($idTrampoline, $exit); ":
1382
- " return q.then($idTrampoline, $exit); ")+
1383
- " try { "+
1384
- " if (q.pop) "+
1385
- " if (q.length) "+
1386
- " return q.pop() ? $idContinuation.call(this) : q; "+
1387
- " else "+
1388
- " q = $idStep; "+
1389
- " else "+
1390
- " q = q.call(this) "+
1391
- " } catch (_exception) { "+
1392
- " return $exit(_exception); "+
1393
- " } "+
1394
- " } "+
1395
- "}).bind(this))($idIter)",
1238
+ function mappableLoop(n) {
1239
+ return n.type === 'AwaitExpression' && !n.$hidden || inAsyncLoop && (n.type === 'BreakStatement' || n.type === 'ContinueStatement') && n.label;
1240
+ }
1241
+
1242
+ if (!node.$mapped && examine(node).isLoop && contains(node, mappableLoop)) {
1243
+ path[0].self.$mapped = true;
1244
+ var p;
1245
+ var mapped = [];
1246
+ var init = node.init;
1247
+ var test = node.test || literal(true);
1248
+ var step = node.update;
1249
+ var body = node.body;
1250
+ var localised = init && init.type === 'VariableDeclaration' && (init.kind === 'let' || init.kind === 'const');
1251
+ if (localised) {
1252
+ init.kind = 'let';
1253
+ }
1254
+ if (step) {
1255
+ step = {
1256
+ type: 'ExpressionStatement',
1257
+ expression: step
1258
+ };
1259
+ }
1260
+ if (init) {
1261
+ if (!examine(init).isStatement) {
1262
+ init = {
1263
+ type: 'ExpressionStatement',
1264
+ expression: init
1265
+ };
1266
+ }
1267
+ if (!localised)
1268
+ mapped.push(init);
1269
+ }
1270
+ var ref, label;
1271
+ if (node.$label) {
1272
+ label = node.$label.name;
1273
+ ref = path[1];
1274
+ } else {
1275
+ label = generatedSymbol++;
1276
+ ref = path[0];
1277
+ }
1278
+ label = opts.generatedSymbolPrefix + "Loop_" + label;
1279
+ var idLocal = localised ? ident(label + "_local"):null ;
1280
+ var idTrampoline = ident(label + "_trampoline");
1281
+ var idIter = ident(label);
1282
+ var idStep = step ? ident(label + "_step") : idIter;
1283
+ var idContinuation = ident(label + "_exit");
1284
+ var idBounce = ident("q");
1285
+ var idCatchParam = ident("$exception");
1286
+ var continuation, deferredCode;
1287
+ if ('index' in ref) {
1288
+ var idx = ref.index;
1289
+ deferredCode = ref.parent[ref.field].splice(idx + 1, ref.parent[ref.field].length - (idx + 1));
1290
+ } else {
1291
+ deferredCode = [];
1292
+ }
1293
+ continuation = makeContinuation(idContinuation, deferredCode);
1294
+ var initIter = localised ? parsePart("$0.bind(this,$1)", [idIter,init ? init.declarations.map(function (d) {
1295
+ return d && d.init ? d.init : ident("undefined");
1296
+ }) : []]).expr : idIter;
1297
+ var returnStep = parsePart("return $0", [idStep]).body[0];
1298
+ var returnBreak = {
1299
+ type: 'ReturnStatement',
1300
+ argument: {
1301
+ "type": "ArrayExpression",
1302
+ "elements": [literal(1)]
1303
+ }
1304
+ };
1305
+ treeWalk(body, function mapExits(n, descend, subpath) {
1306
+ if (examine(n).isFunction || examine(n).isLoop) {
1307
+ return true;
1308
+ } else if (n.type === 'BreakStatement' || n.type === 'ContinueStatement') {
1309
+ if (n.label) {
1310
+ var labelStack = subpath.filter(function (p) {
1311
+ return '$label' in p.self;
1312
+ }).map(function (p, idx) {
1313
+ return p.self.$label && p.self.$label.name;
1314
+ });
1315
+ // Work out how many loops to exit by examining subpath.
1316
+ var loops = [];
1317
+ for (var l = 0;l < labelStack.length; l++) {
1318
+ if (labelStack[l] === n.label.name) {
1319
+ if (n.type === 'BreakStatement')
1320
+ loops.push(literal(1));
1321
+ subpath[0].replace({
1322
+ type: 'ReturnStatement',
1323
+ argument: {
1324
+ "type": "ArrayExpression",
1325
+ "elements": loops.reverse()
1326
+ }
1327
+ });
1328
+ break;
1329
+ }
1330
+ loops.push(literal(0));
1331
+ }
1332
+ } else {
1333
+ if (n.type === 'BreakStatement')
1334
+ subpath[0].replace(returnBreak);
1335
+ else
1336
+ subpath[0].replace(returnStep); // continue;
1337
+ }
1338
+ } else {
1339
+ descend();
1340
+ }
1341
+ }, path);
1342
+ if (body.type === 'BlockStatement')
1343
+ body = body.body.slice(0);
1344
+ else
1345
+ body = [body];
1346
+ if (node.type === 'DoWhileStatement') {
1347
+ body = body.concat({
1348
+ "type": "IfStatement",
1349
+ "test": {
1350
+ type: 'UnaryExpression',
1351
+ argument: test,
1352
+ prefix: true,
1353
+ operator: '!'
1354
+ },
1355
+ "consequent": returnBreak,
1356
+ alternate: returnStep
1357
+ });
1358
+ } else {
1359
+ body = [{
1360
+ "type": "IfStatement",
1361
+ "test": test,
1362
+ "consequent": {
1363
+ "type": "BlockStatement",
1364
+ "body": body.concat(returnStep)
1365
+ },
1366
+ alternate: returnBreak
1367
+ }];
1368
+ }
1369
+ var decls = [];
1370
+ if (opts.noRuntime)
1371
+ decls.push({
1372
+ "type": "VariableDeclarator",
1373
+ "id": idTrampoline
1374
+ });
1375
+ if (step && localised)
1376
+ decls.push({
1377
+ "type": "VariableDeclarator",
1378
+ "id": idLocal
1379
+ });
1380
+ if (decls.length)
1381
+ mapped.push({
1382
+ "type": "VariableDeclaration",
1383
+ "declarations": decls,
1384
+ "kind": "var"
1385
+ });
1386
+ var invokeIterate;
1387
+ var exit = getExit(path, [opts]).$error;
1388
+ if (opts.noRuntime) {
1389
+ invokeIterate = parsePart(
1390
+ opts.es6target?
1391
+ "($idTrampoline = ((q) => { "+
1392
+ " $$setMapped: while (q) { "+
1393
+ " if (q.then) "+
1394
+ (depth===1?
1395
+ " return void q.then($idTrampoline, $exit); ":
1396
+ " return q.then($idTrampoline, $exit); ")+
1397
+ " try { "+
1398
+ " if (q.pop) "+
1399
+ " if (q.length) "+
1400
+ " return q.pop() ? $idContinuation.call(this) : q; "+
1401
+ " else "+
1402
+ " q = $idStep; "+
1403
+ " else "+
1404
+ " q = q.call(this) "+
1405
+ " } catch (_exception) { "+
1406
+ " return $exit(_exception); "+
1407
+ " } "+
1408
+ " } "+
1409
+ "}))($idIter)":
1410
+ "($idTrampoline = (function (q) { "+
1411
+ " $$setMapped: while (q) { "+
1412
+ " if (q.then) "+
1413
+ (depth===1?
1414
+ " return void q.then($idTrampoline, $exit); ":
1415
+ " return q.then($idTrampoline, $exit); ")+
1416
+ " try { "+
1417
+ " if (q.pop) "+
1418
+ " if (q.length) "+
1419
+ " return q.pop() ? $idContinuation.call(this) : q; "+
1420
+ " else "+
1421
+ " q = $idStep; "+
1422
+ " else "+
1423
+ " q = q.call(this) "+
1424
+ " } catch (_exception) { "+
1425
+ " return $exit(_exception); "+
1426
+ " } "+
1427
+ " } "+
1428
+ "}).bind(this))($idIter)",
1396
1429
  {
1397
- setMapped:function(n){ n.$mapped = true ; return n },
1398
- idTrampoline:idTrampoline,
1399
- exit:exit,
1400
- idIter:idIter,
1401
- idContinuation:idContinuation,
1402
- idStep:idStep
1403
- }).expr ;
1404
- } else {
1405
- invokeIterate = parser.part("(Function.$0.trampoline(this,$1,$2,$3,$5)($4))",[
1406
- genIdent.asyncbind,
1407
- idContinuation,idStep,exit,
1408
- idIter,
1409
- literal(depth===1)
1410
- ]).expr;
1411
- }
1412
-
1413
- mapped.push({type:'ReturnStatement',argument:invokeIterate}) ;
1414
- mapped.push({
1415
- $label:node.$label,
1416
- "type": "FunctionDeclaration",
1417
- "id": idIter,
1418
- "params": [],
1419
- "body": {
1420
- "type": "BlockStatement",
1421
- "body": body
1422
- }
1423
- }) ;
1424
-
1425
- if (step) {
1426
- mapped.push({
1427
- "type": "FunctionDeclaration",
1428
- id: idStep,
1429
- "params": [],
1430
- "body": {
1431
- "type": "BlockStatement",
1432
- "body": [ step,returnIter ]
1433
- }
1434
- }) ;
1435
- }
1436
-
1437
- if (init && init.type==='VariableDeclaration' && (init.kind==='let' || init.kind==='const')) {
1438
- if (init.kind==='const')
1439
- init.kind = 'let' ;
1440
-
1441
- path[0].replace([{
1442
- type:'BlockStatement',
1443
- body:mapped.map(down)
1444
- },down(continuation)]) ;
1445
- } else {
1446
- mapped.push(continuation) ;
1447
- path[0].replace(mapped.map(down)) ;
1448
- }
1430
+ setMapped: function (n) {
1431
+ n.$mapped = true;
1432
+ return n;
1433
+ },
1434
+ idTrampoline: idTrampoline,
1435
+ exit: exit,
1436
+ idIter: initIter,
1437
+ idContinuation: idContinuation,
1438
+ idStep: idStep
1439
+ }).expr;
1440
+ } else {
1441
+ invokeIterate = parsePart("($0.$1.trampoline(this,$2,$3,$4,$6)($5))", [opts.$runtime ? genIdent.runtime : ident('Function'),
1442
+ genIdent.asyncbind,idContinuation,idStep,
1443
+ exit,initIter,literal(depth === 1)]).expr;
1444
+ }
1445
+ var iterDecls = init && init.declarations ? init.declarations.map(function (d) {
1446
+ return d.id;
1447
+ }) : [];
1448
+ if (step) {
1449
+ var stepArgs = {
1450
+ idIter: idIter,
1451
+ idStep: idStep,
1452
+ step: step,
1453
+ idLocal: idLocal,
1454
+ decId: iterDecls
1455
+ };
1456
+ if (localised) {
1457
+ stepArgs.iterDecls = iterDecls;
1458
+ mapped.push(parsePart(step.expression.$EmptyExpression ?
1459
+ (opts.es6target ? "function $idStep(){ return $idIter.bind(this,...$idLocal()) }" : "function $idStep(){ var [$decId] = $idLocal(); return $idIter.bind(this,$decId) }") :
1460
+ "function $idStep(){ var [$decId] = $idLocal(); $:step; return $idIter.bind(this,$decId) }", stepArgs).body[0]);
1461
+ body.unshift(parsePart("$idLocal = function(){ return [$decId] }", stepArgs).body[0]);
1462
+ } else {
1463
+ mapped.push(parsePart(step.expression.$EmptyExpression ? "function $idStep(){ return $idIter }" : "function $idStep(){ $:step; return $idIter }", stepArgs).body[0]);
1464
+ }
1465
+ }
1466
+ mapped.push({
1467
+ $label: node.$label,
1468
+ "type": "FunctionDeclaration",
1469
+ "id": idIter,
1470
+ "params": localised ? iterDecls : [],
1471
+ "body": {
1472
+ "type": "BlockStatement",
1473
+ "body": body
1474
+ }
1475
+ });
1476
+ mapped.push({
1477
+ type: 'ReturnStatement',
1478
+ argument: invokeIterate
1479
+ });
1480
+ mapped.push(continuation);
1481
+ path[0].replace(mapped.map(down));
1449
1482
  }
1450
1483
  }
1451
-
1484
+
1452
1485
  /* Previous, recursive implementation for backwards compatibility */
1453
- function asyncLoops_1(ast,state) {
1454
- parser.treeWalker(ast, function (node, descend, path) {
1486
+ function asyncLoops_1(ast, state) {
1487
+ treeWalk(ast, function (node, descend, path) {
1455
1488
  function mapContinue(label) {
1456
1489
  return {
1457
1490
  type: 'ReturnStatement',
@@ -1462,7 +1495,9 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1462
1495
  argument: thisCall(label || symContinue)
1463
1496
  }
1464
1497
  };
1465
- };
1498
+ }
1499
+
1500
+ ;
1466
1501
  function mapExits(n, descend) {
1467
1502
  if (n.type === 'BreakStatement') {
1468
1503
  coerce(n, cloneNode(mapBreak(n.label && opts.generatedSymbolPrefix + "Loop_" + n.label.name + "_exit")));
@@ -1473,9 +1508,9 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1473
1508
  }
1474
1509
  descend();
1475
1510
  }
1476
-
1511
+
1477
1512
  if (node.type === 'ForInStatement' && containsAwait(node)) {
1478
- transformForIn(node, path) ;
1513
+ transformForIn(node, path);
1479
1514
  } else if (node.type === 'ForOfStatement' && containsAwait(node)) {
1480
1515
  iterizeForOf(node, path);
1481
1516
  }
@@ -1486,7 +1521,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1486
1521
  var condition = node.test || literal(true);
1487
1522
  var step = node.update;
1488
1523
  var body = node.body;
1489
- var loopUsesThis = containsThis(body) ;
1524
+ var loopUsesThis = containsThis(body);
1490
1525
  if (init) {
1491
1526
  if (!examine(init).isStatement) {
1492
1527
  init = {
@@ -1498,13 +1533,13 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1498
1533
  step = step && {
1499
1534
  type: 'ExpressionStatement',
1500
1535
  expression: step
1501
- } ;
1536
+ };
1502
1537
  body = examine(body).isBlockStatement ? cloneNode(body).body : [cloneNode(body)];
1503
- var label = node.$label && node.$label.name ;
1538
+ var label = node.$label && node.$label.name;
1504
1539
  label = "Loop_" + (label || generatedSymbol++);
1505
1540
  var symExit = opts.generatedSymbolPrefix + (label + "_exit");
1506
1541
  var symContinue = opts.generatedSymbolPrefix + (label + "_next");
1507
- var loop = ident(opts.generatedSymbolPrefix + (label));
1542
+ var loop = ident(opts.generatedSymbolPrefix + label);
1508
1543
  // How to exit the loop
1509
1544
  var mapBreak = function (label) {
1510
1545
  return {
@@ -1521,20 +1556,19 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1521
1556
  }
1522
1557
  };
1523
1558
  };
1524
-
1525
1559
  // How to continue the loop
1526
1560
  var defContinue = makeContinuation(symContinue, [{
1527
1561
  type: 'ReturnStatement',
1528
1562
  argument: {
1529
1563
  type: 'CallExpression',
1530
- callee: loopUsesThis? bindAsync(loop):loop,
1564
+ callee: loopUsesThis ? bindAsync(loop) : loop,
1531
1565
  arguments: [ident(symExit),genIdent.error]
1532
1566
  }
1533
1567
  }]);
1534
- if (step)
1568
+ if (step)
1535
1569
  defContinue.body.body.unshift(step);
1536
1570
  for (var i = 0;i < body.length; i++) {
1537
- parser.treeWalker(body[i], mapExits);
1571
+ treeWalk(body[i], mapExits);
1538
1572
  }
1539
1573
  body.push(cloneNode(mapContinue()));
1540
1574
  var subCall = {
@@ -1583,17 +1617,15 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1583
1617
  argument: bindAsync(subCall, literal(0))
1584
1618
  }
1585
1619
  };
1586
-
1587
- if (init && init.type==='VariableDeclaration' && (init.kind==='let' || init.kind==='const')) {
1588
- if (init.kind==='const')
1589
- init.kind = 'let' ;
1620
+ if (init && init.type === 'VariableDeclaration' && (init.kind === 'let' || init.kind === 'const')) {
1621
+ if (init.kind === 'const')
1622
+ init.kind = 'let';
1590
1623
  replace = {
1591
- type:'BlockStatement',
1592
- body:[cloneNode(init),replace]
1624
+ type: 'BlockStatement',
1625
+ body: [cloneNode(init),replace]
1593
1626
  };
1594
- init = null ;
1627
+ init = null;
1595
1628
  }
1596
-
1597
1629
  for (p = 0; p < path.length; p++) {
1598
1630
  var ref = path[p];
1599
1631
  if ('index' in ref) {
@@ -1607,29 +1639,27 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1607
1639
  }
1608
1640
  }
1609
1641
  return true;
1610
- },state);
1642
+ }, state);
1611
1643
  return ast;
1612
1644
  }
1613
-
1645
+
1614
1646
  function containsAsyncExit(fn) {
1615
1647
  if (!examine(fn).isFunction) {
1616
- throw new Error("Cannot examine non-Function node types for async exits") ;
1648
+ throw new Error("Cannot examine non-Function node types for async exits");
1617
1649
  }
1618
-
1619
- return contains(fn.body,function(node){
1620
- return ((node.type === 'Identifier' && (node.name === opts.$return || node.name === opts.$error))
1621
- || (isExitStatement(node) && examine(node).isAsync)) ;
1622
- },function(node){
1623
- return !(examine(node).isFunction && (node.$wasAsync || examine(node).isAsync)) ;
1624
- }) ;
1650
+ return contains(fn.body, function (node) {
1651
+ return node.type === 'Identifier' && (node.name === opts.$return || node.name === opts.$error) || isExitStatement(node) && examine(node).isAsync;
1652
+ }, function (node) {
1653
+ return !(examine(node).isFunction && (node.$wasAsync || examine(node).isAsync));
1654
+ });
1625
1655
  }
1626
-
1656
+
1627
1657
  // TODO: Hoist directives (as in asyncDefine)
1628
1658
  function asyncDefineMethod(ast) {
1629
- return parser.treeWalker(ast, function (node, descend, path) {
1659
+ return treeWalk(ast, function (node, descend, path) {
1630
1660
  var transform = getMemberFunction(node);
1631
1661
  descend();
1632
- if (!transform || !examine(transform).isAsync)
1662
+ if (!transform || !examine(transform).isAsync)
1633
1663
  return;
1634
1664
  if (node.kind == 'set') {
1635
1665
  var ex = new SyntaxError(where(transform) + "method 'async set' cannot be invoked", pr.filename, node.start);
@@ -1637,7 +1667,6 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1637
1667
  ex.loc = node.loc.start;
1638
1668
  throw ex;
1639
1669
  }
1640
-
1641
1670
  transform.async = false;
1642
1671
  var usesArgs = replaceArguments(transform);
1643
1672
  if (!containsAsyncExit(transform) && (transform.body.body.length === 0 || transform.body.body[transform.body.body.length - 1].type !== 'ReturnStatement')) {
@@ -1646,12 +1675,11 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1646
1675
  });
1647
1676
  }
1648
1677
  var funcback = bindAsync(setExit({
1649
- type: 'FunctionExpression',
1650
- params: [genIdent.return,genIdent.error],
1651
- body: asyncDefineMethod(mapReturns(transform.body, path)),
1652
- $wasAsync: true
1653
- }, opts),(opts.promises || opts.generators || opts.engine) ? null : literal(opts.lazyThenables?0:true) ) ;
1654
-
1678
+ type: 'FunctionExpression',
1679
+ params: [genIdent.return,genIdent.error],
1680
+ body: asyncDefineMethod(mapReturns(transform.body, path)),
1681
+ $wasAsync: true
1682
+ }, opts), opts.promises || opts.generators || opts.engine ? null : literal(opts.lazyThenables ? 0 : true));
1655
1683
  if (opts.promises) {
1656
1684
  transform.body = {
1657
1685
  type: 'BlockStatement',
@@ -1659,7 +1687,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1659
1687
  type: 'ReturnStatement',
1660
1688
  argument: {
1661
1689
  type: 'NewExpression',
1662
- callee: ident('Promise'),
1690
+ callee: genIdent.Promise,
1663
1691
  arguments: [funcback]
1664
1692
  }
1665
1693
  }]
@@ -1674,30 +1702,29 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1674
1702
  };
1675
1703
  }
1676
1704
  if (usesArgs) {
1677
- afterDirectives(transform.body.body,[assign$Args]);
1705
+ afterDirectives(transform.body.body, [assign$Args]);
1678
1706
  }
1679
1707
  });
1680
1708
  }
1681
-
1709
+
1682
1710
  function asyncDefine(ast) {
1683
- parser.treeWalker(ast, function (node, descend, path) {
1711
+ treeWalk(ast, function (node, descend, path) {
1684
1712
  descend();
1685
1713
  if (examine(node).isAsync && examine(node).isFunction) {
1686
- var member ;
1687
- if ((member = getMemberFunction(path[0].parent))
1688
- && examine(member).isAsync && path[0].parent.kind === 'get') {
1689
- warnAsyncGetter(path[0].parent.key) ;
1714
+ var member;
1715
+ if ((member = getMemberFunction(path[0].parent)) && examine(member).isAsync && path[0].parent.kind === 'get') {
1716
+ warnAsyncGetter(path[0].parent.key);
1690
1717
  }
1691
1718
  delete node.async;
1692
-
1693
1719
  var usesArgs = replaceArguments(node);
1694
1720
  var fnBody = setExit({
1695
1721
  type: 'FunctionExpression',
1696
1722
  params: [genIdent.return,genIdent.error],
1697
1723
  $wasAsync: true
1698
- }, opts) ;
1699
- var thisPath = [{self:fnBody}].concat(path) ;
1700
-
1724
+ }, opts);
1725
+ var thisPath = [{
1726
+ self: fnBody
1727
+ }].concat(path);
1701
1728
  if (examine(node.body).isBlockStatement) {
1702
1729
  if (!containsAsyncExit(node) && (node.body.body.length === 0 || node.body.body[node.body.body.length - 1].type !== 'ReturnStatement')) {
1703
1730
  node.body.body.push({
@@ -1720,13 +1747,11 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1720
1747
  };
1721
1748
  node.expression = false;
1722
1749
  }
1723
-
1724
- fnBody = bindAsync(fnBody,(opts.promises || opts.generators || opts.engine) ? null : literal(opts.lazyThenables?0:true)) ;
1725
-
1750
+ fnBody = bindAsync(fnBody, opts.promises || opts.generators || opts.engine ? null : literal(opts.lazyThenables ? 0 : true));
1726
1751
  if (opts.promises) {
1727
1752
  fnBody = {
1728
1753
  type: 'NewExpression',
1729
- callee: ident('Promise'),
1754
+ callee: genIdent.Promise,
1730
1755
  arguments: [fnBody]
1731
1756
  };
1732
1757
  }
@@ -1738,20 +1763,22 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1738
1763
  argument: fnBody
1739
1764
  }]
1740
1765
  };
1741
- if (usesArgs)
1742
- afterDirectives(fnBody.body,[assign$Args]);
1766
+ if (usesArgs)
1767
+ afterDirectives(fnBody.body, [assign$Args]);
1743
1768
  node.body = fnBody;
1744
1769
  return;
1745
1770
  }
1746
1771
  });
1747
1772
  return ast;
1748
1773
  }
1749
-
1774
+
1750
1775
  /*
1751
1776
  * Rewrite
1752
1777
  async function <name>?<argumentlist><body>
1753
1778
  to
1754
- function <name>?<argumentlist>{ return function*() {<body>}.$asyncspawn(); }
1779
+ function <name>?<argumentlist>{ return function*() {<body>}.$asyncspawn(Promise,this); }
1780
+ or if the $runtime is set:
1781
+ $runtime.$asyncspawn.call(function <name>?<argumentlist>{ return function*() {<body>},Promise,this); }
1755
1782
  */
1756
1783
  // Like mapReturns, but ONLY for return/throw async
1757
1784
  function mapAsyncReturns(ast) {
@@ -1759,7 +1786,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1759
1786
  return ast.map(mapAsyncReturns);
1760
1787
  }
1761
1788
  var lambdaNesting = 0;
1762
- return parser.treeWalker(ast, function (node, descend, path) {
1789
+ return treeWalk(ast, function (node, descend, path) {
1763
1790
  if ((node.type === 'ThrowStatement' || node.type === 'ReturnStatement') && !node.$mapped) {
1764
1791
  if (lambdaNesting > 0) {
1765
1792
  if (examine(node).isAsync) {
@@ -1782,33 +1809,35 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1782
1809
  descend(node);
1783
1810
  });
1784
1811
  }
1785
-
1812
+
1786
1813
  function spawnBody(body, deferExit) {
1787
- if (opts.noRuntime)
1788
- throw new Error("Nodent: 'noRuntime' option only compatible with -promise and -engine modes") ;
1789
-
1790
- return parser.part("{ return (function*($return,$error){ $:body }).$asyncspawn(Promise,this) }",{
1791
- 'return':genIdent.return,
1792
- error:genIdent.error,
1793
- asyncspawn:genIdent.asyncspawn,
1794
- body: mapAsyncReturns(body).concat(deferExit ? [{
1795
- type: 'ReturnStatement',
1796
- argument: genIdent.return
1797
- }] : [])
1798
- }).body[0] ;
1814
+ if (opts.noRuntime)
1815
+ throw new Error("Nodent: 'noRuntime' option only compatible with -promise and -engine modes");
1816
+ var template = !opts.$runtime ? "{ return (function*($return,$error){ $:body }).$asyncspawn($promise,this) }" : "{ return $runtime.$asyncspawn.call(function*($return,$error){ $:body },$promise,this) }";
1817
+ return parsePart(template, {
1818
+ 'return': genIdent.return,
1819
+ error: genIdent.error,
1820
+ asyncspawn: genIdent.asyncspawn,
1821
+ runtime: genIdent.runtime,
1822
+ promise: genIdent.Promise,
1823
+ body: mapAsyncReturns(body).concat(deferExit ? [{
1824
+ type: 'ReturnStatement',
1825
+ argument: genIdent.return
1826
+ }] : [])
1827
+ }).body[0];
1799
1828
  }
1800
-
1829
+
1801
1830
  function warnAsyncGetter(id) {
1802
1831
  if (!id.$asyncgetwarninig) {
1803
1832
  id.$asyncgetwarninig = true;
1804
- logger(where(id) + "'async get "+printNode(id)+"(){...}' is non-standard. See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification");
1833
+ logger(where(id) + "'async get " + printNode(id) + "(){...}' is non-standard. See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification");
1805
1834
  }
1806
1835
  }
1807
-
1808
- function asyncSpawn(ast,engine) {
1809
- function mapAwaits(ast,hide) {
1810
- parser.treeWalker(ast, function (node, descend, path) {
1811
- if (node !== ast && examine(node).isFunction)
1836
+
1837
+ function asyncSpawn(ast, engine) {
1838
+ function mapAwaits(ast, hide) {
1839
+ treeWalk(ast, function (node, descend, path) {
1840
+ if (node !== ast && examine(node).isFunction)
1812
1841
  return;
1813
1842
  if (examine(node).isAwait) {
1814
1843
  if (hide) {
@@ -1820,18 +1849,18 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1820
1849
  node.type = 'YieldExpression';
1821
1850
  descend();
1822
1851
  }
1823
- } else
1852
+ } else
1824
1853
  descend();
1825
1854
  });
1826
1855
  }
1827
-
1856
+
1828
1857
  function promiseTransform(ast) {
1829
1858
  var promises = opts.promises;
1830
1859
  opts.promises = true;
1831
1860
  asyncTransforms(ast, true);
1832
1861
  opts.promises = promises;
1833
1862
  }
1834
-
1863
+
1835
1864
  function expandArrows(fn) {
1836
1865
  if (fn.body.type !== 'BlockStatement') {
1837
1866
  fn.body = {
@@ -1844,25 +1873,24 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1844
1873
  }
1845
1874
  return fn;
1846
1875
  }
1847
-
1876
+
1848
1877
  function warnAsyncExit(exit, fn) {
1849
1878
  if (!fn.$asyncexitwarninig) {
1850
1879
  fn.$asyncexitwarninig = true;
1851
1880
  logger(where(exit) + "'async " + ({
1852
1881
  ReturnStatement: 'return',
1853
1882
  ThrowStatement: 'throw'
1854
- })[exit.type] + "' not possible in "+(engine?'engine':'generator')+" mode. Using Promises for function at " + where(fn));
1883
+ })[exit.type] + "' not possible in " + (engine ? 'engine' : 'generator') + " mode. Using Promises for function at " + where(fn));
1855
1884
  }
1856
1885
  }
1857
-
1858
- parser.treeWalker(ast, function (node, descend, path) {
1886
+
1887
+ treeWalk(ast, function (node, descend, path) {
1859
1888
  descend();
1860
1889
  var fn, exit, usesArgs;
1861
1890
  if (examine(node).isAsync && examine(node).isFunction) {
1862
- var member ;
1863
- if ((member = getMemberFunction(path[0].parent))
1864
- && examine(member).isAsync && path[0].parent.kind === 'get') {
1865
- warnAsyncGetter(path[0].parent.key) ;
1891
+ var member;
1892
+ if ((member = getMemberFunction(path[0].parent)) && examine(member).isAsync && path[0].parent.kind === 'get') {
1893
+ warnAsyncGetter(path[0].parent.key);
1866
1894
  }
1867
1895
  if (exit = containsAsyncExit(node)) {
1868
1896
  // Do the Promise transform
@@ -1872,40 +1900,39 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1872
1900
  fn = node;
1873
1901
  delete fn.async;
1874
1902
  usesArgs = replaceArguments(fn);
1875
- mapAwaits(fn,false);
1903
+ mapAwaits(fn, false);
1876
1904
  fn = expandArrows(fn);
1877
1905
  fn.body = spawnBody(fn.body.body, exit);
1878
- if (usesArgs)
1879
- afterDirectives(fn.body.body,[assign$Args]);
1906
+ if (usesArgs)
1907
+ afterDirectives(fn.body.body, [assign$Args]);
1880
1908
  if (fn.id && path[0].parent.type === 'ExpressionStatement') {
1881
1909
  fn.type = 'FunctionDeclaration';
1882
1910
  path[1].replace(fn);
1883
1911
  } else {
1884
1912
  path[0].replace(fn);
1885
1913
  }
1886
- } else if (path[0].parent.kind !== 'get')
1887
- mapAwaits(node,true) ;
1914
+ } else if (path[0].parent.kind !== 'get')
1915
+ mapAwaits(node, true);
1888
1916
  } else if ((fn = getMemberFunction(node)) && examine(fn).isAsync) {
1889
1917
  if (exit = containsAsyncExit(fn)) {
1890
1918
  // Do the Promise transform
1891
1919
  warnAsyncExit(exit, fn);
1892
1920
  promiseTransform(node);
1893
- } else if (!engine || node.kind==='get') {
1921
+ } else if (!engine || node.kind === 'get') {
1894
1922
  if (engine) {
1895
- promiseTransform(node) ;
1923
+ promiseTransform(node);
1896
1924
  } else {
1897
1925
  node.async = false;
1898
1926
  usesArgs = replaceArguments(fn);
1899
- mapAwaits(fn,false);
1927
+ mapAwaits(fn, false);
1900
1928
  coerce(fn, expandArrows(fn));
1901
1929
  fn.body = spawnBody(fn.body.body, exit);
1902
1930
  }
1903
- if (usesArgs)
1904
- afterDirectives(fn.body.body,[assign$Args]);
1931
+ if (usesArgs)
1932
+ afterDirectives(fn.body.body, [assign$Args]);
1905
1933
  }
1906
1934
  }
1907
1935
  });
1908
-
1909
1936
  // Map (and warn) about any out-of-scope awaits that are being
1910
1937
  // mapped using Promises.
1911
1938
  var st = cloneNode(opts);
@@ -1913,7 +1940,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1913
1940
  opts.generators = false;
1914
1941
  blockifyArrows(ast);
1915
1942
  hoistDeclarations(ast);
1916
- labelTryCatch(ast,st.engine);
1943
+ labelTryCatch(ast, st.engine);
1917
1944
  mapLogicalOp(ast);
1918
1945
  mapCondOp(ast);
1919
1946
  walkDown(ast, [mapTryCatch,mapLoops,mapIfStmt,mapSwitch,mapBlock]);
@@ -1922,47 +1949,52 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1922
1949
  opts.generators = st.generators;
1923
1950
  return ast;
1924
1951
  }
1925
-
1952
+
1926
1953
  /* Find all nodes within this scope matching the specified function */
1927
1954
  function scopedNodes(ast, matching, flat) {
1955
+ if (!flat) flat = ['isScope','isLoop'] ;
1928
1956
  var matches = [];
1929
- parser.treeWalker(ast, function (node, descend, path) {
1930
- if (node === ast)
1957
+ treeWalk(ast, function (node, descend, path) {
1958
+ if (node === ast)
1931
1959
  return descend();
1932
1960
  if (matching(node, path)) {
1933
1961
  matches.push([].concat(path));
1934
1962
  return;
1935
1963
  }
1936
- if (flat || examine(node).isScope) {
1937
- return;
1938
- }
1964
+ if (flat === true) return ;
1965
+ var x = examine(node) ;
1966
+ for (var i=0; i<flat.length; i++)
1967
+ if (x[flat[i]])
1968
+ return ;
1939
1969
  descend();
1940
1970
  });
1941
1971
  return matches;
1942
1972
  }
1943
-
1944
- function extractVars(vars,kind) {
1973
+
1974
+ function extractVars(vars, kind) {
1945
1975
  var varDecls = [];
1946
- var duplicates = {} ;
1947
- vars = vars.filter(function(v){ return v[0].parent.type !== 'ExportNamedDeclaration'}) ;
1976
+ var duplicates = {};
1977
+ vars = vars.filter(function (v) {
1978
+ return v[0].parent.type !== 'ExportNamedDeclaration';
1979
+ });
1948
1980
  if (vars.length) {
1949
1981
  var definitions = {};
1950
1982
  vars.forEach(function (path) {
1951
1983
  function addName(name) {
1952
1984
  if (name in definitions) {
1953
- duplicates[name] = self.declarations[i] ;
1985
+ duplicates[name] = self.declarations[i];
1954
1986
  } else {
1955
- definitions[name] = self.declarations[i] ;
1987
+ definitions[name] = self.declarations[i];
1956
1988
  }
1957
1989
  }
1958
-
1990
+
1959
1991
  var ref = path[0];
1960
1992
  var self = ref.self;
1961
- var kind = self.kind ;
1993
+ var kind = self.kind;
1962
1994
  var values = [];
1963
1995
  for (var i = 0;i < self.declarations.length; i++) {
1964
- var decl = self.declarations[i] ;
1965
- getDeclNames(decl.id).forEach(addName) ;
1996
+ var decl = self.declarations[i];
1997
+ getDeclNames(decl.id).forEach(addName);
1966
1998
  if (decl.init) {
1967
1999
  var value = {
1968
2000
  type: 'AssignmentExpression',
@@ -1973,17 +2005,22 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
1973
2005
  values.push(value);
1974
2006
  }
1975
2007
  }
1976
- if (values.length == 0)
2008
+ if (values.length == 0)
1977
2009
  ref.remove();
1978
- else {
1979
- var repl = (values.length > 1)?{type:'SequenceExpression',expressions:values} : values[0] ;
1980
- if (ref.parent.type.slice(0,3)!=='For')
1981
- repl = {type:'ExpressionStatement',expression:repl} ;
1982
- ref.replace(repl);
2010
+ else {
2011
+ var repl = values.length > 1 ? {
2012
+ type: 'SequenceExpression',
2013
+ expressions: values
2014
+ } : values[0];
2015
+ if (ref.parent.type.slice(0, 3) !== 'For')
2016
+ repl = {
2017
+ type: 'ExpressionStatement',
2018
+ expression: repl
2019
+ };
2020
+ ref.replace(repl);
1983
2021
  }
1984
2022
  });
1985
-
1986
- var defs = Object.keys(definitions) ;
2023
+ var defs = Object.keys(definitions);
1987
2024
  if (defs.length) {
1988
2025
  defs = defs.map(function (name) {
1989
2026
  return {
@@ -2005,200 +2042,215 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2005
2042
  }
2006
2043
  }
2007
2044
  }
2008
- return { decls: varDecls, duplicates: duplicates } ;
2045
+ return {
2046
+ decls: varDecls,
2047
+ duplicates: duplicates
2048
+ };
2009
2049
  }
2010
-
2050
+
2011
2051
  function getDeclNames(id) {
2012
- if (!id) return [] ;
2052
+ if (!id)
2053
+ return [];
2013
2054
  if (Array.isArray(id)) {
2014
- return id.reduce(function(z,j){ return z.concat(getDeclNames(j.id))},[]) ;
2055
+ return id.reduce(function (z, j) {
2056
+ return z.concat(getDeclNames(j.id));
2057
+ }, []);
2015
2058
  }
2016
2059
  switch (id.type) {
2017
- case 'Identifier':
2018
- return [id.name] ;
2019
- case 'AssignmentPattern':
2020
- return getDeclNames(id.left);
2021
- case 'ArrayPattern':
2022
- return id.elements.reduce(function(z,e){ return z.concat(getDeclNames(e)) },[]) ;
2023
- case 'ObjectPattern':
2024
- return id.properties.reduce(function(z,e){ return z.concat(getDeclNames(e)) },[]) ;
2025
- case 'ObjectProperty':
2026
- case 'Property':
2027
- return getDeclNames(id.value) ;
2028
- case 'RestElement':
2029
- case 'RestProperty':
2030
- return getDeclNames(id.argument) ;
2060
+ case 'Identifier':
2061
+ return [id.name];
2062
+ case 'AssignmentPattern':
2063
+ return getDeclNames(id.left);
2064
+ case 'ArrayPattern':
2065
+ return id.elements.reduce(function (z, e) {
2066
+ return z.concat(getDeclNames(e));
2067
+ }, []);
2068
+ case 'ObjectPattern':
2069
+ return id.properties.reduce(function (z, e) {
2070
+ return z.concat(getDeclNames(e));
2071
+ }, []);
2072
+ case 'ObjectProperty':
2073
+ case 'Property':
2074
+ return getDeclNames(id.value);
2075
+ case 'RestElement':
2076
+ case 'RestProperty':
2077
+ return getDeclNames(id.argument);
2031
2078
  }
2032
2079
  }
2033
-
2080
+
2034
2081
  function checkConstsNotAssigned(ast) {
2035
2082
  /* Ensure no consts are on the LHS of an AssignmentExpression */
2036
- var names = {} ;
2037
-
2038
- function fail(node){
2039
- logger(where(node) + "Possible assignment to 'const " + printNode(node)+"'");
2083
+ var names = {};
2084
+ function fail(node) {
2085
+ logger(where(node) + "Possible assignment to 'const " + printNode(node) + "'");
2040
2086
  }
2041
-
2087
+
2042
2088
  function checkAssignable(target) {
2043
2089
  switch (target.type) {
2044
- case 'Identifier':
2045
- // Find the declaration of any names on the left
2046
- if (names[target.name] === 'const') fail(target) ;
2047
- break ;
2048
- case 'ArrayPattern':
2049
- target.elements.forEach(function(e){
2050
- if (names[e.name] === 'const') fail(e) ;
2051
- }) ;
2052
- break ;
2053
- case 'ObjectPattern':
2054
- target.properties.forEach(function(p){
2055
- if (names[p.key.name] === 'const') fail(p) ;
2056
- }) ;
2057
- break ;
2090
+ case 'Identifier':
2091
+ // Find the declaration of any names on the left
2092
+ if (names[target.name] === 'const')
2093
+ fail(target);
2094
+ break;
2095
+ case 'ArrayPattern':
2096
+ target.elements.forEach(function (e) {
2097
+ if (names[e.name] === 'const')
2098
+ fail(e);
2099
+ });
2100
+ break;
2101
+ case 'ObjectPattern':
2102
+ target.properties.forEach(function (p) {
2103
+ if (names[p.key.name] === 'const')
2104
+ fail(p);
2105
+ });
2106
+ break;
2058
2107
  }
2059
2108
  }
2060
-
2061
- parser.treeWalker(ast, function (node, descend, path) {
2062
- var body = examine(node).isBlockStatement ;
2109
+
2110
+ treeWalk(ast, function (node, descend, path) {
2111
+ var body = examine(node).isBlockStatement;
2063
2112
  if (body) {
2064
- names = Object.create(names) ;
2065
-
2066
- for (var h=0; h<body.length; h++) {
2113
+ names = Object.create(names);
2114
+ for (var h = 0;h < body.length; h++) {
2067
2115
  if (body[h].type === 'VariableDeclaration') {
2068
- for (var i=0; i<body[h].declarations.length; i++) {
2069
- getDeclNames(body[h].declarations[i].id).forEach(function(name){
2070
- names[name] = body[h].kind ;
2071
- }) ;
2116
+ for (var i = 0;i < body[h].declarations.length; i++) {
2117
+ getDeclNames(body[h].declarations[i].id).forEach(function (name) {
2118
+ names[name] = body[h].kind;
2119
+ });
2072
2120
  }
2073
2121
  }
2074
2122
  }
2075
2123
  }
2076
- descend() ;
2077
-
2078
- if (node.type === 'AssignmentExpression')
2079
- checkAssignable(node.left) ;
2080
- else if (node.type === 'UpdateExpression')
2081
- checkAssignable(node.argument) ;
2082
- if (body)
2083
- names = Object.getPrototypeOf(names) ;
2124
+ descend();
2125
+ if (node.type === 'AssignmentExpression')
2126
+ checkAssignable(node.left);
2127
+ else if (node.type === 'UpdateExpression')
2128
+ checkAssignable(node.argument);
2129
+ if (body)
2130
+ names = Object.getPrototypeOf(names);
2084
2131
  });
2085
2132
  }
2086
-
2133
+
2087
2134
  /* Move directives, vars and named functions to the top of their scope iff. the scope contains an 'await' */
2088
2135
  function hoistDeclarations(ast) {
2089
- var sequences = {
2090
- TemplateLiteral:function(x) { return x.expressions },
2091
- NewExpression:function(x) { return x.arguments },
2092
- CallExpression:function(x) { return x.arguments },
2093
- SequenceExpression:function(x) { return x.expressions },
2094
- ArrayExpression:function(x) { return x.elements },
2095
- ObjectExpression:function(oe){ return oe.properties.map(function(p){ return p.value })}
2096
- };
2136
+ var sequences = {
2137
+ TemplateLiteral: function (x) {
2138
+ return x.expressions;
2139
+ },
2140
+ NewExpression: function (x) {
2141
+ return x.arguments;
2142
+ },
2143
+ CallExpression: function (x) {
2144
+ return x.arguments;
2145
+ },
2146
+ SequenceExpression: function (x) {
2147
+ return x.expressions;
2148
+ },
2149
+ ArrayExpression: function (x) {
2150
+ return x.elements;
2151
+ },
2152
+ ObjectExpression: function (oe) {
2153
+ return oe.properties.map(function (p) {
2154
+ return p.value;
2155
+ });
2156
+ }
2157
+ };
2097
2158
  /* Identify SequenceExpressions, Parameter lists and VariableDeclarators that contain assigments and split them up
2098
2159
  to ensure the correct evaluation order */
2099
-
2100
- function containsAssign(ast){
2101
- return contains(ast, function(n){
2102
- return n.type==='AssignmentExpression'
2103
- });
2160
+ function containsAssign(ast) {
2161
+ return contains(ast, function (n) {
2162
+ return n.type === 'AssignmentExpression';
2163
+ });
2104
2164
  }
2105
-
2106
- parser.treeWalker(ast, function (node, descend, path) {
2107
- var i ;
2108
- descend() ;
2109
- // Ensure assigments are evaluated before any await expressions, eg:
2110
- // f(a=1, b = await a) --> a=1; f(a,b=await a)
2111
-
2112
- function moveAssignments(dest){
2113
- if (assignments.length) {
2114
- dest.argument = {
2115
- type:'SequenceExpression',
2116
- expressions:assignments.map(function(a){
2117
- var b = cloneNode(a)
2118
- coerce(a,a.left);
2119
- return b ;
2120
- }).concat(dest.argument)
2121
- } ;
2122
- assignments = [] ;
2123
- }
2124
- }
2125
-
2126
-
2127
- if (node.type in sequences && !node.$hoisted) {
2128
- var expr = sequences[node.type](node) ;
2129
- var assignments = [] ;
2130
- var path ;
2131
- for (i=0; i<expr.length;i++) {
2132
- if (examine(expr[i]).isScope)
2133
- continue ;
2134
-
2135
- if (path = containsAwait(expr[i]))
2136
- moveAssignments(path[0].self) ;
2137
-
2138
- if (!containsAwait(expr.slice(i+1)))
2139
- break ;
2140
-
2141
- if (path = containsAssign(expr[i]))
2142
- assignments.push(path[0].self) ;
2143
- }
2144
- } else if (node.type === 'VariableDeclaration') {
2145
- // If any of the VariableDeclarators contain an initial value and are followed by a VariableDeclarator
2146
- // containing an await, split them up into multiple statements
2147
- for (i=node.declarations.length-1; i>0; i--) {
2148
- if (node.declarations[i] && node.declarations[i].init && containsAwait(node.declarations[i].init)) {
2149
- var insert = {
2150
- type:'VariableDeclaration',
2151
- kind: node.kind,
2152
- declarations: node.declarations.splice(i)
2153
- } ;
2154
- var ref = path[0] ;
2155
- if ('index' in ref) {
2156
- ref.parent[ref.field].splice(ref.index+1,0,insert) ;
2157
- } else throw new Error("VariableDeclaration not in a block") ;
2158
- }
2165
+
2166
+ treeWalk(ast, function (node, descend, path) {
2167
+ var i;
2168
+ descend();
2169
+ // Ensure assigments are evaluated before any await expressions, eg:
2170
+ // f(a=1, b = await a) --> a=1; f(a,b=await a)
2171
+ function moveAssignments(dest) {
2172
+ if (assignments.length) {
2173
+ dest.argument = {
2174
+ type: 'SequenceExpression',
2175
+ expressions: assignments.map(function (a) {
2176
+ var b = cloneNode(a);
2177
+ coerce(a, a.left);
2178
+ return b;
2179
+ }).concat(dest.argument)
2180
+ };
2181
+ assignments = [];
2182
+ }
2159
2183
  }
2160
- }
2161
- }) ;
2162
-
2184
+
2185
+ if (node.type in sequences && !node.$hoisted) {
2186
+ var expr = sequences[node.type](node);
2187
+ var assignments = [];
2188
+ var path;
2189
+ for (i = 0; i < expr.length; i++) {
2190
+ if (examine(expr[i]).isScope)
2191
+ continue;
2192
+ if (path = containsAwait(expr[i]))
2193
+ moveAssignments(path[0].self);
2194
+ if (!containsAwait(expr.slice(i + 1)))
2195
+ break;
2196
+ if (path = containsAssign(expr[i]))
2197
+ assignments.push(path[0].self);
2198
+ }
2199
+ } else if (node.type === 'VariableDeclaration') {
2200
+ // If any of the VariableDeclarators contain an initial value and are followed by a VariableDeclarator
2201
+ // containing an await, split them up into multiple statements
2202
+ for (i = node.declarations.length - 1; i > 0; i--) {
2203
+ if (node.declarations[i] && node.declarations[i].init && containsAwait(node.declarations[i].init)) {
2204
+ var insert = {
2205
+ type: 'VariableDeclaration',
2206
+ kind: node.kind,
2207
+ declarations: node.declarations.splice(i)
2208
+ };
2209
+ var ref = path[0];
2210
+ if ('index' in ref) {
2211
+ ref.parent[ref.field].splice(ref.index + 1, 0, insert);
2212
+ } else
2213
+ throw new Error("VariableDeclaration not in a block");
2214
+ }
2215
+ }
2216
+ }
2217
+ });
2163
2218
  /* Hoist declarations */
2164
2219
  function isFreeVariable(kinds) {
2165
- return function(n, path) {
2166
- if (n.type === 'VariableDeclaration' && (n.kind = n.kind || 'var') && kinds.indexOf(n.kind)>=0) {
2167
- var p = path[0] ;
2220
+ return function (n, path) {
2221
+ if (n.type === 'VariableDeclaration' && (n.kind = n.kind || 'var') && kinds.indexOf(n.kind) >= 0) {
2222
+ var p = path[0];
2168
2223
  // Don't hoist the LHS of for (var/let/const _ of/in ... ; ;){}
2169
- if (p.field == "left" && (p.parent.type === 'ForInStatement' || p.parent.type === 'ForOfStatement'))
2224
+ if (p.field == "left" && (p.parent.type === 'ForInStatement' || p.parent.type === 'ForOfStatement'))
2170
2225
  return false;
2171
-
2172
2226
  // Don't hoist the LHS of for (let/const _ = ... ; ;){}
2173
- if (p.field == "init" && p.parent.type === 'ForStatement' && (n.kind==="const" || n.kind==="let"))
2227
+ if (p.field == "init" && p.parent.type === 'ForStatement' && (n.kind === "const" || n.kind === "let"))
2174
2228
  return false;
2175
-
2176
2229
  return true;
2177
2230
  }
2178
- }
2231
+ };
2179
2232
  }
2180
-
2233
+
2181
2234
  function isHoistableFunction(n, path) {
2182
2235
  // YES: We're a named function, but not a continuation
2183
- if (n.type==='FunctionDeclaration' && n.id) {
2236
+ if (n.type === 'FunctionDeclaration' && n.id) {
2184
2237
  return examine(n).isAsync || !n.$continuation;
2185
2238
  }
2186
2239
  // No, we're not a hoistable function
2187
2240
  return false;
2188
2241
  }
2189
-
2190
- checkConstsNotAssigned(ast) ;
2191
-
2192
- var inStrictBody = false ;
2193
- parser.treeWalker(ast, function (node, descend, path) {
2194
- var prevScope = inStrictBody ;
2195
- inStrictBody = inStrictBody || isStrict(node) ;
2196
-
2242
+
2243
+ checkConstsNotAssigned(ast);
2244
+ var inStrictBody = false;
2245
+ treeWalk(ast, function (node, descend, path) {
2246
+ var prevScope = inStrictBody;
2247
+ inStrictBody = inStrictBody || isStrict(node);
2197
2248
  if (examine(node).isBlockStatement) {
2198
2249
  if (containsAwait(node)) {
2199
2250
  // For this scope/block, find all the hoistable functions, vars and directives
2200
- var isScope = !path[0].parent || examine(path[0].parent).isScope ;
2201
-
2251
+ var isVarScope = !path[0].parent || examine(path[0].parent).isScope ;
2252
+ var isLoopScope = path[0].parent && examine(path[0].parent).isLoop ;
2253
+ var isScope = isVarScope || isLoopScope ;
2202
2254
  /* 'const' is highly problematic. In early version of Chrome (Node 0.10, 4.x, 5.x) non-standard behaviour:
2203
2255
  *
2204
2256
  * Node scope multiple-decls
@@ -2217,36 +2269,34 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2217
2269
  * - const's with a single declaration in the current scope (NOT block) should be hoisted to function level, and defined as 'var'
2218
2270
  * - const's with duplicate declarations in the current scope (NOT block) should be hoisted to block level, and defined as 'let'
2219
2271
  */
2220
-
2221
- var directives, consts, vars, lets, functions ;
2272
+ var directives, consts, vars, lets, functions;
2222
2273
  if (isScope) {
2223
- consts = scopedNodes(node, isFreeVariable(['const']),false);
2224
- var names = {}, duplicates = {} ;
2225
-
2274
+ consts = scopedNodes(node, isFreeVariable(['const']), false);
2275
+ var names = {}, duplicates = {};
2226
2276
  // Work out which const identifiers are duplicates
2227
2277
  // Ones that are only declared once can simply be treated as vars, whereas
2228
2278
  // identifiers that are declared multiple times have block-scope and are
2229
- // only valid in node 6 or in strict mode on node 4/5
2230
- consts.forEach(function(d){
2231
- d[0].self.declarations.forEach(function(e){
2232
- getDeclNames(e.id).forEach(function(n){
2233
- if (names[n] || duplicates[n]) {
2234
- delete names[n] ;
2235
- duplicates[n] = e ;
2279
+ // only valid in node 6 or in strict mode on node 4/5.
2280
+ // In strict mode or ES6-a-like targets always assume the correct ES6 semantics (block scope)
2281
+ consts.forEach(function (d) {
2282
+ d[0].self.declarations.forEach(function (e) {
2283
+ getDeclNames(e.id).forEach(function (n) {
2284
+ if (inStrictBody || looksLikeES6 || names[n] || duplicates[n]) {
2285
+ looksLikeES6 = true ;
2286
+ delete names[n];
2287
+ duplicates[n] = e;
2236
2288
  } else {
2237
- names[n] = e ;
2289
+ names[n] = e;
2238
2290
  }
2239
- }) ;
2240
- }) ;
2241
- }) ;
2242
-
2291
+ });
2292
+ });
2293
+ });
2243
2294
  // Change all the declarations into assignments, since consts are always initialized
2244
- consts.forEach(function(d){
2245
- for (var depth=0; depth<d.length; depth++)
2246
- if (examine(d[depth].parent).isBlockStatement)
2247
- break ;
2248
-
2249
- var ref = d[depth] ;
2295
+ consts.forEach(function (d) {
2296
+ for (var depth = 0;depth < d.length; depth++)
2297
+ if (examine(d[depth].parent).isBlockStatement)
2298
+ break;
2299
+ var ref = d[depth];
2250
2300
  ref.append({
2251
2301
  type: 'ExpressionStatement',
2252
2302
  expression: {
@@ -2258,58 +2308,66 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2258
2308
  left: d.id,
2259
2309
  right: d.init
2260
2310
  };
2261
- d.init = null ;
2262
- return a ;
2311
+ d.init = null;
2312
+ return a;
2263
2313
  })
2264
2314
  }
2265
2315
  });
2266
- var ids = getDeclNames(d[0].self.declarations) ;
2267
- var decls = ids.filter(function(name){ return name in duplicates }) ;
2316
+ var ids = getDeclNames(d[0].self.declarations);
2317
+ var decls = ids.filter(function (name) {
2318
+ return name in duplicates;
2319
+ });
2268
2320
  if (decls.length) {
2269
2321
  d[0].append({
2270
- type:'VariableDeclaration',
2271
- kind:'let',
2272
- declarations: decls.map(function(name){
2322
+ type: 'VariableDeclaration',
2323
+ kind: 'let',
2324
+ declarations: decls.map(function (name) {
2273
2325
  return {
2274
- type:'VariableDeclarator',
2275
- id:ident(name)
2276
- }
2326
+ type: 'VariableDeclarator',
2327
+ id: ident(name)
2328
+ };
2277
2329
  })
2278
- }) ;
2330
+ });
2279
2331
  }
2280
-
2281
- d[0].self.kind = 'var' ;
2282
- decls = ids.filter(function(name){ return name in names }) ;
2332
+ d[0].self.kind = 'var';
2333
+ decls = ids.filter(function (name) {
2334
+ return name in names;
2335
+ });
2283
2336
  if (decls.length) {
2284
- d[0].self.declarations = decls.map(function(name){
2337
+ d[0].self.declarations = decls.map(function (name) {
2285
2338
  return {
2286
- type:'VariableDeclarator',
2287
- id:ident(name)
2288
- }
2339
+ type: 'VariableDeclarator',
2340
+ id: ident(name)
2341
+ };
2289
2342
  });
2290
2343
  } else {
2291
- ref.remove() ;
2344
+ ref.remove();
2292
2345
  }
2293
- }) ;
2294
- vars = scopedNodes(node, isFreeVariable(['var']),false);
2295
- lets = [] ;
2346
+ });
2347
+ if (isVarScope && !isLoopScope) vars = scopedNodes(node, isFreeVariable(['var']), ['isScope']);
2348
+ lets = [];
2296
2349
  } else {
2297
- lets = scopedNodes(node, isFreeVariable(['const']),true);
2350
+ lets = scopedNodes(node, isFreeVariable(['const']), true);
2298
2351
  }
2299
- lets = lets.concat(scopedNodes(node, isFreeVariable(['let']),true));
2300
- directives = scopedNodes(node, function (n) { return examine(n).isDirective },true);
2352
+ lets = lets.concat(scopedNodes(node, isFreeVariable(['let']), true));
2353
+ directives = scopedNodes(node, function (n) {
2354
+ return examine(n).isDirective;
2355
+ }, true);
2301
2356
  functions = scopedNodes(node, isHoistableFunction, inStrictBody);
2302
-
2303
- vars = vars?extractVars(vars,'var'):{duplicates:{},decls:[]} ;
2304
- lets = lets?extractVars(lets,'let'):{duplicates:{},decls:[]} ;
2305
-
2306
- Object.keys(vars.duplicates).forEach(function(id){
2357
+ vars = vars ? extractVars(vars, 'var') : {
2358
+ duplicates: {},
2359
+ decls: []
2360
+ };
2361
+ lets = lets ? extractVars(lets, 'let') : {
2362
+ duplicates: {},
2363
+ decls: []
2364
+ };
2365
+ Object.keys(vars.duplicates).forEach(function (id) {
2307
2366
  logger(where(vars.duplicates[id]) + "Duplicate declaration '" + printNode(vars.duplicates[id]) + "'");
2308
- }) ;
2309
- Object.keys(lets.duplicates).forEach(function(id){
2367
+ });
2368
+ Object.keys(lets.duplicates).forEach(function (id) {
2310
2369
  logger(where(lets.duplicates[id]) + "Duplicate declaration '" + printNode(lets.duplicates[id]) + "'");
2311
- }) ;
2312
-
2370
+ });
2313
2371
  functions = functions.map(function (path) {
2314
2372
  var ref = path[0], symName;
2315
2373
  // What is the name of this function (could be async, so check the expression if necessary),
@@ -2330,7 +2388,6 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2330
2388
  var movedFn = ref.self.type === 'FunctionDeclaration' ? ref.remove() : ref.replace(ident(symName));
2331
2389
  return movedFn;
2332
2390
  });
2333
-
2334
2391
  directives = directives.map(function (path) {
2335
2392
  var ref = path[0];
2336
2393
  return ref.remove();
@@ -2339,61 +2396,61 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2339
2396
  node.body = directives.concat(vars.decls).concat(lets.decls).concat(functions).concat(node.body);
2340
2397
  }
2341
2398
  }
2342
- inStrictBody = prevScope ;
2399
+ inStrictBody = prevScope;
2343
2400
  }
2344
-
2345
- // Labeled blocks need to be treated as loops that exit on the first iteration if they contain awaits and labelled breaks
2346
- if (node.type==='LabeledStatement' && node.body.type==='BlockStatement' && containsAwait(node.body) && contains(node.body,function(m){
2347
- return m.type === 'BreakStatement' && m.label
2348
- })) {
2349
- node.body.body.push({ type: 'BreakStatement' }) ;
2350
- node.body = {
2351
- type: 'DoWhileStatement',
2352
- test: literal(0),
2353
- body: node.body
2354
- };
2401
+ // Labeled breaks need to be treated as loops that always exit early, if they contain awaits
2402
+ if (node.type === 'LabeledStatement' && node.body.type === 'BlockStatement' && containsAwait(node.body)) {
2403
+ if (contains(node.body, function (m) {
2404
+ return m.type === 'BreakStatement' && m.label && m.label.name == node.label.name;
2405
+ })) {
2406
+ node.body.body.push({
2407
+ type: 'BreakStatement'
2408
+ });
2409
+ node.body = {
2410
+ type: 'DoWhileStatement',
2411
+ test: literal(0),
2412
+ body: node.body
2413
+ };
2414
+ }
2355
2415
  }
2356
-
2357
2416
  descend();
2358
-
2359
2417
  // It makes life easier if labeled loops have the label to hand, so we simply reference them here with a hidden $label
2360
2418
  // and keep a record of how nested the for loop is (since it's transformed top to bottom and counting during
2361
2419
  // transformation is therefore not possible
2362
- if (node.type==='ForOfStatement' || node.type==='ForInStatement' || examine(node).isLoop) {
2363
- var depth = 0 ;
2364
- for (var n=0; n<path.length;n++)
2365
- if (path[n].self.type==='ForOfStatement' || path[n].self.type==='ForInStatement' || examine(path[n].self).isLoop)
2366
- depth += 1 ;
2367
- else if (examine(path[n].self).isFunction)
2368
- break ;
2369
-
2370
- node.$depth = depth ;
2371
- if (path[0].parent.type==='LabeledStatement') {
2372
- node.$label = path[0].parent.label ;
2420
+ if (node.type === 'ForOfStatement' || node.type === 'ForInStatement' || examine(node).isLoop) {
2421
+ var depth = 0;
2422
+ for (var n = 0;n < path.length; n++)
2423
+ if (path[n].self.type === 'ForOfStatement' || path[n].self.type === 'ForInStatement' || examine(path[n].self).isLoop)
2424
+ depth += 1;
2425
+ else if (examine(path[n].self).isFunction)
2426
+ break;
2427
+ node.$depth = depth;
2428
+ if (path[0].parent.type === 'LabeledStatement') {
2429
+ node.$label = path[0].parent.label;
2373
2430
  } else {
2374
- node.$label = null ;
2431
+ node.$label = null;
2375
2432
  }
2376
2433
  }
2377
2434
  return true;
2378
2435
  });
2379
2436
  return ast;
2380
2437
  }
2381
-
2438
+
2382
2439
  function mapSupers(classNode, engine) {
2383
2440
  function superID() {
2384
2441
  return classNode.$superID = classNode.$superID || ident("$super$" + generatedSymbol++);
2385
2442
  }
2386
-
2443
+
2387
2444
  return function (method) {
2388
2445
  method = getMemberFunction(method);
2389
- if (method && examine(method).isAsync && (!engine || method.kind === 'get' || contains(method,function(n){
2390
- return (examine(n).isFunction && contains(n,function(n){
2391
- return n.type==='Super'
2392
- }) && contains(n,function(n){
2393
- return n.async && (n.type==='ReturnStatement' || n.type==='ThrowStatement') ;
2394
- }))
2395
- },true))) {
2396
- parser.treeWalker(method.body, function (node, descend, path) {
2446
+ if (method && examine(method).isAsync && (!engine || method.kind === 'get' || contains(method, function (n) {
2447
+ return examine(n).isFunction && contains(n, function (n) {
2448
+ return n.type === 'Super';
2449
+ }) && contains(n, function (n) {
2450
+ return n.async && (n.type === 'ReturnStatement' || n.type === 'ThrowStatement');
2451
+ });
2452
+ }, true))) {
2453
+ treeWalk(method.body, function (node, descend, path) {
2397
2454
  var r;
2398
2455
  if (!examine(node).isClass) {
2399
2456
  descend();
@@ -2401,18 +2458,18 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2401
2458
  if (path[0].parent.type === 'MemberExpression') {
2402
2459
  if (path[1].parent.type === 'CallExpression' && path[1].field === 'callee') {
2403
2460
  // super[m](...) maps to: this.$superid(m).call(this,...)
2404
- r = parser.part("this.$super($field).call(this,$args)",{
2405
- 'super':superID(),
2406
- field:path[0].parent.computed ? path[0].parent.property:literal(path[0].parent.property.name),
2407
- args:path[1].parent.arguments
2408
- }).expr ;
2461
+ r = parsePart("this.$super($field).call(this,$args)", {
2462
+ 'super': superID(),
2463
+ field: path[0].parent.computed ? path[0].parent.property : literal(path[0].parent.property.name),
2464
+ args: path[1].parent.arguments
2465
+ }).expr;
2409
2466
  path[2].replace(r);
2410
2467
  } else {
2411
2468
  // super[f], maps to: this.$superid(f)
2412
- r = parser.part("this.$super($field)",{
2413
- 'super':superID(),
2414
- field:path[0].parent.computed ?path[0].parent.property : literal(path[0].parent.property.name)
2415
- }).expr ;
2469
+ r = parsePart("this.$super($field)", {
2470
+ 'super': superID(),
2471
+ field: path[0].parent.computed ? path[0].parent.property : literal(path[0].parent.property.name)
2472
+ }).expr;
2416
2473
  path[1].replace(r);
2417
2474
  }
2418
2475
  } else {
@@ -2424,14 +2481,16 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2424
2481
  }
2425
2482
  };
2426
2483
  }
2427
-
2428
- function fixSuperReferences(ast,engine) {
2429
- return parser.treeWalker(ast, function (node, descend, path) {
2484
+
2485
+ function fixSuperReferences(ast, engine) {
2486
+ return treeWalk(ast, function (node, descend, path) {
2430
2487
  descend();
2431
2488
  if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
2432
- node.body.body.forEach(mapSupers(node,engine));
2489
+ node.body.body.forEach(mapSupers(node, engine));
2433
2490
  if (node.$superID) {
2434
- var method = parser.part("(function($field) { return super[$field] })",{ field:ident("$field") }).expr ;
2491
+ var method = parsePart("(function($field) { return super[$field] })", {
2492
+ field: ident("$field")
2493
+ }).expr;
2435
2494
  if (opts.babelTree) {
2436
2495
  method.type = 'ClassMethod';
2437
2496
  method.key = node.$superID;
@@ -2449,11 +2508,11 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2449
2508
  }
2450
2509
  });
2451
2510
  }
2452
-
2511
+
2453
2512
  function blockifyArrows(ast) {
2454
- parser.treeWalker(ast, function (node, descend, path) {
2513
+ treeWalk(ast, function (node, descend, path) {
2455
2514
  var awaiting = containsAwait(node);
2456
- if (awaiting) {
2515
+ if (awaiting) {
2457
2516
  if (node.type === 'ArrowFunctionExpression' && node.body.type !== 'BlockStatement') {
2458
2517
  node.body = {
2459
2518
  type: "BlockStatement",
@@ -2469,10 +2528,10 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2469
2528
  });
2470
2529
  return ast;
2471
2530
  }
2472
-
2531
+
2473
2532
  function exposeCompilerOpts(ast) {
2474
2533
  // Expose compiler
2475
- parser.treeWalker(ast, function (node, descend, path) {
2534
+ treeWalk(ast, function (node, descend, path) {
2476
2535
  descend();
2477
2536
  if (node.type === 'Identifier' && node.name === '__nodent') {
2478
2537
  coerce(node, literal(opts));
@@ -2480,47 +2539,42 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2480
2539
  });
2481
2540
  return ast;
2482
2541
  }
2483
-
2542
+
2484
2543
  /* Called with a Program or FunctionDeclaration.body */
2485
2544
  function isStrict(node) {
2486
- if (node.type === 'Program' && node.sourceType === 'module')
2487
- return true ;
2488
-
2489
- var nodes ;
2490
- if (node.type === 'Program')
2491
- nodes = node.body ;
2492
- else if (examine(node).isFunction)
2493
- nodes = node.body.body ;
2494
- else return false ;
2495
-
2496
- if (nodes) for (var i=0; i<nodes.length; i++)
2497
- if (examine(nodes[i]).isDirective && nodes[i].expression.value.match(/^\s*use\s+strict\s*$/))
2498
- return true ;
2499
- return false ;
2545
+ if (node.type === 'Program' && node.sourceType === 'module')
2546
+ return true;
2547
+ var nodes;
2548
+ if (node.type === 'Program')
2549
+ nodes = node.body;
2550
+ else if (examine(node).isFunction)
2551
+ nodes = node.body.body;
2552
+ else
2553
+ return false;
2554
+ if (nodes)
2555
+ for (var i = 0;i < nodes.length; i++)
2556
+ if (examine(nodes[i]).isDirective && nodes[i].expression.value.match(/^\s*use\s+strict\s*$/))
2557
+ return true;
2558
+ return false;
2500
2559
  }
2501
-
2560
+
2502
2561
  function containsBlockScopedDeclarations(nodes) {
2503
2562
  for (var i = 0;i < nodes.length; i++) {
2504
2563
  var node = nodes[i];
2505
- if (node.type === 'ClassDeclaration' ||
2506
- (node.type === 'VariableDeclaration' && (node.kind === 'let' || node.kind === 'const')) ||
2507
- (node.type === 'FunctionDeclaration' && node.id && node.id.name && !node.$continuation)) {
2564
+ if (node.type === 'ClassDeclaration' || node.type === 'VariableDeclaration' && (node.kind === 'let' || node.kind === 'const') || node.type === 'FunctionDeclaration' && node.id && node.id.name && !node.$continuation) {
2508
2565
  return true;
2509
2566
  }
2510
2567
  }
2511
2568
  return false;
2512
2569
  }
2513
-
2570
+
2514
2571
  /* Remove un-necessary nested blocks and crunch down empty function implementations */
2515
2572
  function cleanCode(ast) {
2516
2573
  // Coalese BlockStatements
2517
- parser.treeWalker(ast, function (node, descend, path) {
2574
+ treeWalk(ast, function (node, descend, path) {
2518
2575
  descend();
2519
- if (node.type==='ArrowFunctionExpression'
2520
- && node.body.type === 'BlockStatement'
2521
- && node.body.body.length===1
2522
- && node.body.body[0].type==='ReturnStatement') {
2523
- node.body = node.body.body[0].argument
2576
+ if (node.type === 'ArrowFunctionExpression' && node.body.type === 'BlockStatement' && node.body.body.length === 1 && node.body.body[0].type === 'ReturnStatement') {
2577
+ node.body = node.body.body[0].argument;
2524
2578
  } else {
2525
2579
  var block, child;
2526
2580
  // If this node is a block with vanilla BlockStatements (no controlling entity), merge them
@@ -2529,7 +2583,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2529
2583
  // For ES6, this needs more care, as blocks containing 'let/const/class' have a scope of their own
2530
2584
  for (var i = 0;i < block.length; i++) {
2531
2585
  if ((child = examine(block[i]).isBlockStatement) && !containsBlockScopedDeclarations(child)) {
2532
- if (!containsBlockScopedDeclarations(block[i]))
2586
+ if (!containsBlockScopedDeclarations(block[i]))
2533
2587
  [].splice.apply(block, [i,1].concat(child));
2534
2588
  }
2535
2589
  }
@@ -2537,7 +2591,7 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2537
2591
  }
2538
2592
  });
2539
2593
  // Truncate BlockStatements with a Jump (break;continue;return;throw) inside
2540
- parser.treeWalker(ast, function (node, descend, path) {
2594
+ treeWalk(ast, function (node, descend, path) {
2541
2595
  descend();
2542
2596
  if (examine(node).isJump) {
2543
2597
  var ref = path[0];
@@ -2546,9 +2600,9 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2546
2600
  var ctn = ref.parent[ref.field];
2547
2601
  while (i < ctn.length) {
2548
2602
  // Remove any statements EXCEPT for function/var definitions
2549
- if (ctn[i].type === 'VariableDeclaration' || examine(ctn[i]).isFunction && ctn[i].id)
2603
+ if (ctn[i].type === 'VariableDeclaration' || examine(ctn[i]).isFunction && ctn[i].id)
2550
2604
  i += 1;
2551
- else
2605
+ else
2552
2606
  ctn.splice(i, 1);
2553
2607
  }
2554
2608
  }
@@ -2556,11 +2610,11 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2556
2610
  });
2557
2611
  /* Inline continuations that are only referenced once */
2558
2612
  // Find any continuations that have a single reference
2559
- parser.treeWalker(ast, function (node, descend, path) {
2613
+ treeWalk(ast, function (node, descend, path) {
2560
2614
  descend();
2561
2615
  if (node.$thisCall && continuations[node.name]) {
2562
2616
  if (continuations[node.name].ref) {
2563
- delete continuations[node.name]; // Multiple ref
2617
+ delete continuations[node.name]; // Multiple ref
2564
2618
  } else {
2565
2619
  continuations[node.name].ref = node.$thisCall;
2566
2620
  }
@@ -2571,14 +2625,14 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2571
2625
  });
2572
2626
  if (calls.length) {
2573
2627
  // Replace all the calls to the continuation with the body from the continuation followed by 'return;'
2574
- parser.treeWalker(ast, function (node, descend, path) {
2628
+ treeWalk(ast, function (node, descend, path) {
2575
2629
  descend();
2576
2630
  if (calls.indexOf(node) >= 0) {
2577
2631
  if (path[1].self.type === 'ReturnStatement') {
2578
2632
  var sym = node.$thisCallName;
2579
2633
  var repl = cloneNode(continuations[sym].def.body.body);
2580
2634
  continuations[sym].$inlined = true;
2581
- if (!examine(path[1].self).isJump)
2635
+ if (!examine(path[1].self).isJump)
2582
2636
  repl.push({
2583
2637
  type: 'ReturnStatement'
2584
2638
  });
@@ -2590,55 +2644,47 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2590
2644
  return continuations[c].$inlined && continuations[c].def;
2591
2645
  });
2592
2646
  // Remove all the (now inline) declarations of the continuations
2593
- parser.treeWalker(ast, function (node, descend, path) {
2647
+ treeWalk(ast, function (node, descend, path) {
2594
2648
  descend();
2595
2649
  if (defs.indexOf(node) >= 0) {
2596
2650
  path[0].remove();
2597
2651
  }
2598
2652
  });
2599
2653
  }
2600
-
2601
2654
  // Hoist generated FunctionDeclarations within ES5 Strict functions (actually put them at the
2602
2655
  // end of the scope-block, don't hoist them, it's just an expensive operation)
2603
- var looksLikeES6 = (ast.type==='Program' && ast.sourceType==='module') || contains(ast,function(n){
2604
- return examine(n).isES6 ;
2605
- },true) ;
2606
-
2607
2656
  if (!looksLikeES6) {
2608
- var useStrict = isStrict(ast) ;
2609
- (function(ast){
2610
- parser.treeWalker(ast, function (node, descend, path) {
2611
- if (node.type==='Program' || node.type==='FunctionDeclaration' || node.type==='FunctionExpression') {
2612
- var wasStrict = useStrict ;
2613
- useStrict = useStrict || isStrict(node) ;
2657
+ var useStrict = isStrict(ast);
2658
+ (function (ast) {
2659
+ treeWalk(ast, function (node, descend, path) {
2660
+ if (node.type === 'Program' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') {
2661
+ var wasStrict = useStrict;
2662
+ useStrict = useStrict || isStrict(node);
2614
2663
  if (useStrict) {
2615
2664
  descend();
2616
-
2617
- var functionScope = node.type === 'Program' ? node : node.body ;
2618
- var functions = scopedNodes(functionScope,function(n,path){
2619
- if (n.type==='FunctionDeclaration') {
2620
- return path[0].parent !== functionScope ;
2665
+ var functionScope = node.type === 'Program' ? node : node.body;
2666
+ var functions = scopedNodes(functionScope, function (n, path) {
2667
+ if (n.type === 'FunctionDeclaration') {
2668
+ return path[0].parent !== functionScope;
2621
2669
  }
2622
- }) ;
2623
-
2670
+ },['isScope']);
2624
2671
  functions = functions.map(function (path) {
2625
- return path[0].remove() ;
2672
+ return path[0].remove();
2626
2673
  });
2627
- [].push.apply(functionScope.body,functions) ;
2674
+ [].push.apply(functionScope.body, functions);
2628
2675
  } else {
2629
2676
  descend();
2630
2677
  }
2631
- useStrict = wasStrict ;
2678
+ useStrict = wasStrict;
2632
2679
  } else {
2633
2680
  descend();
2634
2681
  }
2635
- }) ;
2682
+ });
2636
2683
  })(ast);
2637
2684
  }
2638
-
2639
2685
  /*
2640
2686
  function replaceSymbols(ast,from,to) {
2641
- parser.treeWalker(ast,function(node,descend,path){
2687
+ treeWalk(ast,function(node,descend,path){
2642
2688
  descend() ;
2643
2689
  if (node.type=='Identifier' && node.name==from) {
2644
2690
  node.name = to ;
@@ -2663,32 +2709,219 @@ function asynchronize(pr, __sourceMapping, opts, logger) {
2663
2709
  // these can be simplified to:
2664
2710
  // $return
2665
2711
  */
2666
-
2667
- // Remove all the 'hiiden' node info generated during transformation
2668
- parser.treeWalker(ast,function(node,descend,path){
2669
- descend() ;
2670
- Object.keys(node).filter(function(k){ return k[0]==='$'}).forEach(function(k){
2671
- delete node[k] ;
2672
- }) ;
2673
- }) ;
2712
+ // Remove all the 'hidden' node info generated during transformation
2713
+ treeWalk(ast, function (node, descend, path) {
2714
+ descend();
2715
+ Object.keys(node).filter(function (k) {
2716
+ return k[0] === '$';
2717
+ }).forEach(function (k) {
2718
+ delete node[k];
2719
+ });
2720
+ });
2674
2721
  return ast;
2675
2722
  }
2723
+
2676
2724
  }
2677
2725
 
2678
- module.exports = {
2679
- printNode:printNode,
2680
- babelLiteralNode: babelLiteralNode,
2681
- asynchronize: function (pr, __sourceMapping, opts, logger) {
2682
- try {
2683
- return asynchronize(pr, __sourceMapping, opts, logger);
2684
- } catch (ex) {
2685
- if (ex instanceof SyntaxError) {
2686
- var l = pr.origCode.substr(ex.pos - ex.loc.column);
2687
- l = l.split("\n")[0];
2688
- ex.message += " (nodent)\n" + l + "\n" + l.replace(/[\S ]/g, "-").substring(0, ex.loc.column) + "^";
2689
- ex.stack = "";
2726
+ /* AST helpers: treeWalk */
2727
+ function loc(old, repl) {
2728
+ ['start','end','loc','range'].forEach(function (k) {
2729
+ if (k in old && !(k in repl))
2730
+ repl[k] = old[k];
2731
+ });
2732
+ }
2733
+
2734
+ var referencePrototypes = {
2735
+ replace: function (newNode) {
2736
+ if (Array.isArray(newNode) && newNode.length === 1)
2737
+ newNode = newNode[0];
2738
+ if ('index' in this) {
2739
+ loc(this.parent[this.field][this.index], newNode);
2740
+ if (Array.isArray(newNode)) {
2741
+ [].splice.apply(this.parent[this.field], [this.index,1].concat(newNode));
2742
+ } else {
2743
+ this.parent[this.field][this.index] = newNode;
2690
2744
  }
2691
- throw ex;
2745
+ } else {
2746
+ loc(this.parent[this.field], newNode);
2747
+ if (Array.isArray(newNode)) {
2748
+ this.parent[this.field] = {
2749
+ type: 'BlockStatement',
2750
+ body: newNode
2751
+ };
2752
+ } else {
2753
+ this.parent[this.field] = newNode;
2754
+ }
2755
+ }
2756
+ return this.self;
2757
+ },
2758
+ append: function (newNode) {
2759
+ if (Array.isArray(newNode) && newNode.length === 1)
2760
+ newNode = newNode[0];
2761
+ if ('index' in this) {
2762
+ if (Array.isArray(newNode)) {
2763
+ [].splice.apply(this.parent[this.field], [this.index + 1,0].concat(newNode));
2764
+ } else {
2765
+ this.parent[this.field].splice(this.index + 1, 0, newNode);
2766
+ }
2767
+ } else {
2768
+ throw new Error("Cannot append Element node to non-array");
2692
2769
  }
2770
+ return this.self;
2771
+ },
2772
+ index: function () {
2773
+ return this.parent[this.field].indexOf(this.self);
2774
+ },
2775
+ removeElement: function () {
2776
+ return this.parent[this.field].splice(this.index, 1)[0];
2777
+ },
2778
+ removeNode: function () {
2779
+ var r = this.parent[this.field];
2780
+ delete this.parent[this.field];
2781
+ return r;
2782
+ }
2783
+ };
2784
+ var notNodeKeys = {
2785
+ start: true,
2786
+ end: true,
2787
+ loc: true,
2788
+ range: true,
2789
+ type: true
2790
+ };
2791
+ function forEachNodeKey(n, down) {
2792
+ if (n && n.type) {
2793
+ var keys = Object.keys(n).filter(function (k) {
2794
+ return k[0] != '$' && k[0] != '_' && !(k in notNodeKeys) && typeof n[k] === 'object' && n[k] && (typeof n[k].type === 'string' || Array.isArray(n[k]));
2795
+ });
2796
+ keys.forEach(function (member) {
2797
+ if (Array.isArray(n[member])) {
2798
+ n[member].forEach(function (node, index) {
2799
+ down(node, member, index);
2800
+ });
2801
+ } else
2802
+ down(n[member], member, null);
2803
+ });
2804
+ }
2805
+ }
2806
+
2807
+ function treeWalk(n, walker, state) {
2808
+ if (!state) {
2809
+ state = [{
2810
+ self: n
2811
+ }];
2812
+ state.replace = function (pos, newNode) {
2813
+ state[pos].replace(newNode);
2814
+ };
2815
+ }
2816
+ function descend() {
2817
+ forEachNodeKey(n, function down(sub, key, index) {
2818
+ if (!sub)
2819
+ return;
2820
+ var ref = {
2821
+ replace: referencePrototypes.replace,
2822
+ append: referencePrototypes.append,
2823
+ self: sub,
2824
+ parent: n,
2825
+ field: key
2826
+ };
2827
+ if (index !== null) {
2828
+ ref.index = true;
2829
+ Object.defineProperties(ref, {
2830
+ index: {
2831
+ enumerable: true,
2832
+ get: referencePrototypes.index
2833
+ }
2834
+ });
2835
+ ref.remove = referencePrototypes.removeElement;
2836
+ } else {
2837
+ ref.remove = referencePrototypes.removeNode;
2838
+ }
2839
+ state.unshift(ref);
2840
+ treeWalk(ref.self, walker, state);
2841
+ state.shift();
2842
+ });
2843
+ }
2844
+
2845
+ ;
2846
+ walker(n, descend, state);
2847
+ return n;
2848
+ }
2849
+
2850
+ /* AST helpers: partialParser */
2851
+ function partialParser(parse) {
2852
+ var parseCache = {};
2853
+ return function partialParse(code, args) {
2854
+ if (!parseCache[code]) {
2855
+ parseCache[code] = parse(code);
2856
+ }
2857
+ var result = substitute(parseCache[code]);
2858
+ return {
2859
+ body: result.body,
2860
+ expr: result.body[0].type === 'ExpressionStatement' ? result.body[0].expression : null
2861
+ };
2862
+ /* parse and substitute:
2863
+ *
2864
+ * $1 Substitute the specified expression. If $1 occupies a slot which is an array of expressions (e.g arguments, params)
2865
+ * and the passed argument is an array, subtitute the whole set
2866
+ * {$:1} Substitute a single statement
2867
+ *
2868
+ */
2869
+ function substitute(src, dest) {
2870
+ if (Array.isArray(dest) && !Array.isArray(src))
2871
+ throw new Error("Can't substitute an array for a node");
2872
+ dest = dest || {};
2873
+ Object.keys(src).forEach(function (k) {
2874
+ if (!(src[k] instanceof Object))
2875
+ return dest[k] = src[k];
2876
+ function moreNodes(v) {
2877
+ if (typeof v === "function")
2878
+ v = v();
2879
+ dest = dest.concat(v);
2880
+ return dest;
2881
+ }
2882
+
2883
+ function copyNode(v) {
2884
+ if (typeof v === "function")
2885
+ v = v();
2886
+ dest[k] = v;
2887
+ return dest;
2888
+ }
2889
+
2890
+ // The src is an array, so create/grow the destination
2891
+ // It could an an array of expressions $1,$2,$3 or statements $:1;$:2;$:3;
2892
+ if (Array.isArray(src[k]))
2893
+ return dest[k] = substitute(src[k], []);
2894
+ var p;
2895
+ if (Array.isArray(dest))
2896
+ p = moreNodes;
2897
+ else
2898
+ p = copyNode;
2899
+ // Substitute a single identifier $.. with an expression (TODO: test provided arg is an expression node)
2900
+ if (src[k].type === 'Identifier' && src[k].name[0] === '$')
2901
+ return p(args[src[k].name.slice(1)]);
2902
+ // Substitute a single labeled statement $:.. with a statement (TODO: test provided arg is a statement node)
2903
+ if (src[k].type === 'LabeledStatement' && src[k].label.name === '$') {
2904
+ var spec = src[k].body.expression;
2905
+ return p(args[spec.name || spec.value]);
2906
+ }
2907
+ // Magic label to call a function to modify a statement node $$method: <statement>
2908
+ // The newNode = args.method(oldNode)
2909
+ if (src[k].type === 'LabeledStatement' && src[k].label.name.slice(0, 2) === '$$') {
2910
+ return p(args[src[k].label.name.slice(2)](substitute(src[k]).body));
2911
+ }
2912
+ return p(substitute(src[k]));
2913
+ });
2914
+ return dest;
2915
+ }
2916
+ };
2917
+ }
2918
+
2919
+ module.exports = {
2920
+ treeWalker: treeWalk,
2921
+ partialParser: partialParser,
2922
+ babelLiteralNode: babelLiteralNode,
2923
+ transform: function (pr, opts, helpers) {
2924
+ /* DEBUG USE ONLY: global.printNode = helpers.printNode ;*/
2925
+ return asynchronize(pr, opts, helpers.logger || function(){}, partialParser(helpers.parse), helpers.printNode);
2693
2926
  }
2694
2927
  };