mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
module.exports = Entity is an alias, just like export = Entity (#23570)
* Make `module.export =` an alias like `export=` is This breaks a couple of tests for previous workarounds. Fix in upcoming commits. * Basically fixes all the breaks, but needs cleanup * More notes to myself * Clean up TODOs * Call mergeSymbolTable and delete export= afterward instead of basically copying the code myself. * More cleanup * Remove unnecessary check in import type checking * Revert to DIY code. It is more correct and will go away in a few days. * Exported class expressions can be used as type In both JS and TS * Do not require named class expressions
This commit is contained in:
@@ -2220,14 +2220,14 @@ namespace ts {
|
||||
bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"` as __String);
|
||||
}
|
||||
|
||||
function bindExportAssignment(node: ExportAssignment | BinaryExpression) {
|
||||
function bindExportAssignment(node: ExportAssignment) {
|
||||
if (!container.symbol || !container.symbol.exports) {
|
||||
// Export assignment in some sort of block construct
|
||||
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node));
|
||||
}
|
||||
else {
|
||||
const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node)
|
||||
// An export default clause with an EntityNameExpression exports all meanings of that identifier
|
||||
// An export default clause with an EntityNameExpression or a class expression exports all meanings of that identifier or expression;
|
||||
? SymbolFlags.Alias
|
||||
// An export default clause with any other expression exports a value
|
||||
: SymbolFlags.Property;
|
||||
@@ -2322,7 +2322,10 @@ namespace ts {
|
||||
|
||||
// 'module.exports = expr' assignment
|
||||
setCommonJsModuleIndicator(node);
|
||||
declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule, SymbolFlags.None);
|
||||
const flags = exportAssignmentIsAlias(node)
|
||||
? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class
|
||||
: SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule;
|
||||
declareSymbol(file.symbol.exports, file.symbol, node, flags, SymbolFlags.None);
|
||||
}
|
||||
|
||||
function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
|
||||
|
||||
+22
-9
@@ -1926,13 +1926,17 @@ namespace ts {
|
||||
resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias);
|
||||
}
|
||||
|
||||
function getTargetOfExportAssignment(node: ExportAssignment, dontResolveAlias: boolean): Symbol | undefined {
|
||||
const aliasLike = resolveEntityName(<EntityNameExpression>node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontResolveAlias);
|
||||
function getTargetOfExportAssignment(node: ExportAssignment | BinaryExpression, dontResolveAlias: boolean): Symbol | undefined {
|
||||
const expression = (isExportAssignment(node) ? node.expression : node.right) as EntityNameExpression | ClassExpression;
|
||||
if (isClassExpression(expression)) {
|
||||
return checkExpression(expression).symbol;
|
||||
}
|
||||
const aliasLike = resolveEntityName(expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontResolveAlias);
|
||||
if (aliasLike) {
|
||||
return aliasLike;
|
||||
}
|
||||
checkExpression(node.expression);
|
||||
return getNodeLinks(node.expression).resolvedSymbol;
|
||||
checkExpression(expression);
|
||||
return getNodeLinks(expression).resolvedSymbol;
|
||||
}
|
||||
|
||||
function getTargetOfAliasDeclaration(node: Declaration, dontRecursivelyResolve?: boolean): Symbol | undefined {
|
||||
@@ -1948,7 +1952,8 @@ namespace ts {
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
return getTargetOfExportSpecifier(<ExportSpecifier>node, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, dontRecursivelyResolve);
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return getTargetOfExportAssignment(<ExportAssignment>node, dontRecursivelyResolve);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return getTargetOfExportAssignment((<ExportAssignment | BinaryExpression>node), dontRecursivelyResolve);
|
||||
case SyntaxKind.NamespaceExportDeclaration:
|
||||
return getTargetOfNamespaceExportDeclaration(<NamespaceExportDeclaration>node, dontRecursivelyResolve);
|
||||
}
|
||||
@@ -2229,20 +2234,28 @@ namespace ts {
|
||||
// An external module with an 'export =' declaration resolves to the target of the 'export =' declaration,
|
||||
// and an external module with no 'export =' declaration resolves to the module itself.
|
||||
function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol {
|
||||
return moduleSymbol && getMergedSymbol(resolveSymbol(getCommonJsExportEquals(moduleSymbol), dontResolveAlias)) || moduleSymbol;
|
||||
return moduleSymbol && getMergedSymbol(getCommonJsExportEquals(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias), moduleSymbol)) || moduleSymbol;
|
||||
}
|
||||
|
||||
function getCommonJsExportEquals(moduleSymbol: Symbol): Symbol {
|
||||
const exported = moduleSymbol.exports.get(InternalSymbolName.ExportEquals);
|
||||
if (!exported || !exported.exports || moduleSymbol.exports.size === 1) {
|
||||
function getCommonJsExportEquals(exported: Symbol, moduleSymbol: Symbol): Symbol {
|
||||
if (!exported || moduleSymbol.exports.size === 1) {
|
||||
return exported;
|
||||
}
|
||||
const merged = cloneSymbol(exported);
|
||||
if (merged.exports === undefined) {
|
||||
merged.flags = merged.flags | SymbolFlags.ValueModule;
|
||||
merged.exports = createSymbolTable();
|
||||
}
|
||||
moduleSymbol.exports.forEach((s, name) => {
|
||||
if (name === InternalSymbolName.ExportEquals) return;
|
||||
if (!merged.exports.has(name)) {
|
||||
merged.exports.set(name, s);
|
||||
}
|
||||
else {
|
||||
const ms = cloneSymbol(merged.exports.get(name));
|
||||
mergeSymbol(ms, s);
|
||||
merged.exports.set(name, ms);
|
||||
}
|
||||
});
|
||||
return merged;
|
||||
}
|
||||
|
||||
@@ -2140,11 +2140,13 @@ namespace ts {
|
||||
node.kind === SyntaxKind.NamespaceImport ||
|
||||
node.kind === SyntaxKind.ImportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node);
|
||||
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node) ||
|
||||
isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === SpecialPropertyAssignmentKind.ModuleExports;
|
||||
}
|
||||
|
||||
export function exportAssignmentIsAlias(node: ExportAssignment): boolean {
|
||||
return isEntityNameExpression(node.expression);
|
||||
export function exportAssignmentIsAlias(node: ExportAssignment | BinaryExpression): boolean {
|
||||
const e = isExportAssignment(node) ? node.expression : node.right;
|
||||
return isEntityNameExpression(e) || isClassExpression(e);
|
||||
}
|
||||
|
||||
export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration | InterfaceDeclaration) {
|
||||
|
||||
Reference in New Issue
Block a user