Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ccc1909

Browse filesBrowse files
authored
Modify synthetic default generation code for dual-mode module resolution (microsoft#46156)
1 parent 016d78b commit ccc1909
Copy full SHA for ccc1909

14 files changed

+236-81Lines changed: 236 additions & 81 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+23-7Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,7 +2629,23 @@ namespace ts {
26292629
return ((isExportAssignment(node) && !node.isExportEquals) || hasSyntacticModifier(node, ModifierFlags.Default) || isExportSpecifier(node));
26302630
}
26312631

2632-
function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean) {
2632+
function getUsageModeForExpression(usage: Expression) {
2633+
return isStringLiteralLike(usage) ? getModeForUsageLocation(getSourceFileOfNode(usage), usage) : undefined;
2634+
}
2635+
2636+
function isESMFormatImportImportingCommonjsFormatFile(usageMode: SourceFile["impliedNodeFormat"], targetMode: SourceFile["impliedNodeFormat"]) {
2637+
return usageMode === ModuleKind.ESNext && targetMode === ModuleKind.CommonJS;
2638+
}
2639+
2640+
function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean, usage: Expression) {
2641+
const usageMode = file && getUsageModeForExpression(usage);
2642+
if (file && usageMode !== undefined) {
2643+
const result = isESMFormatImportImportingCommonjsFormatFile(usageMode, file.impliedNodeFormat);
2644+
if (usageMode === ModuleKind.ESNext || result) {
2645+
return result;
2646+
}
2647+
// fallthrough on cjs usages so we imply defaults for interop'd imports, too
2648+
}
26332649
if (!allowSyntheticDefaultImports) {
26342650
return false;
26352651
}
@@ -2672,7 +2688,7 @@ namespace ts {
26722688
}
26732689

26742690
const file = moduleSymbol.declarations?.find(isSourceFile);
2675-
const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias);
2691+
const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, node.parent.moduleSpecifier);
26762692
if (!exportDefaultSymbol && !hasSyntheticDefault) {
26772693
if (hasExportAssignmentSymbol(moduleSymbol)) {
26782694
const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop";
@@ -2824,7 +2840,7 @@ namespace ts {
28242840
let symbolFromModule = getExportOfModule(targetSymbol, name, specifier, dontResolveAlias);
28252841
if (symbolFromModule === undefined && name.escapedText === InternalSymbolName.Default) {
28262842
const file = moduleSymbol.declarations?.find(isSourceFile);
2827-
if (canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias)) {
2843+
if (canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) {
28282844
symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
28292845
}
28302846
}
@@ -3587,7 +3603,7 @@ namespace ts {
35873603
sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct);
35883604
}
35893605
if (sigs && sigs.length) {
3590-
const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol!);
3606+
const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol!, isImportCall(referenceParent) ? referenceParent.arguments[0] : referenceParent.moduleSpecifier);
35913607
// Create a new symbol which has the module's type less the call and construct signatures
35923608
const result = createSymbol(symbol.flags, symbol.escapedName);
35933609
result.declarations = symbol.declarations ? symbol.declarations.slice() : [];
@@ -30945,18 +30961,18 @@ namespace ts {
3094530961
if (moduleSymbol) {
3094630962
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true, /*suppressUsageError*/ false);
3094730963
if (esModuleSymbol) {
30948-
return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol));
30964+
return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol, specifier));
3094930965
}
3095030966
}
3095130967
return createPromiseReturnType(node, anyType);
3095230968
}
3095330969

