diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d149b044284d8..0091229ee6c5e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2637,6 +2637,11 @@ namespace ts { return usageMode === ModuleKind.ESNext && targetMode === ModuleKind.CommonJS; } + function isOnlyImportedAsDefault(usage: Expression) { + const usageMode = getUsageModeForExpression(usage); + return usageMode === ModuleKind.ESNext && endsWith((usage as StringLiteralLike).text, Extension.Json); + } + function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean, usage: Expression) { const usageMode = file && getUsageModeForExpression(usage); if (file && usageMode !== undefined) { @@ -2688,8 +2693,9 @@ namespace ts { } const file = moduleSymbol.declarations?.find(isSourceFile); + const hasDefaultOnly = isOnlyImportedAsDefault(node.parent.moduleSpecifier); const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, node.parent.moduleSpecifier); - if (!exportDefaultSymbol && !hasSyntheticDefault) { + if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) { if (hasExportAssignmentSymbol(moduleSymbol)) { const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop"; const exportEqualsSymbol = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals); @@ -2708,7 +2714,7 @@ namespace ts { reportNonDefaultExport(moduleSymbol, node); } } - else if (hasSyntheticDefault) { + else if (hasSyntheticDefault || hasDefaultOnly) { // per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present const resolved = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); markSymbolOfAliasDeclarationIfTypeOnly(node, moduleSymbol, resolved, /*overwriteTypeOnly*/ false); @@ -2840,7 +2846,7 @@ namespace ts { let symbolFromModule = getExportOfModule(targetSymbol, name, specifier, dontResolveAlias); if (symbolFromModule === undefined && name.escapedText === InternalSymbolName.Default) { const file = moduleSymbol.declarations?.find(isSourceFile); - if (canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) { + if (isOnlyImportedAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } } @@ -3430,6 +3436,9 @@ namespace ts { if (isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext) { error(errorNode, Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_synchronously_Use_dynamic_import_instead, moduleReference); } + if (mode === ModuleKind.ESNext && compilerOptions.resolveJsonModule && resolvedModule.extension === Extension.Json) { + error(errorNode, Diagnostics.JSON_imports_are_experimental_in_ES_module_mode_imports); + } } // merged symbol is module declaration symbol combined with all augmentations return getMergedSymbol(sourceFile.symbol); @@ -3592,32 +3601,26 @@ namespace ts { return symbol; } - if (getESModuleInterop(compilerOptions)) { - const referenceParent = referencingLocation.parent; - if ( - (isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) || - isImportCall(referenceParent) - ) { - const type = getTypeOfSymbol(symbol); + const referenceParent = referencingLocation.parent; + if ( + (isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) || + isImportCall(referenceParent) + ) { + const reference = isImportCall(referenceParent) ? referenceParent.arguments[0] : referenceParent.moduleSpecifier; + const type = getTypeOfSymbol(symbol); + const defaultOnlyType = getTypeWithSyntheticDefaultOnly(type, symbol, moduleSymbol!, reference); + if (defaultOnlyType) { + return cloneTypeAsModuleType(symbol, defaultOnlyType, referenceParent); + } + + if (getESModuleInterop(compilerOptions)) { let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call); if (!sigs || !sigs.length) { sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct); } - if (sigs && sigs.length) { - const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol!, isImportCall(referenceParent) ? referenceParent.arguments[0] : referenceParent.moduleSpecifier); - // Create a new symbol which has the module's type less the call and construct signatures - const result = createSymbol(symbol.flags, symbol.escapedName); - result.declarations = symbol.declarations ? symbol.declarations.slice() : []; - result.parent = symbol.parent; - result.target = symbol; - result.originatingImport = referenceParent; - if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration; - if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true; - if (symbol.members) result.members = new Map(symbol.members); - if (symbol.exports) result.exports = new Map(symbol.exports); - const resolvedModuleType = resolveStructuredTypeMembers(moduleType as StructuredType); // Should already be resolved from the signature checks above - result.type = createAnonymousType(result, resolvedModuleType.members, emptyArray, emptyArray, resolvedModuleType.indexInfos); - return result; + if ((sigs && sigs.length) || getPropertyOfType(type, InternalSymbolName.Default)) { + const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol!, reference); + return cloneTypeAsModuleType(symbol, moduleType, referenceParent); } } } @@ -3625,6 +3628,24 @@ namespace ts { return symbol; } + /** + * Create a new symbol which has the module's type less the call and construct signatures + */ + function cloneTypeAsModuleType(symbol: Symbol, moduleType: Type, referenceParent: ImportDeclaration | ImportCall) { + const result = createSymbol(symbol.flags, symbol.escapedName); + result.declarations = symbol.declarations ? symbol.declarations.slice() : []; + result.parent = symbol.parent; + result.target = symbol; + result.originatingImport = referenceParent; + if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration; + if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true; + if (symbol.members) result.members = new Map(symbol.members); + if (symbol.exports) result.exports = new Map(symbol.exports); + const resolvedModuleType = resolveStructuredTypeMembers(moduleType as StructuredType); // Should already be resolved from the signature checks above + result.type = createAnonymousType(result, resolvedModuleType.members, emptyArray, emptyArray, resolvedModuleType.indexInfos); + return result; + } + function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean { return moduleSymbol.exports!.get(InternalSymbolName.ExportEquals) !== undefined; } @@ -30980,12 +31001,38 @@ namespace ts { if (moduleSymbol) { const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true, /*suppressUsageError*/ false); if (esModuleSymbol) { - return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol, specifier)); + return createPromiseReturnType(node, + getTypeWithSyntheticDefaultOnly(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol, specifier) || + getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol, specifier) + ); } } return createPromiseReturnType(node, anyType); } + function createDefaultPropertyWrapperForModule(symbol: Symbol, originalSymbol: Symbol, anonymousSymbol?: Symbol | undefined) { + const memberTable = createSymbolTable(); + const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default); + newSymbol.parent = originalSymbol; + newSymbol.nameType = getStringLiteralType("default"); + newSymbol.target = resolveSymbol(symbol); + memberTable.set(InternalSymbolName.Default, newSymbol); + return createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, emptyArray); + } + + function getTypeWithSyntheticDefaultOnly(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression) { + const hasDefaultOnly = isOnlyImportedAsDefault(moduleSpecifier); + if (hasDefaultOnly && type && !isErrorType(type)) { + const synthType = type as SyntheticDefaultModuleType; + if (!synthType.defaultOnlyType) { + const type = createDefaultPropertyWrapperForModule(symbol, originalSymbol); + synthType.defaultOnlyType = type; + } + return synthType.defaultOnlyType; + } + return undefined; + } + function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression): Type { if (allowSyntheticDefaultImports && type && !isErrorType(type)) { const synthType = type as SyntheticDefaultModuleType; @@ -30993,14 +31040,8 @@ namespace ts { const file = originalSymbol.declarations?.find(isSourceFile); const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false, moduleSpecifier); if (hasSyntheticDefault) { - const memberTable = createSymbolTable(); - const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default); - newSymbol.parent = originalSymbol; - newSymbol.nameType = getStringLiteralType("default"); - newSymbol.target = resolveSymbol(symbol); - memberTable.set(InternalSymbolName.Default, newSymbol); const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); - const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, emptyArray); + const defaultContainingObject = createDefaultPropertyWrapperForModule(symbol, originalSymbol, anonymousSymbol); anonymousSymbol.type = defaultContainingObject; synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index a40439d012afd..bade52b478ac3 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -5997,6 +5997,10 @@ "category": "Error", "code": 7061 }, + "JSON imports are experimental in ES module mode imports.": { + "category": "Error", + "code": 7062 + }, "You cannot rename this element.": { "category": "Error", diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 2db75250cce8c..0847e2dbfc3d7 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -3333,7 +3333,9 @@ namespace ts { } if (options.resolveJsonModule) { - if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs) { + if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs && + getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node12 && + getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext) { createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy, "resolveJsonModule"); } // Any emit other than common js, amd, es2015 or esnext is error diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a5b143e06f3bd..6ebdf66a0423e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5579,6 +5579,7 @@ namespace ts { /* @internal */ export interface SyntheticDefaultModuleType extends Type { syntheticType?: Type; + defaultOnlyType?: Type; } export interface InstantiableType extends Type { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4b225a0ad0e99..5a9d22fe2aa96 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6168,6 +6168,8 @@ namespace ts { case ModuleKind.ES2020: case ModuleKind.ES2022: case ModuleKind.ESNext: + case ModuleKind.Node12: + case ModuleKind.NodeNext: return true; default: return false; diff --git a/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).errors.txt b/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).errors.txt new file mode 100644 index 0000000000000..4200a11e7baf9 --- /dev/null +++ b/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).errors.txt @@ -0,0 +1,39 @@ +tests/cases/conformance/node/index.mts(1,17): error TS7062: JSON imports are experimental in ES module mode imports. +tests/cases/conformance/node/index.mts(3,21): error TS7062: JSON imports are experimental in ES module mode imports. +tests/cases/conformance/node/index.ts(1,17): error TS7062: JSON imports are experimental in ES module mode imports. +tests/cases/conformance/node/index.ts(3,21): error TS7062: JSON imports are experimental in ES module mode imports. + + +==== tests/cases/conformance/node/index.ts (2 errors) ==== + import pkg from "./package.json" + ~~~~~~~~~~~~~~~~ +!!! error TS7062: JSON imports are experimental in ES module mode imports. + export const name = pkg.name; + import * as ns from "./package.json"; + ~~~~~~~~~~~~~~~~ +!!! error TS7062: JSON imports are experimental in ES module mode imports. + export const thing = ns; + export const name2 = ns.default.name; +==== tests/cases/conformance/node/index.cts (0 errors) ==== + import pkg from "./package.json" + export const name = pkg.name; + import * as ns from "./package.json"; + export const thing = ns; + export const name2 = ns.default.name; +==== tests/cases/conformance/node/index.mts (2 errors) ==== + import pkg from "./package.json" + ~~~~~~~~~~~~~~~~ +!!! error TS7062: JSON imports are experimental in ES module mode imports. + export const name = pkg.name; + import * as ns from "./package.json"; + ~~~~~~~~~~~~~~~~ +!!! error TS7062: JSON imports are experimental in ES module mode imports. + export const thing = ns; + export const name2 = ns.default.name; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "pkg", + "version": "0.0.1", + "type": "module", + "default": "misedirection" + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).js b/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).js new file mode 100644 index 0000000000000..3736ec5f37a1a --- /dev/null +++ b/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).js @@ -0,0 +1,116 @@ +//// [tests/cases/conformance/node/nodeModulesResolveJsonModule.ts] //// + +//// [index.ts] +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +//// [index.cts] +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +//// [index.mts] +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +//// [package.json] +{ + "name": "pkg", + "version": "0.0.1", + "type": "module", + "default": "misedirection" +} + +//// [package.json] +{ + "name": "pkg", + "version": "0.0.1", + "type": "module", + "default": "misedirection" +} +//// [index.js] +import pkg from "./package.json"; +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +//// [index.cjs] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.name2 = exports.thing = exports.name = void 0; +const package_json_1 = __importDefault(require("./package.json")); +exports.name = package_json_1.default.name; +const ns = __importStar(require("./package.json")); +exports.thing = ns; +exports.name2 = ns.default.name; +//// [index.mjs] +import pkg from "./package.json"; +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; + + +//// [index.d.ts] +export declare const name: string; +export declare const thing: { + default: { + name: string; + version: string; + type: string; + default: string; + }; +}; +export declare const name2: string; +//// [index.d.cts] +export declare const name: string; +export declare const thing: { + default: { + name: string; + version: string; + type: string; + default: string; + }; + name: string; + version: string; + type: string; +}; +export declare const name2: string; +//// [index.d.mts] +export declare const name: string; +export declare const thing: { + default: { + name: string; + version: string; + type: string; + default: string; + }; +}; +export declare const name2: string; diff --git a/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).symbols b/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).symbols new file mode 100644 index 0000000000000..f1927c6899605 --- /dev/null +++ b/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).symbols @@ -0,0 +1,89 @@ +=== tests/cases/conformance/node/index.ts === +import pkg from "./package.json" +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) + +export const name = pkg.name; +>name : Symbol(name, Decl(index.ts, 1, 12)) +>pkg.name : Symbol("name", Decl(package.json, 0, 1)) +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) +>name : Symbol("name", Decl(package.json, 0, 1)) + +import * as ns from "./package.json"; +>ns : Symbol(ns, Decl(index.ts, 2, 6)) + +export const thing = ns; +>thing : Symbol(thing, Decl(index.ts, 3, 12)) +>ns : Symbol(ns, Decl(index.ts, 2, 6)) + +export const name2 = ns.default.name; +>name2 : Symbol(name2, Decl(index.ts, 4, 12)) +>ns.default.name : Symbol("name", Decl(package.json, 0, 1)) +>ns.default : Symbol("tests/cases/conformance/node/package") +>ns : Symbol(ns, Decl(index.ts, 2, 6)) +>default : Symbol("tests/cases/conformance/node/package") +>name : Symbol("name", Decl(package.json, 0, 1)) + +=== tests/cases/conformance/node/index.cts === +import pkg from "./package.json" +>pkg : Symbol(pkg, Decl(index.cts, 0, 6)) + +export const name = pkg.name; +>name : Symbol(name, Decl(index.cts, 1, 12)) +>pkg.name : Symbol("name", Decl(package.json, 0, 1)) +>pkg : Symbol(pkg, Decl(index.cts, 0, 6)) +>name : Symbol("name", Decl(package.json, 0, 1)) + +import * as ns from "./package.json"; +>ns : Symbol(ns, Decl(index.cts, 2, 6)) + +export const thing = ns; +>thing : Symbol(thing, Decl(index.cts, 3, 12)) +>ns : Symbol(ns, Decl(index.cts, 2, 6)) + +export const name2 = ns.default.name; +>name2 : Symbol(name2, Decl(index.cts, 4, 12)) +>ns.default.name : Symbol("name", Decl(package.json, 0, 1)) +>ns.default : Symbol("tests/cases/conformance/node/package") +>ns : Symbol(ns, Decl(index.cts, 2, 6)) +>default : Symbol("tests/cases/conformance/node/package") +>name : Symbol("name", Decl(package.json, 0, 1)) + +=== tests/cases/conformance/node/index.mts === +import pkg from "./package.json" +>pkg : Symbol(pkg, Decl(index.mts, 0, 6)) + +export const name = pkg.name; +>name : Symbol(name, Decl(index.mts, 1, 12)) +>pkg.name : Symbol("name", Decl(package.json, 0, 1)) +>pkg : Symbol(pkg, Decl(index.mts, 0, 6)) +>name : Symbol("name", Decl(package.json, 0, 1)) + +import * as ns from "./package.json"; +>ns : Symbol(ns, Decl(index.mts, 2, 6)) + +export const thing = ns; +>thing : Symbol(thing, Decl(index.mts, 3, 12)) +>ns : Symbol(ns, Decl(index.mts, 2, 6)) + +export const name2 = ns.default.name; +>name2 : Symbol(name2, Decl(index.mts, 4, 12)) +>ns.default.name : Symbol("name", Decl(package.json, 0, 1)) +>ns.default : Symbol("tests/cases/conformance/node/package") +>ns : Symbol(ns, Decl(index.mts, 2, 6)) +>default : Symbol("tests/cases/conformance/node/package") +>name : Symbol("name", Decl(package.json, 0, 1)) + +=== tests/cases/conformance/node/package.json === +{ + "name": "pkg", +>"name" : Symbol("name", Decl(package.json, 0, 1)) + + "version": "0.0.1", +>"version" : Symbol("version", Decl(package.json, 1, 18)) + + "type": "module", +>"type" : Symbol("type", Decl(package.json, 2, 23)) + + "default": "misedirection" +>"default" : Symbol("default", Decl(package.json, 3, 21)) +} diff --git a/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).types b/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).types new file mode 100644 index 0000000000000..f6ad83e175444 --- /dev/null +++ b/tests/baselines/reference/nodeModulesResolveJsonModule(module=node12).types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/node/index.ts === +import pkg from "./package.json" +>pkg : { name: string; version: string; type: string; default: string; } + +export const name = pkg.name; +>name : string +>pkg.name : string +>pkg : { name: string; version: string; type: string; default: string; } +>name : string + +import * as ns from "./package.json"; +>ns : { default: { name: string; version: string; type: string; default: string; }; } + +export const thing = ns; +>thing : { default: { name: string; version: string; type: string; default: string; }; } +>ns : { default: { name: string; version: string; type: string; default: string; }; } + +export const name2 = ns.default.name; +>name2 : string +>ns.default.name : string +>ns.default : { name: string; version: string; type: string; default: string; } +>ns : { default: { name: string; version: string; type: string; default: string; }; } +>default : { name: string; version: string; type: string; default: string; } +>name : string + +=== tests/cases/conformance/node/index.cts === +import pkg from "./package.json" +>pkg : { name: string; version: string; type: string; default: string; } + +export const name = pkg.name; +>name : string +>pkg.name : string +>pkg : { name: string; version: string; type: string; default: string; } +>name : string + +import * as ns from "./package.json"; +>ns : { default: { name: string; version: string; type: string; default: string; }; name: string; version: string; type: string; } + +export const thing = ns; +>thing : { default: { name: string; version: string; type: string; default: string; }; name: string; version: string; type: string; } +>ns : { default: { name: string; version: string; type: string; default: string; }; name: string; version: string; type: string; } + +export const name2 = ns.default.name; +>name2 : string +>ns.default.name : string +>ns.default : { name: string; version: string; type: string; default: string; } +>ns : { default: { name: string; version: string; type: string; default: string; }; name: string; version: string; type: string; } +>default : { name: string; version: string; type: string; default: string; } +>name : string + +=== tests/cases/conformance/node/index.mts === +import pkg from "./package.json" +>pkg : { name: string; version: string; type: string; default: string; } + +export const name = pkg.name; +>name : string +>pkg.name : string +>pkg : { name: string; version: string; type: string; default: string; } +>name : string + +import * as ns from "./package.json"; +>ns : { default: { name: string; version: string; type: string; default: string; }; } + +export const thing = ns; +>thing : { default: { name: string; version: string; type: string; default: string; }; } +>ns : { default: { name: string; version: string; type: string; default: string; }; } + +export const name2 = ns.default.name; +>name2 : string +>ns.default.name : string +>ns.default : { name: string; version: string; type: string; default: string; } +>ns : { default: { name: string; version: string; type: string; default: string; }; } +>default : { name: string; version: string; type: string; default: string; } +>name : string + +=== tests/cases/conformance/node/package.json === +{ +>{ "name": "pkg", "version": "0.0.1", "type": "module", "default": "misedirection"} : { name: string; version: string; type: string; default: string; } + + "name": "pkg", +>"name" : string +>"pkg" : "pkg" + + "version": "0.0.1", +>"version" : string +>"0.0.1" : "0.0.1" + + "type": "module", +>"type" : string +>"module" : "module" + + "default": "misedirection" +>"default" : string +>"misedirection" : "misedirection" +} diff --git a/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).errors.txt b/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).errors.txt new file mode 100644 index 0000000000000..4200a11e7baf9 --- /dev/null +++ b/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).errors.txt @@ -0,0 +1,39 @@ +tests/cases/conformance/node/index.mts(1,17): error TS7062: JSON imports are experimental in ES module mode imports. +tests/cases/conformance/node/index.mts(3,21): error TS7062: JSON imports are experimental in ES module mode imports. +tests/cases/conformance/node/index.ts(1,17): error TS7062: JSON imports are experimental in ES module mode imports. +tests/cases/conformance/node/index.ts(3,21): error TS7062: JSON imports are experimental in ES module mode imports. + + +==== tests/cases/conformance/node/index.ts (2 errors) ==== + import pkg from "./package.json" + ~~~~~~~~~~~~~~~~ +!!! error TS7062: JSON imports are experimental in ES module mode imports. + export const name = pkg.name; + import * as ns from "./package.json"; + ~~~~~~~~~~~~~~~~ +!!! error TS7062: JSON imports are experimental in ES module mode imports. + export const thing = ns; + export const name2 = ns.default.name; +==== tests/cases/conformance/node/index.cts (0 errors) ==== + import pkg from "./package.json" + export const name = pkg.name; + import * as ns from "./package.json"; + export const thing = ns; + export const name2 = ns.default.name; +==== tests/cases/conformance/node/index.mts (2 errors) ==== + import pkg from "./package.json" + ~~~~~~~~~~~~~~~~ +!!! error TS7062: JSON imports are experimental in ES module mode imports. + export const name = pkg.name; + import * as ns from "./package.json"; + ~~~~~~~~~~~~~~~~ +!!! error TS7062: JSON imports are experimental in ES module mode imports. + export const thing = ns; + export const name2 = ns.default.name; +==== tests/cases/conformance/node/package.json (0 errors) ==== + { + "name": "pkg", + "version": "0.0.1", + "type": "module", + "default": "misedirection" + } \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).js b/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).js new file mode 100644 index 0000000000000..3736ec5f37a1a --- /dev/null +++ b/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).js @@ -0,0 +1,116 @@ +//// [tests/cases/conformance/node/nodeModulesResolveJsonModule.ts] //// + +//// [index.ts] +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +//// [index.cts] +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +//// [index.mts] +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +//// [package.json] +{ + "name": "pkg", + "version": "0.0.1", + "type": "module", + "default": "misedirection" +} + +//// [package.json] +{ + "name": "pkg", + "version": "0.0.1", + "type": "module", + "default": "misedirection" +} +//// [index.js] +import pkg from "./package.json"; +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +//// [index.cjs] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.name2 = exports.thing = exports.name = void 0; +const package_json_1 = __importDefault(require("./package.json")); +exports.name = package_json_1.default.name; +const ns = __importStar(require("./package.json")); +exports.thing = ns; +exports.name2 = ns.default.name; +//// [index.mjs] +import pkg from "./package.json"; +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; + + +//// [index.d.ts] +export declare const name: string; +export declare const thing: { + default: { + name: string; + version: string; + type: string; + default: string; + }; +}; +export declare const name2: string; +//// [index.d.cts] +export declare const name: string; +export declare const thing: { + default: { + name: string; + version: string; + type: string; + default: string; + }; + name: string; + version: string; + type: string; +}; +export declare const name2: string; +//// [index.d.mts] +export declare const name: string; +export declare const thing: { + default: { + name: string; + version: string; + type: string; + default: string; + }; +}; +export declare const name2: string; diff --git a/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).symbols b/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).symbols new file mode 100644 index 0000000000000..f1927c6899605 --- /dev/null +++ b/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).symbols @@ -0,0 +1,89 @@ +=== tests/cases/conformance/node/index.ts === +import pkg from "./package.json" +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) + +export const name = pkg.name; +>name : Symbol(name, Decl(index.ts, 1, 12)) +>pkg.name : Symbol("name", Decl(package.json, 0, 1)) +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) +>name : Symbol("name", Decl(package.json, 0, 1)) + +import * as ns from "./package.json"; +>ns : Symbol(ns, Decl(index.ts, 2, 6)) + +export const thing = ns; +>thing : Symbol(thing, Decl(index.ts, 3, 12)) +>ns : Symbol(ns, Decl(index.ts, 2, 6)) + +export const name2 = ns.default.name; +>name2 : Symbol(name2, Decl(index.ts, 4, 12)) +>ns.default.name : Symbol("name", Decl(package.json, 0, 1)) +>ns.default : Symbol("tests/cases/conformance/node/package") +>ns : Symbol(ns, Decl(index.ts, 2, 6)) +>default : Symbol("tests/cases/conformance/node/package") +>name : Symbol("name", Decl(package.json, 0, 1)) + +=== tests/cases/conformance/node/index.cts === +import pkg from "./package.json" +>pkg : Symbol(pkg, Decl(index.cts, 0, 6)) + +export const name = pkg.name; +>name : Symbol(name, Decl(index.cts, 1, 12)) +>pkg.name : Symbol("name", Decl(package.json, 0, 1)) +>pkg : Symbol(pkg, Decl(index.cts, 0, 6)) +>name : Symbol("name", Decl(package.json, 0, 1)) + +import * as ns from "./package.json"; +>ns : Symbol(ns, Decl(index.cts, 2, 6)) + +export const thing = ns; +>thing : Symbol(thing, Decl(index.cts, 3, 12)) +>ns : Symbol(ns, Decl(index.cts, 2, 6)) + +export const name2 = ns.default.name; +>name2 : Symbol(name2, Decl(index.cts, 4, 12)) +>ns.default.name : Symbol("name", Decl(package.json, 0, 1)) +>ns.default : Symbol("tests/cases/conformance/node/package") +>ns : Symbol(ns, Decl(index.cts, 2, 6)) +>default : Symbol("tests/cases/conformance/node/package") +>name : Symbol("name", Decl(package.json, 0, 1)) + +=== tests/cases/conformance/node/index.mts === +import pkg from "./package.json" +>pkg : Symbol(pkg, Decl(index.mts, 0, 6)) + +export const name = pkg.name; +>name : Symbol(name, Decl(index.mts, 1, 12)) +>pkg.name : Symbol("name", Decl(package.json, 0, 1)) +>pkg : Symbol(pkg, Decl(index.mts, 0, 6)) +>name : Symbol("name", Decl(package.json, 0, 1)) + +import * as ns from "./package.json"; +>ns : Symbol(ns, Decl(index.mts, 2, 6)) + +export const thing = ns; +>thing : Symbol(thing, Decl(index.mts, 3, 12)) +>ns : Symbol(ns, Decl(index.mts, 2, 6)) + +export const name2 = ns.default.name; +>name2 : Symbol(name2, Decl(index.mts, 4, 12)) +>ns.default.name : Symbol("name", Decl(package.json, 0, 1)) +>ns.default : Symbol("tests/cases/conformance/node/package") +>ns : Symbol(ns, Decl(index.mts, 2, 6)) +>default : Symbol("tests/cases/conformance/node/package") +>name : Symbol("name", Decl(package.json, 0, 1)) + +=== tests/cases/conformance/node/package.json === +{ + "name": "pkg", +>"name" : Symbol("name", Decl(package.json, 0, 1)) + + "version": "0.0.1", +>"version" : Symbol("version", Decl(package.json, 1, 18)) + + "type": "module", +>"type" : Symbol("type", Decl(package.json, 2, 23)) + + "default": "misedirection" +>"default" : Symbol("default", Decl(package.json, 3, 21)) +} diff --git a/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).types b/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).types new file mode 100644 index 0000000000000..f6ad83e175444 --- /dev/null +++ b/tests/baselines/reference/nodeModulesResolveJsonModule(module=nodenext).types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/node/index.ts === +import pkg from "./package.json" +>pkg : { name: string; version: string; type: string; default: string; } + +export const name = pkg.name; +>name : string +>pkg.name : string +>pkg : { name: string; version: string; type: string; default: string; } +>name : string + +import * as ns from "./package.json"; +>ns : { default: { name: string; version: string; type: string; default: string; }; } + +export const thing = ns; +>thing : { default: { name: string; version: string; type: string; default: string; }; } +>ns : { default: { name: string; version: string; type: string; default: string; }; } + +export const name2 = ns.default.name; +>name2 : string +>ns.default.name : string +>ns.default : { name: string; version: string; type: string; default: string; } +>ns : { default: { name: string; version: string; type: string; default: string; }; } +>default : { name: string; version: string; type: string; default: string; } +>name : string + +=== tests/cases/conformance/node/index.cts === +import pkg from "./package.json" +>pkg : { name: string; version: string; type: string; default: string; } + +export const name = pkg.name; +>name : string +>pkg.name : string +>pkg : { name: string; version: string; type: string; default: string; } +>name : string + +import * as ns from "./package.json"; +>ns : { default: { name: string; version: string; type: string; default: string; }; name: string; version: string; type: string; } + +export const thing = ns; +>thing : { default: { name: string; version: string; type: string; default: string; }; name: string; version: string; type: string; } +>ns : { default: { name: string; version: string; type: string; default: string; }; name: string; version: string; type: string; } + +export const name2 = ns.default.name; +>name2 : string +>ns.default.name : string +>ns.default : { name: string; version: string; type: string; default: string; } +>ns : { default: { name: string; version: string; type: string; default: string; }; name: string; version: string; type: string; } +>default : { name: string; version: string; type: string; default: string; } +>name : string + +=== tests/cases/conformance/node/index.mts === +import pkg from "./package.json" +>pkg : { name: string; version: string; type: string; default: string; } + +export const name = pkg.name; +>name : string +>pkg.name : string +>pkg : { name: string; version: string; type: string; default: string; } +>name : string + +import * as ns from "./package.json"; +>ns : { default: { name: string; version: string; type: string; default: string; }; } + +export const thing = ns; +>thing : { default: { name: string; version: string; type: string; default: string; }; } +>ns : { default: { name: string; version: string; type: string; default: string; }; } + +export const name2 = ns.default.name; +>name2 : string +>ns.default.name : string +>ns.default : { name: string; version: string; type: string; default: string; } +>ns : { default: { name: string; version: string; type: string; default: string; }; } +>default : { name: string; version: string; type: string; default: string; } +>name : string + +=== tests/cases/conformance/node/package.json === +{ +>{ "name": "pkg", "version": "0.0.1", "type": "module", "default": "misedirection"} : { name: string; version: string; type: string; default: string; } + + "name": "pkg", +>"name" : string +>"pkg" : "pkg" + + "version": "0.0.1", +>"version" : string +>"0.0.1" : "0.0.1" + + "type": "module", +>"type" : string +>"module" : "module" + + "default": "misedirection" +>"default" : string +>"misedirection" : "misedirection" +} diff --git a/tests/cases/conformance/node/nodeModulesResolveJsonModule.ts b/tests/cases/conformance/node/nodeModulesResolveJsonModule.ts new file mode 100644 index 0000000000000..c298685c228df --- /dev/null +++ b/tests/cases/conformance/node/nodeModulesResolveJsonModule.ts @@ -0,0 +1,29 @@ +// @module: node12,nodenext +// @resolveJsonModule: true +// @outDir: ./out +// @declaration: true +// @filename: index.ts +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +// @filename: index.cts +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +// @filename: index.mts +import pkg from "./package.json" +export const name = pkg.name; +import * as ns from "./package.json"; +export const thing = ns; +export const name2 = ns.default.name; +// @filename: package.json +{ + "name": "pkg", + "version": "0.0.1", + "type": "module", + "default": "misedirection" +} \ No newline at end of file