diff --git a/package-lock.json b/package-lock.json index d65fdef5c..5514235ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2769,8 +2769,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -2791,14 +2790,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2813,20 +2810,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -2943,8 +2937,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -2956,7 +2949,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2971,7 +2963,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2979,14 +2970,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3005,7 +2994,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3086,8 +3074,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3099,7 +3086,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3185,8 +3171,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -3222,7 +3207,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3242,7 +3226,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3286,14 +3269,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/package.json b/package.json index 97a3f3ac7..251f81ee6 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,9 @@ "pretest": "npm run lint && ts-node --transpile-only ./build_lualib.ts", "test": "jest", "lint": "npm run lint:tslint && npm run lint:prettier", - "lint:prettier": "prettier --check **/*.{js,ts,yml,json,md} || (echo 'Run `npm run fix:prettier` to fix it.' && exit 1)", + "lint:prettier": "prettier --check \"**/*.{js,ts,yml,json,md}\" || (echo 'Run `npm run fix:prettier` to fix it.' && exit 1)", "lint:tslint": "tslint -p . && tslint -p test && tslint -p src/lualib", - "fix:prettier": "prettier --check --write **/*.{js,ts,yml,json,md}", + "fix:prettier": "prettier --check --write \"**/*.{js,ts,yml,json,md}\"", "release-major": "npm version major", "release-minor": "npm version minor", "release-patch": "npm version patch", diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 450ad6af5..07c82680e 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -4876,14 +4876,6 @@ export class LuaTransformer { } public transformIdentifier(identifier: ts.Identifier): tstl.Identifier { - if (identifier.originalKeywordKind === ts.SyntaxKind.UndefinedKeyword) { - // TODO this is a hack that allows use to keep Identifier - // as return time as changing that would break a lot of stuff. - // But this should be changed to return tstl.createNilLiteral() - // at some point. - return tstl.createIdentifier("nil"); - } - if (tsHelper.isForRangeType(identifier, this.checker)) { const callExpression = tsHelper.findFirstNodeAbove(identifier, ts.isCallExpression); if (!callExpression || !callExpression.parent || !ts.isForOfStatement(callExpression.parent)) { @@ -4910,6 +4902,10 @@ export class LuaTransformer { return this.createExportedIdentifier(identifier, exportScope); } + if (expression.originalKeywordKind === ts.SyntaxKind.UndefinedKeyword) { + return tstl.createNilLiteral(); + } + switch (this.getIdentifierText(expression)) { case "NaN": return tstl.createParenthesizedExpression( @@ -4925,6 +4921,9 @@ export class LuaTransformer { const math = tstl.createIdentifier("math"); const huge = tstl.createStringLiteral("huge"); return tstl.createTableIndexExpression(math, huge, expression); + + case "globalThis": + return tstl.createIdentifier("_G", expression, this.getIdentifierSymbolId(expression)); } return identifier; @@ -5432,7 +5431,8 @@ export class LuaTransformer { protected hasUnsafeSymbolName(symbol: ts.Symbol, tsOriginal?: ts.Identifier): boolean { const isLuaKeyword = luaKeywords.has(symbol.name); const isInvalidIdentifier = !tsHelper.isValidLuaIdentifier(symbol.name); - const isAmbient = symbol.declarations.some(d => tsHelper.isAmbientNode(d)); + // TODO rework once microsoft/TypeScript#24706 is fixed and remove check for symbol.declarations + const isAmbient = symbol.declarations && symbol.declarations.some(d => tsHelper.isAmbientNode(d)); if ((isLuaKeyword || isInvalidIdentifier) && isAmbient) { // Catch ambient declarations of identifiers with bad names throw TSTLErrors.InvalidAmbientIdentifierName(tsOriginal || ts.createIdentifier(symbol.name)); diff --git a/test/unit/identifiers.spec.ts b/test/unit/identifiers.spec.ts index 7936de507..d8b00733f 100644 --- a/test/unit/identifiers.spec.ts +++ b/test/unit/identifiers.spec.ts @@ -788,3 +788,66 @@ test("exported variable with lua keyword as name is not renamed", () => { expect(util.transpileExecuteAndReturnExport(code, "print")).toBe("foobar"); }); + +describe("globalThis translation", () => { + test("globalThis to _G (expression)", () => { + const code = ` + var foo = "bar"; + return globalThis.foo;`; + + const lua = util.transpileString(code); + + expect(util.executeLua(lua)).toBe("bar"); + }); + + test("globalThis to _G (assign)", () => { + const code = ` + globalThis.foo = "bar"; + return globalThis.foo;`; + + expect(util.transpileAndExecute(code)).toBe("bar"); + }); + + test("globalThis to _G (reassign)", () => { + const code = ` + globalThis.foo = "bar"; + globalThis.foo = "baz"; + return globalThis.foo;`; + + expect(util.transpileAndExecute(code)).toBe("baz"); + }); + + test("globalThis to _G (function)", () => { + const code = ` + globalThis.foo = () => "bar"; + return globalThis.foo();`; + + expect(util.transpileAndExecute(code)).toBe("bar"); + }); + + test("globalThis to _G (assign + noImplicitAny)", () => { + const code = ` + (globalThis).foo = "bar"; + return (globalThis).foo;`; + + expect(util.transpileAndExecute(code)).toBe("bar"); + }); + + test("globalThis to _G (var)", () => { + const code = ` + var globalFoo = "bar"; + return globalThis.globalFoo;`; + + const lua = util.transpileString(code); + + expect(util.executeLua(lua)).toBe("bar"); + }); + + test("globalThis to _G (let)", () => { + const code = ` + let NotAGlobalFoo = "bar"; + return (globalThis).NotAGlobalFoo;`; + + expect(util.transpileAndExecute(code)).toBe(undefined); + }); +});