30954-
function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol): Type {
30970+
function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression): Type {
3095530971
if (allowSyntheticDefaultImports && type && !isErrorType(type)) {
3095630972
const synthType = type as SyntheticDefaultModuleType;
3095730973
if (!synthType.syntheticType) {
3095830974
const file = originalSymbol.declarations?.find(isSourceFile);
30959-
const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false);
30975+
const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false, moduleSpecifier);
3096030976
if (hasSyntheticDefault) {
3096130977
const memberTable = createSymbolTable();
3096230978
const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default);
Collapse file

‎tests/baselines/reference/nodeModulesAllowJsSynchronousCallErrors(module=node12).types‎

Copy file name to clipboardExpand all lines: tests/baselines/reference/nodeModulesAllowJsSynchronousCallErrors(module=node12).types
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ export async function f() {
2323
>"../index.js" : "../index.js"
2424

2525
const mod4 = await import ("./index.js");
26-
>mod4 : typeof mod2
27-
>await import ("./index.js") : typeof mod2
28-
>import ("./index.js") : Promise<typeof mod2>
26+
>mod4 : { default: typeof mod2; f(): Promise<void>; }
27+
>await import ("./index.js") : { default: typeof mod2; f(): Promise<void>; }
28+
>import ("./index.js") : Promise<{ default: typeof mod2; f(): Promise<void>; }>
2929
>"./index.js" : "./index.js"
3030

3131
h();
@@ -57,9 +57,9 @@ export async function h() {
5757
>"./index.js" : "./index.js"
5858

5959
const mod4 = await import ("./subfolder/index.js");
60-
>mod4 : typeof mod2
61-
>await import ("./subfolder/index.js") : typeof mod2
62-
>import ("./subfolder/index.js") : Promise<typeof mod2>
60+
>mod4 : { default: typeof mod2; f(): Promise<void>; }
61+
>await import ("./subfolder/index.js") : { default: typeof mod2; f(): Promise<void>; }
62+
>import ("./subfolder/index.js") : Promise<{ default: typeof mod2; f(): Promise<void>; }>
6363
>"./subfolder/index.js" : "./subfolder/index.js"
6464

6565
f();
Collapse file

‎tests/baselines/reference/nodeModulesAllowJsSynchronousCallErrors(module=nodenext).types‎

Copy file name to clipboardExpand all lines: tests/baselines/reference/nodeModulesAllowJsSynchronousCallErrors(module=nodenext).types
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ export async function f() {
2323
>"../index.js" : "../index.js"
2424

2525
const mod4 = await import ("./index.js");
26-
>mod4 : typeof mod2
27-
>await import ("./index.js") : typeof mod2
28-
>import ("./index.js") : Promise<typeof mod2>
26+
>mod4 : { default: typeof mod2; f(): Promise<void>; }
27+
>await import ("./index.js") : { default: typeof mod2; f(): Promise<void>; }
28+
>import ("./index.js") : Promise<{ default: typeof mod2; f(): Promise<void>; }>
2929
>"./index.js" : "./index.js"
3030

3131
h();
@@ -57,9 +57,9 @@ export async function h() {
5757
>"./index.js" : "./index.js"
5858

5959
const mod4 = await import ("./subfolder/index.js");
60-
>mod4 : typeof mod2
61-
>await import ("./subfolder/index.js") : typeof mod2
62-
>import ("./subfolder/index.js") : Promise<typeof mod2>
60+
>mod4 : { default: typeof mod2; f(): Promise<void>; }
61+
>await import ("./subfolder/index.js") : { default: typeof mod2; f(): Promise<void>; }
62+
>import ("./subfolder/index.js") : Promise<{ default: typeof mod2; f(): Promise<void>; }>
6363
>"./subfolder/index.js" : "./subfolder/index.js"
6464

6565
f();
Collapse file
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//// [tests/cases/conformance/node/nodeModulesCjsFormatFileAlwaysHasDefault.ts] ////
2+
3+
//// [index.ts]
4+
// cjs format file
5+
export const a = 1;
6+
//// [index.ts]
7+
// esm format file
8+
import mod from "./subfolder/index.js";
9+
mod;
10+
//// [package.json]
11+
{
12+
"name": "package",
13+
"private": true,
14+
"type": "module"
15+
}
16+
//// [package.json]
17+
{
18+
"type": "commonjs"
19+
}
20+
21+
//// [index.js]
22+
"use strict";
23+
Object.defineProperty(exports, "__esModule", { value: true });
24+
exports.a = void 0;
25+
// cjs format file
26+
exports.a = 1;
27+
//// [index.js]
28+
// esm format file
29+
import mod from "./subfolder/index.js";
30+
mod;
31+
32+
33+
//// [index.d.ts]
34+
export declare const a = 1;
35+
//// [index.d.ts]
36+
export {};
Collapse file
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/conformance/node/subfolder/index.ts ===
2+
// cjs format file
3+
export const a = 1;
4+
>a : Symbol(a, Decl(index.ts, 1, 12))
5+
6+
=== tests/cases/conformance/node/index.ts ===
7+
// esm format file
8+
import mod from "./subfolder/index.js";
9+
>mod : Symbol(mod, Decl(index.ts, 1, 6))
10+
11+
mod;
12+
>mod : Symbol(mod, Decl(index.ts, 1, 6))
13+
Collapse file
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/conformance/node/subfolder/index.ts ===
2+
// cjs format file
3+
export const a = 1;
4+
>a : 1
5+
>1 : 1
6+
7+
=== tests/cases/conformance/node/index.ts ===
8+
// esm format file
9+
import mod from "./subfolder/index.js";
10+
>mod : typeof mod
11+
12+
mod;
13+
>mod : typeof mod
14+
Collapse file
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//// [tests/cases/conformance/node/nodeModulesCjsFormatFileAlwaysHasDefault.ts] ////
2+
3+
//// [index.ts]
4+
// cjs format file
5+
export const a = 1;
6+
//// [index.ts]
7+
// esm format file
8+
import mod from "./subfolder/index.js";
9+
mod;
10+
//// [package.json]
11+
{
12+
"name": "package",
13+
"private": true,
14+
"type": "module"
15+
}
16+
//// [package.json]
17+
{
18+
"type": "commonjs"
19+
}
20+
21+
//// [index.js]
22+
"use strict";
23+
Object.defineProperty(exports, "__esModule", { value: true });
24+
exports.a = void 0;
25+
// cjs format file
26+
exports.a = 1;
27+
//// [index.js]
28+
// esm format file
29+
import mod from "./subfolder/index.js";
30+
mod;
31+
32+
33+
//// [index.d.ts]
34+
export declare const a = 1;
35+
//// [index.d.ts]
36+
export {};
Collapse file
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/conformance/node/subfolder/index.ts ===
2+
// cjs format file
3+
export const a = 1;
4+
>a : Symbol(a, Decl(index.ts, 1, 12))
5+
6+
=== tests/cases/conformance/node/index.ts ===
7+
// esm format file
8+
import mod from "./subfolder/index.js";
9+
>mod : Symbol(mod, Decl(index.ts, 1, 6))
10+
11+
mod;
12+
>mod : Symbol(mod, Decl(index.ts, 1, 6))
13+
Collapse file
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/conformance/node/subfolder/index.ts ===
2+
// cjs format file
3+
export const a = 1;
4+
>a : 1
5+
>1 : 1
6+
7+
=== tests/cases/conformance/node/index.ts ===
8+
// esm format file
9+
import mod from "./subfolder/index.js";
10+
>mod : typeof mod
11+
12+
mod;
13+
>mod : typeof mod
14+
Collapse file

‎tests/baselines/reference/nodeModulesDeclarationEmitDynamicImportWithPackageExports.js‎

Copy file name to clipboardExpand all lines: tests/baselines/reference/nodeModulesDeclarationEmitDynamicImportWithPackageExports.js
+28-34Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ export {};
122122
//// [index.d.cts]
123123
export {};
124124
//// [other.d.ts]
125-
export declare const a: typeof import("package/cjs");
125+
export declare const a: {
126+
default: typeof import("package/cjs");
127+
};
126128
export declare const b: typeof import("package/mjs");
127129
export declare const c: typeof import("package");
128130
export declare const f: {
@@ -134,12 +136,11 @@ export declare const d: {
134136
default: typeof import("inner/cjs");
135137
cjsNonmain: true;
136138
};
137-
export declare const e: {
138-
default: typeof import("inner/mjs");
139-
esm: true;
140-
};
139+
export declare const e: typeof import("inner/mjs");
141140
//// [other.d.mts]
142-
export declare const a: typeof import("package/cjs");
141+
export declare const a: {
142+
default: typeof import("package/cjs");
143+
};
143144
export declare const b: typeof import("package/mjs");
144145
export declare const c: typeof import("package");
145146
export declare const f: {
@@ -151,12 +152,11 @@ export declare const d: {
151152
default: typeof import("inner/cjs");
152153
cjsNonmain: true;
153154
};
154-
export declare const e: {
155-
default: typeof import("inner/mjs");
156-
esm: true;
157-
};
155+
export declare const e: typeof import("inner/mjs");
158156
//// [other.d.cts]
159-
export declare const a: Promise<typeof import("package/cjs")>;
157+
export declare const a: Promise<{
158+
default: typeof import("package/cjs");
159+
}>;
160160
export declare const b: Promise<typeof import("package/mjs")>;
161161
export declare const c: Promise<typeof import("package")>;
162162
export declare const f: Promise<{
@@ -168,18 +168,15 @@ export declare const d: Promise<{
168168
default: typeof import("inner/cjs");
169169
cjsNonmain: true;
170170
}>;
171-
export declare const e: Promise<{
172-
default: typeof import("inner/mjs");
173-
esm: true;
174-
}>;
171+
export declare const e: Promise<typeof import("inner/mjs")>;
175172

176173

177174
//// [DtsFileErrors]
178175

179176

180-
tests/cases/conformance/node/other.d.cts(2,47): error TS1471: Module 'package/mjs' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
181-
tests/cases/conformance/node/other.d.cts(3,47): error TS1471: Module 'package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
182-
tests/cases/conformance/node/other2.d.cts(6,28): error TS1471: Module 'inner/mjs' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
177+
tests/cases/conformance/node/other.d.cts(4,47): error TS1471: Module 'package/mjs' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
178+
tests/cases/conformance/node/other.d.cts(5,47): error TS1471: Module 'package' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
179+
tests/cases/conformance/node/other2.d.cts(5,47): error TS1471: Module 'inner/mjs' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
183180

184181

185182
==== tests/cases/conformance/node/index.d.ts (0 errors) ====
@@ -192,7 +189,9 @@ tests/cases/conformance/node/other2.d.cts(6,28): error TS1471: Module 'inner/mjs
192189
export {};
193190

194191
==== tests/cases/conformance/node/other.d.ts (0 errors) ====
195-
export declare const a: typeof import("package/cjs");
192+
export declare const a: {
193+
default: typeof import("package/cjs");
194+
};
196195
export declare const b: typeof import("package/mjs");
197196
export declare const c: typeof import("package");
198197
export declare const f: {
@@ -205,13 +204,12 @@ tests/cases/conformance/node/other2.d.cts(6,28): error TS1471: Module 'inner/mjs
205204
default: typeof import("inner/cjs");
206205
cjsNonmain: true;
207206
};
208-
export declare const e: {
209-
default: typeof import("inner/mjs");
210-
esm: true;
211-
};
207+
export declare const e: typeof import("inner/mjs");
212208

213209
==== tests/cases/conformance/node/other.d.mts (0 errors) ====
214-
export declare const a: typeof import("package/cjs");
210+
export declare const a: {
211+
default: typeof import("package/cjs");
212+
};
215213
export declare const b: typeof import("package/mjs");
216214
export declare const c: typeof import("package");
217215
export declare const f: {
@@ -224,13 +222,12 @@ tests/cases/conformance/node/other2.d.cts(6,28): error TS1471: Module 'inner/mjs
224222
default: typeof import("inner/cjs");
225223
cjsNonmain: true;
226224
};
227-
export declare const e: {
228-
default: typeof import("inner/mjs");
229-
esm: true;
230-
};
225+
export declare const e: typeof import("inner/mjs");
231226

232227
==== tests/cases/conformance/node/other.d.cts (2 errors) ====
233-
export declare const a: Promise<typeof import("package/cjs")>;
228+
export declare const a: Promise<{
229+
default: typeof import("package/cjs");
230+
}>;
234231
export declare const b: Promise<typeof import("package/mjs")>;
235232
~~~~~~~~~~~~~
236233
!!! error TS1471: Module 'package/mjs' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
@@ -247,12 +244,9 @@ tests/cases/conformance/node/other2.d.cts(6,28): error TS1471: Module 'inner/mjs
247244
default: typeof import("inner/cjs");
248245
cjsNonmain: true;
249246
}>;
250-
export declare const e: Promise<{
251-
default: typeof import("inner/mjs");
252-
~~~~~~~~~~~
247+
export declare const e: Promise<typeof import("inner/mjs")>;
248+
~~~~~~~~~~~
253249
!!! error TS1471: Module 'inner/mjs' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported synchronously. Use dynamic import instead.
254-
esm: true;
255-
}>;
256250

257251
==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ====
258252
// cjs format file

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.