diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 027892887..4751f8dbc 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -3664,9 +3664,9 @@ export class LuaTransformer { flags |= tstl.FunctionExpressionFlags.Inline; } - const [transformedBody] = this.transformFunctionBody(node.parameters, body, spreadIdentifier); + const [transformedBody, scope] = this.transformFunctionBody(node.parameters, body, spreadIdentifier); - return tstl.createFunctionExpression( + const functionExpression = tstl.createFunctionExpression( tstl.createBlock(transformedBody), paramNames, dotsLiteral, @@ -3674,6 +3674,24 @@ export class LuaTransformer { flags, node ); + + //Handle named function expressions which reference themselves + if (ts.isFunctionExpression(node) && node.name && scope.referencedSymbols) { + const symbol = this.checker.getSymbolAtLocation(node.name); + if (symbol) { + const symbolId = this.symbolIds.get(symbol); + //Only wrap if the name is actually referenced inside the function + if (symbolId !== undefined && scope.referencedSymbols.has(symbolId)) { + const nameIdentifier = this.transformIdentifier(node.name); + return this.createImmediatelyInvokedFunctionExpression( + [tstl.createVariableDeclarationStatement(nameIdentifier, functionExpression)], + tstl.cloneIdentifier(nameIdentifier) + ); + } + } + } + + return functionExpression; } public transformNewExpression(node: ts.NewExpression): ExpressionVisitResult { @@ -5111,7 +5129,7 @@ export class LuaTransformer { protected createImmediatelyInvokedFunctionExpression( statements: tstl.Statement[], result: tstl.Expression | tstl.Expression[], - tsOriginal: ts.Node + tsOriginal?: ts.Node ): tstl.CallExpression { const body = statements ? statements.slice(0) : []; body.push(tstl.createReturnStatement(Array.isArray(result) ? result : [result])); diff --git a/test/unit/functions.spec.ts b/test/unit/functions.spec.ts index 455b6d70d..41d55e5af 100644 --- a/test/unit/functions.spec.ts +++ b/test/unit/functions.spec.ts @@ -610,3 +610,12 @@ test.each([{}, { noHoisting: true }])("@vararg global", compilerOptions => { expect(util.executeLua(lua)).toBe("ABCD"); }); + +test("named function expression reference", () => { + const code = ` + const y = function x(inp: string) { + return inp + typeof x; + }; + return y("foo-");`; + expect(util.transpileAndExecute(code)).toBe("foo-function"); +});