diff --git a/src/compiler/program.ts b/src/compiler/program.ts index bd9b42caae953..eb1e37416b880 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1396,7 +1396,7 @@ export function getImpliedNodeFormatForFileWorker( const shouldLookupFromPackageJson = ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext || pathContainsNodeModules(fileName); return fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Mjs]) ? ModuleKind.ESNext : - fileExtensionIsOneOf(fileName, [Extension.Dcts, Extension.Cts, Extension.Cjs]) ? ModuleKind.CommonJS : + fileExtensionIsOneOf(fileName, [Extension.Dcts, Extension.Cts, Extension.Cjs]) || (isDeclarationFileName(fileName) && !fileExtensionIs(fileName, Extension.Dts)) ? ModuleKind.CommonJS : shouldLookupFromPackageJson && fileExtensionIsOneOf(fileName, [Extension.Dts, Extension.Ts, Extension.Tsx, Extension.Js, Extension.Jsx]) ? lookupFromPackageJson() : undefined; // other extensions, like `json` or `tsbuildinfo`, are set as `undefined` here but they should never be fed through the transformer pipeline diff --git a/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.errors.txt b/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.errors.txt new file mode 100644 index 0000000000000..73230c800836e --- /dev/null +++ b/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.errors.txt @@ -0,0 +1,66 @@ +cjs/index.mts(2,6): error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +cjs/index.mts(4,7): error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +cjs/secondary.cts(2,6): error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +cjs/secondary.cts(4,7): error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +esm/index.mts(2,6): error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +esm/index.mts(4,7): error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +esm/secondary.cts(2,6): error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +esm/secondary.cts(4,7): error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. + + +==== cjs/package.json (0 errors) ==== + { "type": "commonjs" } +==== cjs/foo.json (0 errors) ==== + ["foo", "bar", "baz"] +==== cjs/foo.d.json.ts (0 errors) ==== + declare const data: ["foo", "bar", "baz"]; + export = data; +==== cjs/index.mts (2 errors) ==== + import data from "./foo.json" with { type: "json" }; + data.default; // foo.d.json.ts is cjs format - error (`default` is whole file, file has no `default` member) + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. + import data2 = require("./foo.json"); + data2.default; // `data2` is the whole json object, no `default` + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +==== cjs/secondary.cts (2 errors) ==== + import data from "./foo.json"; + data.default; // error (cjs format `.d.json.ts`, export= object is require result) + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. + import data2 = require("./foo.json"); + data2.default; // `data2` is the whole json object, no `default` + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +==== esm/package.json (0 errors) ==== + { "type": "module" } +==== esm/foo.json (0 errors) ==== + ["foo", "bar", "baz"] +==== esm/foo.d.json.ts (0 errors) ==== + declare const data: ["foo", "bar", "baz"]; + export = data; +==== esm/index.mts (2 errors) ==== + import data from "./foo.json" with { type: "json" }; + data.default; // foo.d.json.ts is cjs format despite package - error! (default import is already the whole json object) + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. + import data2 = require("./foo.json"); + data2.default; // `data2` is the whole json object, no `default` + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +==== esm/secondary.cts (2 errors) ==== + import data from "./foo.json"; + data.default; // `export=` object is the whole `require` result, hoisted to `default` by interop helper, no 2nd default + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. + import data2 = require("./foo.json"); + data2.default; // `data2` is the whole json object, no `default` + ~~~~~~~ +!!! error TS2339: Property 'default' does not exist on type '["foo", "bar", "baz"]'. +==== root.mts (0 errors) ==== + import "./cjs/index.mjs"; + import "./cjs/secondary.mjs"; + import "./mjs/index.mjs"; + import "./mjs/secondary.mjs"; + \ No newline at end of file diff --git a/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.js b/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.js new file mode 100644 index 0000000000000..ea16f843da3d7 --- /dev/null +++ b/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.js @@ -0,0 +1,97 @@ +//// [tests/cases/compiler/resolveJsonModuleAllowArbitraryExtensionsNodeNext.ts] //// + +//// [package.json] +{ "type": "commonjs" } +//// [foo.json] +["foo", "bar", "baz"] +//// [foo.d.json.ts] +declare const data: ["foo", "bar", "baz"]; +export = data; +//// [index.mts] +import data from "./foo.json" with { type: "json" }; +data.default; // foo.d.json.ts is cjs format - error (`default` is whole file, file has no `default` member) +import data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +//// [secondary.cts] +import data from "./foo.json"; +data.default; // error (cjs format `.d.json.ts`, export= object is require result) +import data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +//// [package.json] +{ "type": "module" } +//// [foo.json] +["foo", "bar", "baz"] +//// [foo.d.json.ts] +declare const data: ["foo", "bar", "baz"]; +export = data; +//// [index.mts] +import data from "./foo.json" with { type: "json" }; +data.default; // foo.d.json.ts is cjs format despite package - error! (default import is already the whole json object) +import data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +//// [secondary.cts] +import data from "./foo.json"; +data.default; // `export=` object is the whole `require` result, hoisted to `default` by interop helper, no 2nd default +import data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +//// [root.mts] +import "./cjs/index.mjs"; +import "./cjs/secondary.mjs"; +import "./mjs/index.mjs"; +import "./mjs/secondary.mjs"; + + +//// [index.mjs] +import { createRequire as _createRequire } from "module"; +const __require = _createRequire(import.meta.url); +import data from "./foo.json" with { type: "json" }; +data.default; // foo.d.json.ts is cjs format - error (`default` is whole file, file has no `default` member) +const data2 = __require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +//// [secondary.cjs] +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const foo_json_1 = __importDefault(require("./foo.json")); +foo_json_1.default.default; // error (cjs format `.d.json.ts`, export= object is require result) +const data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +//// [index.mjs] +import { createRequire as _createRequire } from "module"; +const __require = _createRequire(import.meta.url); +import data from "./foo.json" with { type: "json" }; +data.default; // foo.d.json.ts is cjs format despite package - error! (default import is already the whole json object) +const data2 = __require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +//// [secondary.cjs] +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const foo_json_1 = __importDefault(require("./foo.json")); +foo_json_1.default.default; // `export=` object is the whole `require` result, hoisted to `default` by interop helper, no 2nd default +const data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +//// [root.mjs] +import "./cjs/index.mjs"; +import "./cjs/secondary.mjs"; +import "./mjs/index.mjs"; +import "./mjs/secondary.mjs"; + + +//// [index.d.mts] +export {}; +//// [secondary.d.cts] +export {}; +//// [index.d.mts] +export {}; +//// [secondary.d.cts] +export {}; +//// [root.d.mts] +import "./cjs/index.mjs"; +import "./cjs/secondary.mjs"; +import "./mjs/index.mjs"; +import "./mjs/secondary.mjs"; diff --git a/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.symbols b/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.symbols new file mode 100644 index 0000000000000..839f98395110f --- /dev/null +++ b/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.symbols @@ -0,0 +1,75 @@ +//// [tests/cases/compiler/resolveJsonModuleAllowArbitraryExtensionsNodeNext.ts] //// + +=== cjs/foo.d.json.ts === +declare const data: ["foo", "bar", "baz"]; +>data : Symbol(data, Decl(foo.d.json.ts, 0, 13)) + +export = data; +>data : Symbol(data, Decl(foo.d.json.ts, 0, 13)) + +=== cjs/index.mts === +import data from "./foo.json" with { type: "json" }; +>data : Symbol(data, Decl(index.mts, 0, 6)) + +data.default; // foo.d.json.ts is cjs format - error (`default` is whole file, file has no `default` member) +>data : Symbol(data, Decl(index.mts, 0, 6)) + +import data2 = require("./foo.json"); +>data2 : Symbol(data2, Decl(index.mts, 1, 13)) + +data2.default; // `data2` is the whole json object, no `default` +>data2 : Symbol(data2, Decl(index.mts, 1, 13)) + +=== cjs/secondary.cts === +import data from "./foo.json"; +>data : Symbol(data, Decl(secondary.cts, 0, 6)) + +data.default; // error (cjs format `.d.json.ts`, export= object is require result) +>data : Symbol(data, Decl(secondary.cts, 0, 6)) + +import data2 = require("./foo.json"); +>data2 : Symbol(data2, Decl(secondary.cts, 1, 13)) + +data2.default; // `data2` is the whole json object, no `default` +>data2 : Symbol(data2, Decl(secondary.cts, 1, 13)) + +=== esm/foo.d.json.ts === +declare const data: ["foo", "bar", "baz"]; +>data : Symbol(data, Decl(foo.d.json.ts, 0, 13)) + +export = data; +>data : Symbol(data, Decl(foo.d.json.ts, 0, 13)) + +=== esm/index.mts === +import data from "./foo.json" with { type: "json" }; +>data : Symbol(data, Decl(index.mts, 0, 6)) + +data.default; // foo.d.json.ts is cjs format despite package - error! (default import is already the whole json object) +>data : Symbol(data, Decl(index.mts, 0, 6)) + +import data2 = require("./foo.json"); +>data2 : Symbol(data2, Decl(index.mts, 1, 13)) + +data2.default; // `data2` is the whole json object, no `default` +>data2 : Symbol(data2, Decl(index.mts, 1, 13)) + +=== esm/secondary.cts === +import data from "./foo.json"; +>data : Symbol(data, Decl(secondary.cts, 0, 6)) + +data.default; // `export=` object is the whole `require` result, hoisted to `default` by interop helper, no 2nd default +>data : Symbol(data, Decl(secondary.cts, 0, 6)) + +import data2 = require("./foo.json"); +>data2 : Symbol(data2, Decl(secondary.cts, 1, 13)) + +data2.default; // `data2` is the whole json object, no `default` +>data2 : Symbol(data2, Decl(secondary.cts, 1, 13)) + +=== root.mts === + +import "./cjs/index.mjs"; +import "./cjs/secondary.mjs"; +import "./mjs/index.mjs"; +import "./mjs/secondary.mjs"; + diff --git a/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.types b/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.types new file mode 100644 index 0000000000000..5c72a10b2aec9 --- /dev/null +++ b/tests/baselines/reference/resolveJsonModuleAllowArbitraryExtensionsNodeNext.types @@ -0,0 +1,131 @@ +//// [tests/cases/compiler/resolveJsonModuleAllowArbitraryExtensionsNodeNext.ts] //// + +=== cjs/foo.d.json.ts === +declare const data: ["foo", "bar", "baz"]; +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +export = data; +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +=== cjs/index.mts === +import data from "./foo.json" with { type: "json" }; +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>type : any +> : ^^^ + +data.default; // foo.d.json.ts is cjs format - error (`default` is whole file, file has no `default` member) +>data.default : any +> : ^^^ +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ + +import data2 = require("./foo.json"); +>data2 : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +data2.default; // `data2` is the whole json object, no `default` +>data2.default : any +> : ^^^ +>data2 : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ + +=== cjs/secondary.cts === +import data from "./foo.json"; +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +data.default; // error (cjs format `.d.json.ts`, export= object is require result) +>data.default : any +> : ^^^ +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ + +import data2 = require("./foo.json"); +>data2 : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +data2.default; // `data2` is the whole json object, no `default` +>data2.default : any +> : ^^^ +>data2 : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ + +=== esm/foo.d.json.ts === +declare const data: ["foo", "bar", "baz"]; +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +export = data; +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +=== esm/index.mts === +import data from "./foo.json" with { type: "json" }; +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>type : any +> : ^^^ + +data.default; // foo.d.json.ts is cjs format despite package - error! (default import is already the whole json object) +>data.default : any +> : ^^^ +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ + +import data2 = require("./foo.json"); +>data2 : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +data2.default; // `data2` is the whole json object, no `default` +>data2.default : any +> : ^^^ +>data2 : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ + +=== esm/secondary.cts === +import data from "./foo.json"; +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +data.default; // `export=` object is the whole `require` result, hoisted to `default` by interop helper, no 2nd default +>data.default : any +> : ^^^ +>data : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ + +import data2 = require("./foo.json"); +>data2 : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ + +data2.default; // `data2` is the whole json object, no `default` +>data2.default : any +> : ^^^ +>data2 : ["foo", "bar", "baz"] +> : ^^^^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ + +=== root.mts === + +import "./cjs/index.mjs"; +import "./cjs/secondary.mjs"; +import "./mjs/index.mjs"; +import "./mjs/secondary.mjs"; + diff --git a/tests/baselines/reference/tscWatch/resolveJsonModule/incremental-always-prefers-declaration-file-over-document.js b/tests/baselines/reference/tscWatch/resolveJsonModule/incremental-always-prefers-declaration-file-over-document.js index cf7e08090f750..86aaaff56386c 100644 --- a/tests/baselines/reference/tscWatch/resolveJsonModule/incremental-always-prefers-declaration-file-over-document.js +++ b/tests/baselines/reference/tscWatch/resolveJsonModule/incremental-always-prefers-declaration-file-over-document.js @@ -52,7 +52,7 @@ var x = data_json_1.default; //// [/src/project/tsconfig.tsbuildinfo] -{"fileNames":["../../a/lib/lib.d.ts","./data.d.json.ts","./main.ts"],"fileIdsList":[[2]],"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},"2718060498-declare var val: string; export default val;","6961905452-import data from \"./data.json\"; let x: string = data;"],"root":[2,3],"referencedMap":[[3,1]],"semanticDiagnosticsPerFile":[[3,[{"start":17,"length":13,"messageText":"Module './data.json' was resolved to '/src/project/data.d.json.ts', but '--allowArbitraryExtensions' is not set.","category":1,"code":6263}]]],"version":"FakeTSVersion"} +{"fileNames":["../../a/lib/lib.d.ts","./data.d.json.ts","./main.ts"],"fileIdsList":[[2]],"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},{"version":"2718060498-declare var val: string; export default val;","impliedFormat":1},"6961905452-import data from \"./data.json\"; let x: string = data;"],"root":[2,3],"referencedMap":[[3,1]],"semanticDiagnosticsPerFile":[[3,[{"start":17,"length":13,"messageText":"Module './data.json' was resolved to '/src/project/data.d.json.ts', but '--allowArbitraryExtensions' is not set.","category":1,"code":6263}]]],"version":"FakeTSVersion"} //// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] { @@ -77,8 +77,13 @@ var x = data_json_1.default; "affectsGlobalScope": true }, "./data.d.json.ts": { + "original": { + "version": "2718060498-declare var val: string; export default val;", + "impliedFormat": 1 + }, "version": "2718060498-declare var val: string; export default val;", - "signature": "2718060498-declare var val: string; export default val;" + "signature": "2718060498-declare var val: string; export default val;", + "impliedFormat": "commonjs" }, "./main.ts": { "version": "6961905452-import data from \"./data.json\"; let x: string = data;", @@ -115,7 +120,7 @@ var x = data_json_1.default; ] ], "version": "FakeTSVersion", - "size": 908 + "size": 938 } diff --git a/tests/cases/compiler/resolveJsonModuleAllowArbitraryExtensionsNodeNext.ts b/tests/cases/compiler/resolveJsonModuleAllowArbitraryExtensionsNodeNext.ts new file mode 100644 index 0000000000000..73a80157ef9e3 --- /dev/null +++ b/tests/cases/compiler/resolveJsonModuleAllowArbitraryExtensionsNodeNext.ts @@ -0,0 +1,44 @@ +// @declaration: true +// @module: nodenext +// @allowArbitraryExtensions: true +// @resolveJsonModule: true +// @listFiles: true +// @filename: cjs/package.json +{ "type": "commonjs" } +// @filename: cjs/foo.json +["foo", "bar", "baz"] +// @filename: cjs/foo.d.json.ts +declare const data: ["foo", "bar", "baz"]; +export = data; +// @filename: cjs/index.mts +import data from "./foo.json" with { type: "json" }; +data.default; // foo.d.json.ts is cjs format - error (`default` is whole file, file has no `default` member) +import data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +// @filename: cjs/secondary.cts +import data from "./foo.json"; +data.default; // error (cjs format `.d.json.ts`, export= object is require result) +import data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +// @filename: esm/package.json +{ "type": "module" } +// @filename: esm/foo.json +["foo", "bar", "baz"] +// @filename: esm/foo.d.json.ts +declare const data: ["foo", "bar", "baz"]; +export = data; +// @filename: esm/index.mts +import data from "./foo.json" with { type: "json" }; +data.default; // foo.d.json.ts is cjs format despite package - error! (default import is already the whole json object) +import data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +// @filename: esm/secondary.cts +import data from "./foo.json"; +data.default; // `export=` object is the whole `require` result, hoisted to `default` by interop helper, no 2nd default +import data2 = require("./foo.json"); +data2.default; // `data2` is the whole json object, no `default` +// @filename: root.mts +import "./cjs/index.mjs"; +import "./cjs/secondary.mjs"; +import "./mjs/index.mjs"; +import "./mjs/secondary.mjs";