(code: string)
| 73 | } |
| 74 | |
| 75 | export function rewriteTopLevelAwait(code: string): string | undefined { |
| 76 | // Basic idea is to wrap code in async function, which |
| 77 | // we can await and expose side-effects outside of the function. |
| 78 | // See "rewriteTopLevelAwait" test for examples. |
| 79 | code = '(async () => {' + code + '\n})()'; |
| 80 | let body: ts.Block; |
| 81 | try { |
| 82 | const sourceFile = ts.createSourceFile( |
| 83 | 'file.js', |
| 84 | code, |
| 85 | ts.ScriptTarget.ESNext, |
| 86 | /*setParentNodes */ true, |
| 87 | ); |
| 88 | // eslint-disable-next-line |
| 89 | body = (sourceFile.statements[0] as any)['expression']['expression']['expression'][ |
| 90 | 'body' |
| 91 | ] as ts.Block; |
| 92 | } catch (e) { |
| 93 | return; |
| 94 | } |
| 95 | |
| 96 | const changes: { start: number; end: number; text: string }[] = []; |
| 97 | let containsAwait = false; |
| 98 | let containsReturn = false; |
| 99 | |
| 100 | function traverse(node: ts.Node) { |
| 101 | switch (node.kind) { |
| 102 | case ts.SyntaxKind.ClassDeclaration: |
| 103 | // Expose "class Foo" as "Foo=class Foo" |
| 104 | const cd = node as ts.ClassDeclaration; |
| 105 | if (cd.parent === body && cd.name) |
| 106 | changes.push({ text: cd.name.text + '=', start: cd.pos, end: cd.pos }); |
| 107 | break; |
| 108 | case ts.SyntaxKind.FunctionDeclaration: |
| 109 | // Expose "function foo(..." as "foo=function foo(..." |
| 110 | const fd = node as ts.FunctionDeclaration; |
| 111 | if (fd.name) changes.push({ text: fd.name.text + '=', start: fd.pos, end: fd.pos }); |
| 112 | return; |
| 113 | case ts.SyntaxKind.FunctionExpression: |
| 114 | case ts.SyntaxKind.ArrowFunction: |
| 115 | case ts.SyntaxKind.MethodDeclaration: |
| 116 | // Do not recurse into functions. |
| 117 | return; |
| 118 | case ts.SyntaxKind.AwaitExpression: |
| 119 | containsAwait = true; |
| 120 | break; |
| 121 | case ts.SyntaxKind.ForOfStatement: |
| 122 | if ((node as ts.ForOfStatement).awaitModifier) containsAwait = true; |
| 123 | break; |
| 124 | case ts.SyntaxKind.ReturnStatement: |
| 125 | containsReturn = true; |
| 126 | break; |
| 127 | case ts.SyntaxKind.VariableDeclarationList: |
| 128 | // Expose "var foo=..." as void(foo=...) |
| 129 | const vd = node as ts.VariableDeclarationList; |
| 130 | |
| 131 | let s = code.substr(vd.pos); |
| 132 | let skip = 0; |
nothing calls this directly
no test coverage detected