Merge pull request #5588 from Microsoft/reexport-default-export
Reexport default export
This commit is contained in:
commit
c1ea85fa72
5 changed files with 113 additions and 22 deletions
|
@ -486,9 +486,19 @@ namespace ts {
|
||||||
if (location.kind === SyntaxKind.SourceFile ||
|
if (location.kind === SyntaxKind.SourceFile ||
|
||||||
(location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) {
|
(location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) {
|
||||||
|
|
||||||
// It's an external module. Because of module/namespace merging, a module's exports are in scope,
|
// It's an external module. First see if the module has an export default and if the local
|
||||||
// yet we never want to treat an export specifier as putting a member in scope. Therefore,
|
// name of that export default matches.
|
||||||
// if the name we find is purely an export specifier, it is not actually considered in scope.
|
if (result = moduleExports["default"]) {
|
||||||
|
const localSymbol = getLocalSymbolForExportDefault(result);
|
||||||
|
if (localSymbol && (result.flags & meaning) && localSymbol.name === name) {
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
result = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because of module/namespace merging, a module's exports are in scope,
|
||||||
|
// yet we never want to treat an export specifier as putting a member in scope.
|
||||||
|
// Therefore, if the name we find is purely an export specifier, it is not actually considered in scope.
|
||||||
// Two things to note about this:
|
// Two things to note about this:
|
||||||
// 1. We have to check this without calling getSymbol. The problem with calling getSymbol
|
// 1. We have to check this without calling getSymbol. The problem with calling getSymbol
|
||||||
// on an export specifier is that it might find the export specifier itself, and try to
|
// on an export specifier is that it might find the export specifier itself, and try to
|
||||||
|
@ -502,13 +512,6 @@ namespace ts {
|
||||||
getDeclarationOfKind(moduleExports[name], SyntaxKind.ExportSpecifier)) {
|
getDeclarationOfKind(moduleExports[name], SyntaxKind.ExportSpecifier)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = moduleExports["default"];
|
|
||||||
const localSymbol = getLocalSymbolForExportDefault(result);
|
|
||||||
if (result && localSymbol && (result.flags & meaning) && localSymbol.name === name) {
|
|
||||||
break loop;
|
|
||||||
}
|
|
||||||
result = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result = getSymbol(moduleExports, name, meaning & SymbolFlags.ModuleMember)) {
|
if (result = getSymbol(moduleExports, name, meaning & SymbolFlags.ModuleMember)) {
|
||||||
|
@ -4201,12 +4204,12 @@ namespace ts {
|
||||||
// We only support expressions that are simple qualified names. For other expressions this produces undefined.
|
// We only support expressions that are simple qualified names. For other expressions this produces undefined.
|
||||||
const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeName :
|
const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeName :
|
||||||
isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node) ? (<ExpressionWithTypeArguments>node).expression :
|
isSupportedExpressionWithTypeArguments(<ExpressionWithTypeArguments>node) ? (<ExpressionWithTypeArguments>node).expression :
|
||||||
undefined;
|
undefined;
|
||||||
const symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
|
const symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
|
||||||
const type = symbol === unknownSymbol ? unknownType :
|
const type = symbol === unknownSymbol ? unknownType :
|
||||||
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
|
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
|
||||||
symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) :
|
symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) :
|
||||||
getTypeFromNonGenericTypeReference(node, symbol);
|
getTypeFromNonGenericTypeReference(node, symbol);
|
||||||
// Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
|
// Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
|
||||||
// type reference in checkTypeReferenceOrExpressionWithTypeArguments.
|
// type reference in checkTypeReferenceOrExpressionWithTypeArguments.
|
||||||
links.resolvedSymbol = symbol;
|
links.resolvedSymbol = symbol;
|
||||||
|
@ -11446,7 +11449,7 @@ namespace ts {
|
||||||
|
|
||||||
// Abstract methods can't have an implementation -- in particular, they don't need one.
|
// Abstract methods can't have an implementation -- in particular, they don't need one.
|
||||||
if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
|
if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
|
||||||
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) ) {
|
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract)) {
|
||||||
reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
|
reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14380,8 +14383,8 @@ namespace ts {
|
||||||
if (className) {
|
if (className) {
|
||||||
copySymbol(location.symbol, meaning);
|
copySymbol(location.symbol, meaning);
|
||||||
}
|
}
|
||||||
// fall through; this fall-through is necessary because we would like to handle
|
// fall through; this fall-through is necessary because we would like to handle
|
||||||
// type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration
|
// type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration
|
||||||
case SyntaxKind.ClassDeclaration:
|
case SyntaxKind.ClassDeclaration:
|
||||||
case SyntaxKind.InterfaceDeclaration:
|
case SyntaxKind.InterfaceDeclaration:
|
||||||
// If we didn't come from static member of class or interface,
|
// If we didn't come from static member of class or interface,
|
||||||
|
@ -14537,8 +14540,8 @@ namespace ts {
|
||||||
return resolveEntityName(<EntityName>entityName, meaning);
|
return resolveEntityName(<EntityName>entityName, meaning);
|
||||||
}
|
}
|
||||||
else if ((entityName.parent.kind === SyntaxKind.JsxOpeningElement) ||
|
else if ((entityName.parent.kind === SyntaxKind.JsxOpeningElement) ||
|
||||||
(entityName.parent.kind === SyntaxKind.JsxSelfClosingElement) ||
|
(entityName.parent.kind === SyntaxKind.JsxSelfClosingElement) ||
|
||||||
(entityName.parent.kind === SyntaxKind.JsxClosingElement)) {
|
(entityName.parent.kind === SyntaxKind.JsxClosingElement)) {
|
||||||
return getJsxElementTagSymbol(<JsxOpeningLikeElement>entityName.parent);
|
return getJsxElementTagSymbol(<JsxOpeningLikeElement>entityName.parent);
|
||||||
}
|
}
|
||||||
else if (isExpression(entityName)) {
|
else if (isExpression(entityName)) {
|
||||||
|
@ -14605,8 +14608,8 @@ namespace ts {
|
||||||
: getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
|
: getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
|
||||||
}
|
}
|
||||||
else if (node.parent.kind === SyntaxKind.BindingElement &&
|
else if (node.parent.kind === SyntaxKind.BindingElement &&
|
||||||
node.parent.parent.kind === SyntaxKind.ObjectBindingPattern &&
|
node.parent.parent.kind === SyntaxKind.ObjectBindingPattern &&
|
||||||
node === (<BindingElement>node.parent).propertyName) {
|
node === (<BindingElement>node.parent).propertyName) {
|
||||||
const typeOfPattern = getTypeOfNode(node.parent.parent);
|
const typeOfPattern = getTypeOfNode(node.parent.parent);
|
||||||
const propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (<Identifier>node).text);
|
const propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (<Identifier>node).text);
|
||||||
|
|
||||||
|
@ -14643,7 +14646,7 @@ namespace ts {
|
||||||
(<ImportDeclaration>node.parent).moduleSpecifier === node)) {
|
(<ImportDeclaration>node.parent).moduleSpecifier === node)) {
|
||||||
return resolveExternalModuleName(node, <LiteralExpression>node);
|
return resolveExternalModuleName(node, <LiteralExpression>node);
|
||||||
}
|
}
|
||||||
// Fall through
|
// Fall through
|
||||||
|
|
||||||
case SyntaxKind.NumericLiteral:
|
case SyntaxKind.NumericLiteral:
|
||||||
// index access
|
// index access
|
||||||
|
@ -14839,7 +14842,7 @@ namespace ts {
|
||||||
if (links.isNestedRedeclaration === undefined) {
|
if (links.isNestedRedeclaration === undefined) {
|
||||||
const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
|
const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
|
||||||
links.isNestedRedeclaration = isStatementWithLocals(container) &&
|
links.isNestedRedeclaration = isStatementWithLocals(container) &&
|
||||||
!!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
!!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
||||||
}
|
}
|
||||||
return links.isNestedRedeclaration;
|
return links.isNestedRedeclaration;
|
||||||
}
|
}
|
||||||
|
|
27
tests/baselines/reference/reExportDefaultExport.js
Normal file
27
tests/baselines/reference/reExportDefaultExport.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//// [tests/cases/conformance/es6/modules/reExportDefaultExport.ts] ////
|
||||||
|
|
||||||
|
//// [m1.ts]
|
||||||
|
|
||||||
|
export default function f() {
|
||||||
|
}
|
||||||
|
export {f};
|
||||||
|
|
||||||
|
|
||||||
|
//// [m2.ts]
|
||||||
|
import foo from "./m1";
|
||||||
|
import {f} from "./m1";
|
||||||
|
|
||||||
|
f();
|
||||||
|
foo();
|
||||||
|
|
||||||
|
//// [m1.js]
|
||||||
|
function f() {
|
||||||
|
}
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.default = f;
|
||||||
|
exports.f = f;
|
||||||
|
//// [m2.js]
|
||||||
|
var m1_1 = require("./m1");
|
||||||
|
var m1_2 = require("./m1");
|
||||||
|
m1_2.f();
|
||||||
|
m1_1.default();
|
22
tests/baselines/reference/reExportDefaultExport.symbols
Normal file
22
tests/baselines/reference/reExportDefaultExport.symbols
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
=== tests/cases/conformance/es6/modules/m1.ts ===
|
||||||
|
|
||||||
|
export default function f() {
|
||||||
|
>f : Symbol(f, Decl(m1.ts, 0, 0))
|
||||||
|
}
|
||||||
|
export {f};
|
||||||
|
>f : Symbol(f, Decl(m1.ts, 3, 8))
|
||||||
|
|
||||||
|
|
||||||
|
=== tests/cases/conformance/es6/modules/m2.ts ===
|
||||||
|
import foo from "./m1";
|
||||||
|
>foo : Symbol(foo, Decl(m2.ts, 0, 6))
|
||||||
|
|
||||||
|
import {f} from "./m1";
|
||||||
|
>f : Symbol(f, Decl(m2.ts, 1, 8))
|
||||||
|
|
||||||
|
f();
|
||||||
|
>f : Symbol(f, Decl(m2.ts, 1, 8))
|
||||||
|
|
||||||
|
foo();
|
||||||
|
>foo : Symbol(foo, Decl(m2.ts, 0, 6))
|
||||||
|
|
24
tests/baselines/reference/reExportDefaultExport.types
Normal file
24
tests/baselines/reference/reExportDefaultExport.types
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
=== tests/cases/conformance/es6/modules/m1.ts ===
|
||||||
|
|
||||||
|
export default function f() {
|
||||||
|
>f : () => void
|
||||||
|
}
|
||||||
|
export {f};
|
||||||
|
>f : () => void
|
||||||
|
|
||||||
|
|
||||||
|
=== tests/cases/conformance/es6/modules/m2.ts ===
|
||||||
|
import foo from "./m1";
|
||||||
|
>foo : () => void
|
||||||
|
|
||||||
|
import {f} from "./m1";
|
||||||
|
>f : () => void
|
||||||
|
|
||||||
|
f();
|
||||||
|
>f() : void
|
||||||
|
>f : () => void
|
||||||
|
|
||||||
|
foo();
|
||||||
|
>foo() : void
|
||||||
|
>foo : () => void
|
||||||
|
|
15
tests/cases/conformance/es6/modules/reExportDefaultExport.ts
Normal file
15
tests/cases/conformance/es6/modules/reExportDefaultExport.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// @module: commonjs
|
||||||
|
// @target: ES5
|
||||||
|
|
||||||
|
// @filename: m1.ts
|
||||||
|
export default function f() {
|
||||||
|
}
|
||||||
|
export {f};
|
||||||
|
|
||||||
|
|
||||||
|
// @filename: m2.ts
|
||||||
|
import foo from "./m1";
|
||||||
|
import {f} from "./m1";
|
||||||
|
|
||||||
|
f();
|
||||||
|
foo();
|
Loading…
Reference in a new issue