Skip to content

Commit 6b890f9

Browse files
authoredSep 12, 2022
Handle more places where package direcroy is converted to canonical file path (#50740)
* Add test for node16 resolution with package json lookup making casing incorrect * Handle more places where package direcroy is converted to canonical file path
1 parent f5f2923 commit 6b890f9

13 files changed

+219
-68
lines changed
 

‎src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3630,7 +3630,7 @@ namespace ts {
36303630
if (ext === Extension.Ts || ext === Extension.Js || ext === Extension.Tsx || ext === Extension.Jsx) {
36313631
const scope = currentSourceFile.packageJsonScope;
36323632
const targetExt = ext === Extension.Ts ? Extension.Mts : ext === Extension.Js ? Extension.Mjs : undefined;
3633-
if (scope && !scope.packageJsonContent.type) {
3633+
if (scope && !scope.contents.packageJsonContent.type) {
36343634
if (targetExt) {
36353635
diagnosticDetails = chainDiagnosticMessages(
36363636
/*details*/ undefined,

‎src/compiler/moduleNameResolver.ts

+43-39
Large diffs are not rendered by default.

‎src/compiler/moduleSpecifiers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ namespace ts.moduleSpecifiers {
807807
let maybeBlockedByTypesVersions = false;
808808
const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath);
809809
if (typeof cachedPackageJson === "object" || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) {
810-
const packageJsonContent = cachedPackageJson?.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!);
810+
const packageJsonContent = cachedPackageJson?.contents.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!);
811811
const importMode = overrideMode || importingSourceFile.impliedNodeFormat;
812812
if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext) {
813813
const conditions = ["node", importMode === ModuleKind.ESNext ? "import" : "require", "types"];

‎src/compiler/program.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ namespace ts {
849849

850850
/*@internal*/
851851
export function getImpliedNodeFormatForFileWorker(
852-
fileName: Path,
852+
fileName: string,
853853
packageJsonInfoCache: PackageJsonInfoCache | undefined,
854854
host: ModuleResolutionHost,
855855
options: CompilerOptions,
@@ -870,7 +870,7 @@ namespace ts {
870870
state.failedLookupLocations = packageJsonLocations;
871871
state.affectingLocations = packageJsonLocations;
872872
const packageJsonScope = getPackageScopeForPath(fileName, state);
873-
const impliedNodeFormat = packageJsonScope?.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
873+
const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
874874
return { impliedNodeFormat, packageJsonLocations, packageJsonScope };
875875
}
876876
}
@@ -2834,7 +2834,7 @@ namespace ts {
28342834
// It's a _little odd_ that we can't set `impliedNodeFormat` until the program step - but it's the first and only time we have a resolution cache
28352835
// and a freshly made source file node on hand at the same time, and we need both to set the field. Persisting the resolution cache all the way
28362836
// to the check and emit steps would be bad - so we much prefer detecting and storing the format information on the source file node upfront.
2837-
const result = getImpliedNodeFormatForFileWorker(toPath(fileName), moduleResolutionCache?.getPackageJsonInfoCache(), host, options);
2837+
const result = getImpliedNodeFormatForFileWorker(getNormalizedAbsolutePath(fileName, currentDirectory), moduleResolutionCache?.getPackageJsonInfoCache(), host, options);
28382838
const languageVersion = getEmitScriptTarget(options);
28392839
const setExternalModuleIndicator = getSetExternalModuleIndicator(options);
28402840
return typeof result === "object" ?

‎src/compiler/watch.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ namespace ts {
262262
if (file.packageJsonScope) {
263263
(result ??= []).push(chainDiagnosticMessages(
264264
/*details*/ undefined,
265-
file.packageJsonScope.packageJsonContent.type ?
265+
file.packageJsonScope.contents.packageJsonContent.type ?
266266
Diagnostics.File_is_CommonJS_module_because_0_has_field_type_whose_value_is_not_module :
267267
Diagnostics.File_is_CommonJS_module_because_0_does_not_have_field_type,
268268
toFileName(last(file.packageJsonLocations!), fileNameConvertor)

‎src/server/session.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,7 @@ namespace ts.server {
13781378
const packageDirectory = fileName.substring(0, nodeModulesPathParts.packageRootIndex);
13791379
const packageJsonCache = project.getModuleResolutionCache()?.getPackageJsonInfoCache();
13801380
const compilerOptions = project.getCompilationSettings();
1381-
const packageJson = getPackageScopeForPath(project.toPath(packageDirectory + "/package.json"), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions));
1381+
const packageJson = getPackageScopeForPath(getNormalizedAbsolutePath(packageDirectory + "/package.json", project.getCurrentDirectory()), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions));
13821382
if (!packageJson) return undefined;
13831383
// Use fake options instead of actual compiler options to avoid following export map if the project uses node16 or nodenext -
13841384
// Mapping from an export map entry across packages is out of scope for now. Returned entrypoints will only be what can be

‎src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts

+31
Original file line numberDiff line numberDiff line change
@@ -326,5 +326,36 @@ a;b;
326326
}, { currentDirectory: "/Users/name/projects/web" }),
327327
changes: emptyArray,
328328
});
329+
330+
331+
verifyTscWatch({
332+
scenario: "forceConsistentCasingInFileNames",
333+
subScenario: "package json is looked up for file",
334+
commandLineArgs: ["-w", "--explainFiles"],
335+
sys: () => createWatchedSystem({
336+
"/Users/name/projects/lib-boilerplate/package.json": JSON.stringify({
337+
name: "lib-boilerplate",
338+
version: "0.0.2",
339+
type: "module",
340+
exports: "./src/index.ts",
341+
}),
342+
"/Users/name/projects/lib-boilerplate/src/index.ts": Utils.dedent`
343+
export function thing(): void {}
344+
`,
345+
"/Users/name/projects/lib-boilerplate/test/basic.spec.ts": Utils.dedent`
346+
import { thing } from 'lib-boilerplate'
347+
`,
348+
"/Users/name/projects/lib-boilerplate/tsconfig.json": JSON.stringify({
349+
compilerOptions: {
350+
module: "node16",
351+
target: "es2021",
352+
forceConsistentCasingInFileNames: true,
353+
traceResolution: true,
354+
}
355+
}),
356+
"/a/lib/lib.es2021.full.d.ts": libFile.content,
357+
}, { currentDirectory: "/Users/name/projects/lib-boilerplate" }),
358+
changes: emptyArray,
359+
});
329360
});
330361
}

‎tests/baselines/reference/reactJsxReactResolvedNodeNext.trace.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@
2525
"'package.json' does not have a 'typings' field.",
2626
"'package.json' has 'types' field 'index.d.ts' that references 'tests/cases/compiler/node_modules/@types/react/index.d.ts'.",
2727
"File 'tests/cases/compiler/node_modules/@types/react/index.d.ts' exist - use it as a name resolution result.",
28-
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
28+
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
2929
"File 'tests/cases/compiler/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
3030
"======== Resolving module './' from 'tests/cases/compiler/node_modules/@types/react/jsx-runtime.d.ts'. ========",
3131
"Resolution for module './' was found in cache from location 'tests/cases/compiler/node_modules/@types/react'.",
32-
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
32+
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
3333
"File 'tests/cases/compiler/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
3434
"======== Resolving module './' from 'tests/cases/compiler/node_modules/@types/react/jsx-dev-runtime.d.ts'. ========",
3535
"Resolution for module './' was found in cache from location 'tests/cases/compiler/node_modules/@types/react'.",
36-
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
36+
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
3737
"File 'package.json' does not exist.",
3838
"File '/package.json' does not exist according to earlier cached lookups.",
3939
"File 'package.json' does not exist according to earlier cached lookups.",

‎tests/baselines/reference/reactJsxReactResolvedNodeNextEsm.trace.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
"'package.json' does not have a 'typings' field.",
2020
"'package.json' has 'types' field 'index.d.ts' that references 'tests/cases/compiler/node_modules/@types/react/index.d.ts'.",
2121
"File 'tests/cases/compiler/node_modules/@types/react/index.d.ts' exist - use it as a name resolution result.",
22-
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
22+
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
2323
"File 'tests/cases/compiler/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
2424
"======== Resolving module './' from 'tests/cases/compiler/node_modules/@types/react/jsx-runtime.d.ts'. ========",
2525
"Resolution for module './' was found in cache from location 'tests/cases/compiler/node_modules/@types/react'.",
26-
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
26+
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
2727
"File 'tests/cases/compiler/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
2828
"======== Resolving module './' from 'tests/cases/compiler/node_modules/@types/react/jsx-dev-runtime.d.ts'. ========",
2929
"Resolution for module './' was found in cache from location 'tests/cases/compiler/node_modules/@types/react'.",
30-
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
30+
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
3131
"File 'package.json' does not exist.",
3232
"File '/package.json' does not exist.",
3333
"File 'package.json' does not exist according to earlier cached lookups.",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
Input::
2+
//// [/Users/name/projects/lib-boilerplate/package.json]
3+
{"name":"lib-boilerplate","version":"0.0.2","type":"module","exports":"./src/index.ts"}
4+
5+
//// [/Users/name/projects/lib-boilerplate/src/index.ts]
6+
export function thing(): void {}
7+
8+
9+
//// [/Users/name/projects/lib-boilerplate/test/basic.spec.ts]
10+
import { thing } from 'lib-boilerplate'
11+
12+
13+
//// [/Users/name/projects/lib-boilerplate/tsconfig.json]
14+
{"compilerOptions":{"module":"node16","target":"es2021","forceConsistentCasingInFileNames":true,"traceResolution":true}}
15+
16+
//// [/a/lib/lib.es2021.full.d.ts]
17+
/// <reference no-default-lib="true"/>
18+
interface Boolean {}
19+
interface Function {}
20+
interface CallableFunction {}
21+
interface NewableFunction {}
22+
interface IArguments {}
23+
interface Number { toExponential: any; }
24+
interface Object {}
25+
interface RegExp {}
26+
interface String { charAt: any; }
27+
interface Array<T> { length: number; [n: number]: T; }
28+
29+
30+
/a/lib/tsc.js -w --explainFiles
31+
Output::
32+
>> Screen clear
33+
[12:00:29 AM] Starting compilation in watch mode...
34+
35+
File '/Users/name/projects/lib-boilerplate/src/package.json' does not exist.
36+
Found 'package.json' at '/Users/name/projects/lib-boilerplate/package.json'.
37+
'package.json' does not have a 'typesVersions' field.
38+
File '/Users/name/projects/lib-boilerplate/test/package.json' does not exist.
39+
File '/Users/name/projects/lib-boilerplate/package.json' exists according to earlier cached lookups.
40+
======== Resolving module 'lib-boilerplate' from '/Users/name/projects/lib-boilerplate/test/basic.spec.ts'. ========
41+
Module resolution kind is not specified, using 'Node16'.
42+
File '/Users/name/projects/lib-boilerplate/test/package.json' does not exist according to earlier cached lookups.
43+
File '/Users/name/projects/lib-boilerplate/package.json' exists according to earlier cached lookups.
44+
File '/Users/name/projects/lib-boilerplate/src/index.ts' exist - use it as a name resolution result.
45+
Resolving real path for '/Users/name/projects/lib-boilerplate/src/index.ts', result '/Users/name/projects/lib-boilerplate/src/index.ts'.
46+
======== Module name 'lib-boilerplate' was successfully resolved to '/Users/name/projects/lib-boilerplate/src/index.ts' with Package ID 'lib-boilerplate/src/index.ts@0.0.2'. ========
47+
File '/a/lib/package.json' does not exist.
48+
File '/a/package.json' does not exist.
49+
File '/package.json' does not exist.
50+
../../../../a/lib/lib.es2021.full.d.ts
51+
Default library for target 'es2021'
52+
src/index.ts
53+
Matched by default include pattern '**/*'
54+
Imported via 'lib-boilerplate' from file 'test/basic.spec.ts' with packageId 'lib-boilerplate/src/index.ts@0.0.2'
55+
File is ECMAScript module because 'package.json' has field "type" with value "module"
56+
test/basic.spec.ts
57+
Matched by default include pattern '**/*'
58+
File is ECMAScript module because 'package.json' has field "type" with value "module"
59+
[12:00:34 AM] Found 0 errors. Watching for file changes.
60+
61+
62+
63+
Program root files: ["/Users/name/projects/lib-boilerplate/src/index.ts","/Users/name/projects/lib-boilerplate/test/basic.spec.ts"]
64+
Program options: {"module":100,"target":8,"forceConsistentCasingInFileNames":true,"traceResolution":true,"watch":true,"explainFiles":true,"configFilePath":"/Users/name/projects/lib-boilerplate/tsconfig.json"}
65+
Program structureReused: Not
66+
Program files::
67+
/a/lib/lib.es2021.full.d.ts
68+
/Users/name/projects/lib-boilerplate/src/index.ts
69+
/Users/name/projects/lib-boilerplate/test/basic.spec.ts
70+
71+
Semantic diagnostics in builder refreshed for::
72+
/a/lib/lib.es2021.full.d.ts
73+
/Users/name/projects/lib-boilerplate/src/index.ts
74+
/Users/name/projects/lib-boilerplate/test/basic.spec.ts
75+
76+
Shape signatures in builder refreshed for::
77+
/a/lib/lib.es2021.full.d.ts (used version)
78+
/users/name/projects/lib-boilerplate/src/index.ts (used version)
79+
/users/name/projects/lib-boilerplate/test/basic.spec.ts (used version)
80+
81+
PolledWatches::
82+
/users/name/projects/lib-boilerplate/src/package.json:
83+
{"pollingInterval":2000}
84+
/users/name/projects/lib-boilerplate/test/package.json:
85+
{"pollingInterval":2000}
86+
/users/name/projects/lib-boilerplate/node_modules/@types:
87+
{"pollingInterval":500}
88+
89+
FsWatches::
90+
/users/name/projects/lib-boilerplate/tsconfig.json:
91+
{}
92+
/users/name/projects/lib-boilerplate/src/index.ts:
93+
{}
94+
/users/name/projects/lib-boilerplate/test/basic.spec.ts:
95+
{}
96+
/a/lib/lib.es2021.full.d.ts:
97+
{}
98+
/users/name/projects/lib-boilerplate/package.json:
99+
{}
100+
101+
FsWatchesRecursive::
102+
/users/name/projects/lib-boilerplate/test:
103+
{}
104+
/users/name/projects/lib-boilerplate:
105+
{}
106+
107+
exitCode:: ExitStatus.undefined
108+
109+
//// [/Users/name/projects/lib-boilerplate/src/index.js]
110+
export function thing() { }
111+
112+
113+
//// [/Users/name/projects/lib-boilerplate/test/basic.spec.js]
114+
export {};
115+
116+

‎tests/baselines/reference/tscWatch/forceConsistentCasingInFileNames/self-name-package-reference.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ Output::
3030
>> Screen clear
3131
[12:00:23 AM] Starting compilation in watch mode...
3232

33-
Found 'package.json' at '/users/name/projects/web/package.json'.
33+
Found 'package.json' at '/Users/name/projects/web/package.json'.
3434
'package.json' does not have a 'typesVersions' field.
3535
======== Resolving module '@this/package' from '/Users/name/projects/web/index.ts'. ========
3636
Module resolution kind is not specified, using 'NodeNext'.
37-
File '/users/name/projects/web/package.json' exists according to earlier cached lookups.
37+
File '/Users/name/projects/web/package.json' exists according to earlier cached lookups.
3838
File '/Users/name/projects/web/index.ts' exist - use it as a name resolution result.
3939
Resolving real path for '/Users/name/projects/web/index.ts', result '/Users/name/projects/web/index.ts'.
4040
======== Module name '@this/package' was successfully resolved to '/Users/name/projects/web/index.ts'. ========

0 commit comments

Comments
 (0)