From f325a98f0edfe03bab4b0c07295f2346ac2d271d Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 6 Apr 2016 15:40:17 -0700 Subject: [PATCH 01/12] enable generated names for block-scoped binding in for-of --- src/compiler/transformers/es6.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 648ad7c8eac..552690b15b0 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -1564,6 +1564,9 @@ namespace ts { // var v = _a[_i]; if (isVariableDeclarationList(initializer)) { const firstDeclaration = firstOrUndefined(initializer.declarations); + if (initializer.flags & NodeFlags.BlockScoped) { + enableSubstitutionsForBlockScopedBindings(); + } if (firstDeclaration && isBindingPattern(firstDeclaration.name)) { // This works whether the declaration is a var, let, or const. // It will use rhsIterationValue _a[_i] as the initializer. From 4ead44db9b12a5d86fe898b553e5967c16a512cb Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 6 Apr 2016 18:59:54 -0700 Subject: [PATCH 02/12] Revert to old emit for metadata. Also adds baselines support for transpiler tests. Fixes #7878. --- src/compiler/factory.ts | 6 +- src/compiler/transformers/ts.ts | 31 +- .../baselines/reference/decoratorMetadata.js | 12 +- ...taForMethodWithNoReturnTypeAnnotation01.js | 8 +- .../Does not generate semantic diagnostics.js | 3 + ... expected syntactic diagnostics.errors.txt | 7 + ...enerates expected syntactic diagnostics.js | 4 + .../transpile/Generates module output.js | 5 + ...diagnostics for missing file references.js | 4 + ... diagnostics for missing module imports.js | 2 + ...erates no diagnostics with valid inputs.js | 3 + ...extra errors for file without extension.js | 3 + .../transpile/Rename dependencies - AMD.js | 5 + .../transpile/Rename dependencies - System.js | 16 + .../transpile/Rename dependencies - UMD.js | 13 + .../reference/transpile/Sets module name.js | 12 + .../Supports backslashes in file name.js | 3 + ... with emit decorators and emit metadata.js | 19 + .../Uses correct newLine character.js | 3 + .../transpile/transpile .js files.js | 3 + ...anspile file as tsx if jsx is specified.js | 3 + tests/cases/unittests/transpile.ts | 443 +++++++----------- 22 files changed, 318 insertions(+), 290 deletions(-) create mode 100644 tests/baselines/reference/transpile/Does not generate semantic diagnostics.js create mode 100644 tests/baselines/reference/transpile/Generates expected syntactic diagnostics.errors.txt create mode 100644 tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js create mode 100644 tests/baselines/reference/transpile/Generates module output.js create mode 100644 tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js create mode 100644 tests/baselines/reference/transpile/Generates no diagnostics for missing module imports.js create mode 100644 tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js create mode 100644 tests/baselines/reference/transpile/No extra errors for file without extension.js create mode 100644 tests/baselines/reference/transpile/Rename dependencies - AMD.js create mode 100644 tests/baselines/reference/transpile/Rename dependencies - System.js create mode 100644 tests/baselines/reference/transpile/Rename dependencies - UMD.js create mode 100644 tests/baselines/reference/transpile/Sets module name.js create mode 100644 tests/baselines/reference/transpile/Supports backslashes in file name.js create mode 100644 tests/baselines/reference/transpile/Transpile with emit decorators and emit metadata.js create mode 100644 tests/baselines/reference/transpile/Uses correct newLine character.js create mode 100644 tests/baselines/reference/transpile/transpile .js files.js create mode 100644 tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index f7aa18fa7ea..ec5ac638605 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -854,14 +854,12 @@ namespace ts { ); } - export function createMetadataHelper(metadataKey: string, metadataValue: Expression, defer?: boolean) { + export function createMetadataHelper(metadataKey: string, metadataValue: Expression) { return createCall( createIdentifier("__metadata"), [ createLiteral(metadataKey), - defer - ? createArrowFunction([], metadataValue) - : metadataValue + metadataValue ] ); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 96abcd7cf1d..8fbea0dd367 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -6,6 +6,11 @@ namespace ts { type SuperContainer = ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration; + /** + * Indicates whether to emit type metadata in the new format. + */ + const USE_NEW_TYPE_METADATA_FORMAT = false; + const enum TypeScriptSubstitutionFlags { /** Enables substitutions for decorated classes. */ DecoratedClasses = 1 << 0, @@ -1354,6 +1359,30 @@ namespace ts { * @param decoratorExpressions The destination array to which to add new decorator expressions. */ function addTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) { + if (USE_NEW_TYPE_METADATA_FORMAT) { + addNewTypeMetadata(node, decoratorExpressions); + } + else { + addOldTypeMetadata(node, decoratorExpressions); + } + } + + function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) { + if (compilerOptions.emitDecoratorMetadata) { + let properties: ObjectLiteralElement[]; + if (shouldAddTypeMetadata(node)) { + decoratorExpressions.push(createMetadataHelper("design:type", serializeTypeOfNode(node))); + } + if (shouldAddParamTypesMetadata(node)) { + decoratorExpressions.push(createMetadataHelper("design:paramtypes", serializeParameterTypesOfNode(node))); + } + if (shouldAddReturnTypeMetadata(node)) { + decoratorExpressions.push(createMetadataHelper("design:returntype", serializeReturnTypeOfNode(node))); + } + } + } + + function addNewTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) { if (compilerOptions.emitDecoratorMetadata) { let properties: ObjectLiteralElement[]; if (shouldAddTypeMetadata(node)) { @@ -1366,7 +1395,7 @@ namespace ts { (properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction([], serializeReturnTypeOfNode(node)))); } if (properties) { - decoratorExpressions.push(createMetadataHelper("design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true), /*defer*/ false)); + decoratorExpressions.push(createMetadataHelper("design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true))); } } } diff --git a/tests/baselines/reference/decoratorMetadata.js b/tests/baselines/reference/decoratorMetadata.js index a6991248748..cb253d43c16 100644 --- a/tests/baselines/reference/decoratorMetadata.js +++ b/tests/baselines/reference/decoratorMetadata.js @@ -49,15 +49,11 @@ var MyComponent = (function () { }()); __decorate([ decorator, - __metadata("design:typeinfo", { - type: function () { return Function; }, - paramTypes: function () { return [Object]; }, - returnType: function () { return void 0; } - }) + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", void 0) ], MyComponent.prototype, "method", null); MyComponent = __decorate([ decorator, - __metadata("design:typeinfo", { - paramTypes: function () { return [service_1.default]; } - }) + __metadata("design:paramtypes", [service_1.default]) ], MyComponent); diff --git a/tests/baselines/reference/decoratorMetadataForMethodWithNoReturnTypeAnnotation01.js b/tests/baselines/reference/decoratorMetadataForMethodWithNoReturnTypeAnnotation01.js index 7cc7416cd70..970447efae0 100644 --- a/tests/baselines/reference/decoratorMetadataForMethodWithNoReturnTypeAnnotation01.js +++ b/tests/baselines/reference/decoratorMetadataForMethodWithNoReturnTypeAnnotation01.js @@ -24,9 +24,7 @@ var MyClass = (function () { }()); __decorate([ decorator, - __metadata("design:typeinfo", { - type: function () { return Function; }, - paramTypes: function () { return []; }, - returnType: function () { return void 0; } - }) + __metadata("design:type", Function), + __metadata("design:paramtypes", []), + __metadata("design:returntype", void 0) ], MyClass.prototype, "doSomething", null); diff --git a/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js b/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js new file mode 100644 index 00000000000..61a703e13bb --- /dev/null +++ b/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js @@ -0,0 +1,3 @@ +"use strict"; +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.errors.txt b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.errors.txt new file mode 100644 index 00000000000..6fbdba6f2c6 --- /dev/null +++ b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.errors.txt @@ -0,0 +1,7 @@ +file.ts(1,3): error TS1005: ';' expected. + + +==== file.ts (1 errors) ==== + a b + ~ +!!! error TS1005: ';' expected. \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js new file mode 100644 index 00000000000..9d108d63313 --- /dev/null +++ b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js @@ -0,0 +1,4 @@ +"use strict"; +a; +b; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates module output.js b/tests/baselines/reference/transpile/Generates module output.js new file mode 100644 index 00000000000..9eadd1f2717 --- /dev/null +++ b/tests/baselines/reference/transpile/Generates module output.js @@ -0,0 +1,5 @@ +define(["require", "exports"], function (require, exports) { + "use strict"; + var x = 0; +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js b/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js new file mode 100644 index 00000000000..88d98628eee --- /dev/null +++ b/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js @@ -0,0 +1,4 @@ +"use strict"; +/// +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates no diagnostics for missing module imports.js b/tests/baselines/reference/transpile/Generates no diagnostics for missing module imports.js new file mode 100644 index 00000000000..1ceb1bcd146 --- /dev/null +++ b/tests/baselines/reference/transpile/Generates no diagnostics for missing module imports.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js b/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js new file mode 100644 index 00000000000..61a703e13bb --- /dev/null +++ b/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js @@ -0,0 +1,3 @@ +"use strict"; +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/No extra errors for file without extension.js b/tests/baselines/reference/transpile/No extra errors for file without extension.js new file mode 100644 index 00000000000..61a703e13bb --- /dev/null +++ b/tests/baselines/reference/transpile/No extra errors for file without extension.js @@ -0,0 +1,3 @@ +"use strict"; +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Rename dependencies - AMD.js b/tests/baselines/reference/transpile/Rename dependencies - AMD.js new file mode 100644 index 00000000000..a0dd948c9fc --- /dev/null +++ b/tests/baselines/reference/transpile/Rename dependencies - AMD.js @@ -0,0 +1,5 @@ +define(["require", "exports", "SomeOtherName"], function (require, exports, SomeName_1) { + "use strict"; + use(SomeName_1.foo); +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Rename dependencies - System.js b/tests/baselines/reference/transpile/Rename dependencies - System.js new file mode 100644 index 00000000000..4aad7dd82ec --- /dev/null +++ b/tests/baselines/reference/transpile/Rename dependencies - System.js @@ -0,0 +1,16 @@ +System.register(["SomeOtherName"], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var SomeName_1; + return { + setters: [ + function (SomeName_1_1) { + SomeName_1 = SomeName_1_1; + } + ], + execute: function () { + use(SomeName_1.foo); + } + }; +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Rename dependencies - UMD.js b/tests/baselines/reference/transpile/Rename dependencies - UMD.js new file mode 100644 index 00000000000..88bdc515936 --- /dev/null +++ b/tests/baselines/reference/transpile/Rename dependencies - UMD.js @@ -0,0 +1,13 @@ +(function (dependencies, factory) { + if (typeof module === 'object' && typeof module.exports === 'object') { + var v = factory(require, exports); if (v !== undefined) module.exports = v; + } + else if (typeof define === 'function' && define.amd) { + define(dependencies, factory); + } +})(["require", "exports", "SomeOtherName"], function (require, exports) { + "use strict"; + var SomeName_1 = require("SomeOtherName"); + use(SomeName_1.foo); +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Sets module name.js b/tests/baselines/reference/transpile/Sets module name.js new file mode 100644 index 00000000000..dfe9605fc9e --- /dev/null +++ b/tests/baselines/reference/transpile/Sets module name.js @@ -0,0 +1,12 @@ +System.register("NamedModule", [], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var x; + return { + setters: [], + execute: function () { + x = 1; + } + }; +}); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports backslashes in file name.js b/tests/baselines/reference/transpile/Supports backslashes in file name.js new file mode 100644 index 00000000000..942449753b0 --- /dev/null +++ b/tests/baselines/reference/transpile/Supports backslashes in file name.js @@ -0,0 +1,3 @@ +"use strict"; +var x; +//# sourceMappingURL=b.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Transpile with emit decorators and emit metadata.js b/tests/baselines/reference/transpile/Transpile with emit decorators and emit metadata.js new file mode 100644 index 00000000000..be5c936010d --- /dev/null +++ b/tests/baselines/reference/transpile/Transpile with emit decorators and emit metadata.js @@ -0,0 +1,19 @@ +"use strict"; +var db_1 = require('./db'); +function someDecorator(target) { + return target; +} +var MyClass = (function () { + function MyClass(db) { + this.db = db; + this.db.doSomething(); + } + return MyClass; +}()); +MyClass = __decorate([ + someDecorator, + __metadata("design:paramtypes", [typeof (_a = typeof db_1.db !== "undefined" && db_1.db) === "function" && _a || Object]) +], MyClass); +exports.MyClass = MyClass; +var _a; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Uses correct newLine character.js b/tests/baselines/reference/transpile/Uses correct newLine character.js new file mode 100644 index 00000000000..bab9c3c4443 --- /dev/null +++ b/tests/baselines/reference/transpile/Uses correct newLine character.js @@ -0,0 +1,3 @@ +"use strict"; +var x = 0; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/transpile .js files.js b/tests/baselines/reference/transpile/transpile .js files.js new file mode 100644 index 00000000000..c17099d84ba --- /dev/null +++ b/tests/baselines/reference/transpile/transpile .js files.js @@ -0,0 +1,3 @@ +"use strict"; +var a = 10; +//# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js b/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js new file mode 100644 index 00000000000..baa27ee64ce --- /dev/null +++ b/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js @@ -0,0 +1,3 @@ +"use strict"; +var x = React.createElement("div", null); +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/cases/unittests/transpile.ts b/tests/cases/unittests/transpile.ts index 00f6fb2006f..fb16388ce2f 100644 --- a/tests/cases/unittests/transpile.ts +++ b/tests/cases/unittests/transpile.ts @@ -5,296 +5,195 @@ module ts { interface TranspileTestSettings { options?: TranspileOptions; - expectedOutput?: string; - expectedDiagnosticCodes?: number[]; } - function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes?: number[]) { - if(!expectedDiagnosticCodes) { - return; - } + function transpilesCorrectly(name: string, input: string, testSettings: TranspileTestSettings) { + describe(name, () => { + let justName: string; + let transpileOptions: TranspileOptions; + let canUseOldTranspile: boolean; + let toBeCompiled: Harness.Compiler.TestFile[]; + let transpileResult: TranspileOutput; + let oldTranspileResult: string; + let oldTranspileDiagnostics: Diagnostic[]; - for (let i = 0; i < expectedDiagnosticCodes.length; i++) { - assert.equal(expectedDiagnosticCodes[i], diagnostics[i] && diagnostics[i].code, `Could not find expeced diagnostic.`); - } - assert.equal(diagnostics.length, expectedDiagnosticCodes.length, "Resuting diagnostics count does not match expected"); - } + before(() => { + transpileOptions = testSettings.options || {}; + if (!transpileOptions.compilerOptions) { + transpileOptions.compilerOptions = {}; + } - function test(input: string, testSettings: TranspileTestSettings): void { + if (transpileOptions.compilerOptions.newLine === undefined) { + // use \r\n as default new line + transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed; + } - let transpileOptions: TranspileOptions = testSettings.options || {}; - if (!transpileOptions.compilerOptions) { - transpileOptions.compilerOptions = {}; - } - if(transpileOptions.compilerOptions.newLine === undefined) { - // use \r\n as default new line - transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed; - } + transpileOptions.compilerOptions.sourceMap = true; - let canUseOldTranspile = !transpileOptions.renamedDependencies; + if (!transpileOptions.fileName) { + transpileOptions.fileName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts"; + } - transpileOptions.reportDiagnostics = true; - let transpileModuleResult = transpileModule(input, transpileOptions); + transpileOptions.reportDiagnostics = true; - checkDiagnostics(transpileModuleResult.diagnostics, testSettings.expectedDiagnosticCodes); + justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? ".tsx" : ".ts"); + toBeCompiled = [{ + unitName: transpileOptions.fileName, + content: input + }]; - if (testSettings.expectedOutput !== undefined) { - assert.equal(transpileModuleResult.outputText, testSettings.expectedOutput); - } + canUseOldTranspile = !transpileOptions.renamedDependencies; + transpileResult = transpileModule(input, transpileOptions); - if (canUseOldTranspile) { - let diagnostics: Diagnostic[] = []; - let transpileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, diagnostics, transpileOptions.moduleName); - checkDiagnostics(diagnostics, testSettings.expectedDiagnosticCodes); - if (testSettings.expectedOutput) { - assert.equal(transpileResult, testSettings.expectedOutput); - } - } - - // check source maps - if (!transpileOptions.compilerOptions) { - transpileOptions.compilerOptions = {}; - } - - if (!transpileOptions.fileName) { - transpileOptions.fileName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts"; - } - - transpileOptions.compilerOptions.sourceMap = true; - let transpileModuleResultWithSourceMap = transpileModule(input, transpileOptions); - assert.isTrue(transpileModuleResultWithSourceMap.sourceMapText !== undefined); - - let expectedSourceMapFileName = removeFileExtension(getBaseFileName(normalizeSlashes(transpileOptions.fileName))) + ".js.map"; - let expectedSourceMappingUrlLine = `//# sourceMappingURL=${expectedSourceMapFileName}`; - - if (testSettings.expectedOutput !== undefined) { - assert.equal(transpileModuleResultWithSourceMap.outputText, testSettings.expectedOutput + expectedSourceMappingUrlLine); - } - else { - // expected output is not set, just verify that output text has sourceMappingURL as a last line - let output = transpileModuleResultWithSourceMap.outputText; - assert.isTrue(output.length >= expectedSourceMappingUrlLine.length); - if (output.length === expectedSourceMappingUrlLine.length) { - assert.equal(output, expectedSourceMappingUrlLine); - } - else { - let suffix = getNewLineCharacter(transpileOptions.compilerOptions) + expectedSourceMappingUrlLine - assert.isTrue(output.indexOf(suffix, output.length - suffix.length) !== -1); - } - } - - } - - it("Generates no diagnostics with valid inputs", () => { - // No errors - test(`var x = 0;`, { options: { compilerOptions: { module: ModuleKind.CommonJS } } }); - }); - - it("Generates no diagnostics for missing file references", () => { - test(`/// -var x = 0;`, - { options: { compilerOptions: { module: ModuleKind.CommonJS } } }); - }); - - it("Generates no diagnostics for missing module imports", () => { - test(`import {a} from "module2";`, - { options: { compilerOptions: { module: ModuleKind.CommonJS } } }); - }); - - it("Generates expected syntactic diagnostics", () => { - test(`a b`, - { options: { compilerOptions: { module: ModuleKind.CommonJS } }, expectedDiagnosticCodes: [1005] }); /// 1005: ';' Expected - }); - - it("Does not generate semantic diagnostics", () => { - test(`var x: string = 0;`, - { options: { compilerOptions: { module: ModuleKind.CommonJS } } }); - }); - - it("Generates module output", () => { - test(`var x = 0;`, - { - options: { compilerOptions: { module: ModuleKind.AMD } }, - expectedOutput: `define(["require", "exports"], function (require, exports) {\r\n "use strict";\r\n var x = 0;\r\n});\r\n` + if (canUseOldTranspile) { + oldTranspileDiagnostics = []; + oldTranspileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, oldTranspileDiagnostics, transpileOptions.moduleName); + } }); - }); - it("Uses correct newLine character", () => { - test(`var x = 0;`, - { - options: { compilerOptions: { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed } }, - expectedOutput: `"use strict";\nvar x = 0;\n` + after(() => { + justName = undefined; + transpileOptions = undefined; + canUseOldTranspile = undefined; + toBeCompiled = undefined; + transpileResult = undefined; + oldTranspileResult = undefined; + oldTranspileDiagnostics = undefined; }); - }); - it("Sets module name", () => { - let output = - `System.register("NamedModule", [], function (exports_1, context_1) {\n` + - ` "use strict";\n` + - ` var __moduleName = context_1 && context_1.id;\n` + - ` var x;\n` + - ` return {\n` + - ` setters: [],\n` + - ` execute: function () {\n` + - ` x = 1;\n` + - ` }\n` + - ` };\n` + - `});\n`; - test("var x = 1;", - { - options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, moduleName: "NamedModule" }, - expectedOutput: output - }) - }); - - it("No extra errors for file without extension", () => { - test(`"use strict";\r\nvar x = 0;`, { options: { compilerOptions: { module: ModuleKind.CommonJS }, fileName: "file" } }); - }); - - it("Rename dependencies - System", () => { - let input = - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);` - let output = - `System.register(["SomeOtherName"], function (exports_1, context_1) {\n` + - ` "use strict";\n` + - ` var __moduleName = context_1 && context_1.id;\n` + - ` var SomeName_1;\n` + - ` return {\n` + - ` setters: [\n` + - ` function (SomeName_1_1) {\n` + - ` SomeName_1 = SomeName_1_1;\n` + - ` }\n` + - ` ],\n` + - ` execute: function () {\n` + - ` use(SomeName_1.foo);\n` + - ` }\n` + - ` };\n` + - `});\n` - - test(input, - { - options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } }, - expectedOutput: output - }); - }); - - it("Rename dependencies - AMD", () => { - let input = - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);` - let output = - `define(["require", "exports", "SomeOtherName"], function (require, exports, SomeName_1) {\n` + - ` "use strict";\n` + - ` use(SomeName_1.foo);\n` + - `});\n`; - - test(input, - { - options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } }, - expectedOutput: output - }); - }); - - it("Rename dependencies - UMD", () => { - let input = - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);` - let output = - `(function (dependencies, factory) {\n` + - ` if (typeof module === 'object' && typeof module.exports === 'object') {\n` + - ` var v = factory(require, exports); if (v !== undefined) module.exports = v;\n` + - ` }\n` + - ` else if (typeof define === 'function' && define.amd) {\n` + - ` define(dependencies, factory);\n` + - ` }\n` + - `})(["require", "exports", "SomeOtherName"], function (require, exports) {\n` + - ` "use strict";\n` + - ` var SomeName_1 = require("SomeOtherName");\n` + - ` use(SomeName_1.foo);\n` + - `});\n` - - test(input, - { - options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } }, - expectedOutput: output - }); - }); - - it("Transpile with emit decorators and emit metadata", () => { - let input = - `import {db} from './db';\n` + - `function someDecorator(target) {\n` + - ` return target;\n` + - `} \n` + - `@someDecorator\n` + - `class MyClass {\n` + - ` db: db;\n` + - ` constructor(db: db) {\n` + - ` this.db = db;\n` + - ` this.db.doSomething(); \n` + - ` }\n` + - `}\n` + - `export {MyClass}; \n` - let output = - `"use strict";\n` + - `var db_1 = require(\'./db\');\n` + - `function someDecorator(target) {\n` + - ` return target;\n` + - `}\n` + - `var MyClass = (function () {\n` + - ` function MyClass(db) {\n` + - ` this.db = db;\n` + - ` this.db.doSomething();\n` + - ` }\n` + - ` return MyClass;\n` + - `}());\n` + - `MyClass = __decorate([\n` + - ` someDecorator, \n` + - ` __metadata(\'design:paramtypes\', [(typeof (_a = typeof db_1.db !== \'undefined\' && db_1.db) === \'function\' && _a) || Object])\n` + - `], MyClass);\n` + - `exports.MyClass = MyClass;\n` + - `var _a;\n`; - - test(input, - { - options: { - compilerOptions: { - module: ModuleKind.CommonJS, - newLine: NewLineKind.LineFeed, - noEmitHelpers: true, - emitDecoratorMetadata: true, - experimentalDecorators: true, - target: ScriptTarget.ES5, + it("Correct errors for " + justName, () => { + Harness.Baseline.runBaseline("Correct errors", justName.replace(/\.tsx?$/, ".errors.txt"), () => { + if (transpileResult.diagnostics.length === 0) { + return null; } - }, - expectedOutput: output + + return Harness.Compiler.getErrorBaseline(toBeCompiled, transpileResult.diagnostics); + }); }); - }); - it("Supports backslashes in file name", () => { - test("var x", { expectedOutput: `"use strict";\r\nvar x;\r\n`, options: { fileName: "a\\b.ts" }}); - }); + if (canUseOldTranspile) { + it("Correct errors (old transpile) for " + justName, () => { + Harness.Baseline.runBaseline("Correct errors", justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), () => { + if (oldTranspileDiagnostics.length === 0) { + return null; + } - it("transpile file as 'tsx' if 'jsx' is specified", () => { - let input = `var x =
`; - let output = `"use strict";\nvar x = React.createElement("div", null);\n`; - test(input, { - expectedOutput: output, - options: { compilerOptions: { jsx: JsxEmit.React, newLine: NewLineKind.LineFeed } } - }) - }); - it("transpile .js files", () => { - const input = "const a = 10;"; - const output = `"use strict";\nvar a = 10;\n`; - test(input, { - expectedOutput: output, - options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true }, - expectedDiagnosticCodes: [] + return Harness.Compiler.getErrorBaseline(toBeCompiled, oldTranspileDiagnostics); + }); + }); + } + + it("Correct output for " + justName, () => { + Harness.Baseline.runBaseline("Correct output", justName.replace(/\.tsx?$/, ".js"), () => { + return transpileResult.outputText; + }); + }); + + + if (canUseOldTranspile) { + it("Correct output (old transpile) for " + justName, () => { + Harness.Baseline.runBaseline("Correct output", justName.replace(/\.tsx?$/, ".oldTranspile.js"), () => { + return oldTranspileResult; + }); + }); + } }); - }) + } + + transpilesCorrectly("Generates no diagnostics with valid inputs", `var x = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Generates no diagnostics for missing file references", `/// +var x = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Generates no diagnostics for missing module imports", `import {a} from "module2";`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Generates expected syntactic diagnostics", `a b`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Does not generate semantic diagnostics", `var x: string = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + }); + + transpilesCorrectly("Generates module output", `var x = 0;`, { + options: { compilerOptions: { module: ModuleKind.AMD } } + }); + + transpilesCorrectly("Uses correct newLine character", `var x = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed } } + }); + + transpilesCorrectly("Sets module name", "var x = 1;", { + options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, moduleName: "NamedModule" } + }); + + transpilesCorrectly("No extra errors for file without extension", `"use strict";\r\nvar x = 0;`, { + options: { compilerOptions: { module: ModuleKind.CommonJS }, fileName: "file" } + }); + + transpilesCorrectly("Rename dependencies - System", + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { + options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + }); + + transpilesCorrectly("Rename dependencies - AMD", + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { + options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + }); + + transpilesCorrectly("Rename dependencies - UMD", + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { + options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + }); + + transpilesCorrectly("Transpile with emit decorators and emit metadata", + `import {db} from './db';\n` + + `function someDecorator(target) {\n` + + ` return target;\n` + + `} \n` + + `@someDecorator\n` + + `class MyClass {\n` + + ` db: db;\n` + + ` constructor(db: db) {\n` + + ` this.db = db;\n` + + ` this.db.doSomething(); \n` + + ` }\n` + + `}\n` + + `export {MyClass}; \n`, { + options: { + compilerOptions: { + module: ModuleKind.CommonJS, + newLine: NewLineKind.LineFeed, + noEmitHelpers: true, + emitDecoratorMetadata: true, + experimentalDecorators: true, + target: ScriptTarget.ES5, + } + } + }); + + transpilesCorrectly("Supports backslashes in file name", "var x", { + options: { fileName: "a\\b.ts" } + }); + + transpilesCorrectly("transpile file as 'tsx' if 'jsx' is specified", `var x =
`, { + options: { compilerOptions: { jsx: JsxEmit.React, newLine: NewLineKind.LineFeed } } + }); + + transpilesCorrectly("transpile .js files", "const a = 10;", { + options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } + }); }); } From 42351a8a99038e1cd600a33d424a1536caf9f5e6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 6 Apr 2016 20:34:01 -0700 Subject: [PATCH 03/12] Export the respective let binding when a decorated class is exported. --- src/compiler/transformers/ts.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 1d8dd46edee..d1e28c58911 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -180,7 +180,7 @@ namespace ts { function classElementVisitorWorker(node: Node): VisitResult { switch (node.kind) { case SyntaxKind.Constructor: - // TypeScript constructors are transformed in `transformClassDeclaration`. + // TypeScript constructors are transformed in `visitClassDeclaration`. // We elide them here as `visitorWorker` checks transform flags, which could // erronously include an ES6 constructor without TypeScript syntax. return undefined; @@ -257,7 +257,7 @@ namespace ts { // TypeScript index signatures are elided. case SyntaxKind.Decorator: - // TypeScript decorators are elided. They will be emitted as part of transformClassDeclaration. + // TypeScript decorators are elided. They will be emitted as part of visitClassDeclaration. case SyntaxKind.TypeAliasDeclaration: // TypeScript type-only declarations are elided. @@ -266,7 +266,7 @@ namespace ts { // TypeScript property declarations are elided. case SyntaxKind.Constructor: - // TypeScript constructors are transformed in `transformClassDeclaration`. + // TypeScript constructors are transformed in `visitClassDeclaration`. return undefined; case SyntaxKind.InterfaceDeclaration: @@ -601,11 +601,9 @@ namespace ts { addNode(statements, createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList([ + createLetDeclarationList([ createVariableDeclaration(decoratedClassAlias) - ], - /*location*/ undefined, - NodeFlags.Let) + ]) ) ); @@ -616,19 +614,25 @@ namespace ts { /*location*/ node); } + // When emitting as a *default* export, we'll add a subsequent `export default` statement, + // so we should only be creating a local binding without any modifiers. + // Otherwise, we need preserve and visit all the modifiers. + const bindingModifiers = + isDefaultExternalModuleExport(node) + ? undefined + : visitNodes(node.modifiers, visitor, isModifier); + // let ${name} = ${classExpression}; addNode(statements, setOriginalNode( createVariableStatement( - /*modifiers*/ undefined, - createVariableDeclarationList([ + bindingModifiers, + createLetDeclarationList([ createVariableDeclaration( name, classExpression ) - ], - /*location*/ undefined, - NodeFlags.Let) + ]) ), /*original*/ node ) From 0e0182c1ea7aaaf699a0188b9e49e6a914b0ae09 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 6 Apr 2016 23:49:14 -0700 Subject: [PATCH 04/12] emit unqualified enum members as qualified --- src/compiler/transformers/ts.ts | 80 ++++++++++++------- .../enumWithComputedMember.errors.txt | 12 +++ .../reference/enumWithComputedMember.js | 15 ++++ .../cases/compiler/enumWithComputedMember.ts | 5 ++ 4 files changed, 85 insertions(+), 27 deletions(-) create mode 100644 tests/baselines/reference/enumWithComputedMember.errors.txt create mode 100644 tests/baselines/reference/enumWithComputedMember.js create mode 100644 tests/cases/compiler/enumWithComputedMember.ts diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 96abcd7cf1d..c841f4d0e4c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -13,6 +13,8 @@ namespace ts { NamespaceExports = 1 << 1, /** Enables substitutions for async methods with `super` calls. */ AsyncMethodsWithSuper = 1 << 2, + /* Enables substitutions for unqualified enum members */ + NonQualifiedEnumMembers = 1 << 3 } export function transformTypeScript(context: TransformationContext) { @@ -65,7 +67,7 @@ namespace ts { * Keeps track of whether we are within any containing namespaces when performing * just-in-time substitution while printing an expression identifier. */ - let isEnclosedInNamespace: boolean; + let applicableSubstitutions: TypeScriptSubstitutionFlags; /** * This keeps track of containers where `super` is valid, for use with @@ -2234,26 +2236,29 @@ namespace ts { // ... // })(x || (x = {})); statements.push( - setOriginalNode( - createStatement( - createCall( - createFunctionExpression( + setNodeEmitFlags( + setOriginalNode( + createStatement( + createCall( + createFunctionExpression( /*asteriskToken*/ undefined, /*name*/ undefined, - [createParameter(localName)], - transformEnumBody(node, localName) - ), - [createLogicalOr( - name, - createAssignment( + [createParameter(localName)], + transformEnumBody(node, localName) + ), + [createLogicalOr( name, - createObjectLiteral() - ) - )] - ), + createAssignment( + name, + createObjectLiteral() + ) + )] + ), /*location*/ node - ), + ), /*original*/ node + ), + NodeEmitFlags.AdviseOnEmitNode ) ); @@ -2317,11 +2322,14 @@ namespace ts { if (value !== undefined) { return createLiteral(value); } - else if (member.initializer) { - return visitNode(member.initializer, visitor, isExpression); - } else { - return createVoidZero(); + enableSubstitutionForNonQualifiedEnumMembers(); + if (member.initializer) { + return visitNode(member.initializer, visitor, isExpression); + } + else { + return createVoidZero(); + } } } @@ -2634,8 +2642,12 @@ namespace ts { return getOriginalNode(node).kind === SyntaxKind.ModuleDeclaration; } + function isTransformedEnumDeclaration(node: Node): boolean { + return getOriginalNode(node).kind === SyntaxKind.EnumDeclaration; + } + function onEmitNode(node: Node, emit: (node: Node) => void): void { - const savedIsEnclosedInNamespace = isEnclosedInNamespace; + const savedApplicableSubstitutions = applicableSubstitutions; const savedCurrentSuperContainer = currentSuperContainer; // If we need support substitutions for aliases for decorated classes, @@ -2651,7 +2663,10 @@ namespace ts { } if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node)) { - isEnclosedInNamespace = true; + applicableSubstitutions |= TypeScriptSubstitutionFlags.NamespaceExports; + } + if (enabledSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && isTransformedEnumDeclaration(node)) { + applicableSubstitutions |= TypeScriptSubstitutionFlags.NonQualifiedEnumMembers; } previousOnEmitNode(node, emit); @@ -2660,7 +2675,7 @@ namespace ts { currentDecoratedClassAliases[getOriginalNodeId(node)] = undefined; } - isEnclosedInNamespace = savedIsEnclosedInNamespace; + applicableSubstitutions = savedApplicableSubstitutions; currentSuperContainer = savedCurrentSuperContainer; } @@ -2705,18 +2720,22 @@ namespace ts { } } - if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isEnclosedInNamespace) { + if (enabledSubstitutions & applicableSubstitutions) { // If we are nested within a namespace declaration, we may need to qualifiy // an identifier that is exported from a merged namespace. const original = getOriginalNode(node); if (isIdentifier(original) && original.parent) { const container = resolver.getReferencedExportContainer(original); - if (container && container.kind === SyntaxKind.ModuleDeclaration) { - return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node); + if (container) { + const substitute = + (applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) || + (applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration); + if (substitute) { + return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node); + } } } } - return node; } @@ -2770,6 +2789,13 @@ namespace ts { return node; } + function enableSubstitutionForNonQualifiedEnumMembers() { + if ((enabledSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers) === 0) { + enabledSubstitutions |= TypeScriptSubstitutionFlags.NonQualifiedEnumMembers; + context.enableExpressionSubstitution(SyntaxKind.Identifier); + } + } + function enableExpressionSubstitutionForAsyncMethodsWithSuper() { if ((enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) === 0) { enabledSubstitutions |= TypeScriptSubstitutionFlags.AsyncMethodsWithSuper; diff --git a/tests/baselines/reference/enumWithComputedMember.errors.txt b/tests/baselines/reference/enumWithComputedMember.errors.txt new file mode 100644 index 00000000000..cdbcaf575e8 --- /dev/null +++ b/tests/baselines/reference/enumWithComputedMember.errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/enumWithComputedMember.ts(4,5): error TS1061: Enum member must have initializer. + + +==== tests/cases/compiler/enumWithComputedMember.ts (1 errors) ==== + enum A { + X = "".length, + Y = X, + Z + ~ +!!! error TS1061: Enum member must have initializer. + } + \ No newline at end of file diff --git a/tests/baselines/reference/enumWithComputedMember.js b/tests/baselines/reference/enumWithComputedMember.js new file mode 100644 index 00000000000..ca4bfac7adb --- /dev/null +++ b/tests/baselines/reference/enumWithComputedMember.js @@ -0,0 +1,15 @@ +//// [enumWithComputedMember.ts] +enum A { + X = "".length, + Y = X, + Z +} + + +//// [enumWithComputedMember.js] +var A; +(function (A) { + A[A["X"] = "".length] = "X"; + A[A["Y"] = A.X] = "Y"; + A[A["Z"] = void 0] = "Z"; +})(A || (A = {})); diff --git a/tests/cases/compiler/enumWithComputedMember.ts b/tests/cases/compiler/enumWithComputedMember.ts new file mode 100644 index 00000000000..10c7b1994a9 --- /dev/null +++ b/tests/cases/compiler/enumWithComputedMember.ts @@ -0,0 +1,5 @@ +enum A { + X = "".length, + Y = X, + Z +} From 2abc7369554e5716e3c1a3e3e85cedb2138c0ce7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 7 Apr 2016 00:55:02 -0700 Subject: [PATCH 05/12] Ensure that the entire contents of the prologue are simply 'use strict'. --- src/compiler/factory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index f7aa18fa7ea..0fd423d342c 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1204,7 +1204,7 @@ namespace ts { // Utilities function isUseStrictPrologue(node: ExpressionStatement): boolean { - return !!(node.expression as StringLiteral).text.match(/use strict/); + return (node.expression as StringLiteral).text === "use strict"; } export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean): number { From c57e54eeae5fd3d13c93cb21cc34888b5d43d862 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 7 Apr 2016 00:41:40 -0700 Subject: [PATCH 06/12] Added test. --- tests/cases/compiler/useStrictLikePrologueString01.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/cases/compiler/useStrictLikePrologueString01.ts diff --git a/tests/cases/compiler/useStrictLikePrologueString01.ts b/tests/cases/compiler/useStrictLikePrologueString01.ts new file mode 100644 index 00000000000..b76e38ebb06 --- /dev/null +++ b/tests/cases/compiler/useStrictLikePrologueString01.ts @@ -0,0 +1,7 @@ +//@target: commonjs +//@target: es5 + +"hey!" +" use strict " +export function f() { +} \ No newline at end of file From 3a35aa30da5a1ca2dd40b1f52467aa48ec3b0a36 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 7 Apr 2016 00:42:04 -0700 Subject: [PATCH 07/12] Accepted baselines. --- .../reference/useStrictLikePrologueString01.js | 13 +++++++++++++ .../reference/useStrictLikePrologueString01.symbols | 7 +++++++ .../reference/useStrictLikePrologueString01.types | 11 +++++++++++ 3 files changed, 31 insertions(+) create mode 100644 tests/baselines/reference/useStrictLikePrologueString01.js create mode 100644 tests/baselines/reference/useStrictLikePrologueString01.symbols create mode 100644 tests/baselines/reference/useStrictLikePrologueString01.types diff --git a/tests/baselines/reference/useStrictLikePrologueString01.js b/tests/baselines/reference/useStrictLikePrologueString01.js new file mode 100644 index 00000000000..12cec220725 --- /dev/null +++ b/tests/baselines/reference/useStrictLikePrologueString01.js @@ -0,0 +1,13 @@ +//// [useStrictLikePrologueString01.ts] + +"hey!" +" use strict " +export function f() { +} + +//// [useStrictLikePrologueString01.js] +"hey!"; +" use strict "; +function f() { +} +exports.f = f; diff --git a/tests/baselines/reference/useStrictLikePrologueString01.symbols b/tests/baselines/reference/useStrictLikePrologueString01.symbols new file mode 100644 index 00000000000..e96d48d9933 --- /dev/null +++ b/tests/baselines/reference/useStrictLikePrologueString01.symbols @@ -0,0 +1,7 @@ +=== tests/cases/compiler/useStrictLikePrologueString01.ts === + +"hey!" +" use strict " +export function f() { +>f : Symbol(f, Decl(useStrictLikePrologueString01.ts, 2, 14)) +} diff --git a/tests/baselines/reference/useStrictLikePrologueString01.types b/tests/baselines/reference/useStrictLikePrologueString01.types new file mode 100644 index 00000000000..a12dfe3abd3 --- /dev/null +++ b/tests/baselines/reference/useStrictLikePrologueString01.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/useStrictLikePrologueString01.ts === + +"hey!" +>"hey!" : string + +" use strict " +>" use strict " : string + +export function f() { +>f : () => void +} From 1e18618170ae03c8a6c1ffecd4961db96ac682cc Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 7 Apr 2016 00:47:29 -0700 Subject: [PATCH 08/12] Ensure that the entire contents are simply 'use strict'. --- src/compiler/emitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d132e12e793..bb4d179704c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -7636,7 +7636,7 @@ const _super = (function (geti, seti) { } function isUseStrictPrologue(node: ExpressionStatement): boolean { - return !!(node.expression as StringLiteral).text.match(/use strict/); + return (node.expression as StringLiteral).text === "use strict"; } function ensureUseStrictPrologue(startWithNewLine: boolean, writeUseStrict: boolean) { From cfb9001e188370d177643ee2672bc927a4f5b120 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 7 Apr 2016 00:48:11 -0700 Subject: [PATCH 09/12] Accepted baselines. --- tests/baselines/reference/useStrictLikePrologueString01.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/baselines/reference/useStrictLikePrologueString01.js b/tests/baselines/reference/useStrictLikePrologueString01.js index 12cec220725..56df03abfe5 100644 --- a/tests/baselines/reference/useStrictLikePrologueString01.js +++ b/tests/baselines/reference/useStrictLikePrologueString01.js @@ -8,6 +8,7 @@ export function f() { //// [useStrictLikePrologueString01.js] "hey!"; " use strict "; +"use strict"; function f() { } exports.f = f; From 6076475496e612daa555f7deb3dd74835bb317cc Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 7 Apr 2016 09:56:52 -0700 Subject: [PATCH 10/12] emit missing initializers for shorthand property assignments --- src/compiler/printer.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 4193ac6ef75..f39793a80af 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -1859,6 +1859,10 @@ const _super = (function (geti, seti) { function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { emit(node.name); + if (node.objectAssignmentInitializer) { + write(" = "); + emitExpression(node.objectAssignmentInitializer); + } } // From cc0cb5851bb3a4d681b00e14c6f4c1d050a0fb47 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 7 Apr 2016 12:55:49 -0700 Subject: [PATCH 11/12] elide unused imports in ES6 emit --- src/compiler/factory.ts | 20 ++++++++++ src/compiler/transformers/module/es6.ts | 51 +++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index ec5ac638605..3c368db57fa 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -710,6 +710,26 @@ namespace ts { return createVoid(createLiteral(0)); } + export function createImportDeclaration(importClause: ImportClause, moduleSpecifier?: Expression, location?: TextRange): ImportDeclaration { + const node = createNode(SyntaxKind.ImportDeclaration, location); + node.importClause = importClause; + node.moduleSpecifier = moduleSpecifier; + return node; + } + + export function createImportClause(name: Identifier, namedBindings: NamedImportBindings, location?: TextRange): ImportClause { + const node = createNode(SyntaxKind.ImportClause, location); + node.name = name; + node.namedBindings = namedBindings; + return node; + } + + export function createNamedImports(elements: NodeArray, location?: TextRange): NamedImports { + const node = createNode(SyntaxKind.NamedImports, location); + node.elements = elements; + return node; + } + export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { if (isIdentifier(memberName)) { return createPropertyAccess(target, getSynthesizedClone(memberName), location); diff --git a/src/compiler/transformers/module/es6.ts b/src/compiler/transformers/module/es6.ts index f513ac36dbb..944e8cd6b5d 100644 --- a/src/compiler/transformers/module/es6.ts +++ b/src/compiler/transformers/module/es6.ts @@ -19,21 +19,64 @@ namespace ts { return node; } - function visitor(node: Node) { + function visitor(node: Node): VisitResult { switch (node.kind) { case SyntaxKind.ImportDeclaration: return visitImportDeclaration(node); + case SyntaxKind.ImportClause: + return visitImportClause(node); + case SyntaxKind.NamedImports: + case SyntaxKind.NamespaceImport: + return visitNamedBindings(node); + case SyntaxKind.ImportSpecifier: + return visitImportSpecifier(node); } return node; } function visitImportDeclaration(node: ImportDeclaration) { - if (node.importClause && !resolver.isReferencedAliasDeclaration(node.importClause, /*checkChildren*/ true)) { - return undefined; + if (node.importClause) { + const newImportClause = visitNode(node.importClause, visitor, isImportClause); + if (!newImportClause.name && !newImportClause.namedBindings) { + return undefined; + } + else if (newImportClause !== node.importClause) { + return createImportDeclaration(newImportClause, node.moduleSpecifier); + } } - return node; } + + function visitImportClause(node: ImportClause): ImportClause { + let newDefaultImport = node.name; + if (!resolver.isReferencedAliasDeclaration(node)) { + newDefaultImport = undefined; + } + const newNamedBindings = visitNode(node.namedBindings, visitor, isNamedImportBindings, /*optional*/ true); + return newDefaultImport !== node.name || newNamedBindings !== node.namedBindings + ? createImportClause(newDefaultImport, newNamedBindings) + : node; + } + + function visitNamedBindings(node: NamedImportBindings): VisitResult { + if (node.kind === SyntaxKind.NamespaceImport) { + return resolver.isReferencedAliasDeclaration(node) ? node: undefined; + } + else { + const newNamedImportElements = visitNodes((node).elements, visitor, isImportSpecifier); + if (!newNamedImportElements || newNamedImportElements.length == 0) { + return undefined; + } + if (newNamedImportElements === (node).elements) { + return node; + } + return createNamedImports(newNamedImportElements); + } + } + + function visitImportSpecifier(node: ImportSpecifier) { + return resolver.isReferencedAliasDeclaration(node) ? node : undefined; + } } } \ No newline at end of file From 586404ba09f33e65e35ec06747315d9c7e6c003c Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 7 Apr 2016 15:29:44 -0700 Subject: [PATCH 12/12] record temp variable introduced in spread calls --- src/compiler/factory.ts | 71 +++++++++++++------ src/compiler/transformers/destructuring.ts | 10 ++- src/compiler/transformers/es6.ts | 14 ++-- src/compiler/transformers/es7.ts | 9 +-- src/compiler/transformers/ts.ts | 9 +-- tests/baselines/reference/newWithSpread.js | 53 +++++++------- tests/baselines/reference/newWithSpreadES5.js | 50 ++++++------- 7 files changed, 117 insertions(+), 99 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 9ce03ff77a4..670f6309955 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -149,10 +149,13 @@ namespace ts { return node; } - export function createTempVariable(location?: TextRange): Identifier { + export function createTempVariable(recordTempVariable: (node: Identifier) => void, location?: TextRange): Identifier { const name = createNode(SyntaxKind.Identifier, location); name.autoGenerateKind = GeneratedIdentifierKind.Auto; getNodeId(name); + if (recordTempVariable) { + recordTempVariable(name); + } return name; } @@ -1123,7 +1126,19 @@ namespace ts { thisArg: Expression; } - export function createCallBinding(expression: Expression, languageVersion?: ScriptTarget): CallBinding { + function shouldBeCapturedInTempVariable(node: Expression): boolean { + switch (skipParentheses(node).kind) { + case SyntaxKind.Identifier: + case SyntaxKind.ThisKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: + return false; + default: + return true; + } + } + + export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget): CallBinding { const callee = skipOuterExpressions(expression, OuterExpressionKinds.All); let thisArg: Expression; let target: LeftHandSideExpression; @@ -1138,32 +1153,44 @@ namespace ts { else { switch (callee.kind) { case SyntaxKind.PropertyAccessExpression: { - // for `a.b()` target is `(_a = a).b` and thisArg is `_a` - thisArg = createTempVariable(); - target = createPropertyAccess( - createAssignment( - thisArg, - (callee).expression, - /*location*/ (callee).expression - ), - (callee).name, + if (shouldBeCapturedInTempVariable((callee).expression)) { + // for `a.b()` target is `(_a = a).b` and thisArg is `_a` + thisArg = createTempVariable(recordTempVariable); + target = createPropertyAccess( + createAssignment( + thisArg, + (callee).expression, + /*location*/(callee).expression + ), + (callee).name, /*location*/ callee - ); + ); + } + else { + thisArg = (callee).expression; + target = callee; + } break; } case SyntaxKind.ElementAccessExpression: { - // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` - thisArg = createTempVariable(); - target = createElementAccess( - createAssignment( - thisArg, - (callee).expression, - /*location*/ (callee).expression - ), - (callee).argumentExpression, + if (shouldBeCapturedInTempVariable((callee).expression)) { + // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` + thisArg = createTempVariable(recordTempVariable); + target = createElementAccess( + createAssignment( + thisArg, + (callee).expression, + /*location*/(callee).expression + ), + (callee).argumentExpression, /*location*/ callee - ); + ); + } + else { + thisArg = (callee).expression; + target = callee; + } break; } diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index 107ea016692..7cd37bade6c 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -66,8 +66,7 @@ namespace ts { } function emitTempVariableAssignment(value: Expression, location: TextRange) { - const name = createTempVariable(); - recordTempVariable(name); + const name = createTempVariable(recordTempVariable); emitAssignment(name, value, location); return name; } @@ -102,7 +101,7 @@ namespace ts { } function emitTempVariableAssignment(value: Expression, location: TextRange) { - const name = createTempVariable(); + const name = createTempVariable(/*recordTempVariable*/ undefined); emitAssignment(name, value, location); return name; } @@ -142,7 +141,7 @@ namespace ts { } function emitTempVariableAssignment(value: Expression, location: TextRange) { - const name = createTempVariable(); + const name = createTempVariable(/*recordTempVariable*/ undefined); emitAssignment(name, value, location, /*original*/ undefined); return name; } @@ -177,8 +176,7 @@ namespace ts { } function emitTempVariableAssignment(value: Expression, location: TextRange) { - const name = createTempVariable(); - recordTempVariable(name); + const name = createTempVariable(recordTempVariable); emitPendingAssignment(name, value, location, /*original*/ undefined); return name; } diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index d8bbdd4c326..d2de17b6243 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -1561,7 +1561,7 @@ namespace ts { const counter = createLoopVariable(); const rhsReference = expression.kind === SyntaxKind.Identifier ? createUniqueName((expression).text) - : createTempVariable(); + : createTempVariable(/*recordTempVariable*/ undefined); // Initialize LHS // var v = _a[_i]; @@ -1596,7 +1596,7 @@ namespace ts { /*modifiers*/ undefined, createVariableDeclarationList([ createVariableDeclaration( - firstDeclaration ? firstDeclaration.name : createTempVariable(), + firstDeclaration ? firstDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined), createElementAccess(rhsReference, counter) ) ]), @@ -1686,8 +1686,7 @@ namespace ts { // For computed properties, we need to create a unique handle to the object // literal so we can modify it without risking internal assignments tainting the object. - const temp = createTempVariable(); - hoistVariableDeclaration(temp); + const temp = createTempVariable(hoistVariableDeclaration); // Write out the first non-computed properties, then emit the rest through indexing on the temp variable. const expressions: Expression[] = []; @@ -2232,7 +2231,7 @@ namespace ts { // We are here either because SuperKeyword was used somewhere in the expression, or // because we contain a SpreadElementExpression. - const { target, thisArg } = createCallBinding(node.expression); + const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration); if (node.transformFlags & TransformFlags.ContainsSpreadElementExpression) { // [source] // f(...a, b) @@ -2289,7 +2288,7 @@ namespace ts { // [output] // new ((_a = C).bind.apply(_a, [void 0].concat(a)))() - const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind")); + const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration); return createNew( createFunctionApply( visitNode(target, visitor, isExpression), @@ -2380,8 +2379,7 @@ namespace ts { const tag = visitNode(node.tag, visitor, isExpression); // Allocate storage for the template site object - const temp = createTempVariable(); - hoistVariableDeclaration(temp); + const temp = createTempVariable(hoistVariableDeclaration); // Build up the template arguments and the raw and cooked strings for the template. const templateArguments: Expression[] = [temp]; diff --git a/src/compiler/transformers/es7.ts b/src/compiler/transformers/es7.ts index d04ca55db4b..5d848bc608b 100644 --- a/src/compiler/transformers/es7.ts +++ b/src/compiler/transformers/es7.ts @@ -44,11 +44,9 @@ namespace ts { let value: Expression; if (isElementAccessExpression(left)) { // Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)` - const expressionTemp = createTempVariable(); - hoistVariableDeclaration(expressionTemp); + const expressionTemp = createTempVariable(hoistVariableDeclaration); - const argumentExpressionTemp = createTempVariable(); - hoistVariableDeclaration(argumentExpressionTemp); + const argumentExpressionTemp = createTempVariable(hoistVariableDeclaration); target = createElementAccess( createAssignment(expressionTemp, left.expression, /*location*/ left.expression), @@ -64,8 +62,7 @@ namespace ts { } else if (isPropertyAccessExpression(left)) { // Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)` - const expressionTemp = createTempVariable(); - hoistVariableDeclaration(expressionTemp); + const expressionTemp = createTempVariable(hoistVariableDeclaration); target = createPropertyAccess( createAssignment(expressionTemp, left.expression, /*location*/ left.expression), diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index a55c344ea62..a2fc0b56763 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -674,8 +674,7 @@ namespace ts { if (staticProperties.length > 0) { const expressions: Expression[] = []; - const temp = createTempVariable(); - hoistVariableDeclaration(temp); + const temp = createTempVariable(hoistVariableDeclaration); // To preserve the behavior of the old emitter, we explicitly indent // the body of a class with static initializers. @@ -1614,8 +1613,7 @@ namespace ts { switch (resolver.getTypeReferenceSerializationKind(typeName)) { case TypeReferenceSerializationKind.Unknown: const serialized = serializeEntityNameAsExpression(typeName, /*useFallback*/ true); - const temp = createTempVariable(); - hoistVariableDeclaration(temp); + const temp = createTempVariable(hoistVariableDeclaration); return createLogicalOr( createLogicalAnd( createStrictEquality( @@ -1701,8 +1699,7 @@ namespace ts { left = serializeEntityNameAsExpression(node.left, useFallback); } else if (useFallback) { - const temp = createTempVariable(); - hoistVariableDeclaration(temp); + const temp = createTempVariable(hoistVariableDeclaration); left = createLogicalAnd( createAssignment( temp, diff --git a/tests/baselines/reference/newWithSpread.js b/tests/baselines/reference/newWithSpread.js index 275b8698d20..91c502e50b9 100644 --- a/tests/baselines/reference/newWithSpread.js +++ b/tests/baselines/reference/newWithSpread.js @@ -129,52 +129,53 @@ var h; var i; // Basic expression new f(1, 2, "string"); -new ((_a = f).bind.apply(_a, [void 0, 1, 2].concat(a)))(); -new ((_b = f).bind.apply(_b, [void 0, 1, 2].concat(a, ["string"])))(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a)))(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a, ["string"])))(); // Multiple spreads arguments -new ((_c = f2).bind.apply(_c, [void 0].concat(a, a)))(); -new ((_d = f).bind.apply(_d, [void 0, 1, 2].concat(a, a)))(); +new (f2.bind.apply(f2, [void 0].concat(a, a)))(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a, a)))(); // Call expression new f(1, 2, "string")(); -new ((_e = f).bind.apply(_e, [void 0, 1, 2].concat(a)))()(); -new ((_f = f).bind.apply(_f, [void 0, 1, 2].concat(a, ["string"])))()(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a)))()(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a, ["string"])))()(); // Property access expression new b.f(1, 2, "string"); -new ((_g = b.f).bind.apply(_g, [void 0, 1, 2].concat(a)))(); -new ((_h = b.f).bind.apply(_h, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_a = b.f).bind.apply(_a, [void 0, 1, 2].concat(a)))(); +new ((_b = b.f).bind.apply(_b, [void 0, 1, 2].concat(a, ["string"])))(); // Parenthesised expression new (b.f)(1, 2, "string"); -new ((_j = (b.f)).bind.apply(_j, [void 0, 1, 2].concat(a)))(); -new ((_k = (b.f)).bind.apply(_k, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_c = (b.f)).bind.apply(_c, [void 0, 1, 2].concat(a)))(); +new ((_d = (b.f)).bind.apply(_d, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression new d[1].f(1, 2, "string"); -new ((_l = d[1].f).bind.apply(_l, [void 0, 1, 2].concat(a)))(); -new ((_m = d[1].f).bind.apply(_m, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_e = d[1].f).bind.apply(_e, [void 0, 1, 2].concat(a)))(); +new ((_f = d[1].f).bind.apply(_f, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression with a punctuated key new e["a-b"].f(1, 2, "string"); -new ((_o = e["a-b"].f).bind.apply(_o, [void 0, 1, 2].concat(a)))(); -new ((_p = e["a-b"].f).bind.apply(_p, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_g = e["a-b"].f).bind.apply(_g, [void 0, 1, 2].concat(a)))(); +new ((_h = e["a-b"].f).bind.apply(_h, [void 0, 1, 2].concat(a, ["string"])))(); // Basic expression new B(1, 2, "string"); -new ((_q = B).bind.apply(_q, [void 0, 1, 2].concat(a)))(); -new ((_r = B).bind.apply(_r, [void 0, 1, 2].concat(a, ["string"])))(); +new (B.bind.apply(B, [void 0, 1, 2].concat(a)))(); +new (B.bind.apply(B, [void 0, 1, 2].concat(a, ["string"])))(); // Property access expression new c["a-b"](1, 2, "string"); -new ((_s = c["a-b"]).bind.apply(_s, [void 0, 1, 2].concat(a)))(); -new ((_t = c["a-b"]).bind.apply(_t, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_j = c["a-b"]).bind.apply(_j, [void 0, 1, 2].concat(a)))(); +new ((_k = c["a-b"]).bind.apply(_k, [void 0, 1, 2].concat(a, ["string"])))(); // Parenthesised expression new (c["a-b"])(1, 2, "string"); -new ((_u = (c["a-b"])).bind.apply(_u, [void 0, 1, 2].concat(a)))(); -new ((_v = (c["a-b"])).bind.apply(_v, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_l = (c["a-b"])).bind.apply(_l, [void 0, 1, 2].concat(a)))(); +new ((_m = (c["a-b"])).bind.apply(_m, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression new g[1]["a-b"](1, 2, "string"); -new ((_w = g[1]["a-b"]).bind.apply(_w, [void 0, 1, 2].concat(a)))(); -new ((_x = g[1]["a-b"]).bind.apply(_x, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_o = g[1]["a-b"]).bind.apply(_o, [void 0, 1, 2].concat(a)))(); +new ((_p = g[1]["a-b"]).bind.apply(_p, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression with a punctuated key new h["a-b"]["a-b"](1, 2, "string"); -new ((_y = h["a-b"]["a-b"]).bind.apply(_y, [void 0, 1, 2].concat(a)))(); -new ((_z = h["a-b"]["a-b"]).bind.apply(_z, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_q = h["a-b"]["a-b"]).bind.apply(_q, [void 0, 1, 2].concat(a)))(); +new ((_r = h["a-b"]["a-b"]).bind.apply(_r, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression with a number new i["a-b"][1](1, 2, "string"); -new ((_0 = i["a-b"][1]).bind.apply(_0, [void 0, 1, 2].concat(a)))(); -new ((_1 = i["a-b"][1]).bind.apply(_1, [void 0, 1, 2].concat(a, ["string"])))(); +new ((_s = i["a-b"][1]).bind.apply(_s, [void 0, 1, 2].concat(a)))(); +new ((_t = i["a-b"][1]).bind.apply(_t, [void 0, 1, 2].concat(a, ["string"])))(); +var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; diff --git a/tests/baselines/reference/newWithSpreadES5.js b/tests/baselines/reference/newWithSpreadES5.js index fffa53d7c90..92904062d0a 100644 --- a/tests/baselines/reference/newWithSpreadES5.js +++ b/tests/baselines/reference/newWithSpreadES5.js @@ -128,53 +128,53 @@ var h; var i; // Basic expression new f(1, 2, "string"); -new (f.bind.apply(f, [void 0].concat([1, 2], a)))(); -new (f.bind.apply(f, [void 0].concat([1, 2], a, ["string"])))(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a)))(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a, ["string"])))(); // Multiple spreads arguments new (f2.bind.apply(f2, [void 0].concat(a, a)))(); -new (f.bind.apply(f, [void 0].concat([1, 2], a, a)))(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a, a)))(); // Call expression new f(1, 2, "string")(); -new (f.bind.apply(f, [void 0].concat([1, 2], a)))()(); -new (f.bind.apply(f, [void 0].concat([1, 2], a, ["string"])))()(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a)))()(); +new (f.bind.apply(f, [void 0, 1, 2].concat(a, ["string"])))()(); // Property access expression new b.f(1, 2, "string"); -new ((_a = b.f).bind.apply(_a, [void 0].concat([1, 2], a)))(); -new ((_b = b.f).bind.apply(_b, [void 0].concat([1, 2], a, ["string"])))(); +new ((_a = b.f).bind.apply(_a, [void 0, 1, 2].concat(a)))(); +new ((_b = b.f).bind.apply(_b, [void 0, 1, 2].concat(a, ["string"])))(); // Parenthesised expression new (b.f)(1, 2, "string"); -new ((_c = (b.f)).bind.apply(_c, [void 0].concat([1, 2], a)))(); -new ((_d = (b.f)).bind.apply(_d, [void 0].concat([1, 2], a, ["string"])))(); +new ((_c = (b.f)).bind.apply(_c, [void 0, 1, 2].concat(a)))(); +new ((_d = (b.f)).bind.apply(_d, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression new d[1].f(1, 2, "string"); -new ((_e = d[1].f).bind.apply(_e, [void 0].concat([1, 2], a)))(); -new ((_f = d[1].f).bind.apply(_f, [void 0].concat([1, 2], a, ["string"])))(); +new ((_e = d[1].f).bind.apply(_e, [void 0, 1, 2].concat(a)))(); +new ((_f = d[1].f).bind.apply(_f, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression with a punctuated key new e["a-b"].f(1, 2, "string"); -new ((_g = e["a-b"].f).bind.apply(_g, [void 0].concat([1, 2], a)))(); -new ((_h = e["a-b"].f).bind.apply(_h, [void 0].concat([1, 2], a, ["string"])))(); +new ((_g = e["a-b"].f).bind.apply(_g, [void 0, 1, 2].concat(a)))(); +new ((_h = e["a-b"].f).bind.apply(_h, [void 0, 1, 2].concat(a, ["string"])))(); // Basic expression new B(1, 2, "string"); -new (B.bind.apply(B, [void 0].concat([1, 2], a)))(); -new (B.bind.apply(B, [void 0].concat([1, 2], a, ["string"])))(); +new (B.bind.apply(B, [void 0, 1, 2].concat(a)))(); +new (B.bind.apply(B, [void 0, 1, 2].concat(a, ["string"])))(); // Property access expression new c["a-b"](1, 2, "string"); -new ((_j = c["a-b"]).bind.apply(_j, [void 0].concat([1, 2], a)))(); -new ((_k = c["a-b"]).bind.apply(_k, [void 0].concat([1, 2], a, ["string"])))(); +new ((_j = c["a-b"]).bind.apply(_j, [void 0, 1, 2].concat(a)))(); +new ((_k = c["a-b"]).bind.apply(_k, [void 0, 1, 2].concat(a, ["string"])))(); // Parenthesised expression new (c["a-b"])(1, 2, "string"); -new ((_l = (c["a-b"])).bind.apply(_l, [void 0].concat([1, 2], a)))(); -new ((_m = (c["a-b"])).bind.apply(_m, [void 0].concat([1, 2], a, ["string"])))(); +new ((_l = (c["a-b"])).bind.apply(_l, [void 0, 1, 2].concat(a)))(); +new ((_m = (c["a-b"])).bind.apply(_m, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression new g[1]["a-b"](1, 2, "string"); -new ((_o = g[1]["a-b"]).bind.apply(_o, [void 0].concat([1, 2], a)))(); -new ((_p = g[1]["a-b"]).bind.apply(_p, [void 0].concat([1, 2], a, ["string"])))(); +new ((_o = g[1]["a-b"]).bind.apply(_o, [void 0, 1, 2].concat(a)))(); +new ((_p = g[1]["a-b"]).bind.apply(_p, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression with a punctuated key new h["a-b"]["a-b"](1, 2, "string"); -new ((_q = h["a-b"]["a-b"]).bind.apply(_q, [void 0].concat([1, 2], a)))(); -new ((_r = h["a-b"]["a-b"]).bind.apply(_r, [void 0].concat([1, 2], a, ["string"])))(); +new ((_q = h["a-b"]["a-b"]).bind.apply(_q, [void 0, 1, 2].concat(a)))(); +new ((_r = h["a-b"]["a-b"]).bind.apply(_r, [void 0, 1, 2].concat(a, ["string"])))(); // Element access expression with a number new i["a-b"][1](1, 2, "string"); -new ((_s = i["a-b"][1]).bind.apply(_s, [void 0].concat([1, 2], a)))(); -new ((_t = i["a-b"][1]).bind.apply(_t, [void 0].concat([1, 2], a, ["string"])))(); +new ((_s = i["a-b"][1]).bind.apply(_s, [void 0, 1, 2].concat(a)))(); +new ((_t = i["a-b"][1]).bind.apply(_t, [void 0, 1, 2].concat(a, ["string"])))(); var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;