jass 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/jass.rb +5 -0
- data/lib/jass/compiler.rb +5 -0
- data/lib/jass/plugin.rb +2 -1
- data/lib/jass/version.rb +1 -1
- data/vendor/node_modules/@types/estree/index.d.ts +4 -2
- data/vendor/node_modules/@types/estree/package.json +2 -2
- data/vendor/node_modules/acorn/bin/_acorn.js +12 -12
- data/vendor/node_modules/acorn/bin/run_test262.js +2 -3
- data/vendor/node_modules/acorn/bin/test262.whitelist +0 -5
- data/vendor/node_modules/acorn/dist/acorn.es.js +76 -68
- data/vendor/node_modules/acorn/dist/acorn.js +76 -68
- data/vendor/node_modules/acorn/dist/acorn_loose.es.js +42 -30
- data/vendor/node_modules/acorn/dist/acorn_loose.js +42 -30
- data/vendor/node_modules/acorn/dist/walk.es.js +47 -43
- data/vendor/node_modules/acorn/dist/walk.js +47 -43
- data/vendor/node_modules/acorn/package.json +9 -5
- data/vendor/node_modules/chalk/index.js.flow +93 -0
- data/vendor/node_modules/chalk/package.json +8 -3
- data/vendor/node_modules/color-convert/conversions.js +36 -29
- data/vendor/node_modules/color-convert/package.json +4 -4
- data/vendor/node_modules/estree-walker/index.d.ts +17 -0
- data/vendor/node_modules/estree-walker/package.json +2 -1
- data/vendor/node_modules/fill-range/index.js +2 -2
- data/vendor/node_modules/fill-range/package.json +24 -7
- data/vendor/node_modules/is-reference/node_modules/@types/estree/index.d.ts +546 -0
- data/vendor/node_modules/is-reference/node_modules/@types/estree/package.json +22 -0
- data/vendor/node_modules/math-random/browser.js +17 -0
- data/vendor/node_modules/math-random/node.js +13 -0
- data/vendor/node_modules/math-random/package.json +31 -0
- data/vendor/node_modules/math-random/test.js +26 -0
- data/vendor/node_modules/nodent-compiler/compiler.js +115 -11
- data/vendor/node_modules/nodent-compiler/{lib/output.js → output.js} +0 -0
- data/vendor/node_modules/nodent-compiler/package.json +8 -4
- data/vendor/node_modules/{nodent-compiler/lib → nodent-transform}/arboriculture.js +1340 -1107
- data/vendor/node_modules/nodent-transform/package.json +19 -0
- data/vendor/node_modules/path-parse/package.json +1 -1
- data/vendor/node_modules/pretty-ms/index.js +2 -1
- data/vendor/node_modules/pretty-ms/package.json +2 -3
- data/vendor/node_modules/randomatic/index.js +12 -2
- data/vendor/node_modules/randomatic/node_modules/is-number/index.js +6 -7
- data/vendor/node_modules/randomatic/node_modules/is-number/package.json +9 -16
- data/vendor/node_modules/randomatic/node_modules/kind-of/index.js +112 -102
- data/vendor/node_modules/randomatic/node_modules/kind-of/package.json +18 -20
- data/vendor/node_modules/randomatic/package.json +15 -13
- data/vendor/node_modules/repeat-element/index.js +1 -1
- data/vendor/node_modules/repeat-element/package.json +27 -22
- data/vendor/node_modules/resolve/lib/async.js +20 -17
- data/vendor/node_modules/resolve/lib/core.js +2 -2
- data/vendor/node_modules/resolve/lib/core.json +4 -1
- data/vendor/node_modules/resolve/lib/sync.js +52 -13
- data/vendor/node_modules/resolve/package.json +3 -3
- data/vendor/node_modules/rollup-plugin-commonjs/dist/rollup-plugin-commonjs.cjs.js +50 -12
- data/vendor/node_modules/rollup-plugin-commonjs/dist/rollup-plugin-commonjs.es.js +50 -12
- data/vendor/node_modules/rollup-plugin-commonjs/package.json +2 -2
- data/vendor/node_modules/rollup-plugin-commonjs/src/index.js +49 -11
- data/vendor/node_modules/rollup-plugin-commonjs/src/transform.js +1 -1
- data/vendor/node_modules/rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.cjs.js +82 -85
- data/vendor/node_modules/rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.es.js +82 -85
- data/vendor/node_modules/rollup-plugin-node-resolve/package.json +1 -1
- data/vendor/node_modules/rollup-plugin-node-resolve/src/index.js +81 -84
- data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.cjs.js +81 -2
- data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.es.js +81 -3
- data/vendor/node_modules/rollup-pluginutils/package.json +12 -6
- data/vendor/node_modules/rollup-pluginutils/src/attachScopes.js +10 -2
- data/vendor/node_modules/rollup-pluginutils/src/dataToEsm.js +69 -0
- data/vendor/node_modules/rollup-pluginutils/src/index.js +1 -0
- data/vendor/node_modules/supports-color/index.js +1 -5
- data/vendor/node_modules/supports-color/package.json +51 -51
- data/vendor/yarn.lock +65 -70
- metadata +16 -21
- data/vendor/node_modules/irregular-plurals/irregular-plurals.json +0 -146
- data/vendor/node_modules/irregular-plurals/package.json +0 -39
- data/vendor/node_modules/nodent-compiler/lib/parser.js +0 -291
- data/vendor/node_modules/path-parse/index.min.js +0 -1
- data/vendor/node_modules/path-parse/test.min.js +0 -1
- data/vendor/node_modules/plur/index.js +0 -20
- data/vendor/node_modules/plur/package.json +0 -42
- data/vendor/node_modules/randomatic/node_modules/is-number/node_modules/kind-of/index.js +0 -116
- data/vendor/node_modules/randomatic/node_modules/is-number/node_modules/kind-of/package.json +0 -90
- data/vendor/node_modules/rollup-pluginutils/dist/pluginutils.es6.js +0 -217
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.es.js +0 -55
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.es6.js +0 -59
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/dist/estree-walker.umd.js +0 -65
- data/vendor/node_modules/rollup-pluginutils/node_modules/estree-walker/package.json +0 -33
- 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,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
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
177
|
+
r.ast = acornParse(r.origCode, opts && opts.parser) ;
|
|
104
178
|
if (opts.babelTree) {
|
|
105
|
-
|
|
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
|
-
|
|
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
|
|
|
File without changes
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodent-compiler",
|
|
3
|
-
"version": "3.
|
|
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/
|
|
7
|
+
"test": "node tests tests/semantics/*"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"acorn": ">=2.5.2",
|
|
11
|
-
"acorn-es7-plugin": "
|
|
12
|
-
"
|
|
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 = {
|
|
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)
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
85
|
-
|
|
106
|
+
return true;
|
|
86
107
|
case 'VariableDeclaration':
|
|
87
|
-
|
|
88
|
-
|
|
108
|
+
return this.node.kind && this.node.kind === 'let';
|
|
89
109
|
case 'FunctionDeclaration':
|
|
90
110
|
case 'FunctionExpression':
|
|
91
|
-
|
|
111
|
+
return !(!this.node.generator);
|
|
92
112
|
}
|
|
93
|
-
|
|
113
|
+
}
|
|
94
114
|
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Object.
|
|
98
|
-
|
|
99
|
-
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
290
|
+
if (containsThis(left))
|
|
291
|
+
return parsePart("$0.bind(this)", [left]).expr;
|
|
292
|
+
return left;
|
|
268
293
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
|
|
338
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
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
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
685
|
-
|
|
724
|
+
block.body.push(ctn);
|
|
725
|
+
idx++;
|
|
726
|
+
} else
|
|
727
|
+
idx++;
|
|
728
|
+
} else
|
|
729
|
+
idx++;
|
|
686
730
|
}
|
|
687
|
-
} else
|
|
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
|
-
|
|
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
|
-
|
|
790
|
-
|
|
791
|
-
|
|
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 =
|
|
797
|
-
node.$finallyExit = node.finalizer && inAsync(path) &&
|
|
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;
|
|
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;
|
|
857
|
-
if (examine(path[i].self).isFunction)
|
|
858
|
-
|
|
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 =
|
|
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
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
1118
|
+
callee: opts.promises || opts.generators ? {
|
|
1079
1119
|
type: 'MemberExpression',
|
|
1080
|
-
object:
|
|
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 =
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
inArray,
|
|
1122
|
-
node.
|
|
1123
|
-
|
|
1124
|
-
|
|
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 =
|
|
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
|
-
|
|
1149
|
-
|
|
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 =
|
|
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
|
-
|
|
1229
|
+
transformForIn(node, path);
|
|
1190
1230
|
} else if (node.type === 'ForOfStatement' && containsAwait(node)) {
|
|
1191
|
-
|
|
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
|
|
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
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
if (
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
"
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
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
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
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
|
-
|
|
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 +
|
|
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
|
-
|
|
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
|
-
|
|
1588
|
-
|
|
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
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
}
|
|
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
|
|
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
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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 = [{
|
|
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:
|
|
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
|
|
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
|
|
1791
|
-
'return':genIdent.return,
|
|
1792
|
-
error:genIdent.error,
|
|
1793
|
-
asyncspawn:genIdent.asyncspawn,
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1937
|
-
|
|
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){
|
|
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
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
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 {
|
|
2045
|
+
return {
|
|
2046
|
+
decls: varDecls,
|
|
2047
|
+
duplicates: duplicates
|
|
2048
|
+
};
|
|
2009
2049
|
}
|
|
2010
|
-
|
|
2050
|
+
|
|
2011
2051
|
function getDeclNames(id) {
|
|
2012
|
-
if (!id)
|
|
2052
|
+
if (!id)
|
|
2053
|
+
return [];
|
|
2013
2054
|
if (Array.isArray(id)) {
|
|
2014
|
-
return id.reduce(function(z,
|
|
2055
|
+
return id.reduce(function (z, j) {
|
|
2056
|
+
return z.concat(getDeclNames(j.id));
|
|
2057
|
+
}, []);
|
|
2015
2058
|
}
|
|
2016
2059
|
switch (id.type) {
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
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
|
-
|
|
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;
|
|
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
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
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
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
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
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
});
|
|
2160
|
+
function containsAssign(ast) {
|
|
2161
|
+
return contains(ast, function (n) {
|
|
2162
|
+
return n.type === 'AssignmentExpression';
|
|
2163
|
+
});
|
|
2104
2164
|
}
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
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'
|
|
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
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
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;
|
|
2246
|
-
if (examine(d[depth].parent).isBlockStatement)
|
|
2247
|
-
|
|
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){
|
|
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
|
-
|
|
2282
|
-
|
|
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
|
-
|
|
2344
|
+
ref.remove();
|
|
2292
2345
|
}
|
|
2293
|
-
})
|
|
2294
|
-
vars = scopedNodes(node, isFreeVariable(['var']),
|
|
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) {
|
|
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
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
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
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
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;
|
|
2365
|
-
if (path[n].self.type==='ForOfStatement' || path[n].self.type==='ForInStatement' || examine(path[n].self).isLoop)
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
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
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
},true))) {
|
|
2396
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
if (examine(nodes[i]).isDirective && nodes[i].expression.value.match(/^\s*use\s+strict\s*$/))
|
|
2498
|
-
|
|
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
|
-
|
|
2574
|
+
treeWalk(ast, function (node, descend, path) {
|
|
2518
2575
|
descend();
|
|
2519
|
-
if (node.type==='ArrowFunctionExpression'
|
|
2520
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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]; //
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
2618
|
-
|
|
2619
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
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
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
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
|
-
|
|
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
|
};
|