diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 18e392e914da9..6ffe705294e79 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3900,8 +3900,6 @@ namespace ts { compilerOptions, contextFile, context.tracker.moduleResolverHost, - context.tracker.moduleResolverHost.getSourceFiles!(), // TODO: GH#18217 - { importModuleSpecifierPreference: "non-relative" }, host.redirectTargetsMap, ); links.specifierCache = links.specifierCache || createMap(); diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 51835103c52f9..e56951cb5078c 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -27,11 +27,21 @@ namespace ts.moduleSpecifiers { compilerOptions: CompilerOptions, importingSourceFile: SourceFile, host: ModuleSpecifierResolutionHost, - files: ReadonlyArray, - preferences: ModuleSpecifierPreferences, redirectTargetsMap: RedirectTargetsMap, ): string { - return first(first(getModuleSpecifiers(moduleSymbol, compilerOptions, importingSourceFile, host, files, preferences, redirectTargetsMap))); + const isBundle = (compilerOptions.out || compilerOptions.outFile); + if (isBundle && host.getCommonSourceDirectory) { + // For declaration bundles, we need to generate absolute paths relative to the common source dir for imports, + // just like how the declaration emitter does for the ambient module declarations - we can easily accomplish this + // using the `baseUrl` compiler option (which we would otherwise never use in declaration emit) and a non-relative + // specifier preference + compilerOptions = { + ...compilerOptions, + baseUrl: host.getCommonSourceDirectory(), + }; + } + const preferences: ModuleSpecifierPreferences = { importModuleSpecifierPreference: isBundle ? "non-relative" : "relative" }; + return first(first(getModuleSpecifiers(moduleSymbol, compilerOptions, importingSourceFile, host, host.getSourceFiles ? host.getSourceFiles() : [importingSourceFile], preferences, redirectTargetsMap))); } // For each symlink/original for a module, returns a list of ways to import that file. diff --git a/src/compiler/types.ts b/src/compiler/types.ts index cb0550124e5e3..9c2d7ed916f10 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5334,6 +5334,7 @@ namespace ts { fileExists?(path: string): boolean; readFile?(path: string): string | undefined; getSourceFiles?(): ReadonlyArray; // Used for cached resolutions to find symlinks without traversing the fs (again) + getCommonSourceDirectory?(): string; } // Note: this used to be deprecated in our public API, but is still used internally diff --git a/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.js b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.js new file mode 100644 index 0000000000000..acda44b64c24b --- /dev/null +++ b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.js @@ -0,0 +1,50 @@ +//// [tests/cases/compiler/declarationEmitPrefersPathKindBasedOnBundling.ts] //// + +//// [scalar.ts] +export interface Scalar { + (): string; + value: number; +} + +export function scalar(value: string): Scalar { + return null as any; +} +//// [spacing.ts] +import { scalar } from '../lib/operators/scalar'; + +export default { + get xs() { + return scalar("14px"); + } +}; + + +//// [scalar.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function scalar(value) { + return null; +} +exports.scalar = scalar; +//// [spacing.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var scalar_1 = require("../lib/operators/scalar"); +exports.default = { + get xs() { + return scalar_1.scalar("14px"); + } +}; + + +//// [scalar.d.ts] +export interface Scalar { + (): string; + value: number; +} +export declare function scalar(value: string): Scalar; +//// [spacing.d.ts] +declare const _default: { + readonly xs: import("../lib/operators/scalar").Scalar; +}; +export default _default; diff --git a/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.symbols b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.symbols new file mode 100644 index 0000000000000..683f3ccd71721 --- /dev/null +++ b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/src/lib/operators/scalar.ts === +export interface Scalar { +>Scalar : Symbol(Scalar, Decl(scalar.ts, 0, 0)) + + (): string; + value: number; +>value : Symbol(Scalar.value, Decl(scalar.ts, 1, 12)) +} + +export function scalar(value: string): Scalar { +>scalar : Symbol(scalar, Decl(scalar.ts, 3, 1)) +>value : Symbol(value, Decl(scalar.ts, 5, 23)) +>Scalar : Symbol(Scalar, Decl(scalar.ts, 0, 0)) + + return null as any; +} +=== tests/cases/compiler/src/settings/spacing.ts === +import { scalar } from '../lib/operators/scalar'; +>scalar : Symbol(scalar, Decl(spacing.ts, 0, 8)) + +export default { + get xs() { +>xs : Symbol(xs, Decl(spacing.ts, 2, 16)) + + return scalar("14px"); +>scalar : Symbol(scalar, Decl(spacing.ts, 0, 8)) + } +}; + diff --git a/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.types b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.types new file mode 100644 index 0000000000000..032b8a1b59377 --- /dev/null +++ b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling.types @@ -0,0 +1,32 @@ +=== tests/cases/compiler/src/lib/operators/scalar.ts === +export interface Scalar { + (): string; + value: number; +>value : number +} + +export function scalar(value: string): Scalar { +>scalar : (value: string) => Scalar +>value : string + + return null as any; +>null as any : any +>null : null +} +=== tests/cases/compiler/src/settings/spacing.ts === +import { scalar } from '../lib/operators/scalar'; +>scalar : (value: string) => import("tests/cases/compiler/src/lib/operators/scalar").Scalar + +export default { +>{ get xs() { return scalar("14px"); }} : { readonly xs: import("tests/cases/compiler/src/lib/operators/scalar").Scalar; } + + get xs() { +>xs : import("tests/cases/compiler/src/lib/operators/scalar").Scalar + + return scalar("14px"); +>scalar("14px") : import("tests/cases/compiler/src/lib/operators/scalar").Scalar +>scalar : (value: string) => import("tests/cases/compiler/src/lib/operators/scalar").Scalar +>"14px" : "14px" + } +}; + diff --git a/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.js b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.js new file mode 100644 index 0000000000000..c594c358981d2 --- /dev/null +++ b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.js @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/declarationEmitPrefersPathKindBasedOnBundling2.ts] //// + +//// [scalar.ts] +export interface Scalar { + (): string; + value: number; +} + +export function scalar(value: string): Scalar { + return null as any; +} +//// [spacing.ts] +import { scalar } from '../lib/operators/scalar'; + +export default { + get xs() { + return scalar("14px"); + } +}; + + +//// [dist.js] +define("lib/operators/scalar", ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + function scalar(value) { + return null; + } + exports.scalar = scalar; +}); +define("settings/spacing", ["require", "exports", "lib/operators/scalar"], function (require, exports, scalar_1) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.default = { + get xs() { + return scalar_1.scalar("14px"); + } + }; +}); + + +//// [dist.d.ts] +declare module "lib/operators/scalar" { + export interface Scalar { + (): string; + value: number; + } + export function scalar(value: string): Scalar; +} +declare module "settings/spacing" { + const _default: { + readonly xs: import("lib/operators/scalar").Scalar; + }; + export default _default; +} diff --git a/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.symbols b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.symbols new file mode 100644 index 0000000000000..683f3ccd71721 --- /dev/null +++ b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/src/lib/operators/scalar.ts === +export interface Scalar { +>Scalar : Symbol(Scalar, Decl(scalar.ts, 0, 0)) + + (): string; + value: number; +>value : Symbol(Scalar.value, Decl(scalar.ts, 1, 12)) +} + +export function scalar(value: string): Scalar { +>scalar : Symbol(scalar, Decl(scalar.ts, 3, 1)) +>value : Symbol(value, Decl(scalar.ts, 5, 23)) +>Scalar : Symbol(Scalar, Decl(scalar.ts, 0, 0)) + + return null as any; +} +=== tests/cases/compiler/src/settings/spacing.ts === +import { scalar } from '../lib/operators/scalar'; +>scalar : Symbol(scalar, Decl(spacing.ts, 0, 8)) + +export default { + get xs() { +>xs : Symbol(xs, Decl(spacing.ts, 2, 16)) + + return scalar("14px"); +>scalar : Symbol(scalar, Decl(spacing.ts, 0, 8)) + } +}; + diff --git a/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.types b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.types new file mode 100644 index 0000000000000..032b8a1b59377 --- /dev/null +++ b/tests/baselines/reference/declarationEmitPrefersPathKindBasedOnBundling2.types @@ -0,0 +1,32 @@ +=== tests/cases/compiler/src/lib/operators/scalar.ts === +export interface Scalar { + (): string; + value: number; +>value : number +} + +export function scalar(value: string): Scalar { +>scalar : (value: string) => Scalar +>value : string + + return null as any; +>null as any : any +>null : null +} +=== tests/cases/compiler/src/settings/spacing.ts === +import { scalar } from '../lib/operators/scalar'; +>scalar : (value: string) => import("tests/cases/compiler/src/lib/operators/scalar").Scalar + +export default { +>{ get xs() { return scalar("14px"); }} : { readonly xs: import("tests/cases/compiler/src/lib/operators/scalar").Scalar; } + + get xs() { +>xs : import("tests/cases/compiler/src/lib/operators/scalar").Scalar + + return scalar("14px"); +>scalar("14px") : import("tests/cases/compiler/src/lib/operators/scalar").Scalar +>scalar : (value: string) => import("tests/cases/compiler/src/lib/operators/scalar").Scalar +>"14px" : "14px" + } +}; + diff --git a/tests/cases/compiler/declarationEmitPrefersPathKindBasedOnBundling.ts b/tests/cases/compiler/declarationEmitPrefersPathKindBasedOnBundling.ts new file mode 100644 index 0000000000000..3cdce58fe652a --- /dev/null +++ b/tests/cases/compiler/declarationEmitPrefersPathKindBasedOnBundling.ts @@ -0,0 +1,22 @@ +// @declaration: true +// @target: es5 +// @baseUrl: /.src/tests/cases/compiler +// @outDir: ./dist +// @rootDir: ./tests/cases/compiler/src +// @filename: src/lib/operators/scalar.ts +export interface Scalar { + (): string; + value: number; +} + +export function scalar(value: string): Scalar { + return null as any; +} +// @filename: src/settings/spacing.ts +import { scalar } from '../lib/operators/scalar'; + +export default { + get xs() { + return scalar("14px"); + } +}; diff --git a/tests/cases/compiler/declarationEmitPrefersPathKindBasedOnBundling2.ts b/tests/cases/compiler/declarationEmitPrefersPathKindBasedOnBundling2.ts new file mode 100644 index 0000000000000..df57d488fbb50 --- /dev/null +++ b/tests/cases/compiler/declarationEmitPrefersPathKindBasedOnBundling2.ts @@ -0,0 +1,23 @@ +// @declaration: true +// @target: es5 +// @baseUrl: /.src/tests/cases/compiler +// @module: amd +// @outFile: ./dist.js +// @rootDir: ./tests/cases/compiler/src +// @filename: src/lib/operators/scalar.ts +export interface Scalar { + (): string; + value: number; +} + +export function scalar(value: string): Scalar { + return null as any; +} +// @filename: src/settings/spacing.ts +import { scalar } from '../lib/operators/scalar'; + +export default { + get xs() { + return scalar("14px"); + } +};