diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 30cbc37fd14e9..332804c7d43df 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -259,6 +259,7 @@ export interface ModuleResolutionState { requestContainingDirectory: string | undefined; reportDiagnostic: DiagnosticReporter; isConfigLookup: boolean; + candidateIsFromPackageJsonField: boolean; } /** Just the fields that we use for module resolution. @@ -526,6 +527,7 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string requestContainingDirectory: containingDirectory, reportDiagnostic: diag => void diagnostics.push(diag), isConfigLookup: false, + candidateIsFromPackageJsonField: false, }; let resolved = primaryLookup(); let primary = true; @@ -1652,6 +1654,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa requestContainingDirectory: containingDirectory, reportDiagnostic: diag => void diagnostics.push(diag), isConfigLookup, + candidateIsFromPackageJsonField: false, }; if (traceEnabled && getEmitModuleResolutionKind(compilerOptions) >= ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) <= ModuleResolutionKind.NodeNext) { @@ -1948,7 +1951,7 @@ function tryAddingExtensions(candidate: string, extensions: Extensions, original function tryExtension(ext: string, resolvedUsingTsExtension?: boolean): PathAndExtension | undefined { const path = tryFile(candidate + ext, onlyRecordFailures, state); - return path === undefined ? undefined : { path, ext, resolvedUsingTsExtension }; + return path === undefined ? undefined : { path, ext, resolvedUsingTsExtension: !state.candidateIsFromPackageJsonField && resolvedUsingTsExtension }; } } @@ -2111,6 +2114,7 @@ export function getTemporaryModuleResolutionState(packageJsonInfoCache: PackageJ requestContainingDirectory: undefined, reportDiagnostic: noop, isConfigLookup: false, + candidateIsFromPackageJsonField: false, }; } @@ -2232,11 +2236,14 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st // (technically it only emits a deprecation warning in esm packages right now, but that's probably // enough to mean we don't need to support it) const features = state.features; + const candidateIsFromPackageJsonField = state.candidateIsFromPackageJsonField; + state.candidateIsFromPackageJsonField = true; if (jsonContent?.type !== "module") { state.features &= ~NodeResolutionFeatures.EsmMode; } const result = nodeLoadModuleByRelativeName(expandedExtensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ false); state.features = features; + state.candidateIsFromPackageJsonField = candidateIsFromPackageJsonField; return result; }; @@ -2935,6 +2942,7 @@ export function classicNameResolver(moduleName: string, containingFile: string, requestContainingDirectory: containingDirectory, reportDiagnostic: diag => void diagnostics.push(diag), isConfigLookup: false, + candidateIsFromPackageJsonField: false, }; const resolved = @@ -3015,6 +3023,7 @@ export function loadModuleFromGlobalCache(moduleName: string, projectName: strin requestContainingDirectory: undefined, reportDiagnostic: diag => void diagnostics.push(diag), isConfigLookup: false, + candidateIsFromPackageJsonField: false, }; const resolved = loadModuleFromImmediateNodeModulesDirectory(Extensions.Declaration, moduleName, globalCache, state, /*typesScopeOnly*/ false, /*cache*/ undefined, /*redirectedReference*/ undefined); return createResolvedModuleWithFailedLookupLocations( diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.js b/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.js new file mode 100644 index 0000000000000..094f3a3dd9e7a --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.js @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/resolutionCandidateFromPackageJsonField1.ts] //// + +//// [package.json] +{ + "name": "@angular/core", + "typings": "index.d.ts" +} + +//// [index.ts] +export {}; + +//// [test.ts] +import "@angular/core"; + + +//// [index.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [test.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("@angular/core"); diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.symbols b/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.symbols new file mode 100644 index 0000000000000..c696908e16a5f --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/@angular/core/index.ts === + +export {}; + +=== tests/cases/compiler/@angular/core/testing/test.ts === + +import "@angular/core"; + diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.types b/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.types new file mode 100644 index 0000000000000..c696908e16a5f --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField1.types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/@angular/core/index.ts === + +export {}; + +=== tests/cases/compiler/@angular/core/testing/test.ts === + +import "@angular/core"; + diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).errors.txt b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).errors.txt new file mode 100644 index 0000000000000..ef3ffa721e4ea --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).errors.txt @@ -0,0 +1,25 @@ +tests/cases/compiler/test.ts(1,19): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled. + + +==== tests/cases/compiler/tsconfig.json (0 errors) ==== + { + "compilerOptions": { + "paths": { + "foo/*": ["./dist/*"], + "baz/*.ts": ["./types/*.d.ts"] + } + } + } + +==== tests/cases/compiler/dist/bar.ts (0 errors) ==== + export const a = 1234; + +==== tests/cases/compiler/types/main.d.ts (0 errors) ==== + export const b: string; + +==== tests/cases/compiler/test.ts (1 errors) ==== + import { a } from "foo/bar.ts"; + ~~~~~~~~~~~~ +!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled. + import { b } from "baz/main.ts"; + \ No newline at end of file diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).js b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).js new file mode 100644 index 0000000000000..fc322d5465d3d --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).js @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/resolutionCandidateFromPackageJsonField2.ts] //// + +//// [bar.ts] +export const a = 1234; + +//// [main.d.ts] +export const b: string; + +//// [test.ts] +import { a } from "foo/bar.ts"; +import { b } from "baz/main.ts"; + + +//// [bar.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.a = void 0; +exports.a = 1234; +//// [test.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).symbols b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).symbols new file mode 100644 index 0000000000000..4418c58121945 --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/dist/bar.ts === +export const a = 1234; +>a : Symbol(a, Decl(bar.ts, 0, 12)) + +=== tests/cases/compiler/types/main.d.ts === +export const b: string; +>b : Symbol(b, Decl(main.d.ts, 0, 12)) + +=== tests/cases/compiler/test.ts === +import { a } from "foo/bar.ts"; +>a : Symbol(a, Decl(test.ts, 0, 8)) + +import { b } from "baz/main.ts"; +>b : Symbol(b, Decl(test.ts, 1, 8)) + diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).types b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).types new file mode 100644 index 0000000000000..1687bb192d5de --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=bundler).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/dist/bar.ts === +export const a = 1234; +>a : 1234 +>1234 : 1234 + +=== tests/cases/compiler/types/main.d.ts === +export const b: string; +>b : string + +=== tests/cases/compiler/test.ts === +import { a } from "foo/bar.ts"; +>a : 1234 + +import { b } from "baz/main.ts"; +>b : string + diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).errors.txt b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).errors.txt new file mode 100644 index 0000000000000..ef3ffa721e4ea --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).errors.txt @@ -0,0 +1,25 @@ +tests/cases/compiler/test.ts(1,19): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled. + + +==== tests/cases/compiler/tsconfig.json (0 errors) ==== + { + "compilerOptions": { + "paths": { + "foo/*": ["./dist/*"], + "baz/*.ts": ["./types/*.d.ts"] + } + } + } + +==== tests/cases/compiler/dist/bar.ts (0 errors) ==== + export const a = 1234; + +==== tests/cases/compiler/types/main.d.ts (0 errors) ==== + export const b: string; + +==== tests/cases/compiler/test.ts (1 errors) ==== + import { a } from "foo/bar.ts"; + ~~~~~~~~~~~~ +!!! error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled. + import { b } from "baz/main.ts"; + \ No newline at end of file diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).js b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).js new file mode 100644 index 0000000000000..fc322d5465d3d --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).js @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/resolutionCandidateFromPackageJsonField2.ts] //// + +//// [bar.ts] +export const a = 1234; + +//// [main.d.ts] +export const b: string; + +//// [test.ts] +import { a } from "foo/bar.ts"; +import { b } from "baz/main.ts"; + + +//// [bar.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.a = void 0; +exports.a = 1234; +//// [test.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).symbols b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).symbols new file mode 100644 index 0000000000000..4418c58121945 --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/dist/bar.ts === +export const a = 1234; +>a : Symbol(a, Decl(bar.ts, 0, 12)) + +=== tests/cases/compiler/types/main.d.ts === +export const b: string; +>b : Symbol(b, Decl(main.d.ts, 0, 12)) + +=== tests/cases/compiler/test.ts === +import { a } from "foo/bar.ts"; +>a : Symbol(a, Decl(test.ts, 0, 8)) + +import { b } from "baz/main.ts"; +>b : Symbol(b, Decl(test.ts, 1, 8)) + diff --git a/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).types b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).types new file mode 100644 index 0000000000000..1687bb192d5de --- /dev/null +++ b/tests/baselines/reference/resolutionCandidateFromPackageJsonField2(moduleresolution=node10).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/dist/bar.ts === +export const a = 1234; +>a : 1234 +>1234 : 1234 + +=== tests/cases/compiler/types/main.d.ts === +export const b: string; +>b : string + +=== tests/cases/compiler/test.ts === +import { a } from "foo/bar.ts"; +>a : 1234 + +import { b } from "baz/main.ts"; +>b : string + diff --git a/tests/cases/compiler/resolutionCandidateFromPackageJsonField1.ts b/tests/cases/compiler/resolutionCandidateFromPackageJsonField1.ts new file mode 100644 index 0000000000000..800ec19a53bfe --- /dev/null +++ b/tests/cases/compiler/resolutionCandidateFromPackageJsonField1.ts @@ -0,0 +1,20 @@ +// @filename: tsconfig.json +{ + "compilerOptions": { + "paths": { + "@angular/*": ["./@angular/*"] + } + } +} + +// @filename: @angular/core/package.json +{ + "name": "@angular/core", + "typings": "index.d.ts" +} + +// @filename: @angular/core/index.ts +export {}; + +// @filename: @angular/core/testing/test.ts +import "@angular/core"; diff --git a/tests/cases/compiler/resolutionCandidateFromPackageJsonField2.ts b/tests/cases/compiler/resolutionCandidateFromPackageJsonField2.ts new file mode 100644 index 0000000000000..c1e30c89e5b9d --- /dev/null +++ b/tests/cases/compiler/resolutionCandidateFromPackageJsonField2.ts @@ -0,0 +1,21 @@ +// @moduleResolution: node10,bundler + +// @filename: tsconfig.json +{ + "compilerOptions": { + "paths": { + "foo/*": ["./dist/*"], + "baz/*.ts": ["./types/*.d.ts"] + } + } +} + +// @filename: dist/bar.ts +export const a = 1234; + +// @filename: types/main.d.ts +export const b: string; + +// @filename: test.ts +import { a } from "foo/bar.ts"; +import { b } from "baz/main.ts";