diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 65768332360..c12a9afad62 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -185,8 +185,9 @@ namespace ts { function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol { Debug.assert(!hasDynamicName(node)); + let isDefaultExport = node.flags & NodeFlags.Default; // The exported symbol for an export default function/class node is always named "default" - let name = node.flags & NodeFlags.Default && parent ? "default" : getDeclarationName(node); + let name = isDefaultExport && parent ? "default" : getDeclarationName(node); let symbol: Symbol; if (name !== undefined) { @@ -227,6 +228,13 @@ namespace ts { let message = symbol.flags & SymbolFlags.BlockScopedVariable ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0; + + forEach(symbol.declarations, declaration => { + if (declaration.flags & NodeFlags.Default) { + message = Diagnostics.A_module_cannot_have_multiple_default_exports; + } + }); + forEach(symbol.declarations, declaration => { file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration))); }); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f6656edb250..22b65b58111 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1656,6 +1656,10 @@ "category": "Error", "code": 2527 }, + "A module cannot have multiple default exports.": { + "category": "Error", + "code": 2528 + }, "JSX element attributes type '{0}' must be an object type.": { "category": "Error", "code": 2600 diff --git a/tests/baselines/reference/defaultExportWithOverloads01.js b/tests/baselines/reference/defaultExportWithOverloads01.js new file mode 100644 index 00000000000..9ec8cccf5bf --- /dev/null +++ b/tests/baselines/reference/defaultExportWithOverloads01.js @@ -0,0 +1,16 @@ +//// [defaultExportWithOverloads01.ts] + +export default function f(); +export default function f(x: string); +export default function f(...args: any[]) { +} + +//// [defaultExportWithOverloads01.js] +function f() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i - 0] = arguments[_i]; + } +} +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = f; diff --git a/tests/baselines/reference/defaultExportWithOverloads01.symbols b/tests/baselines/reference/defaultExportWithOverloads01.symbols new file mode 100644 index 00000000000..a5ff0df5262 --- /dev/null +++ b/tests/baselines/reference/defaultExportWithOverloads01.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/es6/modules/defaultExportWithOverloads01.ts === + +export default function f(); +>f : Symbol(f, Decl(defaultExportWithOverloads01.ts, 0, 0), Decl(defaultExportWithOverloads01.ts, 1, 28), Decl(defaultExportWithOverloads01.ts, 2, 37)) + +export default function f(x: string); +>f : Symbol(f, Decl(defaultExportWithOverloads01.ts, 0, 0), Decl(defaultExportWithOverloads01.ts, 1, 28), Decl(defaultExportWithOverloads01.ts, 2, 37)) +>x : Symbol(x, Decl(defaultExportWithOverloads01.ts, 2, 26)) + +export default function f(...args: any[]) { +>f : Symbol(f, Decl(defaultExportWithOverloads01.ts, 0, 0), Decl(defaultExportWithOverloads01.ts, 1, 28), Decl(defaultExportWithOverloads01.ts, 2, 37)) +>args : Symbol(args, Decl(defaultExportWithOverloads01.ts, 3, 26)) +} diff --git a/tests/baselines/reference/defaultExportWithOverloads01.types b/tests/baselines/reference/defaultExportWithOverloads01.types new file mode 100644 index 00000000000..c006083b4ba --- /dev/null +++ b/tests/baselines/reference/defaultExportWithOverloads01.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/es6/modules/defaultExportWithOverloads01.ts === + +export default function f(); +>f : { (): any; (x: string): any; } + +export default function f(x: string); +>f : { (): any; (x: string): any; } +>x : string + +export default function f(...args: any[]) { +>f : { (): any; (x: string): any; } +>args : any[] +} diff --git a/tests/baselines/reference/multipleDefaultExports01.errors.txt b/tests/baselines/reference/multipleDefaultExports01.errors.txt index 72898d474e8..16aa3b2f7b1 100644 --- a/tests/baselines/reference/multipleDefaultExports01.errors.txt +++ b/tests/baselines/reference/multipleDefaultExports01.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/es6/modules/m1.ts(2,22): error TS2300: Duplicate identifier 'foo'. -tests/cases/conformance/es6/modules/m1.ts(6,25): error TS2300: Duplicate identifier 'bar'. -tests/cases/conformance/es6/modules/m1.ts(11,1): error TS2300: Duplicate identifier 'default'. +tests/cases/conformance/es6/modules/m1.ts(2,22): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/es6/modules/m1.ts(6,25): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/es6/modules/m1.ts(11,1): error TS2528: A module cannot have multiple default exports. tests/cases/conformance/es6/modules/m2.ts(3,1): error TS2348: Value of type 'typeof foo' is not callable. Did you mean to include 'new'? @@ -8,20 +8,20 @@ tests/cases/conformance/es6/modules/m2.ts(3,1): error TS2348: Value of type 'typ export default class foo { ~~~ -!!! error TS2300: Duplicate identifier 'foo'. +!!! error TS2528: A module cannot have multiple default exports. } export default function bar() { ~~~ -!!! error TS2300: Duplicate identifier 'bar'. +!!! error TS2528: A module cannot have multiple default exports. } var x = 10; export default x; ~~~~~~~~~~~~~~~~~ -!!! error TS2300: Duplicate identifier 'default'. +!!! error TS2528: A module cannot have multiple default exports. ==== tests/cases/conformance/es6/modules/m2.ts (1 errors) ==== import Entity from "./m1" diff --git a/tests/baselines/reference/multipleDefaultExports03.errors.txt b/tests/baselines/reference/multipleDefaultExports03.errors.txt new file mode 100644 index 00000000000..5c4b075b009 --- /dev/null +++ b/tests/baselines/reference/multipleDefaultExports03.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/es6/modules/multipleDefaultExports03.ts(2,22): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/es6/modules/multipleDefaultExports03.ts(5,22): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/conformance/es6/modules/multipleDefaultExports03.ts (2 errors) ==== + + export default class C { + ~ +!!! error TS2528: A module cannot have multiple default exports. + } + + export default class C { + ~ +!!! error TS2528: A module cannot have multiple default exports. + } \ No newline at end of file diff --git a/tests/baselines/reference/multipleDefaultExports03.js b/tests/baselines/reference/multipleDefaultExports03.js new file mode 100644 index 00000000000..2824c7a5ac1 --- /dev/null +++ b/tests/baselines/reference/multipleDefaultExports03.js @@ -0,0 +1,23 @@ +//// [multipleDefaultExports03.ts] + +export default class C { +} + +export default class C { +} + +//// [multipleDefaultExports03.js] +var C = (function () { + function C() { + } + return C; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = C; +var C = (function () { + function C() { + } + return C; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = C; diff --git a/tests/baselines/reference/multipleDefaultExports04.errors.txt b/tests/baselines/reference/multipleDefaultExports04.errors.txt new file mode 100644 index 00000000000..e67659f6b9f --- /dev/null +++ b/tests/baselines/reference/multipleDefaultExports04.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/es6/modules/multipleDefaultExports04.ts(2,25): error TS2393: Duplicate function implementation. +tests/cases/conformance/es6/modules/multipleDefaultExports04.ts(5,25): error TS2393: Duplicate function implementation. + + +==== tests/cases/conformance/es6/modules/multipleDefaultExports04.ts (2 errors) ==== + + export default function f() { + ~ +!!! error TS2393: Duplicate function implementation. + } + + export default function f() { + ~ +!!! error TS2393: Duplicate function implementation. + } \ No newline at end of file diff --git a/tests/baselines/reference/multipleDefaultExports04.js b/tests/baselines/reference/multipleDefaultExports04.js new file mode 100644 index 00000000000..73582d7389e --- /dev/null +++ b/tests/baselines/reference/multipleDefaultExports04.js @@ -0,0 +1,17 @@ +//// [multipleDefaultExports04.ts] + +export default function f() { +} + +export default function f() { +} + +//// [multipleDefaultExports04.js] +function f() { +} +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = f; +function f() { +} +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = f; diff --git a/tests/cases/conformance/es6/modules/defaultExportWithOverloads01.ts b/tests/cases/conformance/es6/modules/defaultExportWithOverloads01.ts new file mode 100644 index 00000000000..a6761600a1d --- /dev/null +++ b/tests/cases/conformance/es6/modules/defaultExportWithOverloads01.ts @@ -0,0 +1,7 @@ +// @module: commonjs +// @target: ES5 + +export default function f(); +export default function f(x: string); +export default function f(...args: any[]) { +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/modules/multipleDefaultExports03.ts b/tests/cases/conformance/es6/modules/multipleDefaultExports03.ts new file mode 100644 index 00000000000..f2fe7f1a6c3 --- /dev/null +++ b/tests/cases/conformance/es6/modules/multipleDefaultExports03.ts @@ -0,0 +1,8 @@ +// @module: commonjs +// @target: ES5 + +export default class C { +} + +export default class C { +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/modules/multipleDefaultExports04.ts b/tests/cases/conformance/es6/modules/multipleDefaultExports04.ts new file mode 100644 index 00000000000..1dec7b8bea5 --- /dev/null +++ b/tests/cases/conformance/es6/modules/multipleDefaultExports04.ts @@ -0,0 +1,8 @@ +// @module: commonjs +// @target: ES5 + +export default function f() { +} + +export default function f() { +} \ No newline at end of file