Skip to content

Commit 01a0fcb

Browse files
authored
fix for vararg access in async functions (#1096)
Co-authored-by: Tom <tomblind@users.noreply.github.com>
1 parent 6d538b6 commit 01a0fcb

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

src/transformation/visitors/function.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ export function transformFunctionBody(
115115
): [lua.Statement[], Scope] {
116116
const scope = pushScope(context, ScopeType.Function);
117117
scope.node = node;
118-
const bodyStatements = transformFunctionBodyContent(context, body);
118+
let bodyStatements = transformFunctionBodyContent(context, body);
119+
if (node && isAsyncFunction(node)) {
120+
bodyStatements = wrapInAsyncAwaiter(context, bodyStatements);
121+
}
119122
const headerStatements = transformFunctionBodyHeader(context, scope, parameters, spreadIdentifier);
120123
popScope(context);
121124
return [[...headerStatements, ...bodyStatements], scope];
@@ -197,10 +200,8 @@ export function transformFunctionToExpression(
197200
node
198201
);
199202

200-
const possiblyAsyncBody = isAsyncFunction(node) ? wrapInAsyncAwaiter(context, transformedBody) : transformedBody;
201-
202203
const functionExpression = lua.createFunctionExpression(
203-
lua.createBlock(possiblyAsyncBody),
204+
lua.createBlock(transformedBody),
204205
paramNames,
205206
dotsLiteral,
206207
flags,

src/transformation/visitors/spread.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ export function isOptimizedVarArgSpread(context: TransformationContext, symbol:
3737
return false;
3838
}
3939

40+
// Scope cannot be an async function
41+
if (scope.node.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword)) {
42+
return false;
43+
}
44+
4045
// Identifier must be a vararg in the local function scope's parameters
4146
const isSpreadParameter = (p: ts.ParameterDeclaration) =>
4247
p.dotDotDotToken && ts.isIdentifier(p.name) && context.checker.getSymbolAtLocation(p.name) === symbol;

test/unit/builtins/async-await.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,39 @@ test.each([
333333
.setOptions({ module: ModuleKind.ESNext, target: ScriptTarget.ES2017 })
334334
.expectToHaveDiagnostics([awaitMustBeInAsyncFunction.code]);
335335
});
336+
337+
test("async function can access varargs", () => {
338+
util.testFunction`
339+
const { promise, resolve } = defer<string>();
340+
341+
async function a(...args: string[]) {
342+
log(await promise);
343+
log(args[1]);
344+
}
345+
346+
const awaitingPromise = a("A", "B", "C");
347+
resolve("resolved");
348+
349+
return allLogs;
350+
`
351+
.setTsHeader(promiseTestLib)
352+
.expectToEqual(["resolved", "B"]);
353+
});
354+
355+
test("async function can forward varargs", () => {
356+
util.testFunction`
357+
const { promise, resolve } = defer<string>();
358+
359+
async function a(...args: string[]) {
360+
log(await promise);
361+
log(...args);
362+
}
363+
364+
const awaitingPromise = a("A", "B", "C");
365+
resolve("resolved");
366+
367+
return allLogs;
368+
`
369+
.setTsHeader(promiseTestLib)
370+
.expectToEqual(["resolved", "A", "B", "C"]);
371+
});

0 commit comments

Comments
 (0)