Skip to content

[Fix 13709] - Emit __esmodule #13871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Feb 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
23 changes: 22 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="moduleNameResolver.ts"/>
/// <reference path="moduleNameResolver.ts"/>
/// <reference path="binder.ts"/>

/* @internal */
Expand Down Expand Up @@ -22010,6 +22010,11 @@ namespace ts {
}
}

if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.System && !compilerOptions.noEmit &&
!isInAmbientContext(node.parent.parent) && hasModifier(node.parent.parent, ModifierFlags.Export)) {
checkESModuleMarker(node.name);
}

const checkLetConstNames = (isLet(node) || isConst(node));

// 1. LexicalDeclaration : LetOrConst BindingList ;
Expand All @@ -22022,6 +22027,22 @@ namespace ts {
return checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name);
}

function checkESModuleMarker(name: Identifier | BindingPattern): boolean {
if (name.kind === SyntaxKind.Identifier) {
if (unescapeIdentifier(name.text) === "__esModule") {
return grammarErrorOnNode(name, Diagnostics.Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules);
}
}
else {
const elements = (<BindingPattern>name).elements;
for (const element of elements) {
if (!isOmittedExpression(element)) {
return checkESModuleMarker(element.name);
}
}
}
}

function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean {
if (name.kind === SyntaxKind.Identifier) {
if ((<Identifier>name).originalKeywordKind === SyntaxKind.LetKeyword) {
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,10 @@
"category": "Error",
"code": 1215
},
"Identifier expected. '__esModule' is reserved as an exported marker when transforming ECMAScript modules.": {
"category": "Error",
"code": 1216
},
"Export assignment is not supported when '--module' flag is 'system'.": {
"category": "Error",
"code": 1218
Expand Down
74 changes: 40 additions & 34 deletions src/compiler/transformers/module/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ namespace ts {

const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);

if (!currentModuleInfo.exportEquals) {
append(statements, createUnderscoreUnderscoreESModule());
}

append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
addRange(statements, endLexicalEnvironment());
Expand All @@ -92,7 +97,6 @@ namespace ts {
if (currentModuleInfo.hasExportStarsToExportValues) {
addEmitHelper(updated, exportStarHelper);
}

return updated;
}

Expand Down Expand Up @@ -371,6 +375,10 @@ namespace ts {
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);

if (!currentModuleInfo.exportEquals) {
append(statements, createUnderscoreUnderscoreESModule());
}

// Visit each statement of the module body.
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
Expand Down Expand Up @@ -665,6 +673,7 @@ namespace ts {
}

const generatedName = getGeneratedNameForNode(node);

if (node.exportClause) {
const statements: Statement[] = [];
// export { x, y } from "mod";
Expand Down Expand Up @@ -838,6 +847,7 @@ namespace ts {
let statements: Statement[];
let variables: VariableDeclaration[];
let expressions: Expression[];

if (hasModifier(node, ModifierFlags.Export)) {
let modifiers: NodeArray<Modifier>;

Expand Down Expand Up @@ -1127,43 +1137,39 @@ namespace ts {
* @param allowComments Whether to allow comments on the export.
*/
function appendExportStatement(statements: Statement[] | undefined, exportName: Identifier, expression: Expression, location?: TextRange, allowComments?: boolean): Statement[] | undefined {
if (exportName.text === "default") {
const sourceFile = getOriginalNode(currentSourceFile, isSourceFile);
if (sourceFile && !sourceFile.symbol.exports.get("___esModule")) {
if (languageVersion === ScriptTarget.ES3) {
statements = append(statements,
createStatement(
createExportExpression(
createIdentifier("__esModule"),
createTrue()
)
)
);
}
else {
statements = append(statements,
createStatement(
createCall(
createPropertyAccess(createIdentifier("Object"), "defineProperty"),
/*typeArguments*/ undefined,
[
createIdentifier("exports"),
createLiteral("__esModule"),
createObjectLiteral([
createPropertyAssignment("value", createTrue())
])
]
)
)
);
}
}
}

statements = append(statements, createExportStatement(exportName, expression, location, allowComments));
return statements;
}

function createUnderscoreUnderscoreESModule() {
let statement: Statement;
if (languageVersion === ScriptTarget.ES3) {
statement = createStatement(
createExportExpression(
createIdentifier("__esModule"),
createLiteral(true)
)
)
}
else {
statement = createStatement(
createCall(
createPropertyAccess(createIdentifier("Object"), "defineProperty"),
/*typeArguments*/ undefined,
[
createIdentifier("exports"),
createLiteral("__esModule"),
createObjectLiteral([
createPropertyAssignment("value", createLiteral(true))
])
]
)
);
}
setEmitFlags(statement, EmitFlags.CustomPrologue);
return statement;
}

/**
* Creates a call to the current file's export function to export a value.
*
Expand Down
2 changes: 1 addition & 1 deletion src/harness/unittests/compileOnSave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ namespace ts.projectSystem {

const expectedEmittedFileName = "/a/b/f1.js";
assert.isTrue(host.fileExists(expectedEmittedFileName));
assert.equal(host.readFile(expectedEmittedFileName), `"use strict";\r\nfunction Foo() { return 10; }\r\nexports.Foo = Foo;\r\n`);
assert.equal(host.readFile(expectedEmittedFileName), `"use strict";\r\nexports.__esModule = true;\r\nfunction Foo() { return 10; }\r\nexports.Foo = Foo;\r\n`);
});

it("shoud not emit js files in external projects", () => {
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/APISample_compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ compile(process.argv.slice(2), {
* Please log a "breaking change" issue for any API breaking change affecting this issue
*/
"use strict";
exports.__esModule = true;
var ts = require("typescript");
function compile(fileNames, options) {
var program = ts.createProgram(fileNames, options);
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/APISample_linter.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ fileNames.forEach(fileName => {
* Please log a "breaking change" issue for any API breaking change affecting this issue
*/
"use strict";
exports.__esModule = true;
var ts = require("typescript");
function delint(sourceFile) {
delintNode(sourceFile);
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/APISample_parseConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function createProgram(rootFiles: string[], compilerOptionsJson: string):
* Please log a "breaking change" issue for any API breaking change affecting this issue
*/
"use strict";
exports.__esModule = true;
var ts = require("typescript");
function printError(error) {
if (!error) {
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/APISample_transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ console.log(JSON.stringify(result));
* Please log a "breaking change" issue for any API breaking change affecting this issue
*/
"use strict";
exports.__esModule = true;
var ts = require("typescript");
var source = "let x: string = 'string'";
var result = ts.transpile(source, { module: ts.ModuleKind.CommonJS });
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/APISample_watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS });
* Please log a "breaking change" issue for any API breaking change affecting this issue
*/
"use strict";
exports.__esModule = true;
var ts = require("typescript");
function watch(rootFileNames, options) {
var files = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export module A {

//// [part1.js]
"use strict";
exports.__esModule = true;
var A;
(function (A) {
var Utils;
Expand All @@ -44,6 +45,7 @@ var A;
})(A = exports.A || (exports.A = {}));
//// [part2.js]
"use strict";
exports.__esModule = true;
var A;
(function (A) {
// collision with 'Origin' var in other part of merged module
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/aliasAssignments.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ y = moduleA; // should be error

//// [aliasAssignments_moduleA.js]
"use strict";
exports.__esModule = true;
var someClass = (function () {
function someClass() {
}
Expand All @@ -23,6 +24,7 @@ var someClass = (function () {
exports.someClass = someClass;
//// [aliasAssignments_1.js]
"use strict";
exports.__esModule = true;
var moduleA = require("./aliasAssignments_moduleA");
var x = moduleA;
x = 1; // Should be error
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/aliasOnMergedModuleInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var x: foo.A = foo.bar("hello"); // foo.A should be ok but foo.bar should be err
//// [aliasOnMergedModuleInterface_0.js]
//// [aliasOnMergedModuleInterface_1.js]
"use strict";
exports.__esModule = true;
var z;
z.bar("hello"); // This should be ok
var x = foo.bar("hello"); // foo.A should be ok but foo.bar should be error
3 changes: 3 additions & 0 deletions tests/baselines/reference/aliasUsageInAccessorsOfClass.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class C2 {

//// [aliasUsage1_backbone.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Model = (function () {
function Model() {
}
Expand All @@ -47,6 +48,7 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var Backbone = require("./aliasUsage1_backbone");
var VisualizationModel = (function (_super) {
__extends(VisualizationModel, _super);
Expand All @@ -58,6 +60,7 @@ var VisualizationModel = (function (_super) {
exports.VisualizationModel = VisualizationModel;
//// [aliasUsage1_main.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var moduleA = require("./aliasUsage1_moduleA");
var C2 = (function () {
function C2() {
Expand Down
3 changes: 3 additions & 0 deletions tests/baselines/reference/aliasUsageInArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var xs2: typeof moduleA[] = [moduleA];

//// [aliasUsageInArray_backbone.js]
"use strict";
exports.__esModule = true;
var Model = (function () {
function Model() {
}
Expand All @@ -41,6 +42,7 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var Backbone = require("./aliasUsageInArray_backbone");
var VisualizationModel = (function (_super) {
__extends(VisualizationModel, _super);
Expand All @@ -52,6 +54,7 @@ var VisualizationModel = (function (_super) {
exports.VisualizationModel = VisualizationModel;
//// [aliasUsageInArray_main.js]
"use strict";
exports.__esModule = true;
var moduleA = require("./aliasUsageInArray_moduleA");
var xs = [moduleA];
var xs2 = [moduleA];
3 changes: 3 additions & 0 deletions tests/baselines/reference/aliasUsageInFunctionExpression.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ f = (x) => moduleA;

//// [aliasUsageInFunctionExpression_backbone.js]
"use strict";
exports.__esModule = true;
var Model = (function () {
function Model() {
}
Expand All @@ -40,6 +41,7 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var Backbone = require("./aliasUsageInFunctionExpression_backbone");
var VisualizationModel = (function (_super) {
__extends(VisualizationModel, _super);
Expand All @@ -51,6 +53,7 @@ var VisualizationModel = (function (_super) {
exports.VisualizationModel = VisualizationModel;
//// [aliasUsageInFunctionExpression_main.js]
"use strict";
exports.__esModule = true;
var moduleA = require("./aliasUsageInFunctionExpression_moduleA");
var f = function (x) { return x; };
f = function (x) { return moduleA; };
3 changes: 3 additions & 0 deletions tests/baselines/reference/aliasUsageInGenericFunction.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var r2 = foo({ a: <IHasVisualizationModel>null });

//// [aliasUsageInGenericFunction_backbone.js]
"use strict";
exports.__esModule = true;
var Model = (function () {
function Model() {
}
Expand All @@ -44,6 +45,7 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var Backbone = require("./aliasUsageInGenericFunction_backbone");
var VisualizationModel = (function (_super) {
__extends(VisualizationModel, _super);
Expand All @@ -55,6 +57,7 @@ var VisualizationModel = (function (_super) {
exports.VisualizationModel = VisualizationModel;
//// [aliasUsageInGenericFunction_main.js]
"use strict";
exports.__esModule = true;
var moduleA = require("./aliasUsageInGenericFunction_moduleA");
function foo(x) {
return x;
Expand Down
3 changes: 3 additions & 0 deletions tests/baselines/reference/aliasUsageInIndexerOfClass.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class N2 {

//// [aliasUsageInIndexerOfClass_backbone.js]
"use strict";
exports.__esModule = true;
var Model = (function () {
function Model() {
}
Expand All @@ -46,6 +47,7 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var Backbone = require("./aliasUsageInIndexerOfClass_backbone");
var VisualizationModel = (function (_super) {
__extends(VisualizationModel, _super);
Expand All @@ -57,6 +59,7 @@ var VisualizationModel = (function (_super) {
exports.VisualizationModel = VisualizationModel;
//// [aliasUsageInIndexerOfClass_main.js]
"use strict";
exports.__esModule = true;
var moduleA = require("./aliasUsageInIndexerOfClass_moduleA");
var N = (function () {
function N() {
Expand Down
Loading