diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 1406742f7bb..65c41be92f8 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -38,7 +38,6 @@ import { isDiskPathRoot, isEmittedFileOfProgram, isExternalModuleNameRelative, - isExternalOrCommonJsModule, isNodeModulesDirectory, isRootedDiskPath, isTraceEnabled, @@ -779,7 +778,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD if (newProgram !== oldProgram) { cleanupLibResolutionWatching(newProgram); newProgram?.getSourceFiles().forEach(newFile => { - const expected = isExternalOrCommonJsModule(newFile) ? newFile.packageJsonLocations?.length ?? 0 : 0; + const expected = newFile.packageJsonLocations?.length ?? 0; const existing = impliedFormatPackageJsons.get(newFile.resolvedPath) ?? emptyArray; for (let i = existing.length; i < expected; i++) { createFileWatcherOfAffectingLocation(newFile.packageJsonLocations![i], /*forResolution*/ false); diff --git a/src/testRunner/unittests/tscWatch/moduleResolution.ts b/src/testRunner/unittests/tscWatch/moduleResolution.ts index 1fcc87fc3ed..f8abc35a153 100644 --- a/src/testRunner/unittests/tscWatch/moduleResolution.ts +++ b/src/testRunner/unittests/tscWatch/moduleResolution.ts @@ -1,3 +1,8 @@ +import { + ModuleDetectionKind, + ModuleKind, + ModuleResolutionKind, +} from "../../_namespaces/ts.js"; import * as Utils from "../../_namespaces/Utils.js"; import { jsonToReadableText } from "../helpers.js"; import { @@ -6,6 +11,7 @@ import { getFsContentsForAlternateResultDts, getFsContentsForAlternateResultPackageJson, } from "../helpers/alternateResult.js"; +import { compilerOptionsToConfigJson } from "../helpers/contents.js"; import { verifyTscWatch } from "../helpers/tscWatch.js"; import { createWatchedSystem, @@ -712,4 +718,69 @@ describe("unittests:: tsc-watch:: moduleResolution::", () => { }, ], }); + + verifyTscWatch({ + scenario: "moduleResolution", + subScenario: "type reference resolutions with impliedMode", + sys: () => + createWatchedSystem({ + "/user/username/projects/myproject/package.json": jsonToReadableText({ + name: "myproject", + version: "1.0.0", + type: "module", + }), + "/user/username/projects/myproject/tsconfig.json": jsonToReadableText({ + compilerOptions: compilerOptionsToConfigJson({ + moduleResolution: ModuleResolutionKind.Node16, + module: ModuleKind.Node16, + moduleDetection: ModuleDetectionKind.Legacy, + types: [], + }), + }), + "/user/username/projects/myproject/index.ts": Utils.dedent` + /// + interface LocalInterface extends RequireInterface {} + `, + "/user/username/projects/myproject/node_modules/@types/pkg/package.json": jsonToReadableText({ + name: "pkg", + version: "0.0.1", + exports: { + import: "./import.js", + require: "./require.js", + }, + }), + "/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts": Utils.dedent` + export {}; + declare global { + interface ImportInterface {} + } + `, + "/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts": Utils.dedent` + export {}; + declare global { + interface RequireInterface {} + } + `, + [libFile.path]: libFile.content, + ["/a/lib/lib.es2022.full.d.ts"]: libFile.content, + }, { currentDirectory: "/user/username/projects/myproject" }), + commandLineArgs: ["-w", "--traceResolution", "--explainFiles"], + edits: [ + { + caption: "Modify package json", + edit: sys => + sys.prependFile( + "/user/username/projects/myproject/package.json", + jsonToReadableText({ + name: "myproject", + version: "1.0.0", + }), + ), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + ], + }); }); diff --git a/tests/baselines/reference/tscWatch/moduleResolution/type-reference-resolutions-with-impliedMode.js b/tests/baselines/reference/tscWatch/moduleResolution/type-reference-resolutions-with-impliedMode.js new file mode 100644 index 00000000000..f52d139d34a --- /dev/null +++ b/tests/baselines/reference/tscWatch/moduleResolution/type-reference-resolutions-with-impliedMode.js @@ -0,0 +1,326 @@ +currentDirectory:: /user/username/projects/myproject useCaseSensitiveFileNames: false +Input:: +//// [/user/username/projects/myproject/package.json] +{ + "name": "myproject", + "version": "1.0.0", + "type": "module" +} + +//// [/user/username/projects/myproject/tsconfig.json] +{ + "compilerOptions": { + "moduleResolution": "node16", + "module": "node16", + "moduleDetection": "legacy", + "types": [] + } +} + +//// [/user/username/projects/myproject/index.ts] +/// +interface LocalInterface extends RequireInterface {} + + +//// [/user/username/projects/myproject/node_modules/@types/pkg/package.json] +{ + "name": "pkg", + "version": "0.0.1", + "exports": { + "import": "./import.js", + "require": "./require.js" + } +} + +//// [/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts] +export {}; +declare global { + interface ImportInterface {} +} + + +//// [/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts] +export {}; +declare global { + interface RequireInterface {} +} + + +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } + +//// [/a/lib/lib.es2022.full.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } + + +/a/lib/tsc.js -w --traceResolution --explainFiles +Output:: +>> Screen clear +[HH:MM:SS AM] Starting compilation in watch mode... + +Found 'package.json' at '/user/username/projects/myproject/package.json'. +======== Resolving type reference directive 'pkg', containing file '/user/username/projects/myproject/index.ts', root directory '/user/username/projects/myproject/node_modules/@types,/user/username/projects/node_modules/@types,/user/username/node_modules/@types,/user/node_modules/@types,/node_modules/@types'. ======== +Resolving with primary search path '/user/username/projects/myproject/node_modules/@types, /user/username/projects/node_modules/@types, /user/username/node_modules/@types, /user/node_modules/@types, /node_modules/@types'. +Found 'package.json' at '/user/username/projects/myproject/node_modules/@types/pkg/package.json'. +'package.json' does not have a 'typesVersions' field. +'package.json' does not have a 'typings' field. +'package.json' does not have a 'types' field. +'package.json' does not have a 'main' field. +Directory '/user/username/projects/node_modules/@types' does not exist, skipping all lookups in it. +Directory '/user/username/node_modules/@types' does not exist, skipping all lookups in it. +Directory '/user/node_modules/@types' does not exist, skipping all lookups in it. +Directory '/node_modules/@types' does not exist, skipping all lookups in it. +Looking up in 'node_modules' folder, initial location '/user/username/projects/myproject'. +Searching all ancestor node_modules directories for preferred extensions: Declaration. +File '/user/username/projects/myproject/node_modules/@types/pkg/package.json' exists according to earlier cached lookups. +Entering conditional exports. +Matched 'exports' condition 'import'. +Using 'exports' subpath '.' with target './import.js'. +File name '/user/username/projects/myproject/node_modules/@types/pkg/import.js' has a '.js' extension - stripping it. +File '/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts' exists - use it as a name resolution result. +'package.json' does not have a 'peerDependencies' field. +Resolved under condition 'import'. +Exiting conditional exports. +Resolving real path for '/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts', result '/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts'. +======== Type reference directive 'pkg' was successfully resolved to '/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts' with Package ID 'pkg/import.d.ts@0.0.1', primary: false. ======== +File '/user/username/projects/myproject/node_modules/@types/pkg/package.json' exists according to earlier cached lookups. +File '/a/lib/package.json' does not exist. +File '/a/package.json' does not exist. +File '/package.json' does not exist. +index.ts:2:34 - error TS2304: Cannot find name 'RequireInterface'. + +2 interface LocalInterface extends RequireInterface {} +   ~~~~~~~~~~~~~~~~ + +../../../../a/lib/lib.es2022.full.d.ts + Default library for target 'es2022' +node_modules/@types/pkg/import.d.ts + Type library referenced via 'pkg' from file 'index.ts' with packageId 'pkg/import.d.ts@0.0.1' + File is CommonJS module because 'node_modules/@types/pkg/package.json' does not have field "type" +index.ts + Matched by default include pattern '**/*' +[HH:MM:SS AM] Found 1 error. Watching for file changes. + + + +//// [/user/username/projects/myproject/index.js] +/// + + + +PolledWatches:: +/user/username/projects/node_modules: *new* + {"pollingInterval":500} + +FsWatches:: +/a/lib/lib.es2022.full.d.ts: *new* + {} +/user/username/projects/myproject/index.ts: *new* + {} +/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts: *new* + {} +/user/username/projects/myproject/node_modules/@types/pkg/package.json: *new* + {} +/user/username/projects/myproject/package.json: *new* + {} +/user/username/projects/myproject/tsconfig.json: *new* + {} + +FsWatchesRecursive:: +/user/username/projects/myproject: *new* + {} +/user/username/projects/myproject/node_modules: *new* + {} + +Program root files: [ + "/user/username/projects/myproject/index.ts" +] +Program options: { + "moduleResolution": 3, + "module": 100, + "moduleDetection": 1, + "types": [], + "watch": true, + "traceResolution": true, + "explainFiles": true, + "configFilePath": "/user/username/projects/myproject/tsconfig.json" +} +Program structureReused: Not +Program files:: +/a/lib/lib.es2022.full.d.ts +/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts +/user/username/projects/myproject/index.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.es2022.full.d.ts +/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts +/user/username/projects/myproject/index.ts + +Shape signatures in builder refreshed for:: +/a/lib/lib.es2022.full.d.ts (used version) +/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts (used version) +/user/username/projects/myproject/index.ts (used version) + +exitCode:: ExitStatus.undefined + +Change:: Modify package json + +Input:: +//// [/user/username/projects/myproject/package.json] +{ + "name": "myproject", + "version": "1.0.0" +}{ + "name": "myproject", + "version": "1.0.0", + "type": "module" +} + + +Timeout callback:: count: 1 +1: timerToInvalidateFailedLookupResolutions *new* + +Before running Timeout callback:: count: 1 +1: timerToInvalidateFailedLookupResolutions + +Host is moving to new time +After running Timeout callback:: count: 1 + +Timeout callback:: count: 1 +2: timerToUpdateProgram *new* + +Before running Timeout callback:: count: 1 +2: timerToUpdateProgram + +Host is moving to new time +After running Timeout callback:: count: 0 +Output:: +>> Screen clear +[HH:MM:SS AM] File change detected. Starting incremental compilation... + +File '/a/lib/package.json' does not exist according to earlier cached lookups. +File '/a/package.json' does not exist according to earlier cached lookups. +File '/package.json' does not exist according to earlier cached lookups. +File '/user/username/projects/myproject/node_modules/@types/pkg/package.json' exists according to earlier cached lookups. +Found 'package.json' at '/user/username/projects/myproject/package.json'. +File '/user/username/projects/myproject/package.json' exists according to earlier cached lookups. +======== Resolving type reference directive 'pkg', containing file '/user/username/projects/myproject/index.ts', root directory '/user/username/projects/myproject/node_modules/@types,/user/username/projects/node_modules/@types,/user/username/node_modules/@types,/user/node_modules/@types,/node_modules/@types'. ======== +Resolving with primary search path '/user/username/projects/myproject/node_modules/@types, /user/username/projects/node_modules/@types, /user/username/node_modules/@types, /user/node_modules/@types, /node_modules/@types'. +File '/user/username/projects/myproject/node_modules/@types/pkg/package.json' exists according to earlier cached lookups. +'package.json' does not have a 'typings' field. +'package.json' does not have a 'types' field. +'package.json' does not have a 'main' field. +File '/user/username/projects/myproject/node_modules/@types/pkg/index.d.ts' does not exist. +Directory '/user/username/projects/node_modules/@types' does not exist, skipping all lookups in it. +Directory '/user/username/node_modules/@types' does not exist, skipping all lookups in it. +Directory '/user/node_modules/@types' does not exist, skipping all lookups in it. +Directory '/node_modules/@types' does not exist, skipping all lookups in it. +Looking up in 'node_modules' folder, initial location '/user/username/projects/myproject'. +Searching all ancestor node_modules directories for preferred extensions: Declaration. +File '/user/username/projects/myproject/node_modules/pkg.d.ts' does not exist. +File '/user/username/projects/myproject/node_modules/@types/pkg/package.json' exists according to earlier cached lookups. +Entering conditional exports. +Saw non-matching condition 'import'. +Matched 'exports' condition 'require'. +Using 'exports' subpath '.' with target './require.js'. +File name '/user/username/projects/myproject/node_modules/@types/pkg/require.js' has a '.js' extension - stripping it. +File '/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts' exists - use it as a name resolution result. +Resolved under condition 'require'. +Exiting conditional exports. +Resolving real path for '/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts', result '/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts'. +======== Type reference directive 'pkg' was successfully resolved to '/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts' with Package ID 'pkg/require.d.ts@0.0.1', primary: false. ======== +File '/user/username/projects/myproject/node_modules/@types/pkg/package.json' exists according to earlier cached lookups. +File '/a/lib/package.json' does not exist according to earlier cached lookups. +File '/a/package.json' does not exist according to earlier cached lookups. +File '/package.json' does not exist according to earlier cached lookups. +../../../../a/lib/lib.es2022.full.d.ts + Default library for target 'es2022' +node_modules/@types/pkg/require.d.ts + Type library referenced via 'pkg' from file 'index.ts' with packageId 'pkg/require.d.ts@0.0.1' + File is CommonJS module because 'node_modules/@types/pkg/package.json' does not have field "type" +index.ts + Matched by default include pattern '**/*' +[HH:MM:SS AM] Found 0 errors. Watching for file changes. + + + +//// [/user/username/projects/myproject/index.js] file written with same contents + +PolledWatches:: +/user/username/projects/node_modules: + {"pollingInterval":500} + +FsWatches:: +/a/lib/lib.es2022.full.d.ts: + {} +/user/username/projects/myproject/index.ts: + {} +/user/username/projects/myproject/node_modules/@types/pkg/package.json: + {} +/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts: *new* + {} +/user/username/projects/myproject/package.json: + {} +/user/username/projects/myproject/tsconfig.json: + {} + +FsWatches *deleted*:: +/user/username/projects/myproject/node_modules/@types/pkg/import.d.ts: + {} + +FsWatchesRecursive:: +/user/username/projects/myproject: + {} +/user/username/projects/myproject/node_modules: + {} + + +Program root files: [ + "/user/username/projects/myproject/index.ts" +] +Program options: { + "moduleResolution": 3, + "module": 100, + "moduleDetection": 1, + "types": [], + "watch": true, + "traceResolution": true, + "explainFiles": true, + "configFilePath": "/user/username/projects/myproject/tsconfig.json" +} +Program structureReused: SafeModules +Program files:: +/a/lib/lib.es2022.full.d.ts +/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts +/user/username/projects/myproject/index.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.es2022.full.d.ts +/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts +/user/username/projects/myproject/index.ts + +Shape signatures in builder refreshed for:: +/user/username/projects/myproject/node_modules/@types/pkg/require.d.ts (used version) +/user/username/projects/myproject/index.ts (computed .d.ts) + +exitCode:: ExitStatus.undefined