| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | 4 | ArrayFrom, | |
| 5 | + ArrayPrototypeForEach, | ||
| 6 | + ArrayPrototypeIncludes, | ||
| 5 | 7 | ArrayPrototypeJoin, | |
| 6 | 8 | ArrayPrototypePop, | |
| 7 | 9 | ArrayPrototypePush, | |
@@ -21,12 +23,21 @@ const parser = require('internal/deps/acorn/acorn/dist/acorn').Parser; | |||
| 21 | 23 | const walk = require('internal/deps/acorn/acorn-walk/dist/walk'); | |
| 22 | 24 | const { Recoverable } = require('internal/repl'); | |
| 23 | 25 | ||
| 26 | + function isTopLevelDeclaration(state) { | ||
| 27 | + return state.ancestors[state.ancestors.length - 2] === state.body; | ||
| 28 | + } | ||
| 29 | + | ||
| 24 | 30 | const noop = FunctionPrototype; | |
| 25 | 31 | const visitorsWithoutAncestors = { | |
| 26 | 32 | ClassDeclaration(node, state, c) { | |
| 27 | - if (state.ancestors[state.ancestors.length - 2] === state.body) { | ||
| 33 | + if (isTopLevelDeclaration(state)) { | ||
| 28 | 34 | state.prepend(node, `${node.id.name}=`); | |
| 35 | + ArrayPrototypePush( | ||
| 36 | + state.hoistedDeclarationStatements, | ||
| 37 | + `let ${node.id.name}; ` | ||
| 38 | + ); | ||
| 29 | 39 | } | |
| 40 | + | ||
| 30 | 41 | walk.base.ClassDeclaration(node, state, c); | |
| 31 | 42 | }, | |
| 32 | 43 | ForOfStatement(node, state, c) { | |
@@ -37,6 +48,10 @@ const visitorsWithoutAncestors = { | |||
| 37 | 48 | }, | |
| 38 | 49 | FunctionDeclaration(node, state, c) { | |
| 39 | 50 | state.prepend(node, `${node.id.name}=`); | |
| 51 | + ArrayPrototypePush( | ||
| 52 | + state.hoistedDeclarationStatements, | ||
| 53 | + `var ${node.id.name}; ` | ||
| 54 | + ); | ||
| 40 | 55 | }, | |
| 41 | 56 | FunctionExpression: noop, | |
| 42 | 57 | ArrowFunctionExpression: noop, | |
@@ -50,22 +65,72 @@ const visitorsWithoutAncestors = { | |||
| 50 | 65 | walk.base.ReturnStatement(node, state, c); | |
| 51 | 66 | }, | |
| 52 | 67 | VariableDeclaration(node, state, c) { | |
| 53 | - if (node.kind === 'var' || | ||
| 54 | - state.ancestors[state.ancestors.length - 2] === state.body) { | ||
| 55 | - if (node.declarations.length === 1) { | ||
| 56 | - state.replace(node.start, node.start + node.kind.length, 'void'); | ||
| 57 | - } else { | ||
| 58 | - state.replace(node.start, node.start + node.kind.length, 'void ('); | ||
| 59 | - } | ||
| 68 | + const variableKind = node.kind; | ||
| 69 | + const isIterableForDeclaration = ArrayPrototypeIncludes( | ||
| 70 | + ['ForOfStatement', 'ForInStatement'], | ||
| 71 | + state.ancestors[state.ancestors.length - 2].type | ||
| 72 | + ); | ||
| 60 | 73 | ||
| 61 | - for (const decl of node.declarations) { | ||
| 62 | - state.prepend(decl, '('); | ||
| 63 | - state.append(decl, decl.init ? ')' : '=undefined)'); | ||
| 74 | + if (variableKind === 'var' || isTopLevelDeclaration(state)) { | ||
| 75 | + state.replace( | ||
| 76 | + node.start, | ||
| 77 | + node.start + variableKind.length + (isIterableForDeclaration ? 1 : 0), | ||
| 78 | + variableKind === 'var' && isIterableForDeclaration ? | ||
| 79 | + '' : | ||
| 80 | + 'void' + (node.declarations.length === 1 ? '' : ' (') | ||
| 81 | + ); | ||
| 82 | + | ||
| 83 | + if (!isIterableForDeclaration) { | ||
| 84 | + ArrayPrototypeForEach(node.declarations, (decl) => { | ||
| 85 | + state.prepend(decl, '('); | ||
| 86 | + state.append(decl, decl.init ? ')' : '=undefined)'); | ||
| 87 | + }); | ||
| 88 | + | ||
| 89 | + if (node.declarations.length !== 1) { | ||
| 90 | + state.append(node.declarations[node.declarations.length - 1], ')'); | ||
| 91 | + } | ||
| 64 | 92 | } | |
| 65 | 93 | ||
| 66 | - if (node.declarations.length !== 1) { | ||
| 67 | - state.append(node.declarations[node.declarations.length - 1], ')'); | ||
| 94 | + const variableIdentifiersToHoist = [ | ||
| 95 | + ['var', []], | ||
| 96 | + ['let', []], | ||
| 97 | + ]; | ||
| 98 | + function registerVariableDeclarationIdentifiers(node) { | ||
| 99 | + switch (node.type) { | ||
| 100 | + case 'Identifier': | ||
| 101 | + ArrayPrototypePush( | ||
| 102 | + variableIdentifiersToHoist[variableKind === 'var' ? 0 : 1][1], | ||
| 103 | + node.name | ||
| 104 | + ); | ||
| 105 | + break; | ||
| 106 | + case 'ObjectPattern': | ||
| 107 | + ArrayPrototypeForEach(node.properties, (property) => { | ||
| 108 | + registerVariableDeclarationIdentifiers(property.value); | ||
| 109 | + }); | ||
| 110 | + break; | ||
| 111 | + case 'ArrayPattern': | ||
| 112 | + ArrayPrototypeForEach(node.elements, (element) => { | ||
| 113 | + registerVariableDeclarationIdentifiers(element); | ||
| 114 | + }); | ||
| 115 | + break; | ||
| 116 | + } | ||
| 68 | 117 | } | |
| 118 | + | ||
| 119 | + ArrayPrototypeForEach(node.declarations, (decl) => { | ||
| 120 | + registerVariableDeclarationIdentifiers(decl.id); | ||
| 121 | + }); | ||
| 122 | + | ||
| 123 | + ArrayPrototypeForEach( | ||
| 124 | + variableIdentifiersToHoist, | ||
| 125 | + ({ 0: kind, 1: identifiers }) => { | ||
| 126 | + if (identifiers.length > 0) { | ||
| 127 | + ArrayPrototypePush( | ||
| 128 | + state.hoistedDeclarationStatements, | ||
| 129 | + `${kind} ${ArrayPrototypeJoin(identifiers, ', ')}; ` | ||
| 130 | + ); | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + ); | ||
| 69 | 134 | } | |
| 70 | 135 | ||
| 71 | 136 | walk.base.VariableDeclaration(node, state, c); | |
@@ -130,6 +195,7 @@ function processTopLevelAwait(src) { | |||
| 130 | 195 | const state = { | |
| 131 | 196 | body, | |
| 132 | 197 | ancestors: [], | |
| 198 | + hoistedDeclarationStatements: [], | ||
| 133 | 199 | replace(from, to, str) { | |
| 134 | 200 | for (let i = from; i < to; i++) { | |
| 135 | 201 | wrappedArray[i] = ''; | |
@@ -174,7 +240,10 @@ function processTopLevelAwait(src) { | |||
| 174 | 240 | state.append(last.expression, ')'); | |
| 175 | 241 | } | |
| 176 | 242 | ||
| 177 | - return ArrayPrototypeJoin(wrappedArray, ''); | ||
| 243 | + return ( | ||
| 244 | + ArrayPrototypeJoin(state.hoistedDeclarationStatements, '') + | ||
| 245 | + ArrayPrototypeJoin(wrappedArray, '') | ||
| 246 | + ); | ||
| 178 | 247 | } | |
| 179 | 248 | ||
| 180 | 249 | module.exports = { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,38 +29,93 @@ const testCases = [ | |||
| 29 | 29 | [ 'await 0; return 0;', | |
| 30 | 30 | null ], | |
| 31 | 31 | [ 'var a = await 1', | |
| 32 | - '(async () => { void (a = await 1) })()' ], | ||
| 32 | + 'var a; (async () => { void (a = await 1) })()' ], | ||
| 33 | 33 | [ 'let a = await 1', | |
| 34 | - '(async () => { void (a = await 1) })()' ], | ||
| 34 | + 'let a; (async () => { void (a = await 1) })()' ], | ||
| 35 | 35 | [ 'const a = await 1', | |
| 36 | - '(async () => { void (a = await 1) })()' ], | ||
| 36 | + 'let a; (async () => { void (a = await 1) })()' ], | ||
| 37 | 37 | [ 'for (var i = 0; i < 1; ++i) { await i }', | |
| 38 | - '(async () => { for (void (i = 0); i < 1; ++i) { await i } })()' ], | ||
| 38 | + 'var i; (async () => { for (void (i = 0); i < 1; ++i) { await i } })()' ], | ||
| 39 | 39 | [ 'for (let i = 0; i < 1; ++i) { await i }', | |
| 40 | 40 | '(async () => { for (let i = 0; i < 1; ++i) { await i } })()' ], | |
| 41 | 41 | [ 'var {a} = {a:1}, [b] = [1], {c:{d}} = {c:{d: await 1}}', | |
| 42 | - '(async () => { void ( ({a} = {a:1}), ([b] = [1]), ' + | ||
| 42 | + 'var a, b, d; (async () => { void ( ({a} = {a:1}), ([b] = [1]), ' + | ||
| 43 | 43 | '({c:{d}} = {c:{d: await 1}})) })()' ], | |
| 44 | + [ 'let [a, b, c] = await ([1, 2, 3])', | ||
| 45 | + 'let a, b, c; (async () => { void ([a, b, c] = await ([1, 2, 3])) })()'], | ||
| 46 | + [ 'let {a,b,c} = await ({a: 1, b: 2, c: 3})', | ||
| 47 | + 'let a, b, c; (async () => { void ({a,b,c} = ' + | ||
| 48 | + 'await ({a: 1, b: 2, c: 3})) })()'], | ||
| 49 | + [ 'let {a: [b]} = {a: [await 1]}, [{d}] = [{d: 3}]', | ||
| 50 | + 'let b, d; (async () => { void ( ({a: [b]} = {a: [await 1]}),' + | ||
| 51 | + ' ([{d}] = [{d: 3}])) })()'], | ||
| 44 | 52 | /* eslint-disable no-template-curly-in-string */ | |
| 45 | 53 | [ 'console.log(`${(await { a: 1 }).a}`)', | |
| 46 | 54 | '(async () => { return (console.log(`${(await { a: 1 }).a}`)) })()' ], | |
| 47 | 55 | /* eslint-enable no-template-curly-in-string */ | |
| 48 | 56 | [ 'await 0; function foo() {}', | |
| 49 | - '(async () => { await 0; foo=function foo() {} })()' ], | ||
| 57 | + 'var foo; (async () => { await 0; foo=function foo() {} })()' ], | ||
| 50 | 58 | [ 'await 0; class Foo {}', | |
| 51 | - '(async () => { await 0; Foo=class Foo {} })()' ], | ||
| 59 | + 'let Foo; (async () => { await 0; Foo=class Foo {} })()' ], | ||
| 52 | 60 | [ 'if (await true) { function foo() {} }', | |
| 53 | - '(async () => { if (await true) { foo=function foo() {} } })()' ], | ||
| 61 | + 'var foo; (async () => { if (await true) { foo=function foo() {} } })()' ], | ||
| 54 | 62 | [ 'if (await true) { class Foo{} }', | |
| 55 | 63 | '(async () => { if (await true) { class Foo{} } })()' ], | |
| 56 | 64 | [ 'if (await true) { var a = 1; }', | |
| 57 | - '(async () => { if (await true) { void (a = 1); } })()' ], | ||
| 65 | + 'var a; (async () => { if (await true) { void (a = 1); } })()' ], | ||
| 58 | 66 | [ 'if (await true) { let a = 1; }', | |
| 59 | 67 | '(async () => { if (await true) { let a = 1; } })()' ], | |
| 60 | 68 | [ 'var a = await 1; let b = 2; const c = 3;', | |
| 61 | - '(async () => { void (a = await 1); void (b = 2); void (c = 3); })()' ], | ||
| 69 | + 'var a; let b; let c; (async () => { void (a = await 1); void (b = 2);' + | ||
| 70 | + ' void (c = 3); })()' ], | ||
| 62 | 71 | [ 'let o = await 1, p', | |
| 63 | - '(async () => { void ( (o = await 1), (p=undefined)) })()' ], | ||
| 72 | + 'let o, p; (async () => { void ( (o = await 1), (p=undefined)) })()' ], | ||
| 73 | + [ 'await (async () => { let p = await 1; return p; })()', | ||
| 74 | + '(async () => { return (await (async () => ' + | ||
| 75 | + '{ let p = await 1; return p; })()) })()' ], | ||
| 76 | + [ '{ let p = await 1; }', | ||
| 77 | + '(async () => { { let p = await 1; } })()' ], | ||
| 78 | + [ 'var p = await 1', | ||
| 79 | + 'var p; (async () => { void (p = await 1) })()' ], | ||
| 80 | + [ 'await (async () => { var p = await 1; return p; })()', | ||
| 81 | + '(async () => { return (await (async () => ' + | ||
| 82 | + '{ var p = await 1; return p; })()) })()' ], | ||
| 83 | + [ '{ var p = await 1; }', | ||
| 84 | + 'var p; (async () => { { void (p = await 1); } })()' ], | ||
| 85 | + [ 'for await (var i of asyncIterable) { i; }', | ||
| 86 | + 'var i; (async () => { for await (i of asyncIterable) { i; } })()'], | ||
| 87 | + [ 'for await (var [i] of asyncIterable) { i; }', | ||
| 88 | + 'var i; (async () => { for await ([i] of asyncIterable) { i; } })()'], | ||
| 89 | + [ 'for await (var {i} of asyncIterable) { i; }', | ||
| 90 | + 'var i; (async () => { for await ({i} of asyncIterable) { i; } })()'], | ||
| 91 | + [ 'for await (var [{i}, [j]] of asyncIterable) { i; }', | ||
| 92 | + 'var i, j; (async () => { for await ([{i}, [j]] of asyncIterable)' + | ||
| 93 | + ' { i; } })()'], | ||
| 94 | + [ 'for await (let i of asyncIterable) { i; }', | ||
| 95 | + '(async () => { for await (let i of asyncIterable) { i; } })()'], | ||
| 96 | + [ 'for await (const i of asyncIterable) { i; }', | ||
| 97 | + '(async () => { for await (const i of asyncIterable) { i; } })()'], | ||
| 98 | + [ 'for (var i of [1,2,3]) { await 1; }', | ||
| 99 | + 'var i; (async () => { for (i of [1,2,3]) { await 1; } })()'], | ||
| 100 | + [ 'for (var [i] of [[1], [2]]) { await 1; }', | ||
| 101 | + 'var i; (async () => { for ([i] of [[1], [2]]) { await 1; } })()'], | ||
| 102 | + [ 'for (var {i} of [{i: 1}, {i: 2}]) { await 1; }', | ||
| 103 | + 'var i; (async () => { for ({i} of [{i: 1}, {i: 2}]) { await 1; } })()'], | ||
| 104 | + [ 'for (var [{i}, [j]] of [[{i: 1}, [2]]]) { await 1; }', | ||
| 105 | + 'var i, j; (async () => { for ([{i}, [j]] of [[{i: 1}, [2]]])' + | ||
| 106 | + ' { await 1; } })()'], | ||
| 107 | + [ 'for (let i of [1,2,3]) { await 1; }', | ||
| 108 | + '(async () => { for (let i of [1,2,3]) { await 1; } })()'], | ||
| 109 | + [ 'for (const i of [1,2,3]) { await 1; }', | ||
| 110 | + '(async () => { for (const i of [1,2,3]) { await 1; } })()'], | ||
| 111 | + [ 'for (var i in {x:1}) { await 1 }', | ||
| 112 | + 'var i; (async () => { for (i in {x:1}) { await 1 } })()'], | ||
| 113 | + [ 'for (var [a,b] in {xy:1}) { await 1 }', | ||
| 114 | + 'var a, b; (async () => { for ([a,b] in {xy:1}) { await 1 } })()'], | ||
| 115 | + [ 'for (let i in {x:1}) { await 1 }', | ||
| 116 | + '(async () => { for (let i in {x:1}) { await 1 } })()'], | ||
| 117 | + [ 'for (const i in {x:1}) { await 1 }', | ||
| 118 | + '(async () => { for (const i in {x:1}) { await 1 } })()'], | ||
| 64 | 119 | ]; | |
| 65 | 120 | ||
| 66 | 121 | for (const [input, expected] of testCases) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments