Skip to content

Commit 72acfe2

Browse files
committed
validating arguments passed to lua lib functions
1 parent d577493 commit 72acfe2

3 files changed

Lines changed: 63 additions & 31 deletions

File tree

src/LuaTransformer.ts

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3155,53 +3155,53 @@ export class LuaTransformer {
31553155
// If the function being called is of type owner.func, get the type of owner
31563156
const ownerType = this.checker.getTypeAtLocation(node.expression.expression);
31573157

3158+
const signature = this.checker.getResolvedSignature(node);
3159+
31583160
if (tsHelper.isStandardLibraryType(ownerType, "Math", this.program)) {
3159-
return this.transformMathCallExpression(node);
3161+
return this.transformMathCallExpression(node, signature);
31603162
}
31613163

31623164
if (tsHelper.isStandardLibraryType(ownerType, "Console", this.program)) {
3163-
return this.transformConsoleCallExpression(node);
3165+
return this.transformConsoleCallExpression(node, signature);
31643166
}
31653167

31663168
if (tsHelper.isStandardLibraryType(ownerType, "StringConstructor", this.program)) {
31673169
return tstl.createCallExpression(
31683170
this.transformStringExpression(node.expression.name),
3169-
this.transformArguments(node.arguments),
3171+
this.transformArguments(node.arguments, signature),
31703172
node
31713173
);
31723174
}
31733175

31743176
if (tsHelper.isStandardLibraryType(ownerType, "ObjectConstructor", this.program)) {
3175-
return this.transformObjectCallExpression(node);
3177+
return this.transformObjectCallExpression(node, signature);
31763178
}
31773179

31783180
if (tsHelper.isStandardLibraryType(ownerType, "SymbolConstructor", this.program)) {
3179-
return this.transformSymbolCallExpression(node);
3181+
return this.transformSymbolCallExpression(node, signature);
31803182
}
31813183

31823184
switch (ownerType.flags) {
31833185
case ts.TypeFlags.String:
31843186
case ts.TypeFlags.StringLiteral:
3185-
return this.transformStringCallExpression(node);
3187+
return this.transformStringCallExpression(node, signature);
31863188
}
31873189

31883190
// if ownerType is a array, use only supported functions
31893191
if (tsHelper.isExplicitArrayType(ownerType, this.checker)) {
3190-
return this.transformArrayCallExpression(node);
3192+
return this.transformArrayCallExpression(node, signature);
31913193
}
31923194

31933195
// if ownerType inherits from an array, use array calls where appropriate
31943196
if (tsHelper.isArrayType(ownerType, this.checker) &&
31953197
tsHelper.isDefaultArrayCallMethodName(node.expression.name.escapedText as string)) {
3196-
return this.transformArrayCallExpression(node);
3198+
return this.transformArrayCallExpression(node, signature);
31973199
}
31983200

31993201
if (tsHelper.isFunctionType(ownerType, this.checker)) {
3200-
return this.transformFunctionCallExpression(node);
3202+
return this.transformFunctionCallExpression(node, signature);
32013203
}
32023204

3203-
const signature = this.checker.getResolvedSignature(node);
3204-
32053205
// Get the type of the function
32063206
if (node.expression.expression.kind === ts.SyntaxKind.SuperKeyword) {
32073207
// Super calls take the format of super.call(self,...)
@@ -3285,7 +3285,8 @@ export class LuaTransformer {
32853285

32863286
public transformArguments<T extends ts.Expression>(
32873287
params: ts.NodeArray<ts.Expression>,
3288-
sig?: ts.Signature, context?: T
3288+
sig?: ts.Signature,
3289+
context?: T
32893290
): tstl.Expression[]
32903291
{
32913292
const parameters: tstl.Expression[] = [];
@@ -3378,9 +3379,9 @@ export class LuaTransformer {
33783379
}
33793380

33803381
// Transpile a Math._ property
3381-
public transformMathCallExpression(node: ts.CallExpression): tstl.Expression {
3382+
public transformMathCallExpression(node: ts.CallExpression, signature: ts.Signature): tstl.Expression {
33823383
const expression = node.expression as ts.PropertyAccessExpression;
3383-
const params = this.transformArguments(node.arguments);
3384+
const params = this.transformArguments(node.arguments, signature);
33843385
const expressionName = expression.name.escapedText as string;
33853386
switch (expressionName) {
33863387
// math.tan(x / y)
@@ -3537,9 +3538,9 @@ export class LuaTransformer {
35373538
throw TSTLErrors.CouldNotFindEnumMember(enumDeclaration, memberName, tsOriginal);
35383539
}
35393540

3540-
public transformStringCallExpression(node: ts.CallExpression): tstl.Expression {
3541+
public transformStringCallExpression(node: ts.CallExpression, signature: ts.Signature): tstl.Expression {
35413542
const expression = node.expression as ts.PropertyAccessExpression;
3542-
const params = this.transformArguments(node.arguments);
3543+
const params = this.transformArguments(node.arguments, signature);
35433544
const caller = this.transformExpression(expression.expression);
35443545

35453546
const expressionName = expression.name.escapedText as string;
@@ -3681,9 +3682,13 @@ export class LuaTransformer {
36813682
}
36823683

36833684
// Transpile an Object._ property
3684-
public transformObjectCallExpression(expression: ts.CallExpression): ExpressionVisitResult {
3685+
public transformObjectCallExpression(
3686+
expression: ts.CallExpression,
3687+
signature: ts.Signature
3688+
): ExpressionVisitResult
3689+
{
36853690
const method = expression.expression as ts.PropertyAccessExpression;
3686-
const parameters = this.transformArguments(expression.arguments);
3691+
const parameters = this.transformArguments(expression.arguments, signature);
36873692
const caller = this.transformExpression(expression.expression);
36883693
const methodName = method.name.escapedText;
36893694

@@ -3705,7 +3710,11 @@ export class LuaTransformer {
37053710
}
37063711
}
37073712

3708-
public transformConsoleCallExpression(expression: ts.CallExpression): ExpressionVisitResult {
3713+
public transformConsoleCallExpression(
3714+
expression: ts.CallExpression,
3715+
signature: ts.Signature
3716+
): ExpressionVisitResult
3717+
{
37093718
const method = expression.expression as ts.PropertyAccessExpression;
37103719
const methodName = method.name.escapedText;
37113720

@@ -3718,7 +3727,7 @@ export class LuaTransformer {
37183727
tstl.createTableIndexExpression(
37193728
tstl.createIdentifier("string"),
37203729
tstl.createStringLiteral("format")),
3721-
this.transformArguments(expression.arguments)
3730+
this.transformArguments(expression.arguments, signature)
37223731
);
37233732
return tstl.createCallExpression(
37243733
tstl.createIdentifier("print"),
@@ -3728,10 +3737,10 @@ export class LuaTransformer {
37283737
// print([arguments])
37293738
return tstl.createCallExpression(
37303739
tstl.createIdentifier("print"),
3731-
this.transformArguments(expression.arguments)
3740+
this.transformArguments(expression.arguments, signature)
37323741
);
37333742
case "assert":
3734-
const args = this.transformArguments(expression.arguments);
3743+
const args = this.transformArguments(expression.arguments, signature);
37353744
if (expression.arguments.length > 1
37363745
&& this.isStringFormatTemplate(expression.arguments[1])) {
37373746
// assert([condition], string.format([arguments]))
@@ -3759,7 +3768,7 @@ export class LuaTransformer {
37593768
tstl.createTableIndexExpression(
37603769
tstl.createIdentifier("string"),
37613770
tstl.createStringLiteral("format")),
3762-
this.transformArguments(expression.arguments)
3771+
this.transformArguments(expression.arguments, signature)
37633772
);
37643773
const debugTracebackCall = tstl.createCallExpression(
37653774
tstl.createTableIndexExpression(
@@ -3777,7 +3786,7 @@ export class LuaTransformer {
37773786
tstl.createTableIndexExpression(
37783787
tstl.createIdentifier("debug"),
37793788
tstl.createStringLiteral("traceback")),
3780-
this.transformArguments(expression.arguments)
3789+
this.transformArguments(expression.arguments, signature)
37813790
);
37823791
return tstl.createCallExpression(
37833792
tstl.createIdentifier("print"),
@@ -3797,9 +3806,9 @@ export class LuaTransformer {
37973806
}
37983807

37993808
// Transpile a Symbol._ property
3800-
public transformSymbolCallExpression(expression: ts.CallExpression): tstl.CallExpression {
3809+
public transformSymbolCallExpression(expression: ts.CallExpression, signature: ts.Signature): tstl.CallExpression {
38013810
const method = expression.expression as ts.PropertyAccessExpression;
3802-
const parameters = this.transformArguments(expression.arguments);
3811+
const parameters = this.transformArguments(expression.arguments, signature);
38033812
const methodName = method.name.escapedText;
38043813

38053814
switch (methodName) {
@@ -3818,9 +3827,9 @@ export class LuaTransformer {
38183827
}
38193828
}
38203829

3821-
public transformArrayCallExpression(node: ts.CallExpression): tstl.CallExpression {
3830+
public transformArrayCallExpression(node: ts.CallExpression, signature: ts.Signature): tstl.CallExpression {
38223831
const expression = node.expression as ts.PropertyAccessExpression;
3823-
const params = this.transformArguments(node.arguments);
3832+
const params = this.transformArguments(node.arguments, signature);
38243833
const caller = this.transformExpression(expression.expression);
38253834
const expressionName = expression.name.escapedText;
38263835
switch (expressionName) {
@@ -3875,13 +3884,13 @@ export class LuaTransformer {
38753884
}
38763885
}
38773886

3878-
public transformFunctionCallExpression(node: ts.CallExpression): tstl.CallExpression {
3887+
public transformFunctionCallExpression(node: ts.CallExpression, signature: ts.Signature): tstl.CallExpression {
38793888
const expression = node.expression as ts.PropertyAccessExpression;
38803889
const callerType = this.checker.getTypeAtLocation(expression.expression);
38813890
if (tsHelper.getFunctionContextType(callerType, this.checker) === ContextType.Void) {
38823891
throw TSTLErrors.UnsupportedSelfFunctionConversion(node);
38833892
}
3884-
const params = this.transformArguments(node.arguments);
3893+
const params = this.transformArguments(node.arguments, signature);
38853894
const caller = this.transformExpression(expression.expression);
38863895
const expressionName = expression.name.escapedText;
38873896
switch (expressionName) {

test/unit/assignments.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,29 @@ export class AssignmentTests {
663663
Expect(() => util.transpileString(code, undefined, false)).toThrowError(TranspileError, err.message);
664664
}
665665

666+
@Test("Valid lua lib function argument")
667+
public validLuaLibFunctionArgument(): void {
668+
const code =
669+
`let result = "";
670+
function foo(this: any, value: string) { result += value; }
671+
const a = ['foo', 'bar'];
672+
a.forEach(foo);
673+
return result;`;
674+
Expect(util.transpileAndExecute(code)).toBe("foobar");
675+
}
676+
677+
@Test("Invalid lua lib function argument")
678+
public invalidLuaLibFunctionArgument(testFunction: TestFunction, functionType: string, isSelfConversion: boolean)
679+
: void
680+
{
681+
const code =
682+
`declare function foo(this: void, value: string): void;
683+
declare const a: string[];
684+
a.forEach(foo);`;
685+
const err = TSTLErrors.UnsupportedSelfFunctionConversion(undefined, "callbackfn");
686+
Expect(() => util.transpileString(code, undefined, false)).toThrowError(TranspileError, err.message);
687+
}
688+
666689
@TestCases(validTestFunctionCasts)
667690
@Test("Valid function argument with cast")
668691
public validFunctionArgumentWithCast(testFunction: TestFunction, castedFunction: string): void {

test/unit/expressions.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ export class ExpressionTests {
498498
expression: {name: ts.createIdentifier("unknownFunction"), expression: ts.createLiteral(false)},
499499
};
500500

501-
Expect(() => transformer.transformArrayCallExpression(mockNode as ts.CallExpression))
501+
Expect(() => transformer.transformArrayCallExpression(mockNode as ts.CallExpression, undefined))
502502
.toThrowError(TranspileError, "Unsupported property on array: unknownFunction");
503503
}
504504

0 commit comments

Comments
 (0)