Skip to content

Commit 43e758e

Browse files
authored
Create synthetic default exports for dynamic imports (microsoft#17492)
* Create synthetic default exports for dynamic imports * Slightly better solution * Actually accept baselines * Slightly adjust synthetic type * Cache synthetic type * Inline variables, remove non-required calls * Rename function
1 parent 847d7fe commit 43e758e

15 files changed

Lines changed: 224 additions & 129 deletions

src/compiler/checker.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,7 +1757,7 @@ namespace ts {
17571757
// An external module with an 'export =' declaration resolves to the target of the 'export =' declaration,
17581758
// and an external module with no 'export =' declaration resolves to the module itself.
17591759
function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol {
1760-
return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get("export=" as __String), dontResolveAlias)) || moduleSymbol;
1760+
return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias)) || moduleSymbol;
17611761
}
17621762

17631763
// An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export ='
@@ -1772,7 +1772,7 @@ namespace ts {
17721772
}
17731773

17741774
function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean {
1775-
return moduleSymbol.exports.get("export=" as __String) !== undefined;
1775+
return moduleSymbol.exports.get(InternalSymbolName.ExportEquals) !== undefined;
17761776
}
17771777

17781778
function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] {
@@ -16402,12 +16402,35 @@ namespace ts {
1640216402
if (moduleSymbol) {
1640316403
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
1640416404
if (esModuleSymbol) {
16405-
return createPromiseReturnType(node, getTypeOfSymbol(esModuleSymbol));
16405+
return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol));
1640616406
}
1640716407
}
1640816408
return createPromiseReturnType(node, anyType);
1640916409
}
1641016410

