Skip to content

Commit b83e170

Browse files
committed
Merge remote-tracking branch 'upstream/master' into node-module-resolution
2 parents 7e11569 + 7b6580b commit b83e170

18 files changed

Lines changed: 735 additions & 198 deletions

File tree

package-lock.json

Lines changed: 283 additions & 50 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@
3838
"dependencies": {
3939
"enhanced-resolve": "^5.2.0",
4040
"source-map": "^0.7.3",
41-
"typescript": "^3.9.2"
41+
"typescript": ">=4.0.2"
4242
},
4343
"devDependencies": {
4444
"@types/fs-extra": "^8.1.0",
4545
"@types/glob": "^7.1.1",
4646
"@types/jest": "^25.1.3",
4747
"@types/node": "^13.7.7",
4848
"@typescript-eslint/eslint-plugin": "^2.31.0",
49-
"@typescript-eslint/parser": "^2.31.0",
49+
"@typescript-eslint/parser": "^4.1.0",
5050
"eslint": "^6.8.0",
5151
"eslint-plugin-import": "^2.20.1",
5252
"eslint-plugin-jest": "^23.8.2",
@@ -58,7 +58,7 @@
5858
"lua-types": "^2.8.0",
5959
"memfs": "^3.2.0",
6060
"prettier": "^2.0.5",
61-
"ts-jest": "^26.0.0",
61+
"ts-jest": "^26.3.0",
6262
"ts-node": "^8.6.2"
6363
},
6464
"peerDependencies": {

src/LuaLib.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export enum LuaLibFeature {
4949
ObjectKeys = "ObjectKeys",
5050
ObjectRest = "ObjectRest",
5151
ObjectValues = "ObjectValues",
52+
ParseFloat = "ParseFloat",
53+
ParseInt = "ParseInt",
5254
Set = "Set",
5355
WeakMap = "WeakMap",
5456
WeakSet = "WeakSet",

src/lualib/ParseFloat.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function __TS__ParseFloat(this: void, numberString: string): number {
2+
// Check if string is infinity
3+
const infinityMatch = string.match(numberString, "^%s*(-?Infinity)");
4+
if (infinityMatch) {
5+
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
6+
return infinityMatch[0] === "-" ? -Infinity : Infinity;
7+
}
8+
9+
const number = tonumber(string.match(numberString, "^%s*(-?%d+%.?%d*)"));
10+
return number ?? NaN;
11+
}

src/lualib/ParseInt.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const __TS__parseInt_base_pattern = "0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTvVwWxXyYzZ";
2+
3+
function __TS__ParseInt(this: void, numberString: string, base?: number): number {
4+
// Check which base to use if none specified
5+
if (base === undefined) {
6+
base = 10;
7+
const hexMatch = string.match(numberString, "^%s*-?0[xX]");
8+
if (hexMatch) {
9+
base = 16;
10+
numberString = string.match(hexMatch, "-")
11+
? "-" + numberString.substr(hexMatch.length)
12+
: numberString.substr(hexMatch.length);
13+
}
14+
}
15+
16+
// Check if base is in bounds
17+
if (base < 2 || base > 36) {
18+
return NaN;
19+
}
20+
21+
// Calculate string match pattern to use
22+
const allowedDigits =
23+
base <= 10
24+
? __TS__parseInt_base_pattern.substring(0, base)
25+
: __TS__parseInt_base_pattern.substr(0, 10 + 2 * (base - 10));
26+
const pattern = `^%s*(-?[${allowedDigits}]*)`;
27+
28+
// Try to parse with Lua tonumber
29+
const number = tonumber(string.match(numberString, pattern), base);
30+
31+
if (number === undefined) {
32+
return NaN;
33+
}
34+
35+
// Lua uses a different floor convention for negative numbers than JS
36+
if (number >= 0) {
37+
return math.floor(number);
38+
} else {
39+
return math.ceil(number);
40+
}
41+
}

src/lualib/declarations/math.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@ declare namespace math {
88
function atan(y: number, x?: number): number;
99

1010
function atan2(y: number, x: number): number;
11+
12+
function ceil(x: number): number;
13+
function floor(x: number): number;
1114
}

src/lualib/declarations/string.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ declare namespace string {
1313
): [string, number];
1414
function sub(s: string, i: number, j?: number): string;
1515
function format(formatstring: string, ...args: any[]): string;
16+
function match(string: string, pattern: string): string;
1617
}

src/transformation/builtins/global.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,9 @@ export function transformGlobalCall(
3030
node,
3131
...numberParameters
3232
);
33+
case "parseFloat":
34+
return transformLuaLibFunction(context, LuaLibFeature.ParseFloat, node, ...parameters);
35+
case "parseInt":
36+
return transformLuaLibFunction(context, LuaLibFeature.ParseInt, node, ...parameters);
3337
}
3438
}

