From 42d61b5098ac5847b5e09117cf92092c6dc9f284 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 8 Aug 2016 11:55:59 -0700 Subject: [PATCH 1/9] Call checkExpression eventhough there is no appropriate type from destructuring of array --- src/compiler/checker.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4ead19f7c48..74a1e17bd6b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4447,9 +4447,14 @@ namespace ts { return property; } - // Return the symbol for the property with the given name in the given type. Creates synthetic union properties when - // necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from - // Object and Function as appropriate. + /** + * Return the symbol for the property with the given name in the given type. Creates synthetic union properties when + * necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from + * Object and Function as appropriate. + * + * @param type a type to look up property from + * @param name a name of property to look up in a given type + */ function getPropertyOfType(type: Type, name: string): Symbol { type = getApparentType(type); if (type.flags & TypeFlags.ObjectType) { @@ -12856,6 +12861,9 @@ namespace ts { return checkDestructuringAssignment(element, type, contextualMapper); } else { + // We still need to check element expression here because we may need to set appropriate flag on the expression + // such as NodeCheckFlags.LexicalThis on "this"expression. + checkExpression(element); if (isTupleType(sourceType)) { error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), (sourceType).elementTypes.length, elements.length); } From 9a18429184a42f6a34a963908acdc141245d1ade Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 8 Aug 2016 11:56:20 -0700 Subject: [PATCH 2/9] Add tests and baselines --- ...turingThisInTupleDestructuring1.errors.txt | 13 +++++++++++ .../emitCapturingThisInTupleDestructuring1.js | 11 +++++++++ ...turingThisInTupleDestructuring2.errors.txt | 16 +++++++++++++ .../emitCapturingThisInTupleDestructuring2.js | 23 +++++++++++++++++++ .../emitCapturingThisInTupleDestructuring1.ts | 4 ++++ .../emitCapturingThisInTupleDestructuring2.ts | 10 ++++++++ 6 files changed, 77 insertions(+) create mode 100644 tests/baselines/reference/emitCapturingThisInTupleDestructuring1.errors.txt create mode 100644 tests/baselines/reference/emitCapturingThisInTupleDestructuring1.js create mode 100644 tests/baselines/reference/emitCapturingThisInTupleDestructuring2.errors.txt create mode 100644 tests/baselines/reference/emitCapturingThisInTupleDestructuring2.js create mode 100644 tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts create mode 100644 tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts diff --git a/tests/baselines/reference/emitCapturingThisInTupleDestructuring1.errors.txt b/tests/baselines/reference/emitCapturingThisInTupleDestructuring1.errors.txt new file mode 100644 index 00000000000..d0f11d056ca --- /dev/null +++ b/tests/baselines/reference/emitCapturingThisInTupleDestructuring1.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,17): error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'. +tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,29): error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'. + + +==== tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts (2 errors) ==== + declare function wrapper(x: any); + wrapper((array: [any]) => { + [this.test, this.test1, this.test2] = array; // even though there is a compiler error, we should still emit lexical capture for "this" + ~~~~~~~~~~ +!!! error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'. + ~~~~~~~~~~ +!!! error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'. + }); \ No newline at end of file diff --git a/tests/baselines/reference/emitCapturingThisInTupleDestructuring1.js b/tests/baselines/reference/emitCapturingThisInTupleDestructuring1.js new file mode 100644 index 00000000000..9dd7453ba4f --- /dev/null +++ b/tests/baselines/reference/emitCapturingThisInTupleDestructuring1.js @@ -0,0 +1,11 @@ +//// [emitCapturingThisInTupleDestructuring1.ts] +declare function wrapper(x: any); +wrapper((array: [any]) => { + [this.test, this.test1, this.test2] = array; // even though there is a compiler error, we should still emit lexical capture for "this" +}); + +//// [emitCapturingThisInTupleDestructuring1.js] +var _this = this; +wrapper(function (array) { + _this.test = array[0], _this.test1 = array[1], _this.test2 = array[2]; // even though there is a compiler error, we should still emit lexical capture for "this" +}); diff --git a/tests/baselines/reference/emitCapturingThisInTupleDestructuring2.errors.txt b/tests/baselines/reference/emitCapturingThisInTupleDestructuring2.errors.txt new file mode 100644 index 00000000000..25207e28c79 --- /dev/null +++ b/tests/baselines/reference/emitCapturingThisInTupleDestructuring2.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts(8,39): error TS2493: Tuple type '[number, number]' with length '2' cannot be assigned to tuple with length '3'. + + +==== tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts (1 errors) ==== + var array1: [number, number] = [1, 2]; + + class B { + test: number; + test1: any; + test2: any; + method() { + () => [this.test, this.test1, this.test2] = array1; // even though there is a compiler error, we should still emit lexical capture for "this" + ~~~~~~~~~~ +!!! error TS2493: Tuple type '[number, number]' with length '2' cannot be assigned to tuple with length '3'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/emitCapturingThisInTupleDestructuring2.js b/tests/baselines/reference/emitCapturingThisInTupleDestructuring2.js new file mode 100644 index 00000000000..f999cfe70f0 --- /dev/null +++ b/tests/baselines/reference/emitCapturingThisInTupleDestructuring2.js @@ -0,0 +1,23 @@ +//// [emitCapturingThisInTupleDestructuring2.ts] +var array1: [number, number] = [1, 2]; + +class B { + test: number; + test1: any; + test2: any; + method() { + () => [this.test, this.test1, this.test2] = array1; // even though there is a compiler error, we should still emit lexical capture for "this" + } +} + +//// [emitCapturingThisInTupleDestructuring2.js] +var array1 = [1, 2]; +var B = (function () { + function B() { + } + B.prototype.method = function () { + var _this = this; + (function () { return (_this.test = array1[0], _this.test1 = array1[1], _this.test2 = array1[2], array1); }); // even though there is a compiler error, we should still emit lexical capture for "this" + }; + return B; +}()); diff --git a/tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts b/tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts new file mode 100644 index 00000000000..e369cd9fb50 --- /dev/null +++ b/tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts @@ -0,0 +1,4 @@ +declare function wrapper(x: any); +wrapper((array: [any]) => { + [this.test, this.test1, this.test2] = array; // even though there is a compiler error, we should still emit lexical capture for "this" +}); \ No newline at end of file diff --git a/tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts b/tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts new file mode 100644 index 00000000000..2bb931c4f4f --- /dev/null +++ b/tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts @@ -0,0 +1,10 @@ +var array1: [number, number] = [1, 2]; + +class B { + test: number; + test1: any; + test2: any; + method() { + () => [this.test, this.test1, this.test2] = array1; // even though there is a compiler error, we should still emit lexical capture for "this" + } +} \ No newline at end of file From f16d599f79457fee725b942d1e0ca13176950d05 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 9 Aug 2016 15:54:44 -0700 Subject: [PATCH 3/9] Issues an error when there are more than one export default --- src/compiler/binder.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8d8666a67ab..1eedc4535dc 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -337,8 +337,18 @@ namespace ts { ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0; + // If the current node has NodeFlags.Default (e.g. if the node is class declaration or function declaration) + // and there is already another default export (i.e. symbol.declarations is not empty), we need to report such error + if (isDefaultExport && symbol.declarations) { + message = Diagnostics.A_module_cannot_have_multiple_default_exports; + } + forEach(symbol.declarations, declaration => { - if (declaration.flags & NodeFlags.Default) { + // Error on multiple export default in the following case: + // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default + // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) + if ((declaration.flags & NodeFlags.Default) || + (declaration.kind === SyntaxKind.ExportAssignment && !(node).isExportEquals)) { message = Diagnostics.A_module_cannot_have_multiple_default_exports; } }); @@ -1898,7 +1908,9 @@ namespace ts { } else { // An export default clause with an expression exports a value - declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes); + // We want to exclude both class and function here, this is necessary to issue an error when there are both + // default export-assignment and default export function and class declaration. + declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Property, SymbolFlags.Class | SymbolFlags.Function | SymbolFlags.Property); } } From 7c3f27434c13264582e71d7b3580083a847a0fcf Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 9 Aug 2016 15:55:26 -0700 Subject: [PATCH 4/9] Add tests and baselines --- .../multipleExportDefault1.errors.txt | 19 ++++++++++++++++ .../reference/multipleExportDefault1.js | 20 +++++++++++++++++ .../multipleExportDefault2.errors.txt | 18 +++++++++++++++ .../reference/multipleExportDefault2.js | 18 +++++++++++++++ .../multipleExportDefault3.errors.txt | 18 +++++++++++++++ .../reference/multipleExportDefault3.js | 22 +++++++++++++++++++ .../multipleExportDefault4.errors.txt | 16 ++++++++++++++ .../reference/multipleExportDefault4.js | 20 +++++++++++++++++ .../multipleExportDefault5.errors.txt | 11 ++++++++++ .../reference/multipleExportDefault5.js | 16 ++++++++++++++ .../multipleExportDefault6.errors.txt | 20 +++++++++++++++++ .../reference/multipleExportDefault6.js | 19 ++++++++++++++++ .../externalModules/multipleExportDefault1.ts | 7 ++++++ .../externalModules/multipleExportDefault2.ts | 6 +++++ .../externalModules/multipleExportDefault3.ts | 6 +++++ .../externalModules/multipleExportDefault4.ts | 5 +++++ .../externalModules/multipleExportDefault5.ts | 2 ++ .../externalModules/multipleExportDefault6.ts | 7 ++++++ 18 files changed, 250 insertions(+) create mode 100644 tests/baselines/reference/multipleExportDefault1.errors.txt create mode 100644 tests/baselines/reference/multipleExportDefault1.js create mode 100644 tests/baselines/reference/multipleExportDefault2.errors.txt create mode 100644 tests/baselines/reference/multipleExportDefault2.js create mode 100644 tests/baselines/reference/multipleExportDefault3.errors.txt create mode 100644 tests/baselines/reference/multipleExportDefault3.js create mode 100644 tests/baselines/reference/multipleExportDefault4.errors.txt create mode 100644 tests/baselines/reference/multipleExportDefault4.js create mode 100644 tests/baselines/reference/multipleExportDefault5.errors.txt create mode 100644 tests/baselines/reference/multipleExportDefault5.js create mode 100644 tests/baselines/reference/multipleExportDefault6.errors.txt create mode 100644 tests/baselines/reference/multipleExportDefault6.js create mode 100644 tests/cases/conformance/externalModules/multipleExportDefault1.ts create mode 100644 tests/cases/conformance/externalModules/multipleExportDefault2.ts create mode 100644 tests/cases/conformance/externalModules/multipleExportDefault3.ts create mode 100644 tests/cases/conformance/externalModules/multipleExportDefault4.ts create mode 100644 tests/cases/conformance/externalModules/multipleExportDefault5.ts create mode 100644 tests/cases/conformance/externalModules/multipleExportDefault6.ts diff --git a/tests/baselines/reference/multipleExportDefault1.errors.txt b/tests/baselines/reference/multipleExportDefault1.errors.txt new file mode 100644 index 00000000000..3da6afc41e0 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault1.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/externalModules/multipleExportDefault1.ts(1,25): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/externalModules/multipleExportDefault1.ts(5,1): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/conformance/externalModules/multipleExportDefault1.ts (2 errors) ==== + export default function Foo (){ + ~~~ +!!! error TS2528: A module cannot have multiple default exports. + + } + + export default { + ~~~~~~~~~~~~~~~~ + uhoh: "another default", + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~~ +!!! error TS2528: A module cannot have multiple default exports. + \ No newline at end of file diff --git a/tests/baselines/reference/multipleExportDefault1.js b/tests/baselines/reference/multipleExportDefault1.js new file mode 100644 index 00000000000..bec4fb48969 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault1.js @@ -0,0 +1,20 @@ +//// [multipleExportDefault1.ts] +export default function Foo (){ + +} + +export default { + uhoh: "another default", +}; + + +//// [multipleExportDefault1.js] +"use strict"; +function Foo() { +} +exports.__esModule = true; +exports["default"] = Foo; +exports.__esModule = true; +exports["default"] = { + uhoh: "another default" +}; diff --git a/tests/baselines/reference/multipleExportDefault2.errors.txt b/tests/baselines/reference/multipleExportDefault2.errors.txt new file mode 100644 index 00000000000..0543e25a163 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault2.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/externalModules/multipleExportDefault2.ts(1,1): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/externalModules/multipleExportDefault2.ts(5,25): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/conformance/externalModules/multipleExportDefault2.ts (2 errors) ==== + export default { + ~~~~~~~~~~~~~~~~ + uhoh: "another default", + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~~ +!!! error TS2528: A module cannot have multiple default exports. + + export default function Foo() { } + ~~~ +!!! error TS2528: A module cannot have multiple default exports. + + \ No newline at end of file diff --git a/tests/baselines/reference/multipleExportDefault2.js b/tests/baselines/reference/multipleExportDefault2.js new file mode 100644 index 00000000000..dc82500a1d9 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault2.js @@ -0,0 +1,18 @@ +//// [multipleExportDefault2.ts] +export default { + uhoh: "another default", +}; + +export default function Foo() { } + + + +//// [multipleExportDefault2.js] +"use strict"; +exports.__esModule = true; +exports["default"] = { + uhoh: "another default" +}; +function Foo() { } +exports.__esModule = true; +exports["default"] = Foo; diff --git a/tests/baselines/reference/multipleExportDefault3.errors.txt b/tests/baselines/reference/multipleExportDefault3.errors.txt new file mode 100644 index 00000000000..f1e55da9112 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault3.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/externalModules/multipleExportDefault3.ts(1,1): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/externalModules/multipleExportDefault3.ts(5,22): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/conformance/externalModules/multipleExportDefault3.ts (2 errors) ==== + export default { + ~~~~~~~~~~~~~~~~ + uhoh: "another default", + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~~ +!!! 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/multipleExportDefault3.js b/tests/baselines/reference/multipleExportDefault3.js new file mode 100644 index 00000000000..5d7ad48e0ca --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault3.js @@ -0,0 +1,22 @@ +//// [multipleExportDefault3.ts] +export default { + uhoh: "another default", +}; + +export default class C { } + + + +//// [multipleExportDefault3.js] +"use strict"; +exports.__esModule = true; +exports["default"] = { + uhoh: "another default" +}; +var C = (function () { + function C() { + } + return C; +}()); +exports.__esModule = true; +exports["default"] = C; diff --git a/tests/baselines/reference/multipleExportDefault4.errors.txt b/tests/baselines/reference/multipleExportDefault4.errors.txt new file mode 100644 index 00000000000..bba15527d00 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault4.errors.txt @@ -0,0 +1,16 @@ +tests/cases/conformance/externalModules/multipleExportDefault4.ts(1,22): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/externalModules/multipleExportDefault4.ts(3,1): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/conformance/externalModules/multipleExportDefault4.ts (2 errors) ==== + export default class C { } + ~ +!!! error TS2528: A module cannot have multiple default exports. + + export default { + ~~~~~~~~~~~~~~~~ + uhoh: "another default", + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }; + ~~ +!!! error TS2528: A module cannot have multiple default exports. \ No newline at end of file diff --git a/tests/baselines/reference/multipleExportDefault4.js b/tests/baselines/reference/multipleExportDefault4.js new file mode 100644 index 00000000000..1199fa91c9c --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault4.js @@ -0,0 +1,20 @@ +//// [multipleExportDefault4.ts] +export default class C { } + +export default { + uhoh: "another default", +}; + +//// [multipleExportDefault4.js] +"use strict"; +var C = (function () { + function C() { + } + return C; +}()); +exports.__esModule = true; +exports["default"] = C; +exports.__esModule = true; +exports["default"] = { + uhoh: "another default" +}; diff --git a/tests/baselines/reference/multipleExportDefault5.errors.txt b/tests/baselines/reference/multipleExportDefault5.errors.txt new file mode 100644 index 00000000000..30c87339ff2 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault5.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/externalModules/multipleExportDefault5.ts(1,25): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/externalModules/multipleExportDefault5.ts(2,22): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/conformance/externalModules/multipleExportDefault5.ts (2 errors) ==== + export default function bar() { } + ~~~ +!!! 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/multipleExportDefault5.js b/tests/baselines/reference/multipleExportDefault5.js new file mode 100644 index 00000000000..7ae33aee9f4 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault5.js @@ -0,0 +1,16 @@ +//// [multipleExportDefault5.ts] +export default function bar() { } +export default class C {} + +//// [multipleExportDefault5.js] +"use strict"; +function bar() { } +exports.__esModule = true; +exports["default"] = bar; +var C = (function () { + function C() { + } + return C; +}()); +exports.__esModule = true; +exports["default"] = C; diff --git a/tests/baselines/reference/multipleExportDefault6.errors.txt b/tests/baselines/reference/multipleExportDefault6.errors.txt new file mode 100644 index 00000000000..a8bf80e8df0 --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault6.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/externalModules/multipleExportDefault6.ts(1,1): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/externalModules/multipleExportDefault6.ts(5,1): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/conformance/externalModules/multipleExportDefault6.ts (2 errors) ==== + export default { + ~~~~~~~~~~~~~~~~ + lol: 1 + ~~~~~~~~~~ + } + ~ +!!! error TS2528: A module cannot have multiple default exports. + + export default { + ~~~~~~~~~~~~~~~~ + lol: 2 + ~~~~~~~~~~ + } + ~ +!!! error TS2528: A module cannot have multiple default exports. \ No newline at end of file diff --git a/tests/baselines/reference/multipleExportDefault6.js b/tests/baselines/reference/multipleExportDefault6.js new file mode 100644 index 00000000000..a8b93459e4e --- /dev/null +++ b/tests/baselines/reference/multipleExportDefault6.js @@ -0,0 +1,19 @@ +//// [multipleExportDefault6.ts] +export default { + lol: 1 +} + +export default { + lol: 2 +} + +//// [multipleExportDefault6.js] +"use strict"; +exports.__esModule = true; +exports["default"] = { + lol: 1 +}; +exports.__esModule = true; +exports["default"] = { + lol: 2 +}; diff --git a/tests/cases/conformance/externalModules/multipleExportDefault1.ts b/tests/cases/conformance/externalModules/multipleExportDefault1.ts new file mode 100644 index 00000000000..623cc2acc20 --- /dev/null +++ b/tests/cases/conformance/externalModules/multipleExportDefault1.ts @@ -0,0 +1,7 @@ +export default function Foo (){ + +} + +export default { + uhoh: "another default", +}; diff --git a/tests/cases/conformance/externalModules/multipleExportDefault2.ts b/tests/cases/conformance/externalModules/multipleExportDefault2.ts new file mode 100644 index 00000000000..0e14b570aa1 --- /dev/null +++ b/tests/cases/conformance/externalModules/multipleExportDefault2.ts @@ -0,0 +1,6 @@ +export default { + uhoh: "another default", +}; + +export default function Foo() { } + diff --git a/tests/cases/conformance/externalModules/multipleExportDefault3.ts b/tests/cases/conformance/externalModules/multipleExportDefault3.ts new file mode 100644 index 00000000000..3b5460e8141 --- /dev/null +++ b/tests/cases/conformance/externalModules/multipleExportDefault3.ts @@ -0,0 +1,6 @@ +export default { + uhoh: "another default", +}; + +export default class C { } + diff --git a/tests/cases/conformance/externalModules/multipleExportDefault4.ts b/tests/cases/conformance/externalModules/multipleExportDefault4.ts new file mode 100644 index 00000000000..6181c360798 --- /dev/null +++ b/tests/cases/conformance/externalModules/multipleExportDefault4.ts @@ -0,0 +1,5 @@ +export default class C { } + +export default { + uhoh: "another default", +}; \ No newline at end of file diff --git a/tests/cases/conformance/externalModules/multipleExportDefault5.ts b/tests/cases/conformance/externalModules/multipleExportDefault5.ts new file mode 100644 index 00000000000..d2b67fce46f --- /dev/null +++ b/tests/cases/conformance/externalModules/multipleExportDefault5.ts @@ -0,0 +1,2 @@ +export default function bar() { } +export default class C {} \ No newline at end of file diff --git a/tests/cases/conformance/externalModules/multipleExportDefault6.ts b/tests/cases/conformance/externalModules/multipleExportDefault6.ts new file mode 100644 index 00000000000..889ae64376b --- /dev/null +++ b/tests/cases/conformance/externalModules/multipleExportDefault6.ts @@ -0,0 +1,7 @@ +export default { + lol: 1 +} + +export default { + lol: 2 +} \ No newline at end of file From 042da569f71b40b0723b92259dc8a197c64580a5 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Thu, 11 Aug 2016 10:04:22 -0700 Subject: [PATCH 5/9] Address PR: add comment --- src/compiler/binder.ts | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 1eedc4535dc..2547dd2cd5a 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -337,21 +337,24 @@ namespace ts { ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0; - // If the current node has NodeFlags.Default (e.g. if the node is class declaration or function declaration) - // and there is already another default export (i.e. symbol.declarations is not empty), we need to report such error + // If the current node is a default export of some sort, then check if + // there are any other default exports that we need to error on. + // We'll know whether we have other default exports depending on if `symbol` already has a declaration list set. if (isDefaultExport && symbol.declarations) { message = Diagnostics.A_module_cannot_have_multiple_default_exports; } - - forEach(symbol.declarations, declaration => { - // Error on multiple export default in the following case: - // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default - // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) - if ((declaration.flags & NodeFlags.Default) || - (declaration.kind === SyntaxKind.ExportAssignment && !(node).isExportEquals)) { - message = Diagnostics.A_module_cannot_have_multiple_default_exports; - } - }); + else { + // This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration. + forEach(symbol.declarations, declaration => { + // Error on multiple export default in the following case: + // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default + // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) + if ((declaration.flags & NodeFlags.Default) || + (declaration.kind === SyntaxKind.ExportAssignment && !(node).isExportEquals)) { + message = Diagnostics.A_module_cannot_have_multiple_default_exports; + } + }); + } forEach(symbol.declarations, declaration => { file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration))); From 821348b75d60f095f4e88a036fd4928a51527b99 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Thu, 11 Aug 2016 10:48:43 -0700 Subject: [PATCH 6/9] Update baseline --- ...sFileCompilationBindMultipleDefaultExports.errors.txt | 8 +++++++- .../reference/multipleDefaultExports01.errors.txt | 9 +++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/jsFileCompilationBindMultipleDefaultExports.errors.txt b/tests/baselines/reference/jsFileCompilationBindMultipleDefaultExports.errors.txt index 4c1d237aa47..05fecf03d30 100644 --- a/tests/baselines/reference/jsFileCompilationBindMultipleDefaultExports.errors.txt +++ b/tests/baselines/reference/jsFileCompilationBindMultipleDefaultExports.errors.txt @@ -1,9 +1,15 @@ +tests/cases/compiler/a.js(1,22): error TS2528: A module cannot have multiple default exports. +tests/cases/compiler/a.js(3,1): error TS2528: A module cannot have multiple default exports. tests/cases/compiler/a.js(3,16): error TS1109: Expression expected. -==== tests/cases/compiler/a.js (1 errors) ==== +==== tests/cases/compiler/a.js (3 errors) ==== export default class a { + ~ +!!! error TS2528: A module cannot have multiple default exports. } export default var a = 10; + ~~~~~~~~~~~~~~ +!!! error TS2528: A module cannot have multiple default exports. ~~~ !!! error TS1109: Expression expected. \ No newline at end of file diff --git a/tests/baselines/reference/multipleDefaultExports01.errors.txt b/tests/baselines/reference/multipleDefaultExports01.errors.txt index b3e7d757289..16aa3b2f7b1 100644 --- a/tests/baselines/reference/multipleDefaultExports01.errors.txt +++ b/tests/baselines/reference/multipleDefaultExports01.errors.txt @@ -1,16 +1,13 @@ -tests/cases/conformance/es6/modules/m1.ts(2,22): error TS2323: Cannot redeclare exported variable '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 TS2323: Cannot redeclare exported variable 'default'. +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'? -==== tests/cases/conformance/es6/modules/m1.ts (4 errors) ==== +==== tests/cases/conformance/es6/modules/m1.ts (3 errors) ==== export default class foo { ~~~ -!!! error TS2323: Cannot redeclare exported variable 'default'. - ~~~ !!! error TS2528: A module cannot have multiple default exports. } @@ -24,7 +21,7 @@ tests/cases/conformance/es6/modules/m2.ts(3,1): error TS2348: Value of type 'typ var x = 10; export default x; ~~~~~~~~~~~~~~~~~ -!!! error TS2323: Cannot redeclare exported variable 'default'. +!!! error TS2528: A module cannot have multiple default exports. ==== tests/cases/conformance/es6/modules/m2.ts (1 errors) ==== import Entity from "./m1" From 3479f4bcbe233adcd0dd500686de3bf18b8efd57 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Thu, 11 Aug 2016 10:49:36 -0700 Subject: [PATCH 7/9] fix linting --- src/compiler/binder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 573bd0b7e35..c3dab267d02 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1913,7 +1913,7 @@ namespace ts { ? SymbolFlags.Alias // An export default clause with any other expression exports a value : SymbolFlags.Property; - declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.Property | SymbolFlags.AliasExcludes | SymbolFlags.Class | SymbolFlags.Function); //SymbolFlags.Class | SymbolFlags.Function | SymbolFlags.Property); + declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.Property | SymbolFlags.AliasExcludes | SymbolFlags.Class | SymbolFlags.Function); } } From 7b525ea99fb6befa87032741de972dfc0a8f650e Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 17 Aug 2016 16:06:13 -0700 Subject: [PATCH 8/9] Use for..of instead --- src/compiler/binder.ts | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 45dbab15732..5e065a00d2f 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -349,23 +349,26 @@ namespace ts { ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0; - // If the current node is a default export of some sort, then check if - // there are any other default exports that we need to error on. - // We'll know whether we have other default exports depending on if `symbol` already has a declaration list set. - if (isDefaultExport && symbol.declarations) { - message = Diagnostics.A_module_cannot_have_multiple_default_exports; - } - else { - // This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration. - forEach(symbol.declarations, declaration => { - // Error on multiple export default in the following case: - // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default - // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) - if ((declaration.flags & NodeFlags.Default) || - (declaration.kind === SyntaxKind.ExportAssignment && !(node).isExportEquals)) { - message = Diagnostics.A_module_cannot_have_multiple_default_exports; + if (symbol.declarations && symbol.declarations.length) { + // If the current node is a default export of some sort, then check if + // there are any other default exports that we need to error on. + // We'll know whether we have other default exports depending on if `symbol` already has a declaration list set. + if (isDefaultExport) { + message = Diagnostics.A_module_cannot_have_multiple_default_exports; + } + else { + // This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration. + for (const declaration of symbol.declarations) { + // Error on multiple export default in the following case: + // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default + // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) + if ((declaration.flags & NodeFlags.Default) || + (declaration.kind === SyntaxKind.ExportAssignment && !(node).isExportEquals)) { + message = Diagnostics.A_module_cannot_have_multiple_default_exports; + break; + } } - }); + } } forEach(symbol.declarations, declaration => { From a5a71693b73031130fb74c9322c23ee79db2aef2 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Thu, 29 Sep 2016 18:02:59 -0700 Subject: [PATCH 9/9] Address PR --- src/compiler/binder.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 5e065a00d2f..65034476aa1 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -358,16 +358,13 @@ namespace ts { } else { // This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration. - for (const declaration of symbol.declarations) { - // Error on multiple export default in the following case: - // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default - // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) - if ((declaration.flags & NodeFlags.Default) || - (declaration.kind === SyntaxKind.ExportAssignment && !(node).isExportEquals)) { + // Error on multiple export default in the following case: + // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default + // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) + if (symbol.declarations && symbol.declarations.length && + (isDefaultExport || (node.kind === SyntaxKind.ExportAssignment && !(node).isExportEquals))) { message = Diagnostics.A_module_cannot_have_multiple_default_exports; - break; - } - } + } } }