From 90ae9ffe6ed92ab9d3478cc620e5752c658cf121 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 9 Nov 2017 12:21:37 -0800 Subject: [PATCH] If there is an `export default x;` alias declaration, disallow other default exports (#19872) --- src/compiler/binder.ts | 9 ++++----- src/compiler/types.ts | 4 ++++ ...exportDefaultAlias_excludesEverything.errors.txt | 13 +++++++++++++ .../exportDefaultAlias_excludesEverything.js | 9 +++++++++ .../exportDefaultAlias_excludesEverything.symbols | 10 ++++++++++ .../exportDefaultAlias_excludesEverything.types | 10 ++++++++++ .../exportDefaultAlias_excludesEverything.ts | 3 +++ 7 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/exportDefaultAlias_excludesEverything.errors.txt create mode 100644 tests/baselines/reference/exportDefaultAlias_excludesEverything.js create mode 100644 tests/baselines/reference/exportDefaultAlias_excludesEverything.symbols create mode 100644 tests/baselines/reference/exportDefaultAlias_excludesEverything.types create mode 100644 tests/cases/compiler/exportDefaultAlias_excludesEverything.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index cf8b3eefde..4e89abde78 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2205,15 +2205,14 @@ namespace ts { bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)); } else { - // An export default clause with an expression exports a value - // 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. - const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) + const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) // An export default clause with an EntityNameExpression exports all meanings of that identifier ? 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); + // If there is an `export default x;` alias declaration, can't `export default` anything else. + // (In contrast, you can still have `export default function f() {}` and `export default interface I {}`.) + declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.All); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1874821727..d2107572ab 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3021,6 +3021,10 @@ namespace ts { Optional = 1 << 24, // Optional property Transient = 1 << 25, // Transient symbol (created during type check) + /* @internal */ + All = FunctionScopedVariable | BlockScopedVariable | Property | EnumMember | Function | Class | Interface | ConstEnum | RegularEnum | ValueModule | NamespaceModule | TypeLiteral + | ObjectLiteral | Method | Constructor | GetAccessor | SetAccessor | Signature | TypeParameter | TypeAlias | ExportValue | Alias | Prototype | ExportStar | Optional | Transient, + Enum = RegularEnum | ConstEnum, Variable = FunctionScopedVariable | BlockScopedVariable, Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor, diff --git a/tests/baselines/reference/exportDefaultAlias_excludesEverything.errors.txt b/tests/baselines/reference/exportDefaultAlias_excludesEverything.errors.txt new file mode 100644 index 0000000000..9181278db2 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAlias_excludesEverything.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/exportDefaultAlias_excludesEverything.ts(1,26): error TS2528: A module cannot have multiple default exports. +tests/cases/compiler/exportDefaultAlias_excludesEverything.ts(3,16): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/compiler/exportDefaultAlias_excludesEverything.ts (2 errors) ==== + export default interface A {} + ~ +!!! error TS2528: A module cannot have multiple default exports. + interface B {} + export default B; + ~ +!!! error TS2528: A module cannot have multiple default exports. + \ No newline at end of file diff --git a/tests/baselines/reference/exportDefaultAlias_excludesEverything.js b/tests/baselines/reference/exportDefaultAlias_excludesEverything.js new file mode 100644 index 0000000000..27f75954c1 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAlias_excludesEverything.js @@ -0,0 +1,9 @@ +//// [exportDefaultAlias_excludesEverything.ts] +export default interface A {} +interface B {} +export default B; + + +//// [exportDefaultAlias_excludesEverything.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/exportDefaultAlias_excludesEverything.symbols b/tests/baselines/reference/exportDefaultAlias_excludesEverything.symbols new file mode 100644 index 0000000000..73b403e0da --- /dev/null +++ b/tests/baselines/reference/exportDefaultAlias_excludesEverything.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/exportDefaultAlias_excludesEverything.ts === +export default interface A {} +>A : Symbol(A, Decl(exportDefaultAlias_excludesEverything.ts, 0, 0)) + +interface B {} +>B : Symbol(B, Decl(exportDefaultAlias_excludesEverything.ts, 0, 29)) + +export default B; +>B : Symbol(B, Decl(exportDefaultAlias_excludesEverything.ts, 0, 29)) + diff --git a/tests/baselines/reference/exportDefaultAlias_excludesEverything.types b/tests/baselines/reference/exportDefaultAlias_excludesEverything.types new file mode 100644 index 0000000000..cd9dd06f81 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAlias_excludesEverything.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/exportDefaultAlias_excludesEverything.ts === +export default interface A {} +>A : A + +interface B {} +>B : B + +export default B; +>B : B + diff --git a/tests/cases/compiler/exportDefaultAlias_excludesEverything.ts b/tests/cases/compiler/exportDefaultAlias_excludesEverything.ts new file mode 100644 index 0000000000..eea8cb1e69 --- /dev/null +++ b/tests/cases/compiler/exportDefaultAlias_excludesEverything.ts @@ -0,0 +1,3 @@ +export default interface A {} +interface B {} +export default B;