@@ -4962,7 +4962,7 @@ namespace ts {
4962
4962
const oldcontext = context;
4963
4963
context = {
4964
4964
...oldcontext,
4965
- usedSymbolNames: mapMap(symbolTable, (_symbol, name) => [unescapeLeadingUnderscores(name), true] ),
4965
+ usedSymbolNames: createMap( ),
4966
4966
remappedSymbolNames: createMap(),
4967
4967
tracker: {
4968
4968
...oldcontext.tracker,
@@ -4986,6 +4986,10 @@ namespace ts {
4986
4986
context.usedSymbolNames!.set(name, true);
4987
4987
});
4988
4988
}
4989
+ forEachEntry(symbolTable, (symbol, name) => {
4990
+ const baseName = unescapeLeadingUnderscores(name);
4991
+ void getInternalSymbolName(symbol, baseName); // Called to cache values into `usedSymbolNames` and `remappedSymbolNames`
4992
+ });
4989
4993
let addingDeclare = !bundled;
4990
4994
const exportEquals = symbolTable.get(InternalSymbolName.ExportEquals);
4991
4995
if (exportEquals && symbolTable.size > 1 && exportEquals.flags & SymbolFlags.Alias) {
@@ -5198,7 +5202,11 @@ namespace ts {
5198
5202
isPrivate = true;
5199
5203
}
5200
5204
const modifierFlags = (!isPrivate ? ModifierFlags.Export : 0) | (isDefault && !needsPostExportDefault ? ModifierFlags.Default : 0);
5201
- if (symbol.flags & SymbolFlags.Function) {
5205
+ const isConstMergedWithNS = symbol.flags & SymbolFlags.Module &&
5206
+ symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property) &&
5207
+ symbol.escapedName !== InternalSymbolName.ExportEquals;
5208
+ const isConstMergedWithNSPrintableAsSignatureMerge = isConstMergedWithNS && isTypeRepresentableAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol);
5209
+ if (symbol.flags & SymbolFlags.Function || isConstMergedWithNSPrintableAsSignatureMerge) {
5202
5210
serializeAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol, getInternalSymbolName(symbol, symbolName), modifierFlags);
5203
5211
}
5204
5212
if (symbol.flags & SymbolFlags.TypeAlias) {
@@ -5209,7 +5217,8 @@ namespace ts {
5209
5217
if (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property)
5210
5218
&& symbol.escapedName !== InternalSymbolName.ExportEquals
5211
5219
&& !(symbol.flags & SymbolFlags.Prototype)
5212
- && !(symbol.flags & SymbolFlags.Class)) {
5220
+ && !(symbol.flags & SymbolFlags.Class)
5221
+ && !isConstMergedWithNSPrintableAsSignatureMerge) {
5213
5222
serializeVariableOrProperty(symbol, symbolName, isPrivate, needsPostExportDefault, propertyAsAlias, modifierFlags);
5214
5223
}
5215
5224
if (symbol.flags & SymbolFlags.Enum) {
@@ -5226,7 +5235,7 @@ namespace ts {
5226
5235
serializeAsClass(symbol, getInternalSymbolName(symbol, symbolName), modifierFlags);
5227
5236
}
5228
5237
}
5229
- if (symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule)) {
5238
+ if (( symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && (!isConstMergedWithNS || isTypeOnlyNamespace(symbol))) || isConstMergedWithNSPrintableAsSignatureMerge ) {
5230
5239
serializeModule(symbol, symbolName, modifierFlags);
5231
5240
}
5232
5241
if (symbol.flags & SymbolFlags.Interface) {
@@ -5253,7 +5262,9 @@ namespace ts {
5253
5262
}
5254
5263
5255
5264
function includePrivateSymbol(symbol: Symbol) {
5265
+ if (some(symbol.declarations, isParameterDeclaration)) return;
5256
5266
Debug.assertDefined(deferredPrivates);
5267
+ getUnusedName(unescapeLeadingUnderscores(symbol.escapedName), symbol); // Call to cache unique name for symbol
5257
5268
deferredPrivates!.set("" + getSymbolId(symbol), symbol);
5258
5269
}
5259
5270
@@ -5327,8 +5338,16 @@ namespace ts {
5327
5338
), modifierFlags);
5328
5339
}
5329
5340
5341
+ function getNamespaceMembersForSerialization(symbol: Symbol) {
5342
+ return !symbol.exports ? [] : filter(arrayFrom((symbol.exports).values()), p => !((p.flags & SymbolFlags.Prototype) || (p.escapedName === "prototype")));
5343
+ }
5344
+
5345
+ function isTypeOnlyNamespace(symbol: Symbol) {
5346
+ return every(getNamespaceMembersForSerialization(symbol), m => !(resolveSymbol(m).flags & SymbolFlags.Value));
5347
+ }
5348
+
5330
5349
function serializeModule(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) {
5331
- const members = !symbol.exports ? [] : filter(arrayFrom(( symbol.exports).values()), p => !((p.flags & SymbolFlags.Prototype) || (p.escapedName === "prototype")) );
5350
+ const members = getNamespaceMembersForSerialization( symbol);
5332
5351
// Split NS members up by declaration - members whose parent symbol is the ns symbol vs those whose is not (but were added in later via merging)
5333
5352
const locationMap = arrayToMultiMap(members, m => m.parent && m.parent === symbol ? "real" : "merged");
5334
5353
const realMembers = locationMap.get("real") || emptyArray;
@@ -5338,18 +5357,21 @@ namespace ts {
5338
5357
// so we don't even have placeholders to fill in.
5339
5358
if (length(realMembers)) {
5340
5359
const localName = getInternalSymbolName(symbol, symbolName);
5341
- serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & SymbolFlags.Function));
5360
+ serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & ( SymbolFlags.Function | SymbolFlags.Assignment) ));
5342
5361
}
5343
5362
if (length(mergedMembers)) {
5344
5363
const localName = getInternalSymbolName(symbol, symbolName);
5345
- forEach(mergedMembers, includePrivateSymbol);
5346
5364
const nsBody = createModuleBlock([createExportDeclaration(
5347
5365
/*decorators*/ undefined,
5348
5366
/*modifiers*/ undefined,
5349
5367
createNamedExports(map(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => {
5350
5368
const name = unescapeLeadingUnderscores(s.escapedName);
5351
5369
const localName = getInternalSymbolName(s, name);
5352
- return createExportSpecifier(name === localName ? undefined : localName, name);
5370
+ const aliasDecl = s.declarations && getDeclarationOfAliasSymbol(s);
5371
+ const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true);
5372
+ includePrivateSymbol(target || s);
5373
+ const targetName = target ? getInternalSymbolName(target, unescapeLeadingUnderscores(target.escapedName)) : localName;
5374
+ return createExportSpecifier(name === targetName ? undefined : targetName, name);
5353
5375
}))
5354
5376
)]);
5355
5377
addResult(createModuleDeclaration(
@@ -5624,6 +5646,7 @@ namespace ts {
5624
5646
serializeMaybeAliasAssignment(symbol);
5625
5647
break;
5626
5648
case SyntaxKind.BinaryExpression:
5649
+ case SyntaxKind.PropertyAccessExpression:
5627
5650
// Could be best encoded as though an export specifier or as though an export assignment
5628
5651
// If name is default or export=, do an export assignment
5629
5652
// Otherwise do an export specifier
@@ -5634,10 +5657,6 @@ namespace ts {
5634
5657
serializeExportSpecifier(localName, targetName);
5635
5658
}
5636
5659
break;
5637
- case SyntaxKind.PropertyAccessExpression:
5638
- // A PAE alias is _always_ going to exist as an append to a top-level export, where our top level
5639
- // handling should always be sufficient to encode the export action itself
5640
- break;
5641
5660
default:
5642
5661
return Debug.failBadSyntaxKind(node, "Unhandled alias declaration kind in symbol serializer!");
5643
5662
}
@@ -5666,7 +5685,8 @@ namespace ts {
5666
5685
const aliasDecl = symbol.declarations && getDeclarationOfAliasSymbol(symbol);
5667
5686
// serialize what the alias points to, preserve the declaration's initializer
5668
5687
const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true);
5669
- if (target) {
5688
+ // If the target resolves and resolves to a thing defined in this file, emit as an alias, otherwise emit as a const
5689
+ if (target && length(target.declarations) && some(target.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(enclosingDeclaration))) {
5670
5690
// In case `target` refers to a namespace member, look at the declaration and serialize the leftmost symbol in it
5671
5691
// eg, `namespace A { export class B {} }; exports = A.B;`
5672
5692
// Technically, this is all that's required in the case where the assignment is an entity name expression
@@ -5752,6 +5772,7 @@ namespace ts {
5752
5772
return getObjectFlags(typeToSerialize) & (ObjectFlags.Anonymous | ObjectFlags.Mapped) &&
5753
5773
!getIndexInfoOfType(typeToSerialize, IndexKind.String) &&
5754
5774
!getIndexInfoOfType(typeToSerialize, IndexKind.Number) &&
5775
+ !!(length(getPropertiesOfType(typeToSerialize)) || length(getSignaturesOfType(typeToSerialize, SignatureKind.Call))) &&
5755
5776
!length(getSignaturesOfType(typeToSerialize, SignatureKind.Construct)) && // TODO: could probably serialize as function + ns + class, now that that's OK
5756
5777
!getDeclarationWithTypeAnnotation(hostSymbol) &&
5757
5778
!(typeToSerialize.symbol && some(typeToSerialize.symbol.declarations, d => getSourceFileOfNode(d) !== ctxSrc)) &&
@@ -6106,11 +6127,8 @@ namespace ts {
6106
6127
return context.remappedSymbolNames!.get("" + getSymbolId(symbol))!;
6107
6128
}
6108
6129
}
6109
- if (input === InternalSymbolName.Default) {
6110
- input = "_default";
6111
- }
6112
- else if (input === InternalSymbolName.ExportEquals) {
6113
- input = "_exports";
6130
+ if (symbol) {
6131
+ input = getNameCandidateWorker(symbol, input);
6114
6132
}
6115
6133
let i = 0;
6116
6134
const original = input;
@@ -6125,17 +6143,29 @@ namespace ts {
6125
6143
return input;
6126
6144
}
6127
6145
6128
- function getInternalSymbolName(symbol: Symbol, localName: string) {
6129
- if (context.remappedSymbolNames!.has("" + getSymbolId(symbol))) {
6130
- return context.remappedSymbolNames!.get("" + getSymbolId(symbol))!;
6131
- }
6146
+ function getNameCandidateWorker(symbol: Symbol, localName: string) {
6132
6147
if (localName === InternalSymbolName.Default || localName === InternalSymbolName.Class || localName === InternalSymbolName.Function) {
6133
6148
const flags = context.flags;
6134
6149
context.flags |= NodeBuilderFlags.InInitialEntityName;
6135
6150
const nameCandidate = getNameOfSymbolAsWritten(symbol, context);
6136
6151
context.flags = flags;
6137
- localName = isIdentifierText(nameCandidate, languageVersion) && !isStringANonContextualKeyword(nameCandidate) ? nameCandidate : getUnusedName(`_default`, symbol);
6152
+ localName = nameCandidate.length > 0 && isSingleOrDoubleQuote(nameCandidate.charCodeAt(0)) ? stripQuotes(nameCandidate) : nameCandidate;
6153
+ }
6154
+ if (localName === InternalSymbolName.Default) {
6155
+ localName = "_default";
6156
+ }
6157
+ else if (localName === InternalSymbolName.ExportEquals) {
6158
+ localName = "_exports";
6159
+ }
6160
+ localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-zA-Z0-9]/g, "_");
6161
+ return localName;
6162
+ }
6163
+
6164
+ function getInternalSymbolName(symbol: Symbol, localName: string) {
6165
+ if (context.remappedSymbolNames!.has("" + getSymbolId(symbol))) {
6166
+ return context.remappedSymbolNames!.get("" + getSymbolId(symbol))!;
6138
6167
}
6168
+ localName = getNameCandidateWorker(symbol, localName);
6139
6169
// The result of this is going to be used as the symbol's name - lock it in, so `getUnusedName` will also pick it up
6140
6170
context.remappedSymbolNames!.set("" + getSymbolId(symbol), localName);
6141
6171
return localName;
0 commit comments