Skip to content

Commit 06aae98

Browse files
TypeScript Botjakebailey
TypeScript Bot
andauthored
🤖 Pick PR #57973 (Compare package.json paths with cor...) into release-5.4 (#57976)
Co-authored-by: Jake Bailey <[email protected]>
1 parent 6d8134e commit 06aae98

File tree

3 files changed

+331
-1
lines changed

3 files changed

+331
-1
lines changed

‎src/compiler/moduleSpecifiers.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,8 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt
550550

551551
const nearestTargetPackageJson = getNearestAncestorDirectoryWithPackageJson(host, getDirectoryPath(modulePath));
552552
const nearestSourcePackageJson = getNearestAncestorDirectoryWithPackageJson(host, sourceDirectory);
553-
if (nearestSourcePackageJson !== nearestTargetPackageJson) {
553+
const ignoreCase = !hostUsesCaseSensitiveFileNames(host);
554+
if (!packageJsonPathsAreEqual(nearestTargetPackageJson, nearestSourcePackageJson, ignoreCase)) {
554555
// 2. The importing and imported files are part of different packages.
555556
//
556557
// packages/a/
@@ -570,6 +571,12 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt
570571
return isPathRelativeToParent(maybeNonRelative) || countPathComponents(relativePath) < countPathComponents(maybeNonRelative) ? relativePath : maybeNonRelative;
571572
}
572573

574+
function packageJsonPathsAreEqual(a: string | undefined, b: string | undefined, ignoreCase?: boolean) {
575+
if (a === b) return true;
576+
if (a === undefined || b === undefined) return false;
577+
return comparePaths(a, b, ignoreCase) === Comparison.EqualTo;
578+
}
579+
573580
/** @internal */
574581
export function countPathComponents(path: string): number {
575582
let count = 0;

‎src/testRunner/unittests/tsc/declarationEmit.ts

+94
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,98 @@ ${pluginOneAction()}`,
258258
],
259259
changeCaseFileTestPath: str => str.includes("/pkg1"),
260260
});
261+
262+
verifyTscWatch({
263+
scenario: "declarationEmit",
264+
subScenario: "when using Windows paths and uppercase letters",
265+
sys: () =>
266+
createWatchedSystem([
267+
{
268+
path: `D:\\Work\\pkg1\\package.json`,
269+
content: jsonToReadableText({
270+
name: "ts-specifier-bug",
271+
version: "1.0.0",
272+
description: "",
273+
main: "index.js",
274+
scripts: {
275+
build: "tsc",
276+
},
277+
keywords: [],
278+
author: "",
279+
license: "ISC",
280+
dependencies: {
281+
typescript: "5.4.0-dev.20231222",
282+
},
283+
}),
284+
},
285+
{
286+
path: `D:\\Work\\pkg1\\tsconfig.json`,
287+
content: jsonToReadableText({
288+
compilerOptions: {
289+
module: "commonjs",
290+
declaration: true,
291+
removeComments: true,
292+
emitDecoratorMetadata: true,
293+
experimentalDecorators: true,
294+
strictPropertyInitialization: false,
295+
allowSyntheticDefaultImports: true,
296+
target: "es2017",
297+
sourceMap: true,
298+
esModuleInterop: true,
299+
outDir: "./dist",
300+
baseUrl: "./",
301+
skipLibCheck: true,
302+
strictNullChecks: false,
303+
noImplicitAny: false,
304+
strictBindCallApply: false,
305+
forceConsistentCasingInFileNames: false,
306+
noFallthroughCasesInSwitch: false,
307+
moduleResolution: "node",
308+
resolveJsonModule: true,
309+
},
310+
include: ["src"],
311+
}),
312+
},
313+
{
314+
path: `D:\\Work\\pkg1\\src\\main.ts`,
315+
content: Utils.dedent`
316+
import { PartialType } from './utils';
317+
318+
class Common {}
319+
320+
export class Sub extends PartialType(Common) {
321+
id: string;
322+
}
323+
`,
324+
},
325+
{
326+
path: `D:\\Work\\pkg1\\src\\utils\\index.ts`,
327+
content: Utils.dedent`
328+
import { MyType, MyReturnType } from './type-helpers';
329+
330+
export function PartialType<T>(classRef: MyType<T>) {
331+
abstract class PartialClassType {
332+
constructor() {}
333+
}
334+
335+
return PartialClassType as MyReturnType;
336+
}
337+
`,
338+
},
339+
{
340+
path: `D:\\Work\\pkg1\\src\\utils\\type-helpers.ts`,
341+
content: Utils.dedent`
342+
export type MyReturnType = {
343+
new (...args: any[]): any;
344+
};
345+
346+
export interface MyType<T = any> extends Function {
347+
new (...args: any[]): T;
348+
}
349+
`,
350+
},
351+
libFile,
352+
], { currentDirectory: "D:\\Work\\pkg1", windowsStyleRoot: "D:/" }),
353+
commandLineArgs: ["-p", "D:\\Work\\pkg1", "--explainFiles"],
354+
});
261355
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
currentDirectory:: D:\Work\pkg1 useCaseSensitiveFileNames: false
2+
Input::
3+
//// [D:/Work/pkg1/package.json]
4+
{
5+
"name": "ts-specifier-bug",
6+
"version": "1.0.0",
7+
"description": "",
8+
"main": "index.js",
9+
"scripts": {
10+
"build": "tsc"
11+
},
12+
"keywords": [],
13+
"author": "",
14+
"license": "ISC",
15+
"dependencies": {
16+
"typescript": "5.4.0-dev.20231222"
17+
}
18+
}
19+
20+
//// [D:/Work/pkg1/tsconfig.json]
21+
{
22+
"compilerOptions": {
23+
"module": "commonjs",
24+
"declaration": true,
25+
"removeComments": true,
26+
"emitDecoratorMetadata": true,
27+
"experimentalDecorators": true,
28+
"strictPropertyInitialization": false,
29+
"allowSyntheticDefaultImports": true,
30+
"target": "es2017",
31+
"sourceMap": true,
32+
"esModuleInterop": true,
33+
"outDir": "./dist",
34+
"baseUrl": "./",
35+
"skipLibCheck": true,
36+
"strictNullChecks": false,
37+
"noImplicitAny": false,
38+
"strictBindCallApply": false,
39+
"forceConsistentCasingInFileNames": false,
40+
"noFallthroughCasesInSwitch": false,
41+
"moduleResolution": "node",
42+
"resolveJsonModule": true
43+
},
44+
"include": [
45+
"src"
46+
]
47+
}
48+
49+
//// [D:/Work/pkg1/src/main.ts]
50+
import { PartialType } from './utils';
51+
52+
class Common {}
53+
54+
export class Sub extends PartialType(Common) {
55+
id: string;
56+
}
57+
58+
59+
//// [D:/Work/pkg1/src/utils/index.ts]
60+
import { MyType, MyReturnType } from './type-helpers';
61+
62+
export function PartialType<T>(classRef: MyType<T>) {
63+
abstract class PartialClassType {
64+
constructor() {}
65+
}
66+
67+
return PartialClassType as MyReturnType;
68+
}
69+
70+
71+
//// [D:/Work/pkg1/src/utils/type-helpers.ts]
72+
export type MyReturnType = {
73+
new (...args: any[]): any;
74+
};
75+
76+
export interface MyType<T = any> extends Function {
77+
new (...args: any[]): T;
78+
}
79+
80+
81+
//// [D:/a/lib/lib.d.ts]
82+
/// <reference no-default-lib="true"/>
83+
interface Boolean {}
84+
interface Function {}
85+
interface CallableFunction {}
86+
interface NewableFunction {}
87+
interface IArguments {}
88+
interface Number { toExponential: any; }
89+
interface Object {}
90+
interface RegExp {}
91+
interface String { charAt: any; }
92+
interface Array<T> { length: number; [n: number]: T; }
93+
94+
95+
D:/a/lib/tsc.js -p D:\Work\pkg1 --explainFiles
96+
Output::
97+
error TS2318: Cannot find global type 'Array'.
98+
99+
error TS2318: Cannot find global type 'Boolean'.
100+
101+
error TS2318: Cannot find global type 'Function'.
102+
103+
error TS2318: Cannot find global type 'IArguments'.
104+
105+
error TS2318: Cannot find global type 'Number'.
106+
107+
error TS2318: Cannot find global type 'Object'.
108+
109+
error TS2318: Cannot find global type 'RegExp'.
110+
111+
error TS2318: Cannot find global type 'String'.
112+
113+
error TS6053: File 'D:/a/lib/lib.es2017.full.d.ts' not found.
114+
The file is in the program because:
115+
Default library for target 'es2017'
116+
117+
tsconfig.json:10:15
118+
10 "target": "es2017",
119+
   ~~~~~~~~
120+
File is default library for target specified here.
121+
122+
src/utils/type-helpers.ts:5:42 - error TS4022: 'extends' clause of exported interface 'MyType' has or is using private name 'Function'.
123+
124+
5 export interface MyType<T = any> extends Function {
125+
   ~~~~~~~~
126+
127+
src/utils/type-helpers.ts
128+
Imported via './type-helpers' from file 'src/utils/index.ts'
129+
Matched by include pattern 'src' in 'tsconfig.json'
130+
src/utils/index.ts
131+
Imported via './utils' from file 'src/main.ts'
132+
Matched by include pattern 'src' in 'tsconfig.json'
133+
src/main.ts
134+
Matched by include pattern 'src' in 'tsconfig.json'
135+
136+
Found 10 errors in the same file, starting at: src/utils/type-helpers.ts:5
137+
138+
139+
140+
//// [D:/Work/pkg1/dist/utils/type-helpers.js.map]
141+
{"version":3,"file":"type-helpers.js","sourceRoot":"","sources":["../../src/utils/type-helpers.ts"],"names":[],"mappings":""}
142+
143+
//// [D:/Work/pkg1/dist/utils/type-helpers.js]
144+
"use strict";
145+
Object.defineProperty(exports, "__esModule", { value: true });
146+
//# sourceMappingURL=type-helpers.js.map
147+
148+
//// [D:/Work/pkg1/dist/utils/index.js.map]
149+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;AAEA,SAAgB,WAAW,CAAI,QAAmB;IAC9C,MAAe,gBAAgB;QAC3B,gBAAe,CAAC;KACnB;IAED,OAAO,gBAAgC,CAAC;AAC5C,CAAC;AAND,kCAMC"}
150+
151+
//// [D:/Work/pkg1/dist/utils/index.js]
152+
"use strict";
153+
Object.defineProperty(exports, "__esModule", { value: true });
154+
exports.PartialType = void 0;
155+
function PartialType(classRef) {
156+
class PartialClassType {
157+
constructor() { }
158+
}
159+
return PartialClassType;
160+
}
161+
exports.PartialType = PartialType;
162+
//# sourceMappingURL=index.js.map
163+
164+
//// [D:/Work/pkg1/dist/utils/index.d.ts]
165+
import { MyType, MyReturnType } from './type-helpers';
166+
export declare function PartialType<T>(classRef: MyType<T>): MyReturnType;
167+
168+
169+
//// [D:/Work/pkg1/dist/main.js.map]
170+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;AAAA,mCAAsC;AAEtC,MAAM,MAAM;CAAG;AAEf,MAAa,GAAI,SAAQ,IAAA,mBAAW,EAAC,MAAM,CAAC;CAE3C;AAFD,kBAEC"}
171+
172+
//// [D:/Work/pkg1/dist/main.js]
173+
"use strict";
174+
Object.defineProperty(exports, "__esModule", { value: true });
175+
exports.Sub = void 0;
176+
const utils_1 = require("./utils");
177+
class Common {
178+
}
179+
class Sub extends (0, utils_1.PartialType)(Common) {
180+
}
181+
exports.Sub = Sub;
182+
//# sourceMappingURL=main.js.map
183+
184+
//// [D:/Work/pkg1/dist/main.d.ts]
185+
declare const Sub_base: import("./utils/type-helpers").MyReturnType;
186+
export declare class Sub extends Sub_base {
187+
id: string;
188+
}
189+
export {};
190+
191+
192+
193+
Program root files: [
194+
"D:/Work/pkg1/src/main.ts",
195+
"D:/Work/pkg1/src/utils/index.ts",
196+
"D:/Work/pkg1/src/utils/type-helpers.ts"
197+
]
198+
Program options: {
199+
"module": 1,
200+
"declaration": true,
201+
"removeComments": true,
202+
"emitDecoratorMetadata": true,
203+
"experimentalDecorators": true,
204+
"strictPropertyInitialization": false,
205+
"allowSyntheticDefaultImports": true,
206+
"target": 4,
207+
"sourceMap": true,
208+
"esModuleInterop": true,
209+
"outDir": "D:/Work/pkg1/dist",
210+
"baseUrl": "D:/Work/pkg1",
211+
"skipLibCheck": true,
212+
"strictNullChecks": false,
213+
"noImplicitAny": false,
214+
"strictBindCallApply": false,
215+
"forceConsistentCasingInFileNames": false,
216+
"noFallthroughCasesInSwitch": false,
217+
"moduleResolution": 2,
218+
"resolveJsonModule": true,
219+
"project": "D:/Work/pkg1",
220+
"explainFiles": true,
221+
"configFilePath": "D:/Work/pkg1/tsconfig.json"
222+
}
223+
Program structureReused: Not
224+
Program files::
225+
D:/Work/pkg1/src/utils/type-helpers.ts
226+
D:/Work/pkg1/src/utils/index.ts
227+
D:/Work/pkg1/src/main.ts
228+
229+
exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped

0 commit comments

Comments
 (0)