3
3
4
4
/* @internal */
5
5
module ts {
6
- // represents one LexicalEnvironment frame to store unique generated names
7
- interface ScopeFrame {
8
- names : Map < string > ;
9
- previous : ScopeFrame ;
10
- }
11
-
12
6
export function isExternalModuleOrDeclarationFile ( sourceFile : SourceFile ) {
13
7
return isExternalModule ( sourceFile ) || isDeclarationFile ( sourceFile ) ;
14
8
}
@@ -18,7 +12,6 @@ module ts {
18
12
Auto = 0x00000000 , // No preferred name
19
13
CountMask = 0x0FFFFFFF , // Temp variable counter
20
14
_i = 0x10000000 , // Use/preference flag for '_i'
21
- _n = 0x20000000 , // Use/preference flag for '_n'
22
15
}
23
16
24
17
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
@@ -2683,15 +2676,17 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
2683
2676
if ( ! exportEquals && exportSpecifiers && hasProperty ( exportSpecifiers , name . text ) ) {
2684
2677
for ( let specifier of exportSpecifiers [ name . text ] ) {
2685
2678
writeLine ( ) ;
2686
- emitStart ( specifier . name ) ;
2687
2679
if ( compilerOptions . module === ModuleKind . System ) {
2680
+ emitStart ( specifier . name ) ;
2688
2681
write ( `${ exportFunctionForFile } ("` ) ;
2689
2682
emitNodeWithoutSourceMap ( specifier . name ) ;
2690
2683
write ( `", ` ) ;
2691
2684
emitExpressionIdentifier ( name ) ;
2692
2685
write ( ")" )
2686
+ emitEnd ( specifier . name ) ;
2693
2687
}
2694
2688
else {
2689
+ emitStart ( specifier . name ) ;
2695
2690
emitContainingModuleName ( specifier ) ;
2696
2691
write ( "." ) ;
2697
2692
emitNodeWithoutSourceMap ( specifier . name ) ;
@@ -4968,7 +4963,135 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
4968
4963
}
4969
4964
}
4970
4965
4971
- function hoistTopLevelVariableAndFunctionDeclarations ( node : SourceFile ) : void {
4966
+ function emitLocalStorageForExportedNamesIfNecessary ( exportedDeclarations : ( Identifier | Declaration ) [ ] ) : string {
4967
+ // when resolving exports local exported entries/indirect exported entries in the module
4968
+ // should always win over entries with similar names that were added via star exports
4969
+ // to support this we store names of local/indirect exported entries in a set.
4970
+ // this set is used to filter names brought by star expors.
4971
+ if ( ! hasExportStars ) {
4972
+ // local names set is needed only in presence of star exports
4973
+ return undefined ;
4974
+ }
4975
+
4976
+ // local names set should only be added if we have anything exported
4977
+ if ( ! exportedDeclarations && isEmpty ( exportSpecifiers ) ) {
4978
+ // no exported declarations (export var ...) or export specifiers (export {x})
4979
+ // check if we have any non star export declarations.
4980
+ let hasExportDeclarationWithExportClause = false ;
4981
+ for ( let externalImport of externalImports ) {
4982
+ if ( externalImport . kind === SyntaxKind . ExportDeclaration && ( < ExportDeclaration > externalImport ) . exportClause ) {
4983
+ hasExportDeclarationWithExportClause = true ;
4984
+ break ;
4985
+ }
4986
+ }
4987
+
4988
+ if ( ! hasExportDeclarationWithExportClause ) {
4989
+ // we still need to emit exportStar helper
4990
+ return emitExportStarFunction ( /*localNames*/ undefined ) ;
4991
+ }
4992
+ }
4993
+
4994
+ const exportedNamesStorageRef = makeUniqueName ( "exportedNames" ) ;
4995
+
4996
+ writeLine ( ) ;
4997
+ write ( `var ${ exportedNamesStorageRef } = {` ) ;
4998
+ increaseIndent ( ) ;
4999
+
5000
+ let started = false ;
5001
+ if ( exportedDeclarations ) {
5002
+ for ( let i = 0 ; i < exportedDeclarations . length ; ++ i ) {
5003
+ // write name of exported declaration, i.e 'export var x...'
5004
+ writeExportedName ( exportedDeclarations [ i ] ) ;
5005
+ }
5006
+ }
5007
+
5008
+ if ( exportSpecifiers ) {
5009
+ for ( let n in exportSpecifiers ) {
5010
+ for ( let specifier of exportSpecifiers [ n ] ) {
5011
+ // write name of export specified, i.e. 'export {x}'
5012
+ writeExportedName ( specifier . name ) ;
5013
+ }
5014
+ }
5015
+ }
5016
+
5017
+ for ( let externalImport of externalImports ) {
5018
+ if ( externalImport . kind !== SyntaxKind . ExportDeclaration ) {
5019
+ continue ;
5020
+ }
5021
+
5022
+ let exportDecl = < ExportDeclaration > externalImport ;
5023
+ if ( ! exportDecl . exportClause ) {
5024
+ // export * from ...
5025
+ continue ;
5026
+ }
5027
+
5028
+ for ( let element of exportDecl . exportClause . elements ) {
5029
+ // write name of indirectly exported entry, i.e. 'export {x} from ...'
5030
+ writeExportedName ( element . name || element . propertyName ) ;
5031
+ }
5032
+ }
5033
+
5034
+ decreaseIndent ( ) ;
5035
+ writeLine ( ) ;
5036
+ write ( "};" ) ;
5037
+
5038
+ return emitExportStarFunction ( exportedNamesStorageRef ) ;
5039
+
5040
+ function emitExportStarFunction ( localNames : string ) : string {
5041
+ const exportStarFunction = makeUniqueName ( "exportStar" ) ;
5042
+
5043
+ writeLine ( ) ;
5044
+
5045
+ // define an export star helper function
5046
+ write ( `function ${ exportStarFunction } (m) {` ) ;
5047
+ increaseIndent ( ) ;
5048
+ writeLine ( ) ;
5049
+ write ( `for(var n in m) {` ) ;
5050
+ increaseIndent ( ) ;
5051
+ writeLine ( ) ;
5052
+ write ( `if (n !== "default"` ) ;
5053
+ if ( localNames ) {
5054
+ write ( `&& !${ localNames } .hasOwnProperty(n)` ) ;
5055
+ }
5056
+ write ( `) ${ exportFunctionForFile } (n, m[n]);` ) ;
5057
+ decreaseIndent ( ) ;
5058
+ writeLine ( ) ;
5059
+ write ( "}" ) ;
5060
+ decreaseIndent ( ) ;
5061
+ writeLine ( ) ;
5062
+ write ( "}" )
5063
+
5064
+ return exportStarFunction ;
5065
+ }
5066
+
5067
+ function writeExportedName ( node : Identifier | Declaration ) : void {
5068
+ // do not record default exports
5069
+ // they are local to module and never overwritten (explicitly skipped) by star export
5070
+ if ( node . kind !== SyntaxKind . Identifier && node . flags & NodeFlags . Default ) {
5071
+ return ;
5072
+ }
5073
+
5074
+ if ( started ) {
5075
+ write ( "," ) ;
5076
+ }
5077
+ else {
5078
+ started = true ;
5079
+ }
5080
+
5081
+ writeLine ( ) ;
5082
+ write ( "'" ) ;
5083
+ if ( node . kind === SyntaxKind . Identifier ) {
5084
+ emitNodeWithoutSourceMap ( node ) ;
5085
+ }
5086
+ else {
5087
+ emitDeclarationName ( < Declaration > node ) ;
5088
+ }
5089
+
5090
+ write ( "': true" ) ;
5091
+ }
5092
+ }
5093
+
5094
+ function processTopLevelVariableAndFunctionDeclarations ( node : SourceFile ) : ( Identifier | Declaration ) [ ] {
4972
5095
// per ES6 spec:
4973
5096
// 15.2.1.16.4 ModuleDeclarationInstantiation() Concrete Method
4974
5097
// - var declarations are initialized to undefined - 14.a.ii
@@ -4980,6 +5103,7 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
4980
5103
// including variables declarations for module and class declarations
4981
5104
let hoistedVars : ( Identifier | ClassDeclaration | ModuleDeclaration ) [ ] ;
4982
5105
let hoistedFunctionDeclarations : FunctionDeclaration [ ] ;
5106
+ let exportedDeclarations : ( Identifier | Declaration ) [ ] ;
4983
5107
4984
5108
visit ( node ) ;
4985
5109
@@ -4997,6 +5121,14 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
4997
5121
else {
4998
5122
emit ( local ) ;
4999
5123
}
5124
+
5125
+ let flags = getCombinedNodeFlags ( local . kind === SyntaxKind . Identifier ? local . parent : local ) ;
5126
+ if ( flags & NodeFlags . Export ) {
5127
+ if ( ! exportedDeclarations ) {
5128
+ exportedDeclarations = [ ] ;
5129
+ }
5130
+ exportedDeclarations . push ( local ) ;
5131
+ }
5000
5132
}
5001
5133
write ( ";" )
5002
5134
}
@@ -5005,9 +5137,18 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
5005
5137
for ( let f of hoistedFunctionDeclarations ) {
5006
5138
writeLine ( ) ;
5007
5139
emit ( f ) ;
5140
+
5141
+ if ( f . flags & NodeFlags . Export ) {
5142
+ if ( ! exportedDeclarations ) {
5143
+ exportedDeclarations = [ ] ;
5144
+ }
5145
+ exportedDeclarations . push ( f ) ;
5146
+ }
5008
5147
}
5009
5148
}
5010
5149
5150
+ return exportedDeclarations ;
5151
+
5011
5152
function visit ( node : Node ) : void {
5012
5153
if ( node . kind === SyntaxKind . FunctionDeclaration ) {
5013
5154
if ( ! hoistedFunctionDeclarations ) {
@@ -5121,12 +5262,13 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
5121
5262
// }
5122
5263
emitVariableDeclarationsForImports ( ) ;
5123
5264
writeLine ( ) ;
5124
- hoistTopLevelVariableAndFunctionDeclarations ( node ) ;
5265
+ var exportedDeclarations = processTopLevelVariableAndFunctionDeclarations ( node ) ;
5266
+ let exportStarFunction = emitLocalStorageForExportedNamesIfNecessary ( exportedDeclarations )
5125
5267
writeLine ( ) ;
5126
5268
write ( "return {" ) ;
5127
5269
increaseIndent ( ) ;
5128
5270
writeLine ( ) ;
5129
- emitSetters ( ) ;
5271
+ emitSetters ( exportStarFunction ) ;
5130
5272
writeLine ( ) ;
5131
5273
emitExecute ( node , startIndex ) ;
5132
5274
emitTempDeclarations ( /*newLine*/ true )
@@ -5135,7 +5277,7 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
5135
5277
write ( "}" ) ; // return
5136
5278
}
5137
5279
5138
- function emitSetters ( ) {
5280
+ function emitSetters ( exportStarFunction : string ) {
5139
5281
write ( "setters:[" ) ;
5140
5282
for ( let i = 0 ; i < externalImports . length ; ++ i ) {
5141
5283
if ( i !== 0 ) {
@@ -5163,7 +5305,7 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
5163
5305
increaseIndent ( ) ;
5164
5306
writeLine ( ) ;
5165
5307
// save import into the local
5166
- write ( `${ importVariableName } = ${ parameterName } ` ) ;
5308
+ write ( `${ importVariableName } = ${ parameterName } ; ` ) ;
5167
5309
writeLine ( ) ;
5168
5310
5169
5311
let defaultName =
@@ -5228,9 +5370,8 @@ if (typeof __param !== "function") __param = function (paramIndex, decorator) {
5228
5370
writeLine ( ) ;
5229
5371
// export * from 'foo'
5230
5372
// emit as:
5231
- // for (var n in _foo) exports(n, _foo[n]);
5232
- // NOTE: it is safe to use name 'n' since parameter name always starts with '_'
5233
- write ( `for (var n in ${ parameterName } ) ${ exportFunctionForFile } (n, ${ parameterName } [n]);` ) ;
5373
+ // exportStar(_foo);
5374
+ write ( `${ exportStarFunction } (${ parameterName } );` ) ;
5234
5375
}
5235
5376
5236
5377
writeLine ( ) ;
0 commit comments