Skip to content

Commit f6fa5f3

Browse files
committed
Fix test and prevent CJS require from resolving
1 parent 81b9e70 commit f6fa5f3

File tree

8 files changed

+88
-32
lines changed

8 files changed

+88
-32
lines changed

src/compiler/binder.ts

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ import {
8282
getContainingClass,
8383
getEffectiveContainerForJSDocTemplateTag,
8484
getElementOrPropertyAccessName,
85+
getEmitModuleResolutionKind,
8586
getEmitScriptTarget,
8687
getEnclosingBlockScopeContainer,
8788
getErrorSpanForNode,
@@ -227,6 +228,7 @@ import {
227228
ModifierFlags,
228229
ModuleBlock,
229230
ModuleDeclaration,
231+
ModuleResolutionKind,
230232
Mutable,
231233
NamespaceExportDeclaration,
232234
Node,
@@ -3583,6 +3585,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
35833585
if (!isBindingPattern(node.name)) {
35843586
const possibleVariableDecl = node.kind === SyntaxKind.VariableDeclaration ? node : node.parent.parent;
35853587
if (isInJSFile(node) &&
3588+
getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Hybrid &&
35863589
isVariableDeclarationInitializedToBareOrAccessedRequire(possibleVariableDecl) &&
35873590
!getJSDocTypeTag(node) &&
35883591
!(getCombinedModifierFlags(node) & ModifierFlags.Export)

src/compiler/checker.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -4505,6 +4505,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
45054505
if (
45064506
namespace.valueDeclaration &&
45074507
isInJSFile(namespace.valueDeclaration) &&
4508+
getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Hybrid &&
45084509
isVariableDeclaration(namespace.valueDeclaration) &&
45094510
namespace.valueDeclaration.initializer &&
45104511
isCommonJsRequire(namespace.valueDeclaration.initializer)
@@ -33373,7 +33374,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3337333374
}
3337433375

3337533376
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
33376-
if (isInJSFile(node) && isCommonJsRequire(node)) {
33377+
if (isInJSFile(node) && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Hybrid && isCommonJsRequire(node)) {
3337733378
return resolveExternalModuleTypeByLiteral(node.arguments![0] as StringLiteral);
3337833379
}
3337933380

@@ -44099,7 +44100,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4409944100
// 4). type A = import("./f/*gotToDefinitionHere*/oo")
4410044101
if ((isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) ||
4410144102
((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) && (node.parent as ImportDeclaration).moduleSpecifier === node) ||
44102-
((isInJSFile(node) && isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || isImportCall(node.parent)) ||
44103+
((isInJSFile(node) && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Hybrid && isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || isImportCall(node.parent)) ||
4410344104
(isLiteralTypeNode(node.parent) && isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent)
4410444105
) {
4410544106
return resolveExternalModuleName(node, node as LiteralExpression, ignoreErrors);

src/compiler/program.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -3065,7 +3065,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
30653065
for (const node of file.statements) {
30663066
collectModuleReferences(node, /*inAmbientModule*/ false);
30673067
}
3068-
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
3068+
3069+
// `require` has no special meaning in `--moduleResolution hybrid`
3070+
const shouldProcessRequires = isJavaScriptFile && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Hybrid;
3071+
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || shouldProcessRequires) {
30693072
collectDynamicImportOrRequireCalls(file);
30703073
}
30713074

@@ -3127,7 +3130,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
31273130
const r = /import|require/g;
31283131
while (r.exec(file.text) !== null) { // eslint-disable-line no-null/no-null
31293132
const node = getNodeAtPosition(file, r.lastIndex);
3130-
if (isJavaScriptFile && isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
3133+
if (shouldProcessRequires && isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
31313134
setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here
31323135
imports = append(imports, node.arguments[0]);
31333136
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
1+
error TS2468: Cannot find global value 'Promise'.
12
/main.ts(2,1): error TS5099: Import assignment is not allowed when 'moduleResolution' is set to 'hybrid'. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead.
23
/main.ts(3,1): error TS5100: Export assignment cannot be used when 'moduleResolution' is set to 'hybrid'. Consider using 'export default' or another module format instead.
4+
/mainJs.js(2,1): error TS2712: A dynamic import call in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your '--lib' option.
35

46

7+
!!! error TS2468: Cannot find global value 'Promise'.
8+
==== /node_modules/@types/node/index.d.ts (0 errors) ====
9+
declare var require: (...args: any[]) => any;
10+
11+
==== /mainJs.js (1 errors) ====
12+
import {} from "./a";
13+
import("./a");
14+
~~~~~~~~~~~~~
15+
!!! error TS2712: A dynamic import call in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your '--lib' option.
16+
const _ = require("./a"); // No resolution
17+
_.a; // any
18+
519
==== /main.ts (2 errors) ====
620
import {} from "./a";
721
import _ = require("./a"); // Error
@@ -12,13 +26,6 @@
1226
!!! error TS5100: Export assignment cannot be used when 'moduleResolution' is set to 'hybrid'. Consider using 'export default' or another module format instead.
1327
export {};
1428

15-
==== /node_modules/@types/node/index.d.ts (0 errors) ====
16-
declare var require: (...args: any[]) => any;
17-
1829
==== /a.ts (0 errors) ====
19-
export {};
20-
21-
==== /mainJs.js (0 errors) ====
22-
import {} from "./a";
23-
const _ = require("./a"); // No resolution
30+
export const a = "a";
2431

tests/baselines/reference/hybridSyntaxRestrictions.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,33 @@
33
//// [index.d.ts]
44
declare var require: (...args: any[]) => any;
55

6-
//// [a.ts]
7-
export {};
8-
96
//// [mainJs.js]
107
import {} from "./a";
8+
import("./a");
119
const _ = require("./a"); // No resolution
10+
_.a; // any
1211

1312
//// [main.ts]
1413
import {} from "./a";
1514
import _ = require("./a"); // Error
1615
export = {}; // Error
1716
export {};
1817

18+
//// [a.ts]
19+
export const a = "a";
20+
1921

2022
//// [a.js]
2123
"use strict";
2224
exports.__esModule = true;
25+
exports.a = void 0;
26+
exports.a = "a";
27+
//// [mainJs.js]
28+
"use strict";
29+
exports.__esModule = true;
30+
Promise.resolve().then(function () { return require("./a"); });
31+
var _ = require("./a"); // No resolution
32+
_.a; // any
2333
//// [main.js]
2434
"use strict";
2535
module.exports = {};
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
=== /node_modules/@types/node/index.d.ts ===
2+
declare var require: (...args: any[]) => any;
3+
>require : Symbol(require, Decl(index.d.ts, 0, 11))
4+
>args : Symbol(args, Decl(index.d.ts, 0, 22))
5+
6+
=== /mainJs.js ===
7+
import {} from "./a";
8+
import("./a");
9+
>"./a" : Symbol("/a", Decl(a.ts, 0, 0))
10+
11+
const _ = require("./a"); // No resolution
12+
>_ : Symbol(_, Decl(mainJs.js, 2, 5))
13+
>require : Symbol(require, Decl(index.d.ts, 0, 11))
14+
15+
_.a; // any
16+
>_ : Symbol(_, Decl(mainJs.js, 2, 5))
17+
118
=== /main.ts ===
219
import {} from "./a";
320
import _ = require("./a"); // Error
@@ -6,12 +23,7 @@ import _ = require("./a"); // Error
623
export = {}; // Error
724
export {};
825

9-
=== /node_modules/@types/node/index.d.ts ===
10-
declare var require: (...args: any[]) => any;
11-
>require : Symbol(require, Decl(index.d.ts, 0, 11))
12-
>args : Symbol(args, Decl(index.d.ts, 0, 22))
13-
1426
=== /a.ts ===
15-
16-
export {};
27+
export const a = "a";
28+
>a : Symbol(a, Decl(a.ts, 0, 12))
1729

Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
=== /node_modules/@types/node/index.d.ts ===
2+
declare var require: (...args: any[]) => any;
3+
>require : (...args: any[]) => any
4+
>args : any[]
5+
6+
=== /mainJs.js ===
7+
import {} from "./a";
8+
import("./a");
9+
>import("./a") : Promise<typeof import("/a")>
10+
>"./a" : "./a"
11+
12+
const _ = require("./a"); // No resolution
13+
>_ : any
14+
>require("./a") : any
15+
>require : (...args: any[]) => any
16+
>"./a" : "./a"
17+
18+
_.a; // any
19+
>_.a : any
20+
>_ : any
21+
>a : any
22+
123
=== /main.ts ===
224
import {} from "./a";
325
import _ = require("./a"); // Error
@@ -8,12 +30,8 @@ export = {}; // Error
830

931
export {};
1032

11-
=== /node_modules/@types/node/index.d.ts ===
12-
declare var require: (...args: any[]) => any;
13-
>require : (...args: any[]) => any
14-
>args : any[]
15-
1633
=== /a.ts ===
17-
18-
export {};
34+
export const a = "a";
35+
>a : "a"
36+
>"a" : "a"
1937

tests/cases/conformance/moduleResolution/hybrid/hybridSyntaxRestrictions.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@
66
// @Filename: /node_modules/@types/node/index.d.ts
77
declare var require: (...args: any[]) => any;
88

9-
// @Filename: /a.ts
10-
export {};
11-
129
// @Filename: /mainJs.js
1310
import {} from "./a";
11+
import("./a");
1412
const _ = require("./a"); // No resolution
13+
_.a; // any
1514

1615
// @Filename: /main.ts
1716
import {} from "./a";
1817
import _ = require("./a"); // Error
1918
export = {}; // Error
2019
export {};
20+
21+
// @Filename: /a.ts
22+
export const a = "a";

0 commit comments

Comments
 (0)