diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 6d45b769dd69b..75991144d9b1a 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1708,7 +1708,8 @@ namespace ts { return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } - function allKeysStartWithDot(obj: MapLike) { + /* @internal */ + export function allKeysStartWithDot(obj: MapLike) { return every(getOwnKeys(obj), k => startsWith(k, ".")); } @@ -1922,14 +1923,15 @@ namespace ts { } return toSearchResult(/*value*/ undefined); } + } - function isApplicableVersionedTypesKey(conditions: string[], key: string) { - if (conditions.indexOf("types") === -1) return false; // only apply versioned types conditions if the types condition is applied - if (!startsWith(key, "types@")) return false; - const range = VersionRange.tryParse(key.substring("types@".length)); - if (!range) return false; - return range.test(version); - } + /* @internal */ + export function isApplicableVersionedTypesKey(conditions: string[], key: string) { + if (conditions.indexOf("types") === -1) return false; // only apply versioned types conditions if the types condition is applied + if (!startsWith(key, "types@")) return false; + const range = VersionRange.tryParse(key.substring("types@".length)); + if (!range) return false; + return range.test(version); } function loadModuleFromNearestNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index cb8d33dd7b8f2..7c48d891a744c 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -555,6 +555,77 @@ namespace ts.moduleSpecifiers { } } + const enum MatchingMode { + Exact, + Directory, + Pattern + } + + function tryGetModuleNameFromExports(options: CompilerOptions, targetFilePath: string, packageDirectory: string, packageName: string, exports: unknown, conditions: string[], mode = MatchingMode.Exact): { moduleFileToTry: string } | undefined { + if (typeof exports === "string") { + const pathOrPattern = getNormalizedAbsolutePath(combinePaths(packageDirectory, exports), /*currentDirectory*/ undefined); + const extensionSwappedTarget = hasTSFileExtension(targetFilePath) ? removeFileExtension(targetFilePath) + tryGetJSExtensionForFile(targetFilePath, options) : undefined; + switch (mode) { + case MatchingMode.Exact: + if (comparePaths(targetFilePath, pathOrPattern) === Comparison.EqualTo || (extensionSwappedTarget && comparePaths(extensionSwappedTarget, pathOrPattern) === Comparison.EqualTo)) { + return { moduleFileToTry: packageName }; + } + break; + case MatchingMode.Directory: + if (containsPath(pathOrPattern, targetFilePath)) { + const fragment = getRelativePathFromDirectory(pathOrPattern, targetFilePath, /*ignoreCase*/ false); + return { moduleFileToTry: getNormalizedAbsolutePath(combinePaths(combinePaths(packageName, exports), fragment), /*currentDirectory*/ undefined) }; + } + break; + case MatchingMode.Pattern: + const starPos = pathOrPattern.indexOf("*"); + const leadingSlice = pathOrPattern.slice(0, starPos); + const trailingSlice = pathOrPattern.slice(starPos + 1); + if (startsWith(targetFilePath, leadingSlice) && endsWith(targetFilePath, trailingSlice)) { + const starReplacement = targetFilePath.slice(leadingSlice.length, targetFilePath.length - trailingSlice.length); + return { moduleFileToTry: packageName.replace("*", starReplacement) }; + } + if (extensionSwappedTarget && startsWith(extensionSwappedTarget, leadingSlice) && endsWith(extensionSwappedTarget, trailingSlice)) { + const starReplacement = extensionSwappedTarget.slice(leadingSlice.length, extensionSwappedTarget.length - trailingSlice.length); + return { moduleFileToTry: packageName.replace("*", starReplacement) }; + } + break; + } + } + else if (Array.isArray(exports)) { + return forEach(exports, e => tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, packageName, e, conditions)); + } + else if (typeof exports === "object" && exports !== null) { // eslint-disable-line no-null/no-null + if (allKeysStartWithDot(exports as MapLike)) { + // sub-mappings + // 3 cases: + // * directory mappings (legacyish, key ends with / (technically allows index/extension resolution under cjs mode)) + // * pattern mappings (contains a *) + // * exact mappings (no *, does not end with /) + return forEach(getOwnKeys(exports as MapLike), k => { + const subPackageName = getNormalizedAbsolutePath(combinePaths(packageName, k), /*currentDirectory*/ undefined); + const mode = endsWith(k, "/") ? MatchingMode.Directory + : stringContains(k, "*") ? MatchingMode.Pattern + : MatchingMode.Exact; + return tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, subPackageName, (exports as MapLike)[k], conditions, mode); + }); + } + else { + // conditional mapping + for (const key of getOwnKeys(exports as MapLike)) { + if (key === "default" || conditions.indexOf(key) >= 0 || isApplicableVersionedTypesKey(conditions, key)) { + const subTarget = (exports as MapLike)[key]; + const result = tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, packageName, subTarget, conditions); + if (result) { + return result; + } + } + } + } + } + return undefined; + } + function tryGetModuleNameFromRootDirs(rootDirs: readonly string[], moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string, ending: Ending, compilerOptions: CompilerOptions): string | undefined { const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName); if (normalizedTargetPath === undefined) { @@ -586,7 +657,15 @@ namespace ts.moduleSpecifiers { let moduleFileNameForExtensionless: string | undefined; while (true) { // If the module could be imported by a directory name, use that directory's name - const { moduleFileToTry, packageRootPath } = tryDirectoryWithPackageJson(packageRootIndex); + const { moduleFileToTry, packageRootPath, blockedByExports, verbatimFromExports } = tryDirectoryWithPackageJson(packageRootIndex); + if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Classic) { + if (blockedByExports) { + return undefined; // File is under this package.json, but is not publicly exported - there's no way to name it via `node_modules` resolution + } + if (verbatimFromExports) { + return moduleFileToTry; + } + } if (packageRootPath) { moduleSpecifier = packageRootPath; isPackageRootPath = true; @@ -621,12 +700,21 @@ namespace ts.moduleSpecifiers { // For classic resolution, only allow importing from node_modules/@types, not other node_modules return getEmitModuleResolutionKind(options) === ModuleResolutionKind.Classic && packageName === nodeModulesDirectoryName ? undefined : packageName; - function tryDirectoryWithPackageJson(packageRootIndex: number) { + function tryDirectoryWithPackageJson(packageRootIndex: number): { moduleFileToTry: string, packageRootPath?: string, blockedByExports?: true, verbatimFromExports?: true } { const packageRootPath = path.substring(0, packageRootIndex); const packageJsonPath = combinePaths(packageRootPath, "package.json"); let moduleFileToTry = path; if (host.fileExists(packageJsonPath)) { const packageJsonContent = JSON.parse(host.readFile!(packageJsonPath)!); + // TODO: Inject `require` or `import` condition based on the intended import mode + const fromExports = packageJsonContent.exports && typeof packageJsonContent.name === "string" ? tryGetModuleNameFromExports(options, path, packageRootPath, packageJsonContent.name, packageJsonContent.exports, ["node", "types"]) : undefined; + if (fromExports) { + const withJsExtension = !hasTSFileExtension(fromExports.moduleFileToTry) ? fromExports : { moduleFileToTry: removeFileExtension(fromExports.moduleFileToTry) + tryGetJSExtensionForFile(fromExports.moduleFileToTry, options) }; + return { ...withJsExtension, verbatimFromExports: true }; + } + if (packageJsonContent.exports) { + return { moduleFileToTry: path, blockedByExports: true }; + } const versionPaths = packageJsonContent.typesVersions ? getPackageJsonTypesVersionsPaths(packageJsonContent.typesVersions) : undefined; @@ -641,7 +729,6 @@ namespace ts.moduleSpecifiers { moduleFileToTry = combinePaths(packageRootPath, fromPaths); } } - // If the file is the main module, it can be imported by the package name const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; if (isString(mainFileRelative)) { diff --git a/src/testRunner/unittests/tsbuild/moduleSpecifiers.ts b/src/testRunner/unittests/tsbuild/moduleSpecifiers.ts index 8494fd9498a36..9c560a1bd6f4e 100644 --- a/src/testRunner/unittests/tsbuild/moduleSpecifiers.ts +++ b/src/testRunner/unittests/tsbuild/moduleSpecifiers.ts @@ -88,4 +88,101 @@ namespace ts { commandLineArgs: ["-b", "/src", "--verbose"] }); }); + + // https://github.com/microsoft/TypeScript/issues/44434 but with `module: node12`, some `exports` maps blocking direct access, and no `baseUrl` + describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers across referenced projects resolve correctly", () => { + verifyTsc({ + scenario: "moduleSpecifiers", + subScenario: `synthesized module specifiers across projects resolve correctly`, + fs: () => loadProjectFromFiles({ + "/src/src-types/index.ts": Utils.dedent` + export * from './dogconfig.js';`, + "/src/src-types/dogconfig.ts": Utils.dedent` + export interface DogConfig { + name: string; + }`, + "/src/src-dogs/index.ts": Utils.dedent` + export * from 'src-types'; + export * from './lassie/lassiedog.js'; + `, + "/src/src-dogs/dogconfig.ts": Utils.dedent` + import { DogConfig } from 'src-types'; + + export const DOG_CONFIG: DogConfig = { + name: 'Default dog', + }; + `, + "/src/src-dogs/dog.ts": Utils.dedent` + import { DogConfig } from 'src-types'; + import { DOG_CONFIG } from './dogconfig.js'; + + export abstract class Dog { + + public static getCapabilities(): DogConfig { + return DOG_CONFIG; + } + } + `, + "/src/src-dogs/lassie/lassiedog.ts": Utils.dedent` + import { Dog } from '../dog.js'; + import { LASSIE_CONFIG } from './lassieconfig.js'; + + export class LassieDog extends Dog { + protected static getDogConfig = () => LASSIE_CONFIG; + } + `, + "/src/src-dogs/lassie/lassieconfig.ts": Utils.dedent` + import { DogConfig } from 'src-types'; + + export const LASSIE_CONFIG: DogConfig = { name: 'Lassie' }; + `, + "/src/tsconfig-base.json": Utils.dedent` + { + "compilerOptions": { + "declaration": true, + "module": "node12" + } + }`, + "/src/src-types/package.json": Utils.dedent` + { + "type": "module", + "exports": "./index.js" + }`, + "/src/src-dogs/package.json": Utils.dedent` + { + "type": "module", + "exports": "./index.js" + }`, + "/src/src-types/tsconfig.json": Utils.dedent` + { + "extends": "../tsconfig-base.json", + "compilerOptions": { + "composite": true + }, + "include": [ + "**/*" + ] + }`, + "/src/src-dogs/tsconfig.json": Utils.dedent` + { + "extends": "../tsconfig-base.json", + "compilerOptions": { + "composite": true + }, + "references": [ + { "path": "../src-types" } + ], + "include": [ + "**/*" + ] + }`, + }, ""), + modifyFs: fs => { + fs.writeFileSync("/lib/lib.es2020.full.d.ts", tscWatch.libFile.content); + fs.symlinkSync("/src", "/src/src-types/node_modules"); + fs.symlinkSync("/src", "/src/src-dogs/node_modules"); + }, + commandLineArgs: ["-b", "src/src-types", "src/src-dogs", "--verbose"] + }); + }); } diff --git a/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).errors.txt b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).errors.txt new file mode 100644 index 0000000000000..d6b74fdf7e00a --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).errors.txt @@ -0,0 +1,36 @@ +tests/cases/conformance/node/index.ts(2,23): error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. +tests/cases/conformance/node/index.ts(3,14): error TS2742: The inferred type of 'a' cannot be named without a reference to './node_modules/inner/other.js'. This is likely not portable. A type annotation is necessary. +tests/cases/conformance/node/index.ts(3,19): error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. + + +==== tests/cases/conformance/node/index.ts (3 errors) ==== + // esm format file + import { Thing } from "inner/other"; + ~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. + export const a = (await import("inner")).x(); + ~ +!!! error TS2742: The inferred type of 'a' cannot be named without a reference to './node_modules/inner/other.js'. This is likely not portable. A type annotation is necessary. + ~~~~~ +!!! error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. +==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ==== + // esm format file + export { x } from "./other.js"; +==== tests/cases/conformance/node/node_modules/inner/other.d.ts (0 errors) ==== + // esm format file + export interface Thing {} + export const x: () => Thing; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" + } +==== tests/cases/conformance/node/node_modules/inner/package.json (0 errors) ==== + { + "name": "inner", + "private": true, + "type": "module", + "exports": "./index.js" + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).js b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).js new file mode 100644 index 0000000000000..da6fe0fc80095 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).js @@ -0,0 +1,30 @@ +//// [tests/cases/conformance/node/nodeModulesExportsBlocksSpecifierResolution.ts] //// + +//// [index.ts] +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner")).x(); +//// [index.d.ts] +// esm format file +export { x } from "./other.js"; +//// [other.d.ts] +// esm format file +export interface Thing {} +export const x: () => Thing; +//// [package.json] +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +//// [package.json] +{ + "name": "inner", + "private": true, + "type": "module", + "exports": "./index.js" +} + +//// [index.js] +export const a = (await import("inner")).x(); diff --git a/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).symbols b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).symbols new file mode 100644 index 0000000000000..07abee8390f9b --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : Symbol(Thing, Decl(index.ts, 1, 8)) + +export const a = (await import("inner")).x(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>(await import("inner")).x : Symbol(x, Decl(index.d.ts, 1, 8)) +>"inner" : Symbol("tests/cases/conformance/node/node_modules/inner/index", Decl(index.d.ts, 0, 0)) +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + +export const x: () => Thing; +>x : Symbol(x, Decl(other.d.ts, 2, 12)) +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).types b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).types new file mode 100644 index 0000000000000..f7806a6a25572 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=node12).types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : any + +export const a = (await import("inner")).x(); +>a : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")).x() : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")).x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")) : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>await import("inner") : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>import("inner") : Promise +>"inner" : "inner" +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +export const x: () => Thing; +>x : () => Thing + diff --git a/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).errors.txt b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).errors.txt new file mode 100644 index 0000000000000..53ab414e38ba6 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/node/index.ts(2,23): error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. +tests/cases/conformance/node/index.ts(3,14): error TS2742: The inferred type of 'a' cannot be named without a reference to './node_modules/inner/other.js'. This is likely not portable. A type annotation is necessary. + + +==== tests/cases/conformance/node/index.ts (2 errors) ==== + // esm format file + import { Thing } from "inner/other"; + ~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. + export const a = (await import("inner")).x(); + ~ +!!! error TS2742: The inferred type of 'a' cannot be named without a reference to './node_modules/inner/other.js'. This is likely not portable. A type annotation is necessary. +==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ==== + // esm format file + export { x } from "./other.js"; +==== tests/cases/conformance/node/node_modules/inner/other.d.ts (0 errors) ==== + // esm format file + export interface Thing {} + export const x: () => Thing; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" + } +==== tests/cases/conformance/node/node_modules/inner/package.json (0 errors) ==== + { + "name": "inner", + "private": true, + "type": "module", + "exports": "./index.js" + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).js b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).js new file mode 100644 index 0000000000000..da6fe0fc80095 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).js @@ -0,0 +1,30 @@ +//// [tests/cases/conformance/node/nodeModulesExportsBlocksSpecifierResolution.ts] //// + +//// [index.ts] +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner")).x(); +//// [index.d.ts] +// esm format file +export { x } from "./other.js"; +//// [other.d.ts] +// esm format file +export interface Thing {} +export const x: () => Thing; +//// [package.json] +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +//// [package.json] +{ + "name": "inner", + "private": true, + "type": "module", + "exports": "./index.js" +} + +//// [index.js] +export const a = (await import("inner")).x(); diff --git a/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).symbols b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).symbols new file mode 100644 index 0000000000000..07abee8390f9b --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : Symbol(Thing, Decl(index.ts, 1, 8)) + +export const a = (await import("inner")).x(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>(await import("inner")).x : Symbol(x, Decl(index.d.ts, 1, 8)) +>"inner" : Symbol("tests/cases/conformance/node/node_modules/inner/index", Decl(index.d.ts, 0, 0)) +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + +export const x: () => Thing; +>x : Symbol(x, Decl(other.d.ts, 2, 12)) +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).types b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).types new file mode 100644 index 0000000000000..f7806a6a25572 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsBlocksSpecifierResolution(module=nodenext).types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : any + +export const a = (await import("inner")).x(); +>a : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")).x() : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")).x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")) : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>await import("inner") : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>import("inner") : Promise +>"inner" : "inner" +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +export const x: () => Thing; +>x : () => Thing + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).errors.txt b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).errors.txt new file mode 100644 index 0000000000000..1a9b16d74f2d7 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).errors.txt @@ -0,0 +1,40 @@ +tests/cases/conformance/node/index.ts(2,23): error TS2307: Cannot find module 'inner/other.js' or its corresponding type declarations. +tests/cases/conformance/node/index.ts(3,19): error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. + + +==== tests/cases/conformance/node/index.ts (2 errors) ==== + // esm format file + import { Thing } from "inner/other.js"; // should fail + ~~~~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/other.js' or its corresponding type declarations. + export const a = (await import("inner")).x(); + ~~~~~ +!!! error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. +==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ==== + // esm format file + export { x } from "./other.js"; +==== tests/cases/conformance/node/node_modules/inner/other.d.ts (0 errors) ==== + // esm format file + export interface Thing {} + export const x: () => Thing; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" + } +==== tests/cases/conformance/node/node_modules/inner/package.json (0 errors) ==== + { + "name": "inner", + "private": true, + "type": "module", + "exports": { + ".": { + "default": "./index.js" + }, + "./other": { + "default": "./other.js" + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).js b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).js new file mode 100644 index 0000000000000..5db58ae2f7bfa --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).js @@ -0,0 +1,41 @@ +//// [tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationConditions.ts] //// + +//// [index.ts] +// esm format file +import { Thing } from "inner/other.js"; // should fail +export const a = (await import("inner")).x(); +//// [index.d.ts] +// esm format file +export { x } from "./other.js"; +//// [other.d.ts] +// esm format file +export interface Thing {} +export const x: () => Thing; +//// [package.json] +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +//// [package.json] +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + ".": { + "default": "./index.js" + }, + "./other": { + "default": "./other.js" + } + } +} + +//// [index.js] +export const a = (await import("inner")).x(); + + +//// [index.d.ts] +export declare const a: import("inner/other").Thing; diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).symbols b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).symbols new file mode 100644 index 0000000000000..1abea377c5f35 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other.js"; // should fail +>Thing : Symbol(Thing, Decl(index.ts, 1, 8)) + +export const a = (await import("inner")).x(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>(await import("inner")).x : Symbol(x, Decl(index.d.ts, 1, 8)) +>"inner" : Symbol("tests/cases/conformance/node/node_modules/inner/index", Decl(index.d.ts, 0, 0)) +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + +export const x: () => Thing; +>x : Symbol(x, Decl(other.d.ts, 2, 12)) +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).types b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).types new file mode 100644 index 0000000000000..6020ebf5b21be --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=node12).types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other.js"; // should fail +>Thing : any + +export const a = (await import("inner")).x(); +>a : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")).x() : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")).x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")) : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>await import("inner") : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>import("inner") : Promise +>"inner" : "inner" +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +export const x: () => Thing; +>x : () => Thing + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).errors.txt b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).errors.txt new file mode 100644 index 0000000000000..b25fc090f8b5d --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).errors.txt @@ -0,0 +1,37 @@ +tests/cases/conformance/node/index.ts(2,23): error TS2307: Cannot find module 'inner/other.js' or its corresponding type declarations. + + +==== tests/cases/conformance/node/index.ts (1 errors) ==== + // esm format file + import { Thing } from "inner/other.js"; // should fail + ~~~~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/other.js' or its corresponding type declarations. + export const a = (await import("inner")).x(); +==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ==== + // esm format file + export { x } from "./other.js"; +==== tests/cases/conformance/node/node_modules/inner/other.d.ts (0 errors) ==== + // esm format file + export interface Thing {} + export const x: () => Thing; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" + } +==== tests/cases/conformance/node/node_modules/inner/package.json (0 errors) ==== + { + "name": "inner", + "private": true, + "type": "module", + "exports": { + ".": { + "default": "./index.js" + }, + "./other": { + "default": "./other.js" + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).js b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).js new file mode 100644 index 0000000000000..5db58ae2f7bfa --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).js @@ -0,0 +1,41 @@ +//// [tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationConditions.ts] //// + +//// [index.ts] +// esm format file +import { Thing } from "inner/other.js"; // should fail +export const a = (await import("inner")).x(); +//// [index.d.ts] +// esm format file +export { x } from "./other.js"; +//// [other.d.ts] +// esm format file +export interface Thing {} +export const x: () => Thing; +//// [package.json] +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +//// [package.json] +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + ".": { + "default": "./index.js" + }, + "./other": { + "default": "./other.js" + } + } +} + +//// [index.js] +export const a = (await import("inner")).x(); + + +//// [index.d.ts] +export declare const a: import("inner/other").Thing; diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).symbols b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).symbols new file mode 100644 index 0000000000000..1abea377c5f35 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other.js"; // should fail +>Thing : Symbol(Thing, Decl(index.ts, 1, 8)) + +export const a = (await import("inner")).x(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>(await import("inner")).x : Symbol(x, Decl(index.d.ts, 1, 8)) +>"inner" : Symbol("tests/cases/conformance/node/node_modules/inner/index", Decl(index.d.ts, 0, 0)) +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + +export const x: () => Thing; +>x : Symbol(x, Decl(other.d.ts, 2, 12)) +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).types b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).types new file mode 100644 index 0000000000000..6020ebf5b21be --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationConditions(module=nodenext).types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other.js"; // should fail +>Thing : any + +export const a = (await import("inner")).x(); +>a : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")).x() : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")).x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner")) : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>await import("inner") : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>import("inner") : Promise +>"inner" : "inner" +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +export const x: () => Thing; +>x : () => Thing + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).errors.txt b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).errors.txt new file mode 100644 index 0000000000000..7216f0655b9f8 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).errors.txt @@ -0,0 +1,35 @@ +tests/cases/conformance/node/index.ts(2,23): error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. +tests/cases/conformance/node/index.ts(3,19): error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. + + +==== tests/cases/conformance/node/index.ts (2 errors) ==== + // esm format file + import { Thing } from "inner/other"; + ~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. + export const a = (await import("inner/index.js")).x(); + ~~~~~ +!!! error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. +==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ==== + // esm format file + export { x } from "./other.js"; +==== tests/cases/conformance/node/node_modules/inner/other.d.ts (0 errors) ==== + // esm format file + export interface Thing {} + export const x: () => Thing; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" + } +==== tests/cases/conformance/node/node_modules/inner/package.json (0 errors) ==== + { + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./": "./" + } + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).js b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).js new file mode 100644 index 0000000000000..c0d6b006b33cf --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).js @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationDirectory.ts] //// + +//// [index.ts] +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner/index.js")).x(); +//// [index.d.ts] +// esm format file +export { x } from "./other.js"; +//// [other.d.ts] +// esm format file +export interface Thing {} +export const x: () => Thing; +//// [package.json] +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +//// [package.json] +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./": "./" + } +} + +//// [index.js] +export const a = (await import("inner/index.js")).x(); + + +//// [index.d.ts] +export declare const a: import("inner/other.js").Thing; diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).symbols b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).symbols new file mode 100644 index 0000000000000..a12a7b1c026dc --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : Symbol(Thing, Decl(index.ts, 1, 8)) + +export const a = (await import("inner/index.js")).x(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>(await import("inner/index.js")).x : Symbol(x, Decl(index.d.ts, 1, 8)) +>"inner/index.js" : Symbol("tests/cases/conformance/node/node_modules/inner/index", Decl(index.d.ts, 0, 0)) +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + +export const x: () => Thing; +>x : Symbol(x, Decl(other.d.ts, 2, 12)) +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).types b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).types new file mode 100644 index 0000000000000..a75c2359eb0c8 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=node12).types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : any + +export const a = (await import("inner/index.js")).x(); +>a : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")).x() : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")).x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")) : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>await import("inner/index.js") : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>import("inner/index.js") : Promise +>"inner/index.js" : "inner/index.js" +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +export const x: () => Thing; +>x : () => Thing + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).errors.txt b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).errors.txt new file mode 100644 index 0000000000000..b2d874ee38bb1 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).errors.txt @@ -0,0 +1,32 @@ +tests/cases/conformance/node/index.ts(2,23): error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. + + +==== tests/cases/conformance/node/index.ts (1 errors) ==== + // esm format file + import { Thing } from "inner/other"; + ~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. + export const a = (await import("inner/index.js")).x(); +==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ==== + // esm format file + export { x } from "./other.js"; +==== tests/cases/conformance/node/node_modules/inner/other.d.ts (0 errors) ==== + // esm format file + export interface Thing {} + export const x: () => Thing; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" + } +==== tests/cases/conformance/node/node_modules/inner/package.json (0 errors) ==== + { + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./": "./" + } + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).js b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).js new file mode 100644 index 0000000000000..c0d6b006b33cf --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).js @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationDirectory.ts] //// + +//// [index.ts] +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner/index.js")).x(); +//// [index.d.ts] +// esm format file +export { x } from "./other.js"; +//// [other.d.ts] +// esm format file +export interface Thing {} +export const x: () => Thing; +//// [package.json] +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +//// [package.json] +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./": "./" + } +} + +//// [index.js] +export const a = (await import("inner/index.js")).x(); + + +//// [index.d.ts] +export declare const a: import("inner/other.js").Thing; diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).symbols b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).symbols new file mode 100644 index 0000000000000..a12a7b1c026dc --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : Symbol(Thing, Decl(index.ts, 1, 8)) + +export const a = (await import("inner/index.js")).x(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>(await import("inner/index.js")).x : Symbol(x, Decl(index.d.ts, 1, 8)) +>"inner/index.js" : Symbol("tests/cases/conformance/node/node_modules/inner/index", Decl(index.d.ts, 0, 0)) +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + +export const x: () => Thing; +>x : Symbol(x, Decl(other.d.ts, 2, 12)) +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).types b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).types new file mode 100644 index 0000000000000..a75c2359eb0c8 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationDirectory(module=nodenext).types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : any + +export const a = (await import("inner/index.js")).x(); +>a : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")).x() : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")).x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")) : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>await import("inner/index.js") : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>import("inner/index.js") : Promise +>"inner/index.js" : "inner/index.js" +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +export const x: () => Thing; +>x : () => Thing + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).errors.txt b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).errors.txt new file mode 100644 index 0000000000000..9db5139062495 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).errors.txt @@ -0,0 +1,38 @@ +tests/cases/conformance/node/index.ts(2,23): error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. +tests/cases/conformance/node/index.ts(3,19): error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. +tests/cases/conformance/node/index.ts(3,32): error TS2307: Cannot find module 'inner/index.js' or its corresponding type declarations. + + +==== tests/cases/conformance/node/index.ts (3 errors) ==== + // esm format file + import { Thing } from "inner/other"; + ~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. + export const a = (await import("inner/index.js")).x(); + ~~~~~ +!!! error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. + ~~~~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/index.js' or its corresponding type declarations. +==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ==== + // esm format file + export { x } from "./other.js"; +==== tests/cases/conformance/node/node_modules/inner/other.d.ts (0 errors) ==== + // esm format file + export interface Thing {} + export const x: () => Thing; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" + } +==== tests/cases/conformance/node/node_modules/inner/package.json (0 errors) ==== + { + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./*.js": "./*.js" + } + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).js b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).js new file mode 100644 index 0000000000000..63cf2dae87417 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).js @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationPattern.ts] //// + +//// [index.ts] +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner/index.js")).x(); +//// [index.d.ts] +// esm format file +export { x } from "./other.js"; +//// [other.d.ts] +// esm format file +export interface Thing {} +export const x: () => Thing; +//// [package.json] +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +//// [package.json] +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./*.js": "./*.js" + } +} + +//// [index.js] +export const a = (await import("inner/index.js")).x(); + + +//// [index.d.ts] +export declare const a: any; diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).symbols b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).symbols new file mode 100644 index 0000000000000..5bcb54a5bdb68 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : Symbol(Thing, Decl(index.ts, 1, 8)) + +export const a = (await import("inner/index.js")).x(); +>a : Symbol(a, Decl(index.ts, 2, 12)) + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + +export const x: () => Thing; +>x : Symbol(x, Decl(other.d.ts, 2, 12)) +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).types b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).types new file mode 100644 index 0000000000000..4ac4b8a432f64 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=node12).types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : any + +export const a = (await import("inner/index.js")).x(); +>a : any +>(await import("inner/index.js")).x() : any +>(await import("inner/index.js")).x : any +>(await import("inner/index.js")) : any +>await import("inner/index.js") : any +>import("inner/index.js") : Promise +>"inner/index.js" : "inner/index.js" +>x : any + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +export const x: () => Thing; +>x : () => Thing + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).errors.txt b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).errors.txt new file mode 100644 index 0000000000000..c315a2a523203 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).errors.txt @@ -0,0 +1,32 @@ +tests/cases/conformance/node/index.ts(2,23): error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. + + +==== tests/cases/conformance/node/index.ts (1 errors) ==== + // esm format file + import { Thing } from "inner/other"; + ~~~~~~~~~~~~~ +!!! error TS2307: Cannot find module 'inner/other' or its corresponding type declarations. + export const a = (await import("inner/index.js")).x(); +==== tests/cases/conformance/node/node_modules/inner/index.d.ts (0 errors) ==== + // esm format file + export { x } from "./other.js"; +==== tests/cases/conformance/node/node_modules/inner/other.d.ts (0 errors) ==== + // esm format file + export interface Thing {} + export const x: () => Thing; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" + } +==== tests/cases/conformance/node/node_modules/inner/package.json (0 errors) ==== + { + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./*.js": "./*.js" + } + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).js b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).js new file mode 100644 index 0000000000000..dcdd62bed698d --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).js @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationPattern.ts] //// + +//// [index.ts] +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner/index.js")).x(); +//// [index.d.ts] +// esm format file +export { x } from "./other.js"; +//// [other.d.ts] +// esm format file +export interface Thing {} +export const x: () => Thing; +//// [package.json] +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +//// [package.json] +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./*.js": "./*.js" + } +} + +//// [index.js] +export const a = (await import("inner/index.js")).x(); + + +//// [index.d.ts] +export declare const a: import("inner/other.js").Thing; diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).symbols b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).symbols new file mode 100644 index 0000000000000..a12a7b1c026dc --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : Symbol(Thing, Decl(index.ts, 1, 8)) + +export const a = (await import("inner/index.js")).x(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>(await import("inner/index.js")).x : Symbol(x, Decl(index.d.ts, 1, 8)) +>"inner/index.js" : Symbol("tests/cases/conformance/node/node_modules/inner/index", Decl(index.d.ts, 0, 0)) +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : Symbol(x, Decl(index.d.ts, 1, 8)) + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + +export const x: () => Thing; +>x : Symbol(x, Decl(other.d.ts, 2, 12)) +>Thing : Symbol(Thing, Decl(other.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).types b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).types new file mode 100644 index 0000000000000..a75c2359eb0c8 --- /dev/null +++ b/tests/baselines/reference/nodeModulesExportsSpecifierGenerationPattern(module=nodenext).types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/node/index.ts === +// esm format file +import { Thing } from "inner/other"; +>Thing : any + +export const a = (await import("inner/index.js")).x(); +>a : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")).x() : import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")).x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing +>(await import("inner/index.js")) : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>await import("inner/index.js") : typeof import("tests/cases/conformance/node/node_modules/inner/index") +>import("inner/index.js") : Promise +>"inner/index.js" : "inner/index.js" +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/index.d.ts === +// esm format file +export { x } from "./other.js"; +>x : () => import("tests/cases/conformance/node/node_modules/inner/other").Thing + +=== tests/cases/conformance/node/node_modules/inner/other.d.ts === +// esm format file +export interface Thing {} +export const x: () => Thing; +>x : () => Thing + diff --git a/tests/baselines/reference/tsbuild/moduleSpecifiers/initial-build/synthesized-module-specifiers-across-projects-resolve-correctly.js b/tests/baselines/reference/tsbuild/moduleSpecifiers/initial-build/synthesized-module-specifiers-across-projects-resolve-correctly.js new file mode 100644 index 0000000000000..254c7cdef4174 --- /dev/null +++ b/tests/baselines/reference/tsbuild/moduleSpecifiers/initial-build/synthesized-module-specifiers-across-projects-resolve-correctly.js @@ -0,0 +1,405 @@ +Input:: +//// [/lib/lib.d.ts] + + +//// [/lib/lib.es2020.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; } + +//// [/src/src-dogs/dog.ts] +import { DogConfig } from 'src-types'; +import { DOG_CONFIG } from './dogconfig.js'; + +export abstract class Dog { + + public static getCapabilities(): DogConfig { + return DOG_CONFIG; + } +} + + +//// [/src/src-dogs/dogconfig.ts] +import { DogConfig } from 'src-types'; + +export const DOG_CONFIG: DogConfig = { + name: 'Default dog', +}; + + +//// [/src/src-dogs/index.ts] +export * from 'src-types'; +export * from './lassie/lassiedog.js'; + + +//// [/src/src-dogs/lassie/lassieconfig.ts] +import { DogConfig } from 'src-types'; + +export const LASSIE_CONFIG: DogConfig = { name: 'Lassie' }; + + +//// [/src/src-dogs/lassie/lassiedog.ts] +import { Dog } from '../dog.js'; +import { LASSIE_CONFIG } from './lassieconfig.js'; + +export class LassieDog extends Dog { + protected static getDogConfig = () => LASSIE_CONFIG; +} + + +//// [/src/src-dogs/node_modules] symlink(/src) +//// [/src/src-dogs/package.json] +{ + "type": "module", + "exports": "./index.js" +} + +//// [/src/src-dogs/tsconfig.json] +{ + "extends": "../tsconfig-base.json", + "compilerOptions": { + "composite": true + }, + "references": [ + { "path": "../src-types" } + ], + "include": [ + "**/*" + ] +} + +//// [/src/src-types/dogconfig.ts] +export interface DogConfig { + name: string; +} + +//// [/src/src-types/index.ts] +export * from './dogconfig.js'; + +//// [/src/src-types/node_modules] symlink(/src) +//// [/src/src-types/package.json] +{ + "type": "module", + "exports": "./index.js" +} + +//// [/src/src-types/tsconfig.json] +{ + "extends": "../tsconfig-base.json", + "compilerOptions": { + "composite": true + }, + "include": [ + "**/*" + ] +} + +//// [/src/tsconfig-base.json] +{ + "compilerOptions": { + "declaration": true, + "module": "node12" + } +} + + + +Output:: +/lib/tsc -b src/src-types src/src-dogs --verbose +[12:00:00 AM] Projects in this build: + * src/src-types/tsconfig.json + * src/src-dogs/tsconfig.json + +[12:00:00 AM] Project 'src/src-types/tsconfig.json' is out of date because output file 'src/src-types/dogconfig.js' does not exist + +[12:00:00 AM] Building project '/src/src-types/tsconfig.json'... + +[12:00:00 AM] Project 'src/src-dogs/tsconfig.json' is out of date because output file 'src/src-dogs/dog.js' does not exist + +[12:00:00 AM] Building project '/src/src-dogs/tsconfig.json'... + +exitCode:: ExitStatus.Success + + +//// [/src/src-dogs/dog.d.ts] +import { DogConfig } from 'src-types'; +export declare abstract class Dog { + static getCapabilities(): DogConfig; +} + + +//// [/src/src-dogs/dog.js] +import { DOG_CONFIG } from './dogconfig.js'; +export class Dog { + static getCapabilities() { + return DOG_CONFIG; + } +} + + +//// [/src/src-dogs/dogconfig.d.ts] +import { DogConfig } from 'src-types'; +export declare const DOG_CONFIG: DogConfig; + + +//// [/src/src-dogs/dogconfig.js] +export const DOG_CONFIG = { + name: 'Default dog', +}; + + +//// [/src/src-dogs/index.d.ts] +export * from 'src-types'; +export * from './lassie/lassiedog.js'; + + +//// [/src/src-dogs/index.js] +export * from 'src-types'; +export * from './lassie/lassiedog.js'; + + +//// [/src/src-dogs/lassie/lassieconfig.d.ts] +import { DogConfig } from 'src-types'; +export declare const LASSIE_CONFIG: DogConfig; + + +//// [/src/src-dogs/lassie/lassieconfig.js] +export const LASSIE_CONFIG = { name: 'Lassie' }; + + +//// [/src/src-dogs/lassie/lassiedog.d.ts] +import { Dog } from '../dog.js'; +export declare class LassieDog extends Dog { + protected static getDogConfig: () => import("../index.js").DogConfig; +} + + +//// [/src/src-dogs/lassie/lassiedog.js] +import { Dog } from '../dog.js'; +import { LASSIE_CONFIG } from './lassieconfig.js'; +export class LassieDog extends Dog { +} +LassieDog.getDogConfig = () => LASSIE_CONFIG; + + +//// [/src/src-dogs/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.es2020.full.d.ts","../src-types/dogconfig.d.ts","../src-types/index.d.ts","./dogconfig.ts","./dog.ts","./lassie/lassieconfig.ts","./lassie/lassiedog.ts","./index.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true,"impliedFormat":1},"-2632060142-export interface DogConfig {\r\n name: string;\r\n}\r\n","-5608794531-export * from './dogconfig.js';\r\n","1966273863-import { DogConfig } from 'src-types';\n\nexport const DOG_CONFIG: DogConfig = {\n name: 'Default dog',\n};\n","6091345804-import { DogConfig } from 'src-types';\nimport { DOG_CONFIG } from './dogconfig.js';\n\nexport abstract class Dog {\n\n public static getCapabilities(): DogConfig {\n return DOG_CONFIG;\n }\n}\n","4440579024-import { DogConfig } from 'src-types';\n\nexport const LASSIE_CONFIG: DogConfig = { name: 'Lassie' };\n","-32303727812-import { Dog } from '../dog.js';\nimport { LASSIE_CONFIG } from './lassieconfig.js';\n\nexport class LassieDog extends Dog {\n protected static getDogConfig = () => LASSIE_CONFIG;\n}\n","-15974991320-export * from 'src-types';\nexport * from './lassie/lassiedog.js';\n"],"options":{"composite":true,"declaration":true,"module":100},"fileIdsList":[[3,4],[3],[3,7],[5,6],[2]],"referencedMap":[[5,1],[4,2],[8,3],[6,2],[7,4],[3,5]],"exportedModulesMap":[[5,1],[4,2],[8,3],[6,2],[7,4],[3,5]],"semanticDiagnosticsPerFile":[1,5,4,8,6,7,2,3]},"version":"FakeTSVersion"} + +//// [/src/src-dogs/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.es2020.full.d.ts", + "../src-types/dogconfig.d.ts", + "../src-types/index.d.ts", + "./dogconfig.ts", + "./dog.ts", + "./lassie/lassieconfig.ts", + "./lassie/lassiedog.ts", + "./index.ts" + ], + "fileNamesList": [ + [ + "../src-types/index.d.ts", + "./dogconfig.ts" + ], + [ + "../src-types/index.d.ts" + ], + [ + "../src-types/index.d.ts", + "./lassie/lassiedog.ts" + ], + [ + "./dog.ts", + "./lassie/lassieconfig.ts" + ], + [ + "../src-types/dogconfig.d.ts" + ] + ], + "fileInfos": { + "../../lib/lib.es2020.full.d.ts": { + "version": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "signature": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "affectsGlobalScope": true, + "impliedFormat": 1 + }, + "../src-types/dogconfig.d.ts": { + "version": "-2632060142-export interface DogConfig {\r\n name: string;\r\n}\r\n", + "signature": "-2632060142-export interface DogConfig {\r\n name: string;\r\n}\r\n" + }, + "../src-types/index.d.ts": { + "version": "-5608794531-export * from './dogconfig.js';\r\n", + "signature": "-5608794531-export * from './dogconfig.js';\r\n" + }, + "./dogconfig.ts": { + "version": "1966273863-import { DogConfig } from 'src-types';\n\nexport const DOG_CONFIG: DogConfig = {\n name: 'Default dog',\n};\n", + "signature": "1966273863-import { DogConfig } from 'src-types';\n\nexport const DOG_CONFIG: DogConfig = {\n name: 'Default dog',\n};\n" + }, + "./dog.ts": { + "version": "6091345804-import { DogConfig } from 'src-types';\nimport { DOG_CONFIG } from './dogconfig.js';\n\nexport abstract class Dog {\n\n public static getCapabilities(): DogConfig {\n return DOG_CONFIG;\n }\n}\n", + "signature": "6091345804-import { DogConfig } from 'src-types';\nimport { DOG_CONFIG } from './dogconfig.js';\n\nexport abstract class Dog {\n\n public static getCapabilities(): DogConfig {\n return DOG_CONFIG;\n }\n}\n" + }, + "./lassie/lassieconfig.ts": { + "version": "4440579024-import { DogConfig } from 'src-types';\n\nexport const LASSIE_CONFIG: DogConfig = { name: 'Lassie' };\n", + "signature": "4440579024-import { DogConfig } from 'src-types';\n\nexport const LASSIE_CONFIG: DogConfig = { name: 'Lassie' };\n" + }, + "./lassie/lassiedog.ts": { + "version": "-32303727812-import { Dog } from '../dog.js';\nimport { LASSIE_CONFIG } from './lassieconfig.js';\n\nexport class LassieDog extends Dog {\n protected static getDogConfig = () => LASSIE_CONFIG;\n}\n", + "signature": "-32303727812-import { Dog } from '../dog.js';\nimport { LASSIE_CONFIG } from './lassieconfig.js';\n\nexport class LassieDog extends Dog {\n protected static getDogConfig = () => LASSIE_CONFIG;\n}\n" + }, + "./index.ts": { + "version": "-15974991320-export * from 'src-types';\nexport * from './lassie/lassiedog.js';\n", + "signature": "-15974991320-export * from 'src-types';\nexport * from './lassie/lassiedog.js';\n" + } + }, + "options": { + "composite": true, + "declaration": true, + "module": 100 + }, + "referencedMap": { + "./dog.ts": [ + "../src-types/index.d.ts", + "./dogconfig.ts" + ], + "./dogconfig.ts": [ + "../src-types/index.d.ts" + ], + "./index.ts": [ + "../src-types/index.d.ts", + "./lassie/lassiedog.ts" + ], + "./lassie/lassieconfig.ts": [ + "../src-types/index.d.ts" + ], + "./lassie/lassiedog.ts": [ + "./dog.ts", + "./lassie/lassieconfig.ts" + ], + "../src-types/index.d.ts": [ + "../src-types/dogconfig.d.ts" + ] + }, + "exportedModulesMap": { + "./dog.ts": [ + "../src-types/index.d.ts", + "./dogconfig.ts" + ], + "./dogconfig.ts": [ + "../src-types/index.d.ts" + ], + "./index.ts": [ + "../src-types/index.d.ts", + "./lassie/lassiedog.ts" + ], + "./lassie/lassieconfig.ts": [ + "../src-types/index.d.ts" + ], + "./lassie/lassiedog.ts": [ + "./dog.ts", + "./lassie/lassieconfig.ts" + ], + "../src-types/index.d.ts": [ + "../src-types/dogconfig.d.ts" + ] + }, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.es2020.full.d.ts", + "./dog.ts", + "./dogconfig.ts", + "./index.ts", + "./lassie/lassieconfig.ts", + "./lassie/lassiedog.ts", + "../src-types/dogconfig.d.ts", + "../src-types/index.d.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1802 +} + +//// [/src/src-types/dogconfig.d.ts] +export interface DogConfig { + name: string; +} + + +//// [/src/src-types/dogconfig.js] +export {}; + + +//// [/src/src-types/index.d.ts] +export * from './dogconfig.js'; + + +//// [/src/src-types/index.js] +export * from './dogconfig.js'; + + +//// [/src/src-types/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.es2020.full.d.ts","./dogconfig.ts","./index.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true,"impliedFormat":1},"-5575793279-export interface DogConfig {\n name: string;\n}","-6189272282-export * from './dogconfig.js';"],"options":{"composite":true,"declaration":true,"module":100},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[[3,1]],"semanticDiagnosticsPerFile":[1,2,3]},"version":"FakeTSVersion"} + +//// [/src/src-types/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.es2020.full.d.ts", + "./dogconfig.ts", + "./index.ts" + ], + "fileNamesList": [ + [ + "./dogconfig.ts" + ] + ], + "fileInfos": { + "../../lib/lib.es2020.full.d.ts": { + "version": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "signature": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "affectsGlobalScope": true, + "impliedFormat": 1 + }, + "./dogconfig.ts": { + "version": "-5575793279-export interface DogConfig {\n name: string;\n}", + "signature": "-5575793279-export interface DogConfig {\n name: string;\n}" + }, + "./index.ts": { + "version": "-6189272282-export * from './dogconfig.js';", + "signature": "-6189272282-export * from './dogconfig.js';" + } + }, + "options": { + "composite": true, + "declaration": true, + "module": 100 + }, + "referencedMap": { + "./index.ts": [ + "./dogconfig.ts" + ] + }, + "exportedModulesMap": { + "./index.ts": [ + "./dogconfig.ts" + ] + }, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.es2020.full.d.ts", + "./dogconfig.ts", + "./index.ts" + ] + }, + "version": "FakeTSVersion", + "size": 829 +} + diff --git a/tests/cases/conformance/node/nodeModulesExportsBlocksSpecifierResolution.ts b/tests/cases/conformance/node/nodeModulesExportsBlocksSpecifierResolution.ts new file mode 100644 index 0000000000000..ffc5adf8e07e5 --- /dev/null +++ b/tests/cases/conformance/node/nodeModulesExportsBlocksSpecifierResolution.ts @@ -0,0 +1,27 @@ +// @module: node12,nodenext +// @declaration: true +// @filename: index.ts +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner")).x(); +// @filename: node_modules/inner/index.d.ts +// esm format file +export { x } from "./other.js"; +// @filename: node_modules/inner/other.d.ts +// esm format file +export interface Thing {} +export const x: () => Thing; +// @filename: package.json +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +// @filename: node_modules/inner/package.json +{ + "name": "inner", + "private": true, + "type": "module", + "exports": "./index.js" +} \ No newline at end of file diff --git a/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationConditions.ts b/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationConditions.ts new file mode 100644 index 0000000000000..2562c7a4a1139 --- /dev/null +++ b/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationConditions.ts @@ -0,0 +1,34 @@ +// @module: node12,nodenext +// @declaration: true +// @filename: index.ts +// esm format file +import { Thing } from "inner/other.js"; // should fail +export const a = (await import("inner")).x(); +// @filename: node_modules/inner/index.d.ts +// esm format file +export { x } from "./other.js"; +// @filename: node_modules/inner/other.d.ts +// esm format file +export interface Thing {} +export const x: () => Thing; +// @filename: package.json +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +// @filename: node_modules/inner/package.json +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + ".": { + "default": "./index.js" + }, + "./other": { + "default": "./other.js" + } + } +} \ No newline at end of file diff --git a/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationDirectory.ts b/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationDirectory.ts new file mode 100644 index 0000000000000..2eb8ac58e6682 --- /dev/null +++ b/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationDirectory.ts @@ -0,0 +1,29 @@ +// @module: node12,nodenext +// @declaration: true +// @filename: index.ts +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner/index.js")).x(); +// @filename: node_modules/inner/index.d.ts +// esm format file +export { x } from "./other.js"; +// @filename: node_modules/inner/other.d.ts +// esm format file +export interface Thing {} +export const x: () => Thing; +// @filename: package.json +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +// @filename: node_modules/inner/package.json +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./": "./" + } +} \ No newline at end of file diff --git a/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationPattern.ts b/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationPattern.ts new file mode 100644 index 0000000000000..97812da5b57a7 --- /dev/null +++ b/tests/cases/conformance/node/nodeModulesExportsSpecifierGenerationPattern.ts @@ -0,0 +1,29 @@ +// @module: node12,nodenext +// @declaration: true +// @filename: index.ts +// esm format file +import { Thing } from "inner/other"; +export const a = (await import("inner/index.js")).x(); +// @filename: node_modules/inner/index.d.ts +// esm format file +export { x } from "./other.js"; +// @filename: node_modules/inner/other.d.ts +// esm format file +export interface Thing {} +export const x: () => Thing; +// @filename: package.json +{ + "name": "package", + "private": true, + "type": "module", + "exports": "./index.js" +} +// @filename: node_modules/inner/package.json +{ + "name": "inner", + "private": true, + "type": "module", + "exports": { + "./*.js": "./*.js" + } +} \ No newline at end of file