16411+
function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol): Type {
16412+
if (allowSyntheticDefaultImports && type && type !== unknownType) {
16413+
const synthType = type as SyntheticDefaultModuleType;
16414+
if (!synthType.syntheticType) {
16415+
if (!getPropertyOfType(type, InternalSymbolName.Default)) {
16416+
const memberTable = createSymbolTable();
16417+
const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default);
16418+
newSymbol.target = resolveSymbol(symbol);
16419+
memberTable.set(InternalSymbolName.Default, newSymbol);
16420+
const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
16421+
const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
16422+
anonymousSymbol.type = defaultContainingObject;
16423+
synthType.syntheticType = getIntersectionType([type, defaultContainingObject]);
16424+
}
16425+
else {
16426+
synthType.syntheticType = type;
16427+
}
16428+
}
16429+
return synthType.syntheticType;
16430+
}
16431+
return type;
16432+
}
16433+
1641116434
function isCommonJsRequire(node: Node) {
1641216435
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
1641316436
return false;

src/compiler/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3318,6 +3318,11 @@ namespace ts {
33183318
awaitedTypeOfType?: Type;
33193319
}
33203320

3321+
/* @internal */
3322+
export interface SyntheticDefaultModuleType extends Type {
3323+
syntheticType?: Type;
3324+
}
3325+
33213326
export interface TypeVariable extends Type {
33223327
/* @internal */
33233328
resolvedBaseConstraint: Type;

tests/baselines/reference/importCallExpressionAsyncES3System.types

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ export async function fn() {
33
>fn : () => Promise<void>
44

55
const req = await import('./test') // ONE
6-
>req : typeof "tests/cases/conformance/dynamicImport/test"
7-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
8-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
6+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
7+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
8+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
99
>'./test' : "./test"
1010
}
1111

@@ -16,9 +16,9 @@ export class cl1 {
1616
>m : () => Promise<void>
1717

1818
const req = await import('./test') // TWO
19-
>req : typeof "tests/cases/conformance/dynamicImport/test"
20-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
21-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
19+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
20+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
21+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
2222
>'./test' : "./test"
2323
}
2424
}
@@ -32,9 +32,9 @@ export const obj = {
3232
>async () => { const req = await import('./test') // THREE } : () => Promise<void>
3333

3434
const req = await import('./test') // THREE
35-
>req : typeof "tests/cases/conformance/dynamicImport/test"
36-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
37-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
35+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
36+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
37+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
3838
>'./test' : "./test"
3939
}
4040
}
@@ -51,9 +51,9 @@ export class cl2 {
5151
>async () => { const req = await import('./test') // FOUR } : () => Promise<void>
5252

5353
const req = await import('./test') // FOUR
54-
>req : typeof "tests/cases/conformance/dynamicImport/test"
55-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
56-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
54+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
55+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
56+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
5757
>'./test' : "./test"
5858
}
5959
}
@@ -64,9 +64,9 @@ export const l = async () => {
6464
>async () => { const req = await import('./test') // FIVE} : () => Promise<void>
6565

6666
const req = await import('./test') // FIVE
67-
>req : typeof "tests/cases/conformance/dynamicImport/test"
68-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
69-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
67+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
68+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
69+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
7070
>'./test' : "./test"
7171
}
7272

tests/baselines/reference/importCallExpressionAsyncES5System.types

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ export async function fn() {
33
>fn : () => Promise<void>
44

55
const req = await import('./test') // ONE
6-
>req : typeof "tests/cases/conformance/dynamicImport/test"
7-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
8-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
6+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
7+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
8+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
99
>'./test' : "./test"
1010
}
1111

@@ -16,9 +16,9 @@ export class cl1 {
1616
>m : () => Promise<void>
1717

1818
const req = await import('./test') // TWO
19-
>req : typeof "tests/cases/conformance/dynamicImport/test"
20-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
21-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
19+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
20+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
21+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
2222
>'./test' : "./test"
2323
}
2424
}
@@ -32,9 +32,9 @@ export const obj = {
3232
>async () => { const req = await import('./test') // THREE } : () => Promise<void>
3333

3434
const req = await import('./test') // THREE
35-
>req : typeof "tests/cases/conformance/dynamicImport/test"
36-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
37-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
35+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
36+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
37+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
3838
>'./test' : "./test"
3939
}
4040
}
@@ -51,9 +51,9 @@ export class cl2 {
5151
>async () => { const req = await import('./test') // FOUR } : () => Promise<void>
5252

5353
const req = await import('./test') // FOUR
54-
>req : typeof "tests/cases/conformance/dynamicImport/test"
55-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
56-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
54+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
55+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
56+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
5757
>'./test' : "./test"
5858
}
5959
}
@@ -64,9 +64,9 @@ export const l = async () => {
6464
>async () => { const req = await import('./test') // FIVE} : () => Promise<void>
6565

6666
const req = await import('./test') // FIVE
67-
>req : typeof "tests/cases/conformance/dynamicImport/test"
68-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
69-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
67+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
68+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
69+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
7070
>'./test' : "./test"
7171
}
7272

tests/baselines/reference/importCallExpressionAsyncES6System.types

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ export async function fn() {
33
>fn : () => Promise<void>
44

55
const req = await import('./test') // ONE
6-
>req : typeof "tests/cases/conformance/dynamicImport/test"
7-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
8-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
6+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
7+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
8+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
99
>'./test' : "./test"
1010
}
1111

@@ -16,9 +16,9 @@ export class cl1 {
1616
>m : () => Promise<void>
1717

1818
const req = await import('./test') // TWO
19-
>req : typeof "tests/cases/conformance/dynamicImport/test"
20-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
21-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
19+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
20+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
21+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
2222
>'./test' : "./test"
2323
}
2424
}
@@ -32,9 +32,9 @@ export const obj = {
3232
>async () => { const req = await import('./test') // THREE } : () => Promise<void>
3333

3434
const req = await import('./test') // THREE
35-
>req : typeof "tests/cases/conformance/dynamicImport/test"
36-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
37-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
35+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
36+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
37+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
3838
>'./test' : "./test"
3939
}
4040
}
@@ -51,9 +51,9 @@ export class cl2 {
5151
>async () => { const req = await import('./test') // FOUR } : () => Promise<void>
5252

5353
const req = await import('./test') // FOUR
54-
>req : typeof "tests/cases/conformance/dynamicImport/test"
55-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
56-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
54+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
55+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
56+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
5757
>'./test' : "./test"
5858
}
5959
}
@@ -64,9 +64,9 @@ export const l = async () => {
6464
>async () => { const req = await import('./test') // FIVE} : () => Promise<void>
6565

6666
const req = await import('./test') // FIVE
67-
>req : typeof "tests/cases/conformance/dynamicImport/test"
68-
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test"
69-
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test">
67+
>req : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
68+
>await import('./test') : typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }
69+
>import('./test') : Promise<typeof "tests/cases/conformance/dynamicImport/test" & { default: typeof "tests/cases/conformance/dynamicImport/test"; }>
7070
>'./test' : "./test"
7171
}
7272

0 commit comments

Comments
 (0)