@@ -151,7 +151,17 @@ namespace ts {
151151 break ;
152152 }
153153
154- recordEmittedDeclarationInScope ( node ) ;
154+ // Record these declarations provided that they have a name.
155+ if ( ( node as ClassDeclaration | FunctionDeclaration ) . name ) {
156+ recordEmittedDeclarationInScope ( node as ClassDeclaration | FunctionDeclaration ) ;
157+ }
158+ else {
159+ // These nodes should always have names unless they are default-exports;
160+ // however, class declaration parsing allows for undefined names, so syntactically invalid
161+ // programs may also have an undefined name.
162+ Debug . assert ( node . kind === SyntaxKind . ClassDeclaration || hasModifier ( node , ModifierFlags . Default ) ) ;
163+ }
164+
155165 break ;
156166 }
157167 }
@@ -2640,16 +2650,14 @@ namespace ts {
26402650 * Records that a declaration was emitted in the current scope, if it was the first
26412651 * declaration for the provided symbol.
26422652 */
2643- function recordEmittedDeclarationInScope ( node : Node ) {
2644- const name = node . symbol && node . symbol . escapedName ;
2645- if ( name ) {
2646- if ( ! currentScopeFirstDeclarationsOfName ) {
2647- currentScopeFirstDeclarationsOfName = createUnderscoreEscapedMap < Node > ( ) ;
2648- }
2653+ function recordEmittedDeclarationInScope ( node : FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration ) {
2654+ if ( ! currentScopeFirstDeclarationsOfName ) {
2655+ currentScopeFirstDeclarationsOfName = createUnderscoreEscapedMap < Node > ( ) ;
2656+ }
26492657
2650- if ( ! currentScopeFirstDeclarationsOfName . has ( name ) ) {
2651- currentScopeFirstDeclarationsOfName . set ( name , node ) ;
2652- }
2658+ const name = declaredNameInScope ( node ) ;
2659+ if ( ! currentScopeFirstDeclarationsOfName . has ( name ) ) {
2660+ currentScopeFirstDeclarationsOfName . set ( name , node ) ;
26532661 }
26542662 }
26552663
@@ -2658,20 +2666,25 @@ namespace ts {
26582666 * the same name emitted in the current scope. Only returns false if we are absolutely
26592667 * certain a previous declaration has been emitted.
26602668 */
2661- function isPotentiallyFirstEmittedDeclarationInScope ( node : Node ) {
2669+ function isFirstEmittedDeclarationInScope ( node : ModuleDeclaration | EnumDeclaration ) {
26622670 // If the node has a named symbol, then we have enough knowledge to determine
26632671 // whether a prior declaration has been emitted.
26642672 if ( currentScopeFirstDeclarationsOfName ) {
2665- const name = node . symbol && node . symbol . escapedName ;
2666- if ( name ) {
2667- return currentScopeFirstDeclarationsOfName . get ( name ) === node ;
2668- }
2673+ const name = declaredNameInScope ( node ) ;
2674+ return currentScopeFirstDeclarationsOfName . get ( name ) === node ;
26692675 }
26702676
26712677 // Otherwise, we can't be sure. For example, this node could be synthetic.
26722678 return true ;
26732679 }
26742680
2681+ function declaredNameInScope ( node : FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration ) : __String {
2682+ if ( node . name . kind !== SyntaxKind . Identifier ) {
2683+ Debug . fail ( formatSyntaxKind ( node . kind ) + " should have an identifier name." ) ;
2684+ }
2685+ return ( node . name as Identifier ) . escapedText ;
2686+ }
2687+
26752688 /**
26762689 * Adds a leading VariableStatement for a enum or module declaration.
26772690 */
@@ -2691,7 +2704,7 @@ namespace ts {
26912704 setOriginalNode ( statement , node ) ;
26922705
26932706 recordEmittedDeclarationInScope ( node ) ;
2694- if ( isPotentiallyFirstEmittedDeclarationInScope ( node ) ) {
2707+ if ( isFirstEmittedDeclarationInScope ( node ) ) {
26952708 // Adjust the source map emit to match the old emitter.
26962709 if ( node . kind === SyntaxKind . EnumDeclaration ) {
26972710 setSourceMapRange ( statement . declarationList , node ) ;
@@ -2747,7 +2760,7 @@ namespace ts {
27472760 return createNotEmittedStatement ( node ) ;
27482761 }
27492762
2750- Debug . assert ( isIdentifier ( node . name ) , "TypeScript module should have an Identifier name." ) ;
2763+ Debug . assert ( isIdentifier ( node . name ) , "A TypeScript namespace should have an Identifier name." ) ;
27512764 enableSubstitutionForNamespaceExports ( ) ;
27522765
27532766 const statements : Statement [ ] = [ ] ;
0 commit comments