src/transformation/utils/assignment-validation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ export function validateAssignment(
3434

3535
validateFunctionAssignment(context, node, fromType, toType, toName);
3636

37-
const fromTypeNode = context.checker.typeToTypeNode(fromType);
38-
const toTypeNode = context.checker.typeToTypeNode(toType);
37+
const fromTypeNode = context.checker.typeToTypeNode(fromType, undefined, undefined);
38+
const toTypeNode = context.checker.typeToTypeNode(toType, undefined, undefined);
3939
if (!fromTypeNode || !toTypeNode) {
4040
return;
4141
}

src/transformation/utils/lua-ast.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import * as lua from "../../LuaAST";
44
import { assert, castArray } from "../../utils";
55
import { TransformationContext } from "../context";
66
import { createExportedIdentifier, getIdentifierExportScope } from "./export";
7-
import { peekScope, ScopeType } from "./scope";
8-
import { isFunctionType } from "./typescript";
7+
import { peekScope, ScopeType, Scope } from "./scope";
98
import { transformLuaLibFunction } from "./lualib";
109
import { LuaLibFeature } from "../../LuaLib";
1110

@@ -129,6 +128,17 @@ export function createHoistableVariableDeclarationStatement(
129128
return declaration;
130129
}
131130

131+
function hasMultipleReferences(scope: Scope, identifiers: lua.Identifier | lua.Identifier[]) {
132+
const scopeSymbols = scope.referencedSymbols;
133+
if (!scopeSymbols) {
134+
return false;
135+
}
136+
137+
const referenceLists = castArray(identifiers).map(i => i.symbolId && scopeSymbols.get(i.symbolId));
138+
139+
return referenceLists.some(symbolRefs => symbolRefs && symbolRefs.length > 1);
140+
}
141+
132142
export function createLocalOrExportedOrGlobalDeclaration(
133143
context: TransformationContext,
134144
lhs: lua.Identifier | lua.Identifier[],
@@ -163,15 +173,8 @@ export function createLocalOrExportedOrGlobalDeclaration(
163173
const isTopLevelVariable = scope.type === ScopeType.File;
164174

165175
if (context.isModule || !isTopLevelVariable) {
166-
const isPossibleWrappedFunction =
167-
!isFunctionDeclaration &&
168-
tsOriginal &&
169-
ts.isVariableDeclaration(tsOriginal) &&
170-
tsOriginal.initializer &&
171-
isFunctionType(context, context.checker.getTypeAtLocation(tsOriginal.initializer));
172-
173-
if (isPossibleWrappedFunction || scope.type === ScopeType.Switch) {
174-
// Split declaration and assignment for wrapped function types to allow recursion
176+
if (scope.type === ScopeType.Switch || (!isFunctionDeclaration && hasMultipleReferences(scope, lhs))) {
177+
// Split declaration and assignment of identifiers that reference themselves in their declaration
175178
declaration = lua.createVariableDeclarationStatement(lhs, undefined, tsOriginal);
176179
assignment = lua.createAssignmentStatement(lhs, rhs, tsOriginal);
177180
} else {

0 commit comments

Comments
 (0)