From 4fe75376a0714852a2802b2c55f21f8692d88a43 Mon Sep 17 00:00:00 2001
From: Tom <26638278+tomblind@users.noreply.github.com>
Date: Thu, 15 Jul 2021 04:59:46 +0800
Subject: [PATCH] fixed vararg optimization logic
---
src/transformation/utils/scope.ts | 6 ++--
test/unit/__snapshots__/spread.spec.ts.snap | 33 +++++++++++++++++++++
test/unit/spread.spec.ts | 24 +++++++++++++++
3 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/src/transformation/utils/scope.ts b/src/transformation/utils/scope.ts
index dcb877db7..53169765a 100644
--- a/src/transformation/utils/scope.ts
+++ b/src/transformation/utils/scope.ts
@@ -92,9 +92,9 @@ export function popScope(context: TransformationContext): Scope {
return scope;
}
-function isDeclaredInScope(symbol: ts.Symbol, scopeNode: ts.Node) {
+function isHoistableFunctionDeclaredInScope(symbol: ts.Symbol, scopeNode: ts.Node) {
return symbol?.declarations?.some(
- d => findFirstNodeAbove(d, (n): n is ts.Node => n === scopeNode) && !ts.isParameter(d.parent)
+ d => ts.isFunctionDeclaration(d) && findFirstNodeAbove(d, (n): n is ts.Node => n === scopeNode)
);
}
@@ -109,7 +109,7 @@ export function hasReferencedUndefinedLocalFunction(context: TransformationConte
if (
!scope.functionDefinitions?.has(symbolId) &&
type.getCallSignatures().length > 0 &&
- isDeclaredInScope(type.symbol, scope.node)
+ isHoistableFunctionDeclaredInScope(type.symbol, scope.node)
) {
return true;
}
diff --git a/test/unit/__snapshots__/spread.spec.ts.snap b/test/unit/__snapshots__/spread.spec.ts.snap
index 85d1c4ac3..0b49fd80a 100644
--- a/test/unit/__snapshots__/spread.spec.ts.snap
+++ b/test/unit/__snapshots__/spread.spec.ts.snap
@@ -81,6 +81,24 @@ end
return ____exports"
`;
+exports[`vararg spread optimization curry with indirect type 1`] = `
+"local ____exports = {}
+function ____exports.__main(self)
+ local function test(self, obj, ...)
+ local fn = obj.fn
+ return fn(nil, ...)
+ end
+ return test(
+ nil,
+ {
+ fn = function(____, arg) return arg end
+ },
+ \\"foobar\\"
+ )
+end
+return ____exports"
+`;
+
exports[`vararg spread optimization finally clause 1`] = `
"local ____exports = {}
function ____exports.__main(self)
@@ -105,6 +123,21 @@ end
return ____exports"
`;
+exports[`vararg spread optimization function type declared inside scope 1`] = `
+"local ____exports = {}
+function ____exports.__main(self)
+ local function test(self, ...)
+ local function fn(____, ...)
+ local args = {...}
+ return args[1]
+ end
+ return fn(nil, ...)
+ end
+ test(nil, \\"foobar\\")
+end
+return ____exports"
+`;
+
exports[`vararg spread optimization if statement 1`] = `
"local ____exports = {}
function ____exports.__main(self)
diff --git a/test/unit/spread.spec.ts b/test/unit/spread.spec.ts
index e65ee7ee7..5d7ed93a7 100644
--- a/test/unit/spread.spec.ts
+++ b/test/unit/spread.spec.ts
@@ -241,6 +241,30 @@ describe("vararg spread optimization", () => {
.expectLuaToMatchSnapshot()
.expectToMatchJsResult();
});
+
+ test("curry with indirect type", () => {
+ util.testFunction`
+ function test(obj: {fn: (...args: A) => void}, ...args: A) {
+ const fn = obj.fn;
+ return fn(...args);
+ }
+ return test({fn: (arg: string) => arg}, "foobar");
+ `
+ .expectLuaToMatchSnapshot()
+ .expectToMatchJsResult();
+ });
+
+ test("function type declared inside scope", () => {
+ util.testFunction`
+ function test(...args: A) {
+ const fn: (...args: A) => A[0] = (...args) => args[0];
+ return fn(...args);
+ }
+ test("foobar");
+ `
+ .expectLuaToMatchSnapshot()
+ .expectToMatchJsResult();
+ });
});
describe("vararg spread de-optimization", () => {