diff --git a/tsc/internal/compiler/fileloader.go b/tsc/internal/compiler/fileloader.go index f8bba578a534a..c37a678d4ffec 100644 --- a/tsc/internal/compiler/fileloader.go +++ b/tsc/internal/compiler/fileloader.go @@ -886,6 +886,18 @@ func (p *fileLoader) resolveImportsAndModuleAugmentations(t *parseTask) { } mode := getModeForUsageLocation(file.FileName(), meta, entry, optionsForFile) + // We know moduleName resolves to an ambient module provided that moduleName: + // - is in the list of ambient modules locally declared in the current source file. + if slices.Contains(file.AmbientModuleNames, moduleName) { + if optionsForFile.TraceResolution.IsTrue() { + resolutionsTrace = append(resolutionsTrace, module.DiagAndArgs{ + Message: diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, + Args: []any{moduleName, file.FileName()}, + }) + } + resolutionsInFile[module.ModeAwareCacheKey{Name: moduleName, Mode: mode}] = &module.ResolvedModule{} + continue + } var resolvedModule *module.ResolvedModule var trace []module.DiagAndArgs var err error diff --git a/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.errors.txt b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.errors.txt new file mode 100644 index 0000000000000..1b2c6e7d3a294 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.errors.txt @@ -0,0 +1,25 @@ +/a.ts(2,1): error TS2304: Cannot find name 'fooGlobal'. + + +==== /a.ts (1 errors) ==== + /// + fooGlobal; + ~~~~~~~~~ +!!! error TS2304: Cannot find name 'fooGlobal'. + +==== /node_modules/foo/package.json (0 errors) ==== + { "name": "foo", "version": "1.0.0", "types": "index.d.ts" } + +==== /node_modules/foo/index.d.ts (0 errors) ==== + declare global { + var fooGlobal: string; + } + declare function foo(value: unknown): boolean; + export default foo; + +==== /declarations.d.ts (0 errors) ==== + declare module "foo" { + import _foo from "foo"; + export function isFoo(value: unknown): boolean; + } + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.js b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.js new file mode 100644 index 0000000000000..194020a028d0c --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.js @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/ambientModuleImportingItselfNotResolved.ts] //// + +//// [package.json] +{ "name": "foo", "version": "1.0.0", "types": "index.d.ts" } + +//// [index.d.ts] +declare global { + var fooGlobal: string; +} +declare function foo(value: unknown): boolean; +export default foo; + +//// [declarations.d.ts] +declare module "foo" { + import _foo from "foo"; + export function isFoo(value: unknown): boolean; +} + +//// [a.ts] +/// +fooGlobal; + + +//// [a.js] +"use strict"; +/// +fooGlobal; diff --git a/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.symbols b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.symbols new file mode 100644 index 0000000000000..fab01f6eb827e --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.symbols @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/ambientModuleImportingItselfNotResolved.ts] //// + +=== /a.ts === + +/// +fooGlobal; + +=== /declarations.d.ts === +declare module "foo" { +>"foo" : Symbol(_foo, Decl(declarations.d.ts, 0, 0)) + + import _foo from "foo"; +>_foo : Symbol(_foo, Decl(declarations.d.ts, 1, 10)) + + export function isFoo(value: unknown): boolean; +>isFoo : Symbol(isFoo, Decl(declarations.d.ts, 1, 27)) +>value : Symbol(value, Decl(declarations.d.ts, 2, 26)) +} + diff --git a/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.trace.json b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.trace.json new file mode 100644 index 0000000000000..d403a0e3b4f6e --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.trace.json @@ -0,0 +1 @@ +Module 'foo' was resolved as locally declared ambient module in file '/declarations.d.ts'. diff --git a/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.types b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.types new file mode 100644 index 0000000000000..300793c04bba9 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/ambientModuleImportingItselfNotResolved.types @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/ambientModuleImportingItselfNotResolved.ts] //// + +=== /a.ts === +/// +fooGlobal; +>fooGlobal : any + +=== /declarations.d.ts === +declare module "foo" { +>"foo" : typeof _foo + + import _foo from "foo"; +>_foo : typeof _foo + + export function isFoo(value: unknown): boolean; +>isFoo : (value: unknown) => boolean +>value : unknown +} + diff --git a/tsc/testdata/baselines/reference/compiler/nodeColonModuleResolution.trace.json b/tsc/testdata/baselines/reference/compiler/nodeColonModuleResolution.trace.json index 7484c14bb1785..4838932736fcb 100644 --- a/tsc/testdata/baselines/reference/compiler/nodeColonModuleResolution.trace.json +++ b/tsc/testdata/baselines/reference/compiler/nodeColonModuleResolution.trace.json @@ -1,35 +1,9 @@ -======== Resolving module 'ph' from '/a/b/node_modules/@types/node/ph.d.ts'. ======== +Module 'ph' was resolved as locally declared ambient module in file '/a/b/node_modules/@types/node/ph.d.ts'. +======== Resolving module 'node:ph' from '/a/b/main.ts'. ======== Explicitly specified module resolution kind: 'Bundler'. Resolving in CJS mode with conditions 'import', 'types'. -File '/a/b/node_modules/@types/node/package.json' does not exist. -File '/a/b/node_modules/@types/package.json' does not exist. -File '/a/b/node_modules/package.json' does not exist. File '/a/b/package.json' does not exist. File '/a/package.json' does not exist. File '/package.json' does not exist. -Loading module 'ph' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON. -Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration. -Directory '/a/b/node_modules/@types/node/node_modules' does not exist, skipping all lookups in it. -Directory '/a/b/node_modules/@types/node_modules' does not exist, skipping all lookups in it. -File '/a/b/node_modules/ph.ts' does not exist. -File '/a/b/node_modules/ph.tsx' does not exist. -File '/a/b/node_modules/ph.d.ts' does not exist. -File '/a/b/node_modules/@types/ph.d.ts' does not exist. -Directory '/a/node_modules' does not exist, skipping all lookups in it. -Directory '/node_modules' does not exist, skipping all lookups in it. -Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON. -Directory '/a/b/node_modules/@types/node/node_modules' does not exist, skipping all lookups in it. -Directory '/a/b/node_modules/@types/node_modules' does not exist, skipping all lookups in it. -File '/a/b/node_modules/ph.js' does not exist. -File '/a/b/node_modules/ph.jsx' does not exist. -Directory '/a/node_modules' does not exist, skipping all lookups in it. -Directory '/node_modules' does not exist, skipping all lookups in it. -======== Module name 'ph' was not resolved. ======== -======== Resolving module 'node:ph' from '/a/b/main.ts'. ======== -Explicitly specified module resolution kind: 'Bundler'. -Resolving in CJS mode with conditions 'import', 'types'. -File '/a/b/package.json' does not exist according to earlier cached lookups. -File '/a/package.json' does not exist according to earlier cached lookups. -File '/package.json' does not exist according to earlier cached lookups. Skipping module 'node:ph' that looks like an absolute URI, target file types: TypeScript, JavaScript, Declaration, JSON. ======== Module name 'node:ph' was not resolved. ======== diff --git a/tsc/testdata/tests/cases/compiler/ambientModuleImportingItselfNotResolved.ts b/tsc/testdata/tests/cases/compiler/ambientModuleImportingItselfNotResolved.ts new file mode 100644 index 0000000000000..1493925999644 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/ambientModuleImportingItselfNotResolved.ts @@ -0,0 +1,28 @@ +// @target: esnext +// @module: preserve +// @moduleResolution: bundler +// @noImplicitReferences: true +// @traceResolution: true + +// An import inside an ambient module declaration that names the same module +// resolves to that declaration, so the real package must not be pulled in. + +// @filename: /node_modules/foo/package.json +{ "name": "foo", "version": "1.0.0", "types": "index.d.ts" } + +// @filename: /node_modules/foo/index.d.ts +declare global { + var fooGlobal: string; +} +declare function foo(value: unknown): boolean; +export default foo; + +// @filename: /declarations.d.ts +declare module "foo" { + import _foo from "foo"; + export function isFoo(value: unknown): boolean; +} + +// @filename: /a.ts +/// +fooGlobal;