diff --git a/src/compiler/_namespaces/ts.ts b/src/compiler/_namespaces/ts.ts index cd755a0baed2f..94fb16857d38e 100644 --- a/src/compiler/_namespaces/ts.ts +++ b/src/compiler/_namespaces/ts.ts @@ -54,7 +54,7 @@ export * from "../transformers/generators.js"; export * from "../transformers/module/module.js"; export * from "../transformers/module/system.js"; export * from "../transformers/module/esnextAnd2015.js"; -export * from "../transformers/module/node.js"; +export * from "../transformers/module/impliedNodeFormatDependent.js"; export * from "../transformers/declarations/diagnostics.js"; export * from "../transformers/declarations.js"; export * from "../transformer.js"; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 770e1a7c1c60a..7a867fbfbcaa0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -60,6 +60,7 @@ import { canHaveJSDoc, canHaveLocals, canHaveModifiers, + canHaveModuleSpecifier, canHaveSymbol, canIncludeBindAndCheckDiagnostics, canUsePropertyAccess, @@ -3656,27 +3657,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { || isNamespaceExport(node)); } - function getUsageModeForExpression(usage: Expression) { - return isStringLiteralLike(usage) ? host.getModeForUsageLocation(getSourceFileOfNode(usage), usage) : undefined; + function getEmitSyntaxForModuleSpecifierExpression(usage: Expression) { + return isStringLiteralLike(usage) ? host.getEmitSyntaxForUsageLocation(getSourceFileOfNode(usage), usage) : undefined; } function isESMFormatImportImportingCommonjsFormatFile(usageMode: ResolutionMode, targetMode: ResolutionMode) { 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 isOnlyImportableAsDefault(usage: Expression) { + // In Node.js, JSON modules don't get named exports + if (ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) { + const usageMode = getEmitSyntaxForModuleSpecifierExpression(usage); + return usageMode === ModuleKind.ESNext && endsWith((usage as StringLiteralLike).text, Extension.Json); + } + return false; } function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean, usage: Expression) { - const usageMode = file && getUsageModeForExpression(usage); - if (file && usageMode !== undefined && ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) { - const result = isESMFormatImportImportingCommonjsFormatFile(usageMode, file.impliedNodeFormat); - if (usageMode === ModuleKind.ESNext || result) { - return result; + const usageMode = file && getEmitSyntaxForModuleSpecifierExpression(usage); + if (file && usageMode !== undefined) { + const targetMode = host.getImpliedNodeFormatForEmit(file); + if (usageMode === ModuleKind.ESNext && targetMode === ModuleKind.CommonJS && ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) { + // In Node.js, CommonJS modules always have a synthetic default when imported into ESM + return true; + } + if (usageMode === ModuleKind.ESNext && targetMode === ModuleKind.ESNext) { + // No matter what the `module` setting is, if we're confident that both files + // are ESM, there cannot be a synthetic default. + return false; } - // fallthrough on cjs usages so we imply defaults for interop'd imports, too } if (!allowSyntheticDefaultImports) { return false; @@ -3729,7 +3739,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!specifier) { return exportDefaultSymbol; } - const hasDefaultOnly = isOnlyImportedAsDefault(specifier); + const hasDefaultOnly = isOnlyImportableAsDefault(specifier); const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier); if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) { if (hasExportAssignmentSymbol(moduleSymbol) && !allowSyntheticDefaultImports) { @@ -3914,7 +3924,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let symbolFromModule = getExportOfModule(targetSymbol, nameText, specifier, dontResolveAlias); if (symbolFromModule === undefined && nameText === InternalSymbolName.Default) { const file = moduleSymbol.declarations?.find(isSourceFile); - if (isOnlyImportedAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) { + if (isOnlyImportableAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } } @@ -4578,7 +4588,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { findAncestor(location, isImportDeclaration)?.moduleSpecifier || findAncestor(location, isExternalModuleImportEqualsDeclaration)?.moduleReference.expression || findAncestor(location, isExportDeclaration)?.moduleSpecifier; - const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? host.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) + ? host.getModeForUsageLocation(currentSourceFile, contextSpecifier) + : host.getDefaultResolutionModeForFile(currentSourceFile); const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions); const resolvedModule = host.getResolvedModule(currentSourceFile, moduleReference, mode)?.resolvedModule; const resolutionDiagnostic = errorNode && resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile); @@ -4869,7 +4881,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const targetFile = moduleSymbol?.declarations?.find(isSourceFile); - const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(getUsageModeForExpression(reference), targetFile.impliedNodeFormat); + const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(getEmitSyntaxForModuleSpecifierExpression(reference), host.getImpliedNodeFormatForEmit(targetFile)); if (getESModuleInterop(compilerOptions) || isEsmCjsRef) { let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call); if (!sigs || !sigs.length) { @@ -7803,8 +7815,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return getSourceFileOfNode(getNonAugmentationDeclaration(symbol)!).fileName; // A resolver may not be provided for baselines and errors - in those cases we use the fileName in full } + const enclosingDeclaration = getOriginalNode(context.enclosingDeclaration); + const originalModuleSpecifier = canHaveModuleSpecifier(enclosingDeclaration) ? tryGetModuleSpecifierFromDeclaration(enclosingDeclaration) : undefined; const contextFile = context.enclosingFile; - const resolutionMode = overrideImportMode || contextFile?.impliedNodeFormat; + const resolutionMode = overrideImportMode + || originalModuleSpecifier && host.getModeForUsageLocation(contextFile, originalModuleSpecifier) + || contextFile && host.getDefaultResolutionModeForFile(contextFile); const cacheKey = createModeAwareCacheKey(contextFile.path, resolutionMode); const links = getSymbolLinks(symbol); let specifier = links.specifierCache && links.specifierCache.get(cacheKey); @@ -36946,7 +36962,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTypeWithSyntheticDefaultOnly(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression) { - const hasDefaultOnly = isOnlyImportedAsDefault(moduleSpecifier); + const hasDefaultOnly = isOnlyImportableAsDefault(moduleSpecifier); if (hasDefaultOnly && type && !isErrorType(type)) { const synthType = type as SyntheticDefaultModuleType; if (!synthType.defaultOnlyType) { @@ -43492,7 +43508,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier | undefined) { // No need to check for require or exports for ES6 modules and later - if (moduleKind >= ModuleKind.ES2015 && !(moduleKind >= ModuleKind.Node16 && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) { + if (host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) >= ModuleKind.ES2015) { return; } @@ -45381,7 +45397,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkClassNameCollisionWithObject(name: Identifier): void { if ( languageVersion >= ScriptTarget.ES5 && name.escapedText === "Object" - && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(name).impliedNodeFormat === ModuleKind.CommonJS) + && host.getEmitModuleFormatOfFile(getSourceFileOfNode(name)) < ModuleKind.ES2015 ) { error(name, Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ModuleKind[moduleKind]); // https://github.com/Microsoft/TypeScript/issues/17494 } @@ -46720,7 +46736,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ( compilerOptions.verbatimModuleSyntax && node.parent.kind === SyntaxKind.SourceFile && - (moduleKind === ModuleKind.CommonJS || node.parent.impliedNodeFormat === ModuleKind.CommonJS) + host.getEmitModuleFormatOfFile(node.parent) === ModuleKind.CommonJS ) { const exportModifier = node.modifiers?.find(m => m.kind === SyntaxKind.ExportKeyword); if (exportModifier) { @@ -47012,10 +47028,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { compilerOptions.verbatimModuleSyntax && node.kind !== SyntaxKind.ImportEqualsDeclaration && !isInJSFile(node) && - (moduleKind === ModuleKind.CommonJS || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) === ModuleKind.CommonJS ) { error(node, Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); } + else if ( + moduleKind === ModuleKind.Preserve && + node.kind !== SyntaxKind.ImportEqualsDeclaration && + node.kind !== SyntaxKind.VariableDeclaration && + host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) === ModuleKind.CommonJS + ) { + // In `--module preserve`, ESM input syntax emits ESM output syntax, but there will be times + // when we look at the `impliedNodeFormat` of this file and decide it's CommonJS (i.e., currently, + // only if the file extension is .cjs/.cts). To avoid that inconsistency, we disallow ESM syntax + // in files that are unambiguously CommonJS in this mode. + error(node, Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_module_is_set_to_preserve); + } } if (isImportSpecifier(node)) { @@ -47065,7 +47093,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ( moduleExportNameIsDefault(node.propertyName || node.name) && getESModuleInterop(compilerOptions) && - moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < ModuleKind.System ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault); } @@ -47087,7 +47115,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; // Other grammar checks do not apply to type-only imports with resolution mode assertions } - const mode = (moduleKind === ModuleKind.NodeNext) && declaration.moduleSpecifier && getUsageModeForExpression(declaration.moduleSpecifier); + const mode = (moduleKind === ModuleKind.NodeNext) && declaration.moduleSpecifier && getEmitSyntaxForModuleSpecifierExpression(declaration.moduleSpecifier); if (mode !== ModuleKind.ESNext && moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.Preserve) { const message = isImportAttributes ? moduleKind === ModuleKind.NodeNext @@ -47131,7 +47159,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (importClause.namedBindings) { if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { checkImportBinding(importClause.namedBindings); - if (moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && getESModuleInterop(compilerOptions)) { + if (host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < ModuleKind.System && getESModuleInterop(compilerOptions)) { // import * as ns from "foo"; checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportStar); } @@ -47178,8 +47206,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else { - if (moduleKind >= ModuleKind.ES2015 && moduleKind !== ModuleKind.Preserve && getSourceFileOfNode(node).impliedNodeFormat === undefined && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient)) { - // Import equals declaration is deprecated in es6 or above + if (ModuleKind.ES2015 <= moduleKind && moduleKind <= ModuleKind.ESNext && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient)) { + // Import equals declaration cannot be emitted as ESM grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } } @@ -47220,7 +47248,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkAliasSymbol(node.exportClause); checkModuleExportName(node.exportClause.name); } - if (moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) { + if (host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < ModuleKind.System) { if (node.exportClause) { // export * as ns from "foo"; // For ES2015 modules, we emit it as a pair of `import * as a_1 ...; export { a_1 as ns }` and don't need the helper. @@ -47279,8 +47307,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { if ( getESModuleInterop(compilerOptions) && - moduleKind !== ModuleKind.System && - (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && + host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < ModuleKind.System && moduleExportNameIsDefault(node.propertyName || node.name) ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault); @@ -47321,7 +47348,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const isIllegalExportDefaultInCJS = !node.isExportEquals && !(node.flags & NodeFlags.Ambient) && compilerOptions.verbatimModuleSyntax && - (moduleKind === ModuleKind.CommonJS || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS); + host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) === ModuleKind.CommonJS; if (node.expression.kind === SyntaxKind.Identifier) { const id = node.expression as Identifier; @@ -47419,8 +47446,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ( moduleKind >= ModuleKind.ES2015 && moduleKind !== ModuleKind.Preserve && - ((node.flags & NodeFlags.Ambient && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.ESNext) || - (!(node.flags & NodeFlags.Ambient) && getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.CommonJS)) + ((node.flags & NodeFlags.Ambient && host.getImpliedNodeFormatForEmit(getSourceFileOfNode(node)) === ModuleKind.ESNext) || + (!(node.flags & NodeFlags.Ambient) && host.getImpliedNodeFormatForEmit(getSourceFileOfNode(node)) !== ModuleKind.CommonJS)) ) { // export assignment is not supported in es6 modules grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead); @@ -50357,7 +50384,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // ModuleDeclaration needs to be checked that it is uninstantiated later node.kind !== SyntaxKind.ModuleDeclaration && node.parent.kind === SyntaxKind.SourceFile && - (moduleKind === ModuleKind.CommonJS || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) === ModuleKind.CommonJS ) { return grammarErrorOnNode(modifier, Diagnostics.A_top_level_export_modifier_cannot_be_used_on_value_declarations_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); } @@ -51516,7 +51543,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( - (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && moduleKind !== ModuleKind.System && + host.getEmitModuleFormatOfFile(getSourceFileOfNode(node)) < ModuleKind.System && !(node.parent.parent.flags & NodeFlags.Ambient) && hasSyntacticModifier(node.parent.parent, ModifierFlags.Export) ) { checkESModuleMarker(node.name); @@ -52162,6 +52189,8 @@ function createBasicNodeBuilderModuleSpecifierResolutionHost(host: TypeCheckerHo fileExists: fileName => host.fileExists(fileName), getFileIncludeReasons: () => host.getFileIncludeReasons(), readFile: host.readFile ? (fileName => host.readFile!(fileName)) : undefined, + getDefaultResolutionModeForFile: file => host.getDefaultResolutionModeForFile(file), + getModeForResolutionAtIndex: (file, index) => host.getModeForResolutionAtIndex(file, index), }; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ee05ca893c7e6..1ff508ec55774 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -967,6 +967,10 @@ "category": "Error", "code": 1292 }, + "ESM syntax is not allowed in a CommonJS module when 'module' is set to 'preserve'.": { + "category": "Error", + "code": 1293 + }, "'with' statements are not allowed in an async function block.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index c3b8babf5f954..17de49958ff2e 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -131,6 +131,7 @@ import { getEmitFlags, getEmitHelpers, getEmitModuleKind, + getEmitModuleResolutionKind, getEmitScriptTarget, getExternalModuleName, getIdentifierTypeArguments, @@ -828,6 +829,7 @@ export function emitFiles( newLine: compilerOptions.newLine, noEmitHelpers: compilerOptions.noEmitHelpers, module: getEmitModuleKind(compilerOptions), + moduleResolution: getEmitModuleResolutionKind(compilerOptions), target: getEmitScriptTarget(compilerOptions), sourceMap: compilerOptions.sourceMap, inlineSourceMap: compilerOptions.inlineSourceMap, @@ -903,6 +905,7 @@ export function emitFiles( newLine: compilerOptions.newLine, noEmitHelpers: true, module: compilerOptions.module, + moduleResolution: compilerOptions.moduleResolution, target: compilerOptions.target, sourceMap: !forceDtsEmit && compilerOptions.declarationMap, inlineSourceMap: compilerOptions.inlineSourceMap, diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index b06682c7d8718..852017bd5012e 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -51,10 +51,12 @@ import { getAllAccessorDeclarations, getEmitFlags, getEmitHelpers, + getEmitModuleFormatOfFileWorker, getEmitModuleKind, getESModuleInterop, getExternalModuleName, getExternalModuleNameFromPath, + getImpliedNodeFormatForEmitWorker, getJSDocType, getJSDocTypeTag, getModifiers, @@ -687,7 +689,7 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: Node if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { let namedBindings: NamedImportBindings | undefined; const moduleKind = getEmitModuleKind(compilerOptions); - if ((moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) || sourceFile.impliedNodeFormat === ModuleKind.ESNext) { + if ((moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) || getImpliedNodeFormatForEmitWorker(sourceFile, compilerOptions) === ModuleKind.ESNext) { // use named imports const helpers = getEmitHelpers(sourceFile); if (helpers) { @@ -743,10 +745,8 @@ function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node return externalHelpersModuleName; } - const moduleKind = getEmitModuleKind(compilerOptions); let create = (hasExportStarsToExportValues || (getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault)) - && moduleKind !== ModuleKind.System - && (moduleKind < ModuleKind.ES2015 || node.impliedNodeFormat === ModuleKind.CommonJS); + && getEmitModuleFormatOfFileWorker(node, compilerOptions) < ModuleKind.System; if (!create) { const helpers = getEmitHelpers(node); if (helpers) { diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 2fe39cfb22c2b..6e21b0678a9c1 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -37,9 +37,9 @@ import { getBaseFileName, GetCanonicalFileName, getConditions, + getDefaultResolutionModeForFileWorker, getDirectoryPath, getEmitModuleResolutionKind, - getModeForResolutionAtIndex, getModuleNameStringLiteralAt, getModuleSpecifierEndingPreference, getNodeModulePathParts, @@ -143,12 +143,13 @@ export interface ModuleSpecifierPreferences { /** * @param syntaxImpliedNodeFormat Used when the import syntax implies ESM or CJS irrespective of the mode of the file. */ - getAllowedEndingsInPreferredOrder(syntaxImpliedNodeFormat?: SourceFile["impliedNodeFormat"]): ModuleSpecifierEnding[]; + getAllowedEndingsInPreferredOrder(syntaxImpliedNodeFormat?: ResolutionMode): ModuleSpecifierEnding[]; } /** @internal */ export function getModuleSpecifierPreferences( { importModuleSpecifierPreference, importModuleSpecifierEnding }: UserPreferences, + host: Pick, compilerOptions: CompilerOptions, importingSourceFile: Pick, oldImportSpecifier?: string, @@ -163,8 +164,10 @@ export function getModuleSpecifierPreferences( importModuleSpecifierPreference === "project-relative" ? RelativePreference.ExternalNonRelative : RelativePreference.Shortest, getAllowedEndingsInPreferredOrder: syntaxImpliedNodeFormat => { - const preferredEnding = syntaxImpliedNodeFormat !== importingSourceFile.impliedNodeFormat ? getPreferredEnding(syntaxImpliedNodeFormat) : filePreferredEnding; - if ((syntaxImpliedNodeFormat ?? importingSourceFile.impliedNodeFormat) === ModuleKind.ESNext) { + const impliedNodeFormat = getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions); + const preferredEnding = syntaxImpliedNodeFormat !== impliedNodeFormat ? getPreferredEnding(syntaxImpliedNodeFormat) : filePreferredEnding; + const moduleResolution = getEmitModuleResolutionKind(compilerOptions); + if ((syntaxImpliedNodeFormat ?? impliedNodeFormat) === ModuleKind.ESNext && ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext) { if (shouldAllowImportingTsExtension(compilerOptions, importingSourceFile.fileName)) { return [ModuleSpecifierEnding.TsExtension, ModuleSpecifierEnding.JsExtension]; } @@ -204,7 +207,7 @@ export function getModuleSpecifierPreferences( } return getModuleSpecifierEndingPreference( importModuleSpecifierEnding, - resolutionMode ?? importingSourceFile.impliedNodeFormat, + resolutionMode ?? getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions), compilerOptions, isFullSourceFile(importingSourceFile) ? importingSourceFile : undefined, ); @@ -225,7 +228,7 @@ export function updateModuleSpecifier( oldImportSpecifier: string, options: ModuleSpecifierOptions = {}, ): string | undefined { - const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getModuleSpecifierPreferences({}, compilerOptions, importingSourceFile, oldImportSpecifier), {}, options); + const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getModuleSpecifierPreferences({}, host, compilerOptions, importingSourceFile, oldImportSpecifier), {}, options); if (res === oldImportSpecifier) return undefined; return res; } @@ -245,7 +248,7 @@ export function getModuleSpecifier( host: ModuleSpecifierResolutionHost, options: ModuleSpecifierOptions = {}, ): string { - return getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getModuleSpecifierPreferences({}, compilerOptions, importingSourceFile), {}, options); + return getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getModuleSpecifierPreferences({}, host, compilerOptions, importingSourceFile), {}, options); } /** @internal */ @@ -275,7 +278,7 @@ function getModuleSpecifierWorker( const info = getInfo(importingSourceFileName, host); const modulePaths = getAllModulePaths(info, toFileName, host, userPreferences, compilerOptions, options); return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode)) || - getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || importingSourceFile.impliedNodeFormat, preferences); + getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions), preferences); } /** @internal */ @@ -403,7 +406,7 @@ export function getLocalModuleSpecifierBetweenFileNames( compilerOptions, host, importMode, - getModuleSpecifierPreferences({}, compilerOptions, importingFile), + getModuleSpecifierPreferences({}, host, compilerOptions, importingFile), ); } @@ -417,7 +420,7 @@ function computeModuleSpecifiers( forAutoImport: boolean, ): ModuleSpecifierResult { const info = getInfo(importingSourceFile.fileName, host); - const preferences = getModuleSpecifierPreferences(userPreferences, compilerOptions, importingSourceFile); + const preferences = getModuleSpecifierPreferences(userPreferences, host, compilerOptions, importingSourceFile); const existingSpecifier = isFullSourceFile(importingSourceFile) && forEach(modulePaths, modulePath => forEach( host.getFileIncludeReasons().get(toPath(modulePath.path, host.getCurrentDirectory(), info.getCanonicalFileName)), @@ -425,7 +428,11 @@ function computeModuleSpecifiers( if (reason.kind !== FileIncludeKind.Import || reason.file !== importingSourceFile.path) return undefined; // If the candidate import mode doesn't match the mode we're generating for, don't consider it // TODO: maybe useful to keep around as an alternative option for certain contexts where the mode is overridable - if (importingSourceFile.impliedNodeFormat && importingSourceFile.impliedNodeFormat !== getModeForResolutionAtIndex(importingSourceFile, reason.index, compilerOptions)) return undefined; + const existingMode = host.getModeForResolutionAtIndex(importingSourceFile, reason.index); + const targetMode = options.overrideImportMode ?? host.getDefaultResolutionModeForFile(importingSourceFile); + if (existingMode !== targetMode && existingMode !== undefined && targetMode !== undefined) { + return undefined; + } const specifier = getModuleNameStringLiteralAt(importingSourceFile, reason.index).text; // If the preference is for non relative and the module specifier is relative, ignore it return preferences.relativePreference !== RelativePreference.NonRelative || !pathIsRelative(specifier) ? @@ -1093,7 +1100,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan // Simplify the full file path to something that can be resolved by Node. - const preferences = getModuleSpecifierPreferences(userPreferences, options, importingSourceFile); + const preferences = getModuleSpecifierPreferences(userPreferences, host, options, importingSourceFile); const allowedEndings = preferences.getAllowedEndingsInPreferredOrder(); let moduleSpecifier = path; let isPackageRootPath = false; @@ -1153,7 +1160,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath); if (isPackageJsonInfo(cachedPackageJson) || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) { const packageJsonContent: Record | undefined = cachedPackageJson?.contents.packageJsonContent || tryParseJson(host.readFile!(packageJsonPath)!); - const importMode = overrideMode || importingSourceFile.impliedNodeFormat; + const importMode = overrideMode || getDefaultResolutionModeForFile(importingSourceFile, host, options); if (getResolvePackageJsonExports(options)) { // The package name that we found in node_modules could be different from the package // name in the package.json content via url/filepath dependency specifiers. We need to @@ -1348,3 +1355,7 @@ function getRelativePathIfInSameVolume(path: string, directoryPath: string, getC function isPathRelativeToParent(path: string): boolean { return startsWith(path, ".."); } + +function getDefaultResolutionModeForFile(file: Pick, host: Pick, compilerOptions: CompilerOptions) { + return isFullSourceFile(file) ? host.getDefaultResolutionModeForFile(file) : getDefaultResolutionModeForFileWorker(file, compilerOptions); +} diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f111faaa4efdb..329748a7bf380 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -175,6 +175,7 @@ import { ImportClause, ImportDeclaration, ImportOrExportSpecifier, + importSyntaxAffectsModuleResolution, InternalEmitFlags, inverseJsxOptionMap, isAmbientModule, @@ -840,9 +841,11 @@ export function flattenDiagnosticMessageText(diag: string | DiagnosticMessageCha * @internal */ export interface SourceFileImportsList { - /** @internal */ imports: SourceFile["imports"]; - /** @internal */ moduleAugmentations: SourceFile["moduleAugmentations"]; + imports: SourceFile["imports"]; + moduleAugmentations: SourceFile["moduleAugmentations"]; impliedNodeFormat?: ResolutionMode; + fileName: string; + packageJsonScope?: SourceFile["packageJsonScope"]; } /** @@ -866,7 +869,7 @@ export function getModeForFileReference(ref: FileReference | string, containingF * should be the options of the referenced project, not the referencing project. */ export function getModeForResolutionAtIndex(file: SourceFile, index: number, compilerOptions: CompilerOptions): ResolutionMode; -/** @internal */ +/** @internal @knipignore */ // eslint-disable-next-line @typescript-eslint/unified-signatures export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number, compilerOptions: CompilerOptions): ResolutionMode; export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number, compilerOptions?: CompilerOptions): ResolutionMode { @@ -888,22 +891,47 @@ export function isExclusivelyTypeOnlyImportOrExport(decl: ImportDeclaration | Ex /** * Use `program.getModeForUsageLocation`, which retrieves the correct `compilerOptions`, instead of this function whenever possible. - * Calculates the final resolution mode for a given module reference node. This is the resolution mode explicitly provided via import - * attributes, if present, or the syntax the usage would have if emitted to JavaScript. In `--module node16` or `nodenext`, this may - * depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the input syntax of the reference. In other - * `module` modes, when overriding import attributes are not provided, this function returns `undefined`, as the result would have no - * impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for a given module reference node. This function only returns a result when module resolution + * settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided via import attributes, + * which cause an `import` or `require` condition to be used during resolution regardless of module resolution settings. In absence of + * overriding attributes, and in modes that support differing resolution, the result indicates the syntax the usage would emit to JavaScript. + * Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` + * * @param file The file the import or import-like reference is contained within * @param usage The module reference string * @param compilerOptions The compiler options for the program that owns the file. If the file belongs to a referenced project, the compiler options * should be the options of the referenced project, not the referencing project. * @returns The final resolution mode of the import */ -export function getModeForUsageLocation(file: { impliedNodeFormat?: ResolutionMode; }, usage: StringLiteralLike, compilerOptions: CompilerOptions) { +export function getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike, compilerOptions: CompilerOptions) { return getModeForUsageLocationWorker(file, usage, compilerOptions); } -function getModeForUsageLocationWorker(file: { impliedNodeFormat?: ResolutionMode; }, usage: StringLiteralLike, compilerOptions?: CompilerOptions) { +function getModeForUsageLocationWorker(file: Pick, usage: StringLiteralLike, compilerOptions?: CompilerOptions) { if (isImportDeclaration(usage.parent) || isExportDeclaration(usage.parent) || isJSDocImportTag(usage.parent)) { const isTypeOnly = isExclusivelyTypeOnlyImportOrExport(usage.parent); if (isTypeOnly) { @@ -919,20 +947,36 @@ function getModeForUsageLocationWorker(file: { impliedNodeFormat?: ResolutionMod return override; } } - if (compilerOptions && getEmitModuleKind(compilerOptions) === ModuleKind.Preserve) { - return (usage.parent.parent && isImportEqualsDeclaration(usage.parent.parent) || isRequireCall(usage.parent, /*requireStringLiteralLikeArgument*/ false)) - ? ModuleKind.CommonJS - : ModuleKind.ESNext; + + if (compilerOptions && importSyntaxAffectsModuleResolution(compilerOptions)) { + return getEmitSyntaxForUsageLocationWorker(file, usage, compilerOptions); } - if (file.impliedNodeFormat === undefined) return undefined; - if (file.impliedNodeFormat !== ModuleKind.ESNext) { - // in cjs files, import call expressions are esm format, otherwise everything is cjs - return isImportCall(walkUpParenthesizedExpressions(usage.parent)) ? ModuleKind.ESNext : ModuleKind.CommonJS; +} + +function getEmitSyntaxForUsageLocationWorker(file: Pick, usage: StringLiteralLike, compilerOptions?: CompilerOptions): ResolutionMode { + if (!compilerOptions) { + // This should always be provided, but we try to fail somewhat + // gracefully to allow projects like ts-node time to update. + return undefined; } - // in esm files, import=require statements are cjs format, otherwise everything is esm - // imports are only parent'd up to their containing declaration/expression, so access farther parents with care const exprParentParent = walkUpParenthesizedExpressions(usage.parent)?.parent; - return exprParentParent && isImportEqualsDeclaration(exprParentParent) ? ModuleKind.CommonJS : ModuleKind.ESNext; + if (exprParentParent && isImportEqualsDeclaration(exprParentParent) || isRequireCall(usage.parent, /*requireStringLiteralLikeArgument*/ false)) { + return ModuleKind.CommonJS; + } + if (isImportCall(walkUpParenthesizedExpressions(usage.parent))) { + return shouldTransformImportCallWorker(file, compilerOptions) ? ModuleKind.CommonJS : ModuleKind.ESNext; + } + // If we're in --module preserve on an input file, we know that an import + // is an import. But if this is a declaration file, we'd prefer to use the + // impliedNodeFormat. Since we want things to be consistent between the two, + // we need to issue errors when the user writes ESM syntax in a definitely-CJS + // file, until/unless declaration emit can indicate a true ESM import. On the + // other hand, writing CJS syntax in a definitely-ESM file is fine, since declaration + // emit preserves the CJS syntax. + const fileEmitMode = getEmitModuleFormatOfFileWorker(file, compilerOptions); + return fileEmitMode === ModuleKind.CommonJS ? ModuleKind.CommonJS : + emitModuleKindIsNonNodeESM(fileEmitMode) || fileEmitMode === ModuleKind.Preserve ? ModuleKind.ESNext : + undefined; } /** @internal */ @@ -1028,7 +1072,7 @@ function getTypeReferenceResolutionName(entry: const typeReferenceResolutionNameAndModeGetter: ResolutionNameAndModeGetter = { getName: getTypeReferenceResolutionName, - getMode: (entry, file) => getModeForFileReference(entry, file?.impliedNodeFormat), + getMode: (entry, file, compilerOptions) => getModeForFileReference(entry, file && getDefaultResolutionModeForFileWorker(file, compilerOptions)), }; /** @internal */ @@ -1358,6 +1402,7 @@ export function getImpliedNodeFormatForFileWorker( default: return undefined; } + function lookupFromPackageJson(): Partial { const state = getTemporaryModuleResolutionState(packageJsonInfoCache, host, options); const packageJsonLocations: string[] = []; @@ -1928,6 +1973,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg isSourceFileFromExternalLibrary, isSourceFileDefaultLibrary, getModeForUsageLocation, + getEmitSyntaxForUsageLocation, getModeForResolutionAtIndex, getSourceFileFromReference, getLibFileFromReference, @@ -1956,6 +2002,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg forEachResolvedProjectReference, isSourceOfProjectReferenceRedirect, getRedirectReferenceForResolutionFromSourceOfProject, + getCompilerOptionsForFile, + getDefaultResolutionModeForFile, + getEmitModuleFormatOfFile, + getImpliedNodeFormatForEmit, + shouldTransformImportCall, emitBuildInfo, fileExists, readFile, @@ -2704,6 +2755,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg getSymlinkCache, writeFile: writeFileCallback || writeFile, isEmitBlocked, + shouldTransformImportCall, + getEmitModuleFormatOfFile, + getDefaultResolutionModeForFile, + getModeForResolutionAtIndex, readFile: f => host.readFile(f), fileExists: f => { // Use local caches @@ -3990,11 +4045,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // store resolved type directive on the file const fileName = ref.fileName; resolutionsInFile.set(fileName, getModeForFileReference(ref, file.impliedNodeFormat), resolvedTypeReferenceDirective); - const mode = ref.resolutionMode || file.impliedNodeFormat; + const mode = ref.resolutionMode || getDefaultResolutionModeForFile(file); processTypeReferenceDirective(fileName, mode, resolvedTypeReferenceDirective, { kind: FileIncludeKind.TypeReferenceDirective, file: file.path, index }); } } + function getCompilerOptionsForFile(file: SourceFile): CompilerOptions { + return getRedirectReferenceForResolution(file)?.commandLine.options || options; + } + function processTypeReferenceDirective( typeReferenceDirective: string, mode: ResolutionMode, @@ -4109,7 +4168,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const resolutions = resolvedModulesProcessing?.get(file.path) || resolveModuleNamesReusingOldState(moduleNames, file); Debug.assert(resolutions.length === moduleNames.length); - const optionsForFile = getRedirectReferenceForResolution(file)?.commandLine.options || options; + const optionsForFile = getCompilerOptionsForFile(file); const resolutionsInFile = createModeAwareCache(); (resolvedModules ??= new Map()).set(file.path, resolutionsInFile); for (let index = 0; index < moduleNames.length; index++) { @@ -4699,7 +4758,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } else { reasons?.forEach(processReason); - redirectInfo = file && explainIfFileIsRedirectAndImpliedFormat(file); + redirectInfo = file && explainIfFileIsRedirectAndImpliedFormat(file, getCompilerOptionsForFile(file)); } if (fileProcessingReason) processReason(fileProcessingReason); @@ -5133,13 +5192,70 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } function getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike): ResolutionMode { - const optionsForFile = getRedirectReferenceForResolution(file)?.commandLine.options || options; - return getModeForUsageLocationWorker(file, usage, optionsForFile); + return getModeForUsageLocationWorker(file, usage, getCompilerOptionsForFile(file)); + } + + function getEmitSyntaxForUsageLocation(file: SourceFile, usage: StringLiteralLike): ResolutionMode { + return getEmitSyntaxForUsageLocationWorker(file, usage, getCompilerOptionsForFile(file)); } function getModeForResolutionAtIndex(file: SourceFile, index: number): ResolutionMode { return getModeForUsageLocation(file, getModuleNameStringLiteralAt(file, index)); } + + function getDefaultResolutionModeForFile(sourceFile: SourceFile): ResolutionMode { + return getDefaultResolutionModeForFileWorker(sourceFile, getCompilerOptionsForFile(sourceFile)); + } + + function getImpliedNodeFormatForEmit(sourceFile: SourceFile): ResolutionMode { + return getImpliedNodeFormatForEmitWorker(sourceFile, getCompilerOptionsForFile(sourceFile)); + } + + function getEmitModuleFormatOfFile(sourceFile: SourceFile): ModuleKind { + return getEmitModuleFormatOfFileWorker(sourceFile, getCompilerOptionsForFile(sourceFile)); + } + + function shouldTransformImportCall(sourceFile: SourceFile): boolean { + return shouldTransformImportCallWorker(sourceFile, getCompilerOptionsForFile(sourceFile)); + } +} + +function shouldTransformImportCallWorker(sourceFile: Pick, options: CompilerOptions): boolean { + const moduleKind = getEmitModuleKind(options); + if (ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext || moduleKind === ModuleKind.Preserve) { + return false; + } + return getEmitModuleFormatOfFileWorker(sourceFile, options) < ModuleKind.ES2015; +} +/** @internal Prefer `program.getEmitModuleFormatOfFile` when possible. */ +export function getEmitModuleFormatOfFileWorker(sourceFile: Pick, options: CompilerOptions): ModuleKind { + return getImpliedNodeFormatForEmitWorker(sourceFile, options) ?? getEmitModuleKind(options); +} +/** @internal Prefer `program.getImpliedNodeFormatForEmit` when possible. */ +export function getImpliedNodeFormatForEmitWorker(sourceFile: Pick, options: CompilerOptions): ResolutionMode { + const moduleKind = getEmitModuleKind(options); + if (ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) { + return sourceFile.impliedNodeFormat; + } + if ( + sourceFile.impliedNodeFormat === ModuleKind.CommonJS + && (sourceFile.packageJsonScope?.contents.packageJsonContent.type === "commonjs" + || fileExtensionIsOneOf(sourceFile.fileName, [Extension.Cjs, Extension.Cts])) + ) { + return ModuleKind.CommonJS; + } + if ( + sourceFile.impliedNodeFormat === ModuleKind.ESNext + && (sourceFile.packageJsonScope?.contents.packageJsonContent.type === "module" + || fileExtensionIsOneOf(sourceFile.fileName, [Extension.Mjs, Extension.Mts])) + ) { + return ModuleKind.ESNext; + } + return undefined; +} +/** @internal Prefer `program.getDefaultResolutionModeForFile` when possible. */ +export function getDefaultResolutionModeForFileWorker(sourceFile: Pick, options: CompilerOptions): ResolutionMode { + return importSyntaxAffectsModuleResolution(options) ? getImpliedNodeFormatForEmitWorker(sourceFile, options) : undefined; } interface HostForUseSourceOfProjectReferenceRedirect { diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 1ca1657eac038..bd181e5f3c028 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -65,10 +65,10 @@ import { transformESDecorators, transformESNext, transformGenerators, + transformImpliedNodeFormatDependentModule, transformJsx, transformLegacyDecorators, transformModule, - transformNodeModule, transformSystemModule, transformTypeScript, VariableDeclaration, @@ -77,17 +77,23 @@ import * as performance from "./_namespaces/ts.performance.js"; function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory { switch (moduleKind) { + case ModuleKind.Preserve: + // `transformECMAScriptModule` contains logic for preserving + // CJS input syntax in `--module preserve` + return transformECMAScriptModule; case ModuleKind.ESNext: case ModuleKind.ES2022: case ModuleKind.ES2020: case ModuleKind.ES2015: - case ModuleKind.Preserve: - return transformECMAScriptModule; - case ModuleKind.System: - return transformSystemModule; case ModuleKind.Node16: case ModuleKind.NodeNext: - return transformNodeModule; + case ModuleKind.CommonJS: + // Wraps `transformModule` and `transformECMAScriptModule` and + // selects between them based on the `impliedNodeFormat` of the + // source file. + return transformImpliedNodeFormatDependentModule; + case ModuleKind.System: + return transformSystemModule; default: return transformModule; } diff --git a/src/compiler/transformers/module/node.ts b/src/compiler/transformers/module/impliedNodeFormatDependent.ts similarity index 84% rename from src/compiler/transformers/module/node.ts rename to src/compiler/transformers/module/impliedNodeFormatDependent.ts index 20b34a3ce2a7b..7a5bf9e210fcd 100644 --- a/src/compiler/transformers/module/node.ts +++ b/src/compiler/transformers/module/impliedNodeFormatDependent.ts @@ -14,7 +14,7 @@ import { } from "../../_namespaces/ts.js"; /** @internal */ -export function transformNodeModule(context: TransformationContext) { +export function transformImpliedNodeFormatDependentModule(context: TransformationContext) { const previousOnSubstituteNode = context.onSubstituteNode; const previousOnEmitNode = context.onEmitNode; @@ -30,6 +30,7 @@ export function transformNodeModule(context: TransformationContext) { const cjsOnSubstituteNode = context.onSubstituteNode; const cjsOnEmitNode = context.onEmitNode; + const getEmitModuleFormatOfFile = (file: SourceFile) => context.getEmitHost().getEmitModuleFormatOfFile(file); context.onSubstituteNode = onSubstituteNode; context.onEmitNode = onEmitNode; @@ -51,7 +52,7 @@ export function transformNodeModule(context: TransformationContext) { if (!currentSourceFile) { return previousOnSubstituteNode(hint, node); } - if (currentSourceFile.impliedNodeFormat === ModuleKind.ESNext) { + if (getEmitModuleFormatOfFile(currentSourceFile) >= ModuleKind.ES2015) { return esmOnSubstituteNode(hint, node); } return cjsOnSubstituteNode(hint, node); @@ -65,14 +66,14 @@ export function transformNodeModule(context: TransformationContext) { if (!currentSourceFile) { return previousOnEmitNode(hint, node, emitCallback); } - if (currentSourceFile.impliedNodeFormat === ModuleKind.ESNext) { + if (getEmitModuleFormatOfFile(currentSourceFile) >= ModuleKind.ES2015) { return esmOnEmitNode(hint, node, emitCallback); } return cjsOnEmitNode(hint, node, emitCallback); } function getModuleTransformForFile(file: SourceFile): typeof esmTransform { - return file.impliedNodeFormat === ModuleKind.ESNext ? esmTransform : cjsTransform; + return getEmitModuleFormatOfFile(file) >= ModuleKind.ES2015 ? esmTransform : cjsTransform; } function transformSourceFile(node: SourceFile) { diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 72028eebed49a..dc30bca2bb8d2 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -797,7 +797,7 @@ export function transformModule(context: TransformationContext): (x: SourceFile case SyntaxKind.PartiallyEmittedExpression: return visitPartiallyEmittedExpression(node as PartiallyEmittedExpression, valueIsDiscarded); case SyntaxKind.CallExpression: - if (isImportCall(node) && currentSourceFile.impliedNodeFormat === undefined) { + if (isImportCall(node) && host.shouldTransformImportCall(currentSourceFile)) { return visitImportCallExpression(node); } break; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 508042f69bee8..c2bba2dd30a05 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4750,21 +4750,79 @@ export interface Program extends ScriptReferenceHost { isSourceFileFromExternalLibrary(file: SourceFile): boolean; isSourceFileDefaultLibrary(file: SourceFile): boolean; /** - * Calculates the final resolution mode for a given module reference node. This is the resolution mode explicitly provided via import - * attributes, if present, or the syntax the usage would have if emitted to JavaScript. In `--module node16` or `nodenext`, this may - * depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the input syntax of the reference. In other - * `module` modes, when overriding import attributes are not provided, this function returns `undefined`, as the result would have no - * impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for a given module reference node. This function only returns a result when module resolution + * settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided via import attributes, + * which cause an `import` or `require` condition to be used during resolution regardless of module resolution settings. In absence of + * overriding attributes, and in modes that support differing resolution, the result indicates the syntax the usage would emit to JavaScript. + * Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` */ getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike): ResolutionMode; /** - * Calculates the final resolution mode for an import at some index within a file's `imports` list. This is the resolution mode - * explicitly provided via import attributes, if present, or the syntax the usage would have if emitted to JavaScript. In - * `--module node16` or `nodenext`, this may depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the - * input syntax of the reference. In other `module` modes, when overriding import attributes are not provided, this function returns - * `undefined`, as the result would have no impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for an import at some index within a file's `imports` list. This function only returns a result + * when module resolution settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided + * via import attributes, which cause an `import` or `require` condition to be used during resolution regardless of module resolution + * settings. In absence of overriding attributes, and in modes that support differing resolution, the result indicates the syntax the + * usage would emit to JavaScript. Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` */ getModeForResolutionAtIndex(file: SourceFile, index: number): ResolutionMode; + /** + * @internal + * The resolution mode to use for module resolution or module specifier resolution + * outside the context of an existing module reference, where + * `program.getModeForUsageLocation` should be used instead. + */ + getDefaultResolutionModeForFile(sourceFile: SourceFile): ResolutionMode; + /** @internal */ getImpliedNodeFormatForEmit(sourceFile: SourceFile): ResolutionMode; + /** @internal */ getEmitModuleFormatOfFile(sourceFile: SourceFile): ModuleKind; + /** @internal */ shouldTransformImportCall(sourceFile: SourceFile): boolean; // For testing purposes only. // This is set on created program to let us know how the program was created using old program @@ -4819,6 +4877,7 @@ export interface Program extends ScriptReferenceHost { /** @internal */ getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined; /** @internal */ getRedirectReferenceForResolutionFromSourceOfProject(filePath: Path): ResolvedProjectReference | undefined; /** @internal */ isSourceOfProjectReferenceRedirect(fileName: string): boolean; + /** @internal */ getCompilerOptionsForFile(file: SourceFile): CompilerOptions; /** @internal */ getBuildInfo?(): BuildInfo; /** @internal */ emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult; /** @@ -4934,8 +4993,12 @@ export interface TypeCheckerHost extends ModuleSpecifierResolutionHost { getSourceFile(fileName: string): SourceFile | undefined; getProjectReferenceRedirect(fileName: string): string | undefined; isSourceOfProjectReferenceRedirect(fileName: string): boolean; + getEmitSyntaxForUsageLocation(file: SourceFile, usage: StringLiteralLike): ResolutionMode; getRedirectReferenceForResolutionFromSourceOfProject(filePath: Path): ResolvedProjectReference | undefined; getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike): ResolutionMode; + getDefaultResolutionModeForFile(sourceFile: SourceFile): ResolutionMode; + getImpliedNodeFormatForEmit(sourceFile: SourceFile): ResolutionMode; + getEmitModuleFormatOfFile(sourceFile: SourceFile): ModuleKind; getResolvedModule(f: SourceFile, moduleName: string, mode: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined; @@ -5600,6 +5663,9 @@ export interface RequireVariableDeclarationList extends VariableDeclarationList readonly declarations: NodeArray>; } +/** @internal */ +export type CanHaveModuleSpecifier = AnyImportOrBareOrAccessedRequire | AliasDeclarationNode | ExportDeclaration | ImportTypeNode; + /** @internal */ export type LateVisibilityPaintedStatement = | AnyImportOrJsDocImport @@ -8358,6 +8424,8 @@ export interface EmitHost extends ScriptReferenceHost, ModuleSpecifierResolution getCanonicalFileName(fileName: string): string; isEmitBlocked(emitFileName: string): boolean; + shouldTransformImportCall(sourceFile: SourceFile): boolean; + getEmitModuleFormatOfFile(sourceFile: SourceFile): ModuleKind; writeFile: WriteFileCallback; getBuildInfo(): BuildInfo | undefined; @@ -9598,6 +9666,7 @@ export interface PrinterOptions { omitTrailingSemicolon?: boolean; noEmitHelpers?: boolean; /** @internal */ module?: CompilerOptions["module"]; + /** @internal */ moduleResolution?: CompilerOptions["moduleResolution"]; /** @internal */ target?: CompilerOptions["target"]; /** @internal */ sourceMap?: boolean; /** @internal */ inlineSourceMap?: boolean; @@ -9732,6 +9801,8 @@ export interface ModuleSpecifierResolutionHost { isSourceOfProjectReferenceRedirect(fileName: string): boolean; getFileIncludeReasons(): MultiMap; getCommonSourceDirectory(): string; + getDefaultResolutionModeForFile(sourceFile: SourceFile): ResolutionMode; + getModeForResolutionAtIndex(file: SourceFile, index: number): ResolutionMode; getModuleResolutionCache?(): ModuleResolutionCache | undefined; trace?(s: string): void; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1b972e990f7fb..6b340cb4b2f2f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5,7 +5,6 @@ import { addRange, affectsDeclarationPathOptionDeclarations, affectsEmitOptionDeclarations, - AliasDeclarationNode, AllAccessorDeclarations, AmbientModuleDeclaration, AmpersandAmpersandEqualsToken, @@ -41,6 +40,7 @@ import { canHaveDecorators, canHaveLocals, canHaveModifiers, + CanHaveModuleSpecifier, CanonicalDiagnostic, CaseBlock, CaseClause, @@ -167,6 +167,7 @@ import { getCommonSourceDirectory, getContainerFlags, getDirectoryPath, + getImpliedNodeFormatForEmitWorker, getJSDocAugmentsTag, getJSDocDeprecatedTagNoCache, getJSDocImplementsTags, @@ -4114,7 +4115,26 @@ export function isFunctionSymbol(symbol: Symbol | undefined) { } /** @internal */ -export function tryGetModuleSpecifierFromDeclaration(node: AnyImportOrBareOrAccessedRequire | AliasDeclarationNode | ExportDeclaration | ImportTypeNode | JSDocImportTag): StringLiteralLike | undefined { +export function canHaveModuleSpecifier(node: Node | undefined): node is CanHaveModuleSpecifier { + switch (node?.kind) { + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BindingElement: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceExport: + case SyntaxKind.NamespaceImport: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportType: + return true; + } + return false; +} + +/** @internal */ +export function tryGetModuleSpecifierFromDeclaration(node: CanHaveModuleSpecifier | JSDocImportTag): StringLiteralLike | undefined { switch (node.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: @@ -8685,11 +8705,11 @@ function isFileModuleFromUsingJSXTag(file: SourceFile): Node | undefined { * Note that this requires file.impliedNodeFormat be set already; meaning it must be set very early on * in SourceFile construction. */ -function isFileForcedToBeModuleByFormat(file: SourceFile): true | undefined { +function isFileForcedToBeModuleByFormat(file: SourceFile, options: CompilerOptions): true | undefined { // Excludes declaration files - they still require an explicit `export {}` or the like // for back compat purposes. The only non-declaration files _not_ forced to be a module are `.js` files // that aren't esm-mode (meaning not in a `type: module` scope). - return (file.impliedNodeFormat === ModuleKind.ESNext || (fileExtensionIsOneOf(file.fileName, [Extension.Cjs, Extension.Cts, Extension.Mjs, Extension.Mts]))) && !file.isDeclarationFile ? true : undefined; + return (getImpliedNodeFormatForEmitWorker(file, options) === ModuleKind.ESNext || (fileExtensionIsOneOf(file.fileName, [Extension.Cjs, Extension.Cts, Extension.Mjs, Extension.Mts]))) && !file.isDeclarationFile ? true : undefined; } /** @internal */ @@ -8710,17 +8730,29 @@ export function getSetExternalModuleIndicator(options: CompilerOptions): (file: // If module is nodenext or node16, all esm format files are modules // If jsx is react-jsx or react-jsxdev then jsx tags force module-ness // otherwise, the presence of import or export statments (or import.meta) implies module-ness - const checks: ((file: SourceFile) => Node | true | undefined)[] = [isFileProbablyExternalModule]; + const checks: ((file: SourceFile, options: CompilerOptions) => Node | true | undefined)[] = [isFileProbablyExternalModule]; if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { checks.push(isFileModuleFromUsingJSXTag); } checks.push(isFileForcedToBeModuleByFormat); const combined = or(...checks); - const callback = (file: SourceFile) => void (file.externalModuleIndicator = combined(file)); + const callback = (file: SourceFile) => void (file.externalModuleIndicator = combined(file, options)); return callback; } } +/** + * @internal + * Returns true if an `import` and a `require` of the same module specifier + * can resolve to a different file. + */ +export function importSyntaxAffectsModuleResolution(options: CompilerOptions) { + const moduleResolution = getEmitModuleResolutionKind(options); + return ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext + || getResolvePackageJsonExports(options) + || getResolvePackageJsonImports(options); +} + type CompilerOptionKeys = keyof { [K in keyof CompilerOptions as string extends K ? never : K]: any; }; function createComputedCompilerOptions>( options: { diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 618545564c592..89c6f13b102c7 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -57,6 +57,7 @@ import { getDirectoryPath, getEmitDeclarations, getEmitScriptTarget, + getImpliedNodeFormatForEmitWorker, getLineAndCharacterOfPosition, getNameOfScriptTarget, getNewLineCharacter, @@ -352,13 +353,14 @@ export function explainFiles(program: Program, write: (s: string) => void) { for (const file of program.getSourceFiles()) { write(`${toFileName(file, relativeFileName)}`); reasons.get(file.path)?.forEach(reason => write(` ${fileIncludeReasonToDiagnostics(program, reason, relativeFileName).messageText}`)); - explainIfFileIsRedirectAndImpliedFormat(file, relativeFileName)?.forEach(d => write(` ${d.messageText}`)); + explainIfFileIsRedirectAndImpliedFormat(file, program.getCompilerOptionsForFile(file), relativeFileName)?.forEach(d => write(` ${d.messageText}`)); } } /** @internal */ export function explainIfFileIsRedirectAndImpliedFormat( file: SourceFile, + options: CompilerOptions, fileNameConvertor?: (fileName: string) => string, ): DiagnosticMessageChain[] | undefined { let result: DiagnosticMessageChain[] | undefined; @@ -377,7 +379,7 @@ export function explainIfFileIsRedirectAndImpliedFormat( )); } if (isExternalOrCommonJsModule(file)) { - switch (file.impliedNodeFormat) { + switch (getImpliedNodeFormatForEmitWorker(file, options)) { case ModuleKind.ESNext: if (file.packageJsonScope) { (result ??= []).push(chainDiagnosticMessages( diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 6eedc5b8e38c0..f622a0d55f34b 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -50,10 +50,12 @@ import { getDeclarationOfKind, getDefaultLikeExportInfo, getDirectoryPath, + getEmitModuleFormatOfFileWorker, getEmitModuleKind, getEmitModuleResolutionKind, getEmitScriptTarget, getExportInfoMap, + getImpliedNodeFormatForEmitWorker, getIsFileExcluded, getMeaningFromLocation, getNameForExportedSymbol, @@ -335,7 +337,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog compilerOptions, createModuleSpecifierResolutionHost(program, host), ); - const importKind = getImportKind(futureExportingSourceFile, exportKind, compilerOptions); + const importKind = getImportKind(futureExportingSourceFile, exportKind, program); const addAsTypeOnly = getAddAsTypeOnly( isImportUsageValidAsTypeOnly, /*isForNewImportDeclaration*/ true, @@ -699,7 +701,7 @@ export interface ImportSpecifierResolver { /** @internal */ export function createImportSpecifierResolver(importingFile: SourceFile, program: Program, host: LanguageServiceHost, preferences: UserPreferences): ImportSpecifierResolver { const packageJsonImportFilter = createPackageJsonImportFilter(importingFile, preferences, host); - const importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); + const importMap = createExistingImportMap(importingFile, program); return { getModuleSpecifierForBestExportInfo }; function getModuleSpecifierForBestExportInfo( @@ -911,7 +913,7 @@ function getImportFixes( sourceFile: SourceFile | FutureSourceFile, host: LanguageServiceHost, preferences: UserPreferences, - importMap = isFullSourceFile(sourceFile) ? createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()) : undefined, + importMap = isFullSourceFile(sourceFile) ? createExistingImportMap(sourceFile, program) : undefined, fromCacheOnly?: boolean, ): { computedWithoutCacheCount: number; fixes: readonly ImportFixWithModuleSpecifier[]; } { const checker = program.getTypeChecker(); @@ -1078,7 +1080,8 @@ function tryAddToExistingImport(existingImports: readonly FixAddToExistingImport } } -function createExistingImportMap(checker: TypeChecker, importingFile: SourceFile, compilerOptions: CompilerOptions) { +function createExistingImportMap(importingFile: SourceFile, program: Program) { + const checker = program.getTypeChecker(); let importMap: MultiMap | undefined; for (const moduleSpecifier of importingFile.imports) { const i = importFromModuleSpecifier(moduleSpecifier); @@ -1108,7 +1111,7 @@ function createExistingImportMap(checker: TypeChecker, importingFile: SourceFile && !every(matchingDeclarations, isJSDocImportTag) ) return emptyArray; - const importKind = getImportKind(importingFile, exportKind, compilerOptions); + const importKind = getImportKind(importingFile, exportKind, program); return matchingDeclarations.map(declaration => ({ declaration, importKind, symbol, targetFlags })); }, }; @@ -1132,8 +1135,9 @@ function shouldUseRequire(sourceFile: SourceFile | FutureSourceFile, program: Pr // 4. In --module nodenext, assume we're not emitting JS -> JS, so use // whatever syntax Node expects based on the detected module kind - if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) return true; - if (sourceFile.impliedNodeFormat === ModuleKind.ESNext) return false; + // TODO: consider removing `impliedNodeFormatForEmit` + if (getImpliedNodeFormatForEmit(sourceFile, program) === ModuleKind.CommonJS) return true; + if (getImpliedNodeFormatForEmit(sourceFile, program) === ModuleKind.ESNext) return false; // 5. Match the first other JS file in the program that's unambiguously CJS or ESM for (const otherFile of program.getSourceFiles()) { @@ -1186,7 +1190,7 @@ function getNewImportFixes( // `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types. return { kind: ImportFixKind.JsdocTypeImport, moduleSpecifierKind, moduleSpecifier, usagePosition, exportInfo, isReExport: i > 0 }; } - const importKind = getImportKind(sourceFile, exportInfo.exportKind, compilerOptions); + const importKind = getImportKind(sourceFile, exportInfo.exportKind, program); let qualification: Qualification | undefined; if (usagePosition !== undefined && importKind === ImportKind.CommonJS && exportInfo.exportKind === ExportKind.Named) { // Compiler options are restricting our import options to a require, but we need to access @@ -1198,7 +1202,7 @@ function getNewImportFixes( const exportEquals = checker.resolveExternalModuleSymbol(exportInfo.moduleSymbol); let namespacePrefix; if (exportEquals !== exportInfo.moduleSymbol) { - namespacePrefix = forEachNameOfDefaultExport(exportEquals, checker, compilerOptions, /*preferCapitalizedNames*/ false, identity)!; + namespacePrefix = forEachNameOfDefaultExport(exportEquals, checker, getEmitScriptTarget(compilerOptions), identity)!; } namespacePrefix ||= moduleSymbolToValidIdentifier( exportInfo.moduleSymbol, @@ -1417,8 +1421,8 @@ function getUmdSymbol(token: Node, checker: TypeChecker): Symbol | undefined { * * @internal */ -export function getImportKind(importingFile: SourceFile | FutureSourceFile, exportKind: ExportKind, compilerOptions: CompilerOptions, forceImportKeyword?: boolean): ImportKind { - if (compilerOptions.verbatimModuleSyntax && (getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS || importingFile.impliedNodeFormat === ModuleKind.CommonJS)) { +export function getImportKind(importingFile: SourceFile | FutureSourceFile, exportKind: ExportKind, program: Program, forceImportKeyword?: boolean): ImportKind { + if (program.getCompilerOptions().verbatimModuleSyntax && getEmitModuleFormatOfFile(importingFile, program) === ModuleKind.CommonJS) { // TODO: if the exporting file is ESM under nodenext, or `forceImport` is given in a JS file, this is impossible return ImportKind.CommonJS; } @@ -1428,22 +1432,22 @@ export function getImportKind(importingFile: SourceFile | FutureSourceFile, expo case ExportKind.Default: return ImportKind.Default; case ExportKind.ExportEquals: - return getExportEqualsImportKind(importingFile, compilerOptions, !!forceImportKeyword); + return getExportEqualsImportKind(importingFile, program.getCompilerOptions(), !!forceImportKeyword); case ExportKind.UMD: - return getUmdImportKind(importingFile, compilerOptions, !!forceImportKeyword); + return getUmdImportKind(importingFile, program, !!forceImportKeyword); default: return Debug.assertNever(exportKind); } } -function getUmdImportKind(importingFile: SourceFile | FutureSourceFile, compilerOptions: CompilerOptions, forceImportKeyword: boolean): ImportKind { +function getUmdImportKind(importingFile: SourceFile | FutureSourceFile, program: Program, forceImportKeyword: boolean): ImportKind { // Import a synthetic `default` if enabled. - if (getAllowSyntheticDefaultImports(compilerOptions)) { + if (getAllowSyntheticDefaultImports(program.getCompilerOptions())) { return ImportKind.Default; } // When a synthetic `default` is unavailable, use `import..require` if the module kind supports it. - const moduleKind = getEmitModuleKind(compilerOptions); + const moduleKind = getEmitModuleKind(program.getCompilerOptions()); switch (moduleKind) { case ModuleKind.AMD: case ModuleKind.CommonJS: @@ -1463,7 +1467,7 @@ function getUmdImportKind(importingFile: SourceFile | FutureSourceFile, compiler return ImportKind.Namespace; case ModuleKind.Node16: case ModuleKind.NodeNext: - return importingFile.impliedNodeFormat === ModuleKind.ESNext ? ImportKind.Namespace : ImportKind.CommonJS; + return getImpliedNodeFormatForEmit(importingFile, program) === ModuleKind.ESNext ? ImportKind.Namespace : ImportKind.CommonJS; default: return Debug.assertNever(moduleKind, `Unexpected moduleKind ${moduleKind}`); } @@ -1555,7 +1559,7 @@ function getExportInfos( if ( defaultInfo && symbolFlagsHaveMeaning(checker.getSymbolFlags(defaultInfo.symbol), currentTokenMeaning) - && forEachNameOfDefaultExport(defaultInfo.symbol, checker, compilerOptions, isJsxTagName, name => name === symbolName) + && forEachNameOfDefaultExport(defaultInfo.symbol, checker, getEmitScriptTarget(compilerOptions), (name, capitalizedName) => (isJsxTagName ? capitalizedName ?? name : name) === symbolName) ) { addSymbol(moduleSymbol, sourceFile, defaultInfo.symbol, defaultInfo.exportKind, program, isFromPackageJson); } @@ -2038,3 +2042,11 @@ function symbolFlagsHaveMeaning(flags: SymbolFlags, meaning: SemanticMeaning): b meaning & SemanticMeaning.Namespace ? !!(flags & SymbolFlags.Namespace) : false; } + +function getImpliedNodeFormatForEmit(file: SourceFile | FutureSourceFile, program: Program) { + return isFullSourceFile(file) ? program.getImpliedNodeFormatForEmit(file) : getImpliedNodeFormatForEmitWorker(file, program.getCompilerOptions()); +} + +function getEmitModuleFormatOfFile(file: SourceFile | FutureSourceFile, program: Program) { + return isFullSourceFile(file) ? program.getEmitModuleFormatOfFile(file) : getEmitModuleFormatOfFileWorker(file, program.getCompilerOptions()); +} diff --git a/src/services/completions.ts b/src/services/completions.ts index d240cacc2c3c3..43148e14182af 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1161,11 +1161,13 @@ function getJSDocParamAnnotation( ? createSnippetPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, }) : createPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, }); setEmitFlags(typeNode, EmitFlags.SingleLine); @@ -1459,6 +1461,7 @@ function getExhaustiveCaseSnippets( const printer = createSnippetPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, newLine: getNewLineKind(newLineChar), }); @@ -1720,7 +1723,7 @@ function createCompletionEntry( if (originIsResolvedExport(origin)) { sourceDisplay = [textPart(origin.moduleSpecifier)]; if (importStatementCompletion) { - ({ insertText, replacementSpan } = getInsertTextAndReplacementSpanForImportCompletion(name, importStatementCompletion, origin, useSemicolons, sourceFile, options, preferences)); + ({ insertText, replacementSpan } = getInsertTextAndReplacementSpanForImportCompletion(name, importStatementCompletion, origin, useSemicolons, sourceFile, program, preferences)); isSnippet = preferences.includeCompletionsWithSnippetText ? true : undefined; } } @@ -1978,6 +1981,7 @@ function getEntryForMemberCompletion( const printer = createSnippetPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, omitTrailingSemicolon: false, newLine: getNewLineKind(getNewLineOrDefaultFromHost(host, formatContext?.options)), @@ -2204,6 +2208,7 @@ function getEntryForObjectLiteralMethodCompletion( const printer = createSnippetPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, omitTrailingSemicolon: false, newLine: getNewLineKind(getNewLineOrDefaultFromHost(host, formatContext?.options)), @@ -2218,6 +2223,7 @@ function getEntryForObjectLiteralMethodCompletion( const signaturePrinter = createPrinter({ removeComments: true, module: options.module, + moduleResolution: options.moduleResolution, target: options.target, omitTrailingSemicolon: true, }); @@ -2520,14 +2526,14 @@ function completionEntryDataToSymbolOriginInfo(data: CompletionEntryData, comple return unresolvedOrigin; } -function getInsertTextAndReplacementSpanForImportCompletion(name: string, importStatementCompletion: ImportStatementCompletionInfo, origin: SymbolOriginInfoResolvedExport, useSemicolons: boolean, sourceFile: SourceFile, options: CompilerOptions, preferences: UserPreferences) { +function getInsertTextAndReplacementSpanForImportCompletion(name: string, importStatementCompletion: ImportStatementCompletionInfo, origin: SymbolOriginInfoResolvedExport, useSemicolons: boolean, sourceFile: SourceFile, program: Program, preferences: UserPreferences) { const replacementSpan = importStatementCompletion.replacementSpan; const quotedModuleSpecifier = escapeSnippetText(quote(sourceFile, preferences, origin.moduleSpecifier)); const exportKind = origin.isDefaultExport ? ExportKind.Default : origin.exportName === InternalSymbolName.ExportEquals ? ExportKind.ExportEquals : ExportKind.Named; const tabStop = preferences.includeCompletionsWithSnippetText ? "$1" : ""; - const importKind = codefix.getImportKind(sourceFile, exportKind, options, /*forceImportKeyword*/ true); + const importKind = codefix.getImportKind(sourceFile, exportKind, program, /*forceImportKeyword*/ true); const isImportSpecifierTypeOnly = importStatementCompletion.couldBeTypeOnlyImportSpecifier; const topLevelTypeOnlyText = importStatementCompletion.isTopLevelTypeOnly ? ` ${tokenToString(SyntaxKind.TypeKeyword)} ` : " "; const importSpecifierTypeOnlyText = isImportSpecifierTypeOnly ? `${tokenToString(SyntaxKind.TypeKeyword)} ` : ""; diff --git a/src/services/exportInfoMap.ts b/src/services/exportInfoMap.ts index 6bc8d84c4fe2c..2af062cd4e0f9 100644 --- a/src/services/exportInfoMap.ts +++ b/src/services/exportInfoMap.ts @@ -4,7 +4,6 @@ import { append, arrayIsEqualTo, CancellationToken, - CompilerOptions, consumesNodeCoreModules, createMultiMap, Debug, @@ -18,9 +17,7 @@ import { GetCanonicalFileName, getDefaultLikeExportNameFromDeclaration, getDirectoryPath, - getEmitScriptTarget, getLocalSymbolForExportDefault, - getNamesForExportedSymbol, getNodeModulePathParts, getPackageNameFromTypesPackageName, getRegexFromPattern, @@ -46,6 +43,7 @@ import { Path, pathContainsNodeModules, Program, + ScriptTarget, skipAlias, SourceFile, startsWith, @@ -198,7 +196,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): // get a better name. const names = exportKind === ExportKind.Named || isExternalModuleSymbol(namedSymbol) ? unescapeLeadingUnderscores(symbolTableKey) - : getNamesForExportedSymbol(namedSymbol, /*scriptTarget*/ undefined); + : getNamesForExportedSymbol(namedSymbol, checker, /*scriptTarget*/ undefined); const symbolName = typeof names === "string" ? names : names[0]; const capitalizedSymbolName = typeof names === "string" ? undefined : names[1]; @@ -572,12 +570,21 @@ function isImportableSymbol(symbol: Symbol, checker: TypeChecker) { return !checker.isUndefinedSymbol(symbol) && !checker.isUnknownSymbol(symbol) && !isKnownSymbol(symbol) && !isPrivateIdentifierSymbol(symbol); } +function getNamesForExportedSymbol(defaultExport: Symbol, checker: TypeChecker, scriptTarget: ScriptTarget | undefined) { + let names: string | string[] | undefined; + forEachNameOfDefaultExport(defaultExport, checker, scriptTarget, (name, capitalizedName) => { + names = capitalizedName ? [name, capitalizedName] : name; + return true; + }); + return Debug.checkDefined(names); +} + /** * @internal * May call `cb` multiple times with the same name. * Terminates when `cb` returns a truthy value. */ -export function forEachNameOfDefaultExport(defaultExport: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions, preferCapitalizedNames: boolean, cb: (name: string) => T | undefined): T | undefined { +export function forEachNameOfDefaultExport(defaultExport: Symbol, checker: TypeChecker, scriptTarget: ScriptTarget | undefined, cb: (name: string, capitalizedName?: string) => T | undefined): T | undefined { let chain: Symbol[] | undefined; let current: Symbol | undefined = defaultExport; @@ -602,7 +609,10 @@ export function forEachNameOfDefaultExport(defaultExport: Symbol, checker: Ty for (const symbol of chain ?? emptyArray) { if (symbol.parent && isExternalModuleSymbol(symbol.parent)) { - const final = cb(moduleSymbolToValidIdentifier(symbol.parent, getEmitScriptTarget(compilerOptions), preferCapitalizedNames)); + const final = cb( + moduleSymbolToValidIdentifier(symbol.parent, scriptTarget, /*forceCapitalize*/ false), + moduleSymbolToValidIdentifier(symbol.parent, scriptTarget, /*forceCapitalize*/ true), + ); if (final) return final; } } diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index e0af6ca745cad..b96e06138dee3 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -200,7 +200,7 @@ export function getStringLiteralCompletions( includeSymbol: boolean, ): CompletionInfo | undefined { if (isInReferenceComment(sourceFile, position)) { - const entries = getTripleSlashReferenceCompletion(sourceFile, position, options, host); + const entries = getTripleSlashReferenceCompletion(sourceFile, position, program, host); return entries && convertPathCompletions(entries); } if (isInString(sourceFile, position, contextToken)) { @@ -614,8 +614,8 @@ function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: SourceFile const extensionOptions = getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile, typeChecker, preferences, mode); return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && !compilerOptions.paths && (isRootedDiskPath(literalValue) || isUrl(literalValue)) - ? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath, extensionOptions) - : getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, mode, compilerOptions, host, extensionOptions, typeChecker); + ? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, program, host, scriptPath, extensionOptions) + : getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, mode, program, host, extensionOptions); } interface ExtensionOptions { @@ -635,20 +635,21 @@ function getExtensionOptions(compilerOptions: CompilerOptions, referenceKind: Re resolutionMode, }; } -function getCompletionEntriesForRelativeModules(literalValue: string, scriptDirectory: string, compilerOptions: CompilerOptions, host: LanguageServiceHost, scriptPath: Path, extensionOptions: ExtensionOptions) { +function getCompletionEntriesForRelativeModules(literalValue: string, scriptDirectory: string, program: Program, host: LanguageServiceHost, scriptPath: Path, extensionOptions: ExtensionOptions) { + const compilerOptions = program.getCompilerOptions(); if (compilerOptions.rootDirs) { return getCompletionEntriesForDirectoryFragmentWithRootDirs( compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, - compilerOptions, + program, host, scriptPath, ); } else { - return arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, scriptPath).values()); + return arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, program, host, /*moduleSpecifierIsRelative*/ true, scriptPath).values()); } } @@ -686,12 +687,13 @@ function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, sc ); } -function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptDirectory: string, extensionOptions: ExtensionOptions, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude: string): readonly NameAndKind[] { +function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptDirectory: string, extensionOptions: ExtensionOptions, program: Program, host: LanguageServiceHost, exclude: string): readonly NameAndKind[] { + const compilerOptions = program.getCompilerOptions(); const basePath = compilerOptions.project || host.getCurrentDirectory(); const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase); return deduplicate( - flatMap(baseDirectories, baseDirectory => arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, exclude).values())), + flatMap(baseDirectories, baseDirectory => arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, program, host, /*moduleSpecifierIsRelative*/ true, exclude).values())), (itemA, itemB) => itemA.name === itemB.name && itemA.kind === itemB.kind && itemA.extension === itemB.extension, ); } @@ -707,6 +709,7 @@ function getCompletionEntriesForDirectoryFragment( fragment: string, scriptDirectory: string, extensionOptions: ExtensionOptions, + program: Program, host: LanguageServiceHost, moduleSpecifierIsRelative: boolean, exclude?: string, @@ -746,7 +749,7 @@ function getCompletionEntriesForDirectoryFragment( if (versionPaths) { const packageDirectory = getDirectoryPath(packageJsonPath); const pathInPackage = absolutePath.slice(ensureTrailingDirectorySeparator(packageDirectory).length); - if (addCompletionEntriesFromPaths(result, pathInPackage, packageDirectory, extensionOptions, host, versionPaths)) { + if (addCompletionEntriesFromPaths(result, pathInPackage, packageDirectory, extensionOptions, program, host, versionPaths)) { // A true result means one of the `versionPaths` was matched, which will block relative resolution // to files and folders from here. All reachable paths given the pattern match are already added. return result; @@ -769,7 +772,7 @@ function getCompletionEntriesForDirectoryFragment( continue; } - const { name, extension } = getFilenameWithExtensionOption(getBaseFileName(filePath), host.getCompilationSettings(), extensionOptions, /*isExportsWildcard*/ false); + const { name, extension } = getFilenameWithExtensionOption(getBaseFileName(filePath), program, extensionOptions, /*isExportsWildcard*/ false); result.add(nameAndKind(name, ScriptElementKind.scriptElement, extension)); } } @@ -789,7 +792,7 @@ function getCompletionEntriesForDirectoryFragment( return result; } -function getFilenameWithExtensionOption(name: string, compilerOptions: CompilerOptions, extensionOptions: ExtensionOptions, isExportsWildcard: boolean): { name: string; extension: Extension | undefined; } { +function getFilenameWithExtensionOption(name: string, program: Program, extensionOptions: ExtensionOptions, isExportsWildcard: boolean): { name: string; extension: Extension | undefined; } { const nonJsResult = moduleSpecifiers.tryGetRealFileNameForNonJsDeclarationFileName(name); if (nonJsResult) { return { name: nonJsResult, extension: tryGetExtensionFromPath(nonJsResult) }; @@ -800,7 +803,8 @@ function getFilenameWithExtensionOption(name: string, compilerOptions: CompilerO let allowedEndings = getModuleSpecifierPreferences( { importModuleSpecifierEnding: extensionOptions.endingPreference }, - compilerOptions, + program, + program.getCompilerOptions(), extensionOptions.importingSourceFile, ).getAllowedEndingsInPreferredOrder(extensionOptions.resolutionMode); @@ -814,7 +818,7 @@ function getFilenameWithExtensionOption(name: string, compilerOptions: CompilerO if (fileExtensionIsOneOf(name, supportedTSImplementationExtensions)) { return { name, extension: tryGetExtensionFromPath(name) }; } - const outputExtension = moduleSpecifiers.tryGetJSExtensionForFile(name, compilerOptions); + const outputExtension = moduleSpecifiers.tryGetJSExtensionForFile(name, program.getCompilerOptions()); return outputExtension ? { name: changeExtension(name, outputExtension), extension: outputExtension } : { name, extension: tryGetExtensionFromPath(name) }; @@ -828,7 +832,7 @@ function getFilenameWithExtensionOption(name: string, compilerOptions: CompilerO return { name: removeFileExtension(name), extension: tryGetExtensionFromPath(name) }; } - const outputExtension = moduleSpecifiers.tryGetJSExtensionForFile(name, compilerOptions); + const outputExtension = moduleSpecifiers.tryGetJSExtensionForFile(name, program.getCompilerOptions()); return outputExtension ? { name: changeExtension(name, outputExtension), extension: outputExtension } : { name, extension: tryGetExtensionFromPath(name) }; @@ -840,6 +844,7 @@ function addCompletionEntriesFromPaths( fragment: string, baseDirectory: string, extensionOptions: ExtensionOptions, + program: Program, host: LanguageServiceHost, paths: MapLike, ) { @@ -851,7 +856,7 @@ function addCompletionEntriesFromPaths( const lengthB = typeof patternB === "object" ? patternB.prefix.length : b.length; return compareValues(lengthB, lengthA); }; - return addCompletionEntriesFromPathsOrExports(result, /*isExports*/ false, fragment, baseDirectory, extensionOptions, host, getOwnKeys(paths), getPatternsForKey, comparePaths); + return addCompletionEntriesFromPathsOrExports(result, /*isExports*/ false, fragment, baseDirectory, extensionOptions, program, host, getOwnKeys(paths), getPatternsForKey, comparePaths); } /** @returns whether `fragment` was a match for any `paths` (which should indicate whether any other path completions should be offered) */ @@ -861,6 +866,7 @@ function addCompletionEntriesFromPathsOrExports( fragment: string, baseDirectory: string, extensionOptions: ExtensionOptions, + program: Program, host: LanguageServiceHost, keys: readonly string[], getPatternsForKey: (key: string) => string[] | undefined, @@ -895,7 +901,7 @@ function addCompletionEntriesFromPathsOrExports( if (typeof pathPattern === "string" || matchedPath === undefined || comparePaths(key, matchedPath) !== Comparison.GreaterThan) { pathResults.push({ matchedPattern: isMatch, - results: getCompletionsForPathMapping(keyWithoutLeadingDotSlash, patterns, fragment, baseDirectory, extensionOptions, isExports && isMatch, host) + results: getCompletionsForPathMapping(keyWithoutLeadingDotSlash, patterns, fragment, baseDirectory, extensionOptions, isExports && isMatch, program, host) .map(({ name, kind, extension }) => nameAndKind(name, kind, extension)), }); } @@ -917,11 +923,12 @@ function getCompletionEntriesForNonRelativeModules( fragment: string, scriptPath: string, mode: ResolutionMode, - compilerOptions: CompilerOptions, + program: Program, host: LanguageServiceHost, extensionOptions: ExtensionOptions, - typeChecker: TypeChecker, ): readonly NameAndKind[] { + const typeChecker = program.getTypeChecker(); + const compilerOptions = program.getCompilerOptions(); const { baseUrl, paths } = compilerOptions; const result = createNameAndKindSet(); @@ -929,12 +936,12 @@ function getCompletionEntriesForNonRelativeModules( if (baseUrl) { const absolute = normalizePath(combinePaths(host.getCurrentDirectory(), baseUrl)); - getCompletionEntriesForDirectoryFragment(fragment, absolute, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); + getCompletionEntriesForDirectoryFragment(fragment, absolute, extensionOptions, program, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); } if (paths) { const absolute = getPathsBasePath(compilerOptions, host)!; - addCompletionEntriesFromPaths(result, fragment, absolute, extensionOptions, host, paths); + addCompletionEntriesFromPaths(result, fragment, absolute, extensionOptions, program, host, paths); } const fragmentDirectory = getFragmentDirectory(fragment); @@ -942,7 +949,7 @@ function getCompletionEntriesForNonRelativeModules( result.add(nameAndKind(ambientName, ScriptElementKind.externalModuleName, /*extension*/ undefined)); } - getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); + getCompletionEntriesFromTypings(host, program, scriptPath, fragmentDirectory, extensionOptions, result); if (moduleResolutionUsesNodeModules(moduleResolution)) { // If looking for a global package name, don't just include everything in `node_modules` because that includes dependencies' own dependencies. @@ -961,7 +968,7 @@ function getCompletionEntriesForNonRelativeModules( let ancestorLookup: (directory: string) => void | undefined = ancestor => { const nodeModules = combinePaths(ancestor, "node_modules"); if (tryDirectoryExists(host, nodeModules)) { - getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); + getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, program, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); } }; if (fragmentDirectory && getResolvePackageJsonExports(compilerOptions)) { @@ -998,6 +1005,7 @@ function getCompletionEntriesForNonRelativeModules( fragmentSubpath, packageDirectory, extensionOptions, + program, host, keys, key => singleElementArray(getPatternFromFirstMatchingCondition(exports[key], conditions)), @@ -1041,6 +1049,7 @@ function getCompletionsForPathMapping( packageDirectory: string, extensionOptions: ExtensionOptions, isExportsWildcard: boolean, + program: Program, host: LanguageServiceHost, ): readonly NameAndKind[] { if (!endsWith(path, "*")) { @@ -1052,9 +1061,9 @@ function getCompletionsForPathMapping( const remainingFragment = tryRemovePrefix(fragment, pathPrefix); if (remainingFragment === undefined) { const starIsFullPathComponent = path[path.length - 2] === "/"; - return starIsFullPathComponent ? justPathMappingName(pathPrefix, ScriptElementKind.directory) : flatMap(patterns, pattern => getModulesForPathsPattern("", packageDirectory, pattern, extensionOptions, isExportsWildcard, host)?.map(({ name, ...rest }) => ({ name: pathPrefix + name, ...rest }))); + return starIsFullPathComponent ? justPathMappingName(pathPrefix, ScriptElementKind.directory) : flatMap(patterns, pattern => getModulesForPathsPattern("", packageDirectory, pattern, extensionOptions, isExportsWildcard, program, host)?.map(({ name, ...rest }) => ({ name: pathPrefix + name, ...rest }))); } - return flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, isExportsWildcard, host)); + return flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, isExportsWildcard, program, host)); function justPathMappingName(name: string, kind: ScriptElementKind.directory | ScriptElementKind.scriptElement): readonly NameAndKind[] { return startsWith(name, fragment) ? [{ name: removeTrailingDirectorySeparator(name), kind, extension: undefined }] : emptyArray; @@ -1067,6 +1076,7 @@ function getModulesForPathsPattern( pattern: string, extensionOptions: ExtensionOptions, isExportsWildcard: boolean, + program: Program, host: LanguageServiceHost, ): readonly NameAndKind[] | undefined { if (!host.readDirectory) { @@ -1115,7 +1125,7 @@ function getModulesForPathsPattern( if (containsSlash(trimmedWithPattern)) { return directoryResult(getPathComponents(removeLeadingDirectorySeparator(trimmedWithPattern))[1]); } - const { name, extension } = getFilenameWithExtensionOption(trimmedWithPattern, host.getCompilationSettings(), extensionOptions, isExportsWildcard); + const { name, extension } = getFilenameWithExtensionOption(trimmedWithPattern, program, extensionOptions, isExportsWildcard); return nameAndKind(name, ScriptElementKind.scriptElement, extension); } }); @@ -1159,7 +1169,8 @@ function getAmbientModuleCompletions(fragment: string, fragmentDirectory: string return nonRelativeModuleNames; } -function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): readonly PathCompletion[] | undefined { +function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, program: Program, host: LanguageServiceHost): readonly PathCompletion[] | undefined { + const compilerOptions = program.getCompilerOptions(); const token = getTokenAtPosition(sourceFile, position); const commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); const range = commentRanges && find(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end); @@ -1174,13 +1185,14 @@ function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: num const [, prefix, kind, toComplete] = match; const scriptPath = getDirectoryPath(sourceFile.path); - const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, ReferenceKind.Filename, sourceFile), host, /*moduleSpecifierIsRelative*/ true, sourceFile.path) - : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile)) + const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, ReferenceKind.Filename, sourceFile), program, host, /*moduleSpecifierIsRelative*/ true, sourceFile.path) + : kind === "types" ? getCompletionEntriesFromTypings(host, program, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile)) : Debug.fail(); return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values())); } -function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): NameAndKindSet { +function getCompletionEntriesFromTypings(host: LanguageServiceHost, program: Program, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): NameAndKindSet { + const options = program.getCompilerOptions(); // Check for typings specified in compiler options const seen = new Map(); @@ -1215,7 +1227,7 @@ function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: Com const baseDirectory = combinePaths(directory, typeDirectoryName); const remainingFragment = tryRemoveDirectoryPrefix(fragmentDirectory, packageName, hostGetCanonicalFileName(host)); if (remainingFragment !== undefined) { - getCompletionEntriesForDirectoryFragment(remainingFragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); + getCompletionEntriesForDirectoryFragment(remainingFragment, baseDirectory, extensionOptions, program, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); } } } diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index b5daa7052b844..a5daf3e6666f2 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -66,7 +66,7 @@ export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Pr program.getSemanticDiagnostics(sourceFile, cancellationToken); const diags: DiagnosticWithLocation[] = []; const checker = program.getTypeChecker(); - const isCommonJSFile = sourceFile.impliedNodeFormat === ModuleKind.CommonJS || fileExtensionIsOneOf(sourceFile.fileName, [Extension.Cts, Extension.Cjs]); + const isCommonJSFile = program.getImpliedNodeFormatForEmit(sourceFile) === ModuleKind.CommonJS || fileExtensionIsOneOf(sourceFile.fileName, [Extension.Cts, Extension.Cjs]); if ( !isCommonJSFile && diff --git a/src/services/utilities.ts b/src/services/utilities.ts index a34b936d7a240..9c954d4318949 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -95,6 +95,7 @@ import { getEmitModuleKind, getEmitScriptTarget, getExternalModuleImportEqualsDeclarationExpression, + getImpliedNodeFormatForEmitWorker, getImpliedNodeFormatForFile, getImpliedNodeFormatForFileWorker, getIndentString, @@ -2476,6 +2477,8 @@ export function createModuleSpecifierResolutionHost(program: Program, host: Lang getNearestAncestorDirectoryWithPackageJson: maybeBind(host, host.getNearestAncestorDirectoryWithPackageJson), getFileIncludeReasons: () => program.getFileIncludeReasons(), getCommonSourceDirectory: () => program.getCommonSourceDirectory(), + getDefaultResolutionModeForFile: file => program.getDefaultResolutionModeForFile(file), + getModeForResolutionAtIndex: (file, index) => program.getModeForResolutionAtIndex(file, index), }; } @@ -3987,22 +3990,13 @@ export function firstOrOnly(valueOrArray: T | readonly T[]): T { return isArray(valueOrArray) ? first(valueOrArray) : valueOrArray; } -/** @internal */ -export function getNamesForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined): string | [lowercase: string, capitalized: string] { - if (needsNameFromDeclaration(symbol)) { - const fromDeclaration = getDefaultLikeExportNameFromDeclaration(symbol); - if (fromDeclaration) return fromDeclaration; - const fileNameCase = moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*forceCapitalize*/ false); - const capitalized = moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*forceCapitalize*/ true); - if (fileNameCase === capitalized) return fileNameCase; - return [fileNameCase, capitalized]; - } - return symbol.name; -} - -/** @internal */ +/** + * If a type checker and multiple files are available, consider using `forEachNameOfDefaultExport` + * instead, which searches for names of re-exported defaults/namespaces in target files. + * @internal + */ export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined, preferCapitalized?: boolean) { - if (needsNameFromDeclaration(symbol)) { + if (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default) { // Names for default exports: // - export default foo => foo // - export { foo as default } => foo @@ -4013,11 +4007,11 @@ export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTar return symbol.name; } -function needsNameFromDeclaration(symbol: Symbol) { - return !(symbol.flags & SymbolFlags.Transient) && (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default); -} - -/** @internal */ +/** + * If a type checker and multiple files are available, consider using `forEachNameOfDefaultExport` + * instead, which searches for names of re-exported defaults/namespaces in target files. + * @internal + */ export function getDefaultLikeExportNameFromDeclaration(symbol: Symbol): string | undefined { return firstDefined(symbol.declarations, d => { // "export default" in this case. See `ExportAssignment`for more details. @@ -4250,11 +4244,13 @@ export function fileShouldUseJavaScriptRequire(file: SourceFile | string, progra if (!hasJSFileExtension(fileName)) { return false; } - const compilerOptions = program.getCompilerOptions(); + const compilerOptions = typeof file === "string" ? program.getCompilerOptions() : program.getCompilerOptionsForFile(file); const moduleKind = getEmitModuleKind(compilerOptions); - const impliedNodeFormat = typeof file === "string" - ? getImpliedNodeFormatForFile(toPath(file, host.getCurrentDirectory(), hostGetCanonicalFileName(host)), program.getPackageJsonInfoCache?.(), host, compilerOptions) - : file.impliedNodeFormat; + const sourceFileLike = typeof file === "string" ? { + fileName: file, + impliedNodeFormat: getImpliedNodeFormatForFile(toPath(file, host.getCurrentDirectory(), hostGetCanonicalFileName(host)), program.getPackageJsonInfoCache?.(), host, compilerOptions), + } : file; + const impliedNodeFormat = getImpliedNodeFormatForEmitWorker(sourceFileLike, compilerOptions); if (impliedNodeFormat === ModuleKind.ESNext) { return false; diff --git a/src/testRunner/unittests/tsc/projectReferences.ts b/src/testRunner/unittests/tsc/projectReferences.ts index 1b446a995747c..d1dda68e0784c 100644 --- a/src/testRunner/unittests/tsc/projectReferences.ts +++ b/src/testRunner/unittests/tsc/projectReferences.ts @@ -44,6 +44,51 @@ describe("unittests:: tsc:: projectReferences::", () => { commandLineArgs: ["--p", "src/project"], }); + verifyTsc({ + scenario: "projectReferences", + subScenario: "default import interop uses referenced project settings", + fs: () => + loadProjectFromFiles({ + "/node_modules/ambiguous-package/package.json": `{ "name": "ambiguous-package" }`, + "/node_modules/ambiguous-package/index.d.ts": "export declare const ambiguous: number;", + "/node_modules/esm-package/package.json": `{ "name": "esm-package", "type": "module" }`, + "/node_modules/esm-package/index.d.ts": "export declare const esm: number;", + "/lib/tsconfig.json": jsonToReadableText({ + compilerOptions: { + composite: true, + declaration: true, + rootDir: "src", + outDir: "dist", + module: "esnext", + moduleResolution: "bundler", + }, + include: ["src"], + }), + "/lib/src/a.ts": "export const a = 0;", + "/lib/dist/a.d.ts": "export declare const a = 0;", + "/app/tsconfig.json": jsonToReadableText({ + compilerOptions: { + module: "esnext", + moduleResolution: "bundler", + rootDir: "src", + outDir: "dist", + }, + include: ["src"], + references: [ + { path: "../lib" }, + ], + }), + "/app/src/local.ts": "export const local = 0;", + "/app/src/index.ts": ` + import local from "./local"; // Error + import esm from "esm-package"; // Error + import referencedSource from "../../lib/src/a"; // Error + import referencedDeclaration from "../../lib/dist/a"; // Error + import ambiguous from "ambiguous-package"; // Ok`, + }), + commandLineArgs: ["--p", "app", "--pretty", "false"], + }); + verifyTsc({ scenario: "projectReferences", subScenario: "referencing ambient const enum from referenced project with preserveConstEnums", diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index f7899cecd2551..bcef42eb60a74 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5978,19 +5978,67 @@ declare namespace ts { isSourceFileFromExternalLibrary(file: SourceFile): boolean; isSourceFileDefaultLibrary(file: SourceFile): boolean; /** - * Calculates the final resolution mode for a given module reference node. This is the resolution mode explicitly provided via import - * attributes, if present, or the syntax the usage would have if emitted to JavaScript. In `--module node16` or `nodenext`, this may - * depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the input syntax of the reference. In other - * `module` modes, when overriding import attributes are not provided, this function returns `undefined`, as the result would have no - * impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for a given module reference node. This function only returns a result when module resolution + * settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided via import attributes, + * which cause an `import` or `require` condition to be used during resolution regardless of module resolution settings. In absence of + * overriding attributes, and in modes that support differing resolution, the result indicates the syntax the usage would emit to JavaScript. + * Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` */ getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike): ResolutionMode; /** - * Calculates the final resolution mode for an import at some index within a file's `imports` list. This is the resolution mode - * explicitly provided via import attributes, if present, or the syntax the usage would have if emitted to JavaScript. In - * `--module node16` or `nodenext`, this may depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the - * input syntax of the reference. In other `module` modes, when overriding import attributes are not provided, this function returns - * `undefined`, as the result would have no impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for an import at some index within a file's `imports` list. This function only returns a result + * when module resolution settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided + * via import attributes, which cause an `import` or `require` condition to be used during resolution regardless of module resolution + * settings. In absence of overriding attributes, and in modes that support differing resolution, the result indicates the syntax the + * usage would emit to JavaScript. Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` */ getModeForResolutionAtIndex(file: SourceFile, index: number): ResolutionMode; getProjectReferences(): readonly ProjectReference[] | undefined; @@ -9349,24 +9397,43 @@ declare namespace ts { function getModeForResolutionAtIndex(file: SourceFile, index: number, compilerOptions: CompilerOptions): ResolutionMode; /** * Use `program.getModeForUsageLocation`, which retrieves the correct `compilerOptions`, instead of this function whenever possible. - * Calculates the final resolution mode for a given module reference node. This is the resolution mode explicitly provided via import - * attributes, if present, or the syntax the usage would have if emitted to JavaScript. In `--module node16` or `nodenext`, this may - * depend on the file's `impliedNodeFormat`. In `--module preserve`, it depends only on the input syntax of the reference. In other - * `module` modes, when overriding import attributes are not provided, this function returns `undefined`, as the result would have no - * impact on module resolution, emit, or type checking. + * Calculates the final resolution mode for a given module reference node. This function only returns a result when module resolution + * settings allow differing resolution between ESM imports and CJS requires, or when a mode is explicitly provided via import attributes, + * which cause an `import` or `require` condition to be used during resolution regardless of module resolution settings. In absence of + * overriding attributes, and in modes that support differing resolution, the result indicates the syntax the usage would emit to JavaScript. + * Some examples: + * + * ```ts + * // tsc foo.mts --module nodenext + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `impliedNodeFormat` set by .mts file extension + * + * // tsc foo.cts --module nodenext + * import {} from "mod"; + * // Result: CommonJS - the import emits as CJS due to `impliedNodeFormat` set by .cts file extension + * + * // tsc foo.ts --module preserve --moduleResolution bundler + * import {} from "mod"; + * // Result: ESNext - the import emits as ESM due to `--module preserve` and `--moduleResolution bundler` + * // supports conditional imports/exports + * + * // tsc foo.ts --module preserve --moduleResolution node10 + * import {} from "mod"; + * // Result: undefined - the import emits as ESM due to `--module preserve`, but `--moduleResolution node10` + * // does not support conditional imports/exports + * + * // tsc foo.ts --module commonjs --moduleResolution node10 + * import type {} from "mod" with { "resolution-mode": "import" }; + * // Result: ESNext - conditional imports/exports always supported with "resolution-mode" attribute + * ``` + * * @param file The file the import or import-like reference is contained within * @param usage The module reference string * @param compilerOptions The compiler options for the program that owns the file. If the file belongs to a referenced project, the compiler options * should be the options of the referenced project, not the referencing project. * @returns The final resolution mode of the import */ - function getModeForUsageLocation( - file: { - impliedNodeFormat?: ResolutionMode; - }, - usage: StringLiteralLike, - compilerOptions: CompilerOptions, - ): ModuleKind.CommonJS | ModuleKind.ESNext | undefined; + function getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike, compilerOptions: CompilerOptions): ResolutionMode; function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): readonly Diagnostic[]; /** * A function for determining if a given file is esm or cjs format, assuming modern node module resolution rules, as configured by the diff --git a/tests/baselines/reference/conditionalExportsResolutionFallback(moduleresolution=bundler).errors.txt b/tests/baselines/reference/conditionalExportsResolutionFallback(moduleresolution=bundler).errors.txt deleted file mode 100644 index e66a5c3ddddfc..0000000000000 --- a/tests/baselines/reference/conditionalExportsResolutionFallback(moduleresolution=bundler).errors.txt +++ /dev/null @@ -1,29 +0,0 @@ -error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. - - -!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. -==== /node_modules/dep/package.json (0 errors) ==== - { - "name": "dep", - "version": "1.0.0", - "exports": { - ".": { - "import": "./dist/index.mjs", - "require": "./dist/index.js", - "types": "./dist/index.d.ts", - } - } - } - -==== /node_modules/dep/dist/index.d.ts (0 errors) ==== - export {}; - -==== /node_modules/dep/dist/index.mjs (0 errors) ==== - export {}; - -==== /index.mts (0 errors) ==== - import {} from "dep"; - // Should be an untyped resolution to dep/dist/index.mjs, - // but the first search is only for TS files, and when - // there's no dist/index.d.mts, it continues looking for - // matching conditions and resolves via `types`. \ No newline at end of file diff --git a/tests/baselines/reference/customConditions(resolvepackagejsonexports=false).errors.txt b/tests/baselines/reference/customConditions(resolvepackagejsonexports=false).errors.txt deleted file mode 100644 index 9e462a35eaf70..0000000000000 --- a/tests/baselines/reference/customConditions(resolvepackagejsonexports=false).errors.txt +++ /dev/null @@ -1,31 +0,0 @@ -error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. - - -!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. -==== /node_modules/lodash/package.json (0 errors) ==== - { - "name": "lodash", - "version": "1.0.0", - "main": "index.js", - "exports": { - "browser": "./browser.js", - "webpack": "./webpack.js", - "default": "./index.js" - } - } - -==== /node_modules/lodash/index.d.ts (0 errors) ==== - declare const _: "index"; - export = _; - -==== /node_modules/lodash/browser.d.ts (0 errors) ==== - declare const _: "browser"; - export default _; - -==== /node_modules/lodash/webpack.d.ts (0 errors) ==== - declare const _: "webpack"; - export = _; - -==== /index.ts (0 errors) ==== - import _ from "lodash"; - \ No newline at end of file diff --git a/tests/baselines/reference/customConditions(resolvepackagejsonexports=false).js b/tests/baselines/reference/customConditions(resolvepackagejsonexports=false).js index 1ac29a4a032d3..2d484ff74b5d3 100644 --- a/tests/baselines/reference/customConditions(resolvepackagejsonexports=false).js +++ b/tests/baselines/reference/customConditions(resolvepackagejsonexports=false).js @@ -29,5 +29,3 @@ import _ from "lodash"; //// [index.js] -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/customConditions(resolvepackagejsonexports=true).errors.txt b/tests/baselines/reference/customConditions(resolvepackagejsonexports=true).errors.txt deleted file mode 100644 index 9e462a35eaf70..0000000000000 --- a/tests/baselines/reference/customConditions(resolvepackagejsonexports=true).errors.txt +++ /dev/null @@ -1,31 +0,0 @@ -error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. - - -!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. -==== /node_modules/lodash/package.json (0 errors) ==== - { - "name": "lodash", - "version": "1.0.0", - "main": "index.js", - "exports": { - "browser": "./browser.js", - "webpack": "./webpack.js", - "default": "./index.js" - } - } - -==== /node_modules/lodash/index.d.ts (0 errors) ==== - declare const _: "index"; - export = _; - -==== /node_modules/lodash/browser.d.ts (0 errors) ==== - declare const _: "browser"; - export default _; - -==== /node_modules/lodash/webpack.d.ts (0 errors) ==== - declare const _: "webpack"; - export = _; - -==== /index.ts (0 errors) ==== - import _ from "lodash"; - \ No newline at end of file diff --git a/tests/baselines/reference/customConditions(resolvepackagejsonexports=true).js b/tests/baselines/reference/customConditions(resolvepackagejsonexports=true).js index 1ac29a4a032d3..2d484ff74b5d3 100644 --- a/tests/baselines/reference/customConditions(resolvepackagejsonexports=true).js +++ b/tests/baselines/reference/customConditions(resolvepackagejsonexports=true).js @@ -29,5 +29,3 @@ import _ from "lodash"; //// [index.js] -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/emitHelpersWithLocalCollisions(module=node16).js b/tests/baselines/reference/emitHelpersWithLocalCollisions(module=node16).js index 2bf5641f43b50..47204b7a76f30 100644 --- a/tests/baselines/reference/emitHelpersWithLocalCollisions(module=node16).js +++ b/tests/baselines/reference/emitHelpersWithLocalCollisions(module=node16).js @@ -10,20 +10,17 @@ const y = { ...o }; //// [a.js] -"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.A = void 0; let A = class A { }; -exports.A = A; -exports.A = A = __decorate([ +A = __decorate([ dec ], A); +export { A }; const o = { a: 1 }; const y = Object.assign({}, o); diff --git a/tests/baselines/reference/emitHelpersWithLocalCollisions(module=nodenext).js b/tests/baselines/reference/emitHelpersWithLocalCollisions(module=nodenext).js index 2bf5641f43b50..47204b7a76f30 100644 --- a/tests/baselines/reference/emitHelpersWithLocalCollisions(module=nodenext).js +++ b/tests/baselines/reference/emitHelpersWithLocalCollisions(module=nodenext).js @@ -10,20 +10,17 @@ const y = { ...o }; //// [a.js] -"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.A = void 0; let A = class A { }; -exports.A = A; -exports.A = A = __decorate([ +A = __decorate([ dec ], A); +export { A }; const o = { a: 1 }; const y = Object.assign({}, o); diff --git a/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).js b/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).js new file mode 100644 index 0000000000000..0c1812fa06439 --- /dev/null +++ b/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).js @@ -0,0 +1,25 @@ +//// [tests/cases/compiler/esmNoSynthesizedDefault.ts] //// + +//// [package.json] +{ "type": "module" } + +//// [index.d.ts] +export function toString(): string; + +//// [index.ts] +import mdast, { toString } from 'mdast-util-to-string'; +mdast; +mdast.toString(); + +const mdast2 = await import('mdast-util-to-string'); +mdast2.toString(); +mdast2.default; + + +//// [index.js] +import mdast from 'mdast-util-to-string'; +mdast; +mdast.toString(); +const mdast2 = await import('mdast-util-to-string'); +mdast2.toString(); +mdast2.default; diff --git a/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).symbols b/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).symbols new file mode 100644 index 0000000000000..49f52de2941e1 --- /dev/null +++ b/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).symbols @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/esmNoSynthesizedDefault.ts] //// + +=== /node_modules/mdast-util-to-string/index.d.ts === +export function toString(): string; +>toString : Symbol(toString, Decl(index.d.ts, 0, 0)) + +=== /index.ts === +import mdast, { toString } from 'mdast-util-to-string'; +>mdast : Symbol(mdast, Decl(index.ts, 0, 6)) +>toString : Symbol(toString, Decl(index.ts, 0, 15)) + +mdast; +>mdast : Symbol(mdast, Decl(index.ts, 0, 6)) + +mdast.toString(); +>mdast.toString : Symbol(mdast.toString, Decl(index.d.ts, 0, 0)) +>mdast : Symbol(mdast, Decl(index.ts, 0, 6)) +>toString : Symbol(mdast.toString, Decl(index.d.ts, 0, 0)) + +const mdast2 = await import('mdast-util-to-string'); +>mdast2 : Symbol(mdast2, Decl(index.ts, 4, 5)) +>'mdast-util-to-string' : Symbol(mdast, Decl(index.d.ts, 0, 0)) + +mdast2.toString(); +>mdast2.toString : Symbol(mdast.toString, Decl(index.d.ts, 0, 0)) +>mdast2 : Symbol(mdast2, Decl(index.ts, 4, 5)) +>toString : Symbol(mdast.toString, Decl(index.d.ts, 0, 0)) + +mdast2.default; +>mdast2.default : Symbol(mdast.default) +>mdast2 : Symbol(mdast2, Decl(index.ts, 4, 5)) +>default : Symbol(mdast.default) + diff --git a/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).types b/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).types new file mode 100644 index 0000000000000..fa24f3a53623c --- /dev/null +++ b/tests/baselines/reference/esmNoSynthesizedDefault(module=esnext).types @@ -0,0 +1,56 @@ +//// [tests/cases/compiler/esmNoSynthesizedDefault.ts] //// + +=== /node_modules/mdast-util-to-string/index.d.ts === +export function toString(): string; +>toString : () => string +> : ^^^^^^ + +=== /index.ts === +import mdast, { toString } from 'mdast-util-to-string'; +>mdast : typeof mdast +> : ^^^^^^^^^^^^ +>toString : () => string +> : ^^^^^^ + +mdast; +>mdast : typeof mdast +> : ^^^^^^^^^^^^ + +mdast.toString(); +>mdast.toString() : string +> : ^^^^^^ +>mdast.toString : () => string +> : ^^^^^^ +>mdast : typeof mdast +> : ^^^^^^^^^^^^ +>toString : () => string +> : ^^^^^^ + +const mdast2 = await import('mdast-util-to-string'); +>mdast2 : { default: typeof mdast; toString(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>await import('mdast-util-to-string') : { default: typeof mdast; toString(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>import('mdast-util-to-string') : Promise<{ default: typeof mdast; toString(): string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ +>'mdast-util-to-string' : "mdast-util-to-string" +> : ^^^^^^^^^^^^^^^^^^^^^^ + +mdast2.toString(); +>mdast2.toString() : string +> : ^^^^^^ +>mdast2.toString : () => string +> : ^^^^^^ +>mdast2 : { default: typeof mdast; toString(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>toString : () => string +> : ^^^^^^ + +mdast2.default; +>mdast2.default : typeof mdast +> : ^^^^^^^^^^^^ +>mdast2 : { default: typeof mdast; toString(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>default : typeof mdast +> : ^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).js b/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).js new file mode 100644 index 0000000000000..0c1812fa06439 --- /dev/null +++ b/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).js @@ -0,0 +1,25 @@ +//// [tests/cases/compiler/esmNoSynthesizedDefault.ts] //// + +//// [package.json] +{ "type": "module" } + +//// [index.d.ts] +export function toString(): string; + +//// [index.ts] +import mdast, { toString } from 'mdast-util-to-string'; +mdast; +mdast.toString(); + +const mdast2 = await import('mdast-util-to-string'); +mdast2.toString(); +mdast2.default; + + +//// [index.js] +import mdast from 'mdast-util-to-string'; +mdast; +mdast.toString(); +const mdast2 = await import('mdast-util-to-string'); +mdast2.toString(); +mdast2.default; diff --git a/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).symbols b/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).symbols new file mode 100644 index 0000000000000..49f52de2941e1 --- /dev/null +++ b/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).symbols @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/esmNoSynthesizedDefault.ts] //// + +=== /node_modules/mdast-util-to-string/index.d.ts === +export function toString(): string; +>toString : Symbol(toString, Decl(index.d.ts, 0, 0)) + +=== /index.ts === +import mdast, { toString } from 'mdast-util-to-string'; +>mdast : Symbol(mdast, Decl(index.ts, 0, 6)) +>toString : Symbol(toString, Decl(index.ts, 0, 15)) + +mdast; +>mdast : Symbol(mdast, Decl(index.ts, 0, 6)) + +mdast.toString(); +>mdast.toString : Symbol(mdast.toString, Decl(index.d.ts, 0, 0)) +>mdast : Symbol(mdast, Decl(index.ts, 0, 6)) +>toString : Symbol(mdast.toString, Decl(index.d.ts, 0, 0)) + +const mdast2 = await import('mdast-util-to-string'); +>mdast2 : Symbol(mdast2, Decl(index.ts, 4, 5)) +>'mdast-util-to-string' : Symbol(mdast, Decl(index.d.ts, 0, 0)) + +mdast2.toString(); +>mdast2.toString : Symbol(mdast.toString, Decl(index.d.ts, 0, 0)) +>mdast2 : Symbol(mdast2, Decl(index.ts, 4, 5)) +>toString : Symbol(mdast.toString, Decl(index.d.ts, 0, 0)) + +mdast2.default; +>mdast2.default : Symbol(mdast.default) +>mdast2 : Symbol(mdast2, Decl(index.ts, 4, 5)) +>default : Symbol(mdast.default) + diff --git a/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).types b/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).types new file mode 100644 index 0000000000000..fa24f3a53623c --- /dev/null +++ b/tests/baselines/reference/esmNoSynthesizedDefault(module=preserve).types @@ -0,0 +1,56 @@ +//// [tests/cases/compiler/esmNoSynthesizedDefault.ts] //// + +=== /node_modules/mdast-util-to-string/index.d.ts === +export function toString(): string; +>toString : () => string +> : ^^^^^^ + +=== /index.ts === +import mdast, { toString } from 'mdast-util-to-string'; +>mdast : typeof mdast +> : ^^^^^^^^^^^^ +>toString : () => string +> : ^^^^^^ + +mdast; +>mdast : typeof mdast +> : ^^^^^^^^^^^^ + +mdast.toString(); +>mdast.toString() : string +> : ^^^^^^ +>mdast.toString : () => string +> : ^^^^^^ +>mdast : typeof mdast +> : ^^^^^^^^^^^^ +>toString : () => string +> : ^^^^^^ + +const mdast2 = await import('mdast-util-to-string'); +>mdast2 : { default: typeof mdast; toString(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>await import('mdast-util-to-string') : { default: typeof mdast; toString(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>import('mdast-util-to-string') : Promise<{ default: typeof mdast; toString(): string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ +>'mdast-util-to-string' : "mdast-util-to-string" +> : ^^^^^^^^^^^^^^^^^^^^^^ + +mdast2.toString(); +>mdast2.toString() : string +> : ^^^^^^ +>mdast2.toString : () => string +> : ^^^^^^ +>mdast2 : { default: typeof mdast; toString(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>toString : () => string +> : ^^^^^^ + +mdast2.default; +>mdast2.default : typeof mdast +> : ^^^^^^^^^^^^ +>mdast2 : { default: typeof mdast; toString(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>default : typeof mdast +> : ^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=amd).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit1(module=amd).errors.txt new file mode 100644 index 0000000000000..b837dc175ce01 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=amd).errors.txt @@ -0,0 +1,37 @@ +error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. + + +!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /h.mts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /i.cts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=amd).js b/tests/baselines/reference/impliedNodeFormatEmit1(module=amd).js new file mode 100644 index 0000000000000..8cdc5ac2b5358 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=amd).js @@ -0,0 +1,98 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit1.ts] //// + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [b.mjs] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [c.cjs] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [d.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [e.mjs] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [f.mjs] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [g.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); +}); +//// [h.mjs] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); +}); +//// [i.cjs] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); +}); +//// [dummy.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); +}); diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=commonjs).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit1(module=commonjs).errors.txt new file mode 100644 index 0000000000000..b837dc175ce01 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=commonjs).errors.txt @@ -0,0 +1,37 @@ +error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. + + +!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /h.mts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /i.cts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=commonjs).js b/tests/baselines/reference/impliedNodeFormatEmit1(module=commonjs).js new file mode 100644 index 0000000000000..358d98e9fea8b --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=commonjs).js @@ -0,0 +1,78 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit1.ts] //// + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [b.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [c.cjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [d.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [e.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [f.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [g.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [h.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [i.cjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [dummy.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=esnext).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit1(module=esnext).errors.txt new file mode 100644 index 0000000000000..08c39ac0e9b36 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=esnext).errors.txt @@ -0,0 +1,44 @@ +/g.ts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +/h.mts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +/i.cts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + + +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /h.mts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /i.cts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=esnext).js b/tests/baselines/reference/impliedNodeFormatEmit1(module=esnext).js new file mode 100644 index 0000000000000..69cd5d21e55f1 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=esnext).js @@ -0,0 +1,56 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit1.ts] //// + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +export var _ = 0; +//// [b.mjs] +export var _ = 0; +//// [c.cjs] +export var _ = 0; +//// [d.js] +export var _ = 0; +//// [e.mjs] +export var _ = 0; +//// [f.mjs] +export var _ = 0; +//// [g.js] +export {}; +//// [h.mjs] +export {}; +//// [i.cjs] +export {}; +//// [dummy.js] +export {}; diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=preserve).js b/tests/baselines/reference/impliedNodeFormatEmit1(module=preserve).js new file mode 100644 index 0000000000000..067de7888d3e7 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=preserve).js @@ -0,0 +1,52 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit1.ts] //// + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +export var _ = 0; +//// [b.mjs] +export var _ = 0; +//// [c.cjs] +export var _ = 0; +//// [d.js] +export var _ = 0; +//// [e.mjs] +export var _ = 0; +//// [f.mjs] +export var _ = 0; +//// [g.js] +//// [h.mjs] +//// [i.cjs] +//// [dummy.js] diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=system).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit1(module=system).errors.txt new file mode 100644 index 0000000000000..0482da58d7b5d --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=system).errors.txt @@ -0,0 +1,39 @@ +error TS5071: Option '--resolveJsonModule' cannot be specified when 'module' is set to 'none', 'system', or 'umd'. +error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. + + +!!! error TS5071: Option '--resolveJsonModule' cannot be specified when 'module' is set to 'none', 'system', or 'umd'. +!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /h.mts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /i.cts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=system).js b/tests/baselines/reference/impliedNodeFormatEmit1(module=system).js new file mode 100644 index 0000000000000..f991a4eac017d --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=system).js @@ -0,0 +1,148 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit1.ts] //// + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var _; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + exports_1("_", _ = 0); + } + }; +}); +//// [b.mjs] +System.register([], function (exports_1, context_1) { + "use strict"; + var _; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + exports_1("_", _ = 0); + } + }; +}); +//// [c.cjs] +System.register([], function (exports_1, context_1) { + "use strict"; + var _; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + exports_1("_", _ = 0); + } + }; +}); +//// [d.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var _; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + exports_1("_", _ = 0); + } + }; +}); +//// [e.mjs] +System.register([], function (exports_1, context_1) { + "use strict"; + var _; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + exports_1("_", _ = 0); + } + }; +}); +//// [f.mjs] +System.register([], function (exports_1, context_1) { + "use strict"; + var _; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + exports_1("_", _ = 0); + } + }; +}); +//// [g.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + } + }; +}); +//// [h.mjs] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + } + }; +}); +//// [i.cjs] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + } + }; +}); +//// [dummy.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + } + }; +}); diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=umd).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit1(module=umd).errors.txt new file mode 100644 index 0000000000000..0482da58d7b5d --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=umd).errors.txt @@ -0,0 +1,39 @@ +error TS5071: Option '--resolveJsonModule' cannot be specified when 'module' is set to 'none', 'system', or 'umd'. +error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. + + +!!! error TS5071: Option '--resolveJsonModule' cannot be specified when 'module' is set to 'none', 'system', or 'umd'. +!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /h.mts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /i.cts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit1(module=umd).js b/tests/baselines/reference/impliedNodeFormatEmit1(module=umd).js new file mode 100644 index 0000000000000..9fff0d4cd16d4 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit1(module=umd).js @@ -0,0 +1,178 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit1.ts] //// + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [b.mjs] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [c.cjs] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [d.js] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [e.mjs] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [f.mjs] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports._ = void 0; + exports._ = 0; +}); +//// [g.js] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); +}); +//// [h.mjs] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); +}); +//// [i.cjs] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); +}); +//// [dummy.js] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); +}); diff --git a/tests/baselines/reference/impliedNodeFormatEmit2(module=commonjs).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit2(module=commonjs).errors.txt new file mode 100644 index 0000000000000..b783a3b97e8cd --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit2(module=commonjs).errors.txt @@ -0,0 +1,40 @@ +error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. + + +!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. +==== /package.json (0 errors) ==== + {} + +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /h.mts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /i.cts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit2(module=commonjs).js b/tests/baselines/reference/impliedNodeFormatEmit2(module=commonjs).js new file mode 100644 index 0000000000000..3acea3e04d3a5 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit2(module=commonjs).js @@ -0,0 +1,81 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit2.ts] //// + +//// [package.json] +{} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [b.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [c.cjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [d.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [e.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [f.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [g.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [h.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [i.cjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [dummy.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/impliedNodeFormatEmit2(module=esnext).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit2(module=esnext).errors.txt new file mode 100644 index 0000000000000..a74bc098343a7 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit2(module=esnext).errors.txt @@ -0,0 +1,47 @@ +/g.ts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +/h.mts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +/i.cts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + + +==== /package.json (0 errors) ==== + {} + +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /h.mts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /i.cts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit2(module=esnext).js b/tests/baselines/reference/impliedNodeFormatEmit2(module=esnext).js new file mode 100644 index 0000000000000..ef36dafea558c --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit2(module=esnext).js @@ -0,0 +1,59 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit2.ts] //// + +//// [package.json] +{} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +export var _ = 0; +//// [b.mjs] +export var _ = 0; +//// [c.cjs] +export var _ = 0; +//// [d.js] +export var _ = 0; +//// [e.mjs] +export var _ = 0; +//// [f.mjs] +export var _ = 0; +//// [g.js] +export {}; +//// [h.mjs] +export {}; +//// [i.cjs] +export {}; +//// [dummy.js] +export {}; diff --git a/tests/baselines/reference/impliedNodeFormatEmit2(module=preserve).js b/tests/baselines/reference/impliedNodeFormatEmit2(module=preserve).js new file mode 100644 index 0000000000000..ca5229e56031b --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit2(module=preserve).js @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit2.ts] //// + +//// [package.json] +{} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +export var _ = 0; +//// [b.mjs] +export var _ = 0; +//// [c.cjs] +export var _ = 0; +//// [d.js] +export var _ = 0; +//// [e.mjs] +export var _ = 0; +//// [f.mjs] +export var _ = 0; +//// [g.js] +//// [h.mjs] +//// [i.cjs] +//// [dummy.js] diff --git a/tests/baselines/reference/impliedNodeFormatEmit3(module=commonjs).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit3(module=commonjs).errors.txt new file mode 100644 index 0000000000000..bad14be6e619e --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit3(module=commonjs).errors.txt @@ -0,0 +1,42 @@ +error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. + + +!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. +==== /package.json (0 errors) ==== + { + "type": "module" + } + +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /h.mts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /i.cts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit3(module=commonjs).js b/tests/baselines/reference/impliedNodeFormatEmit3(module=commonjs).js new file mode 100644 index 0000000000000..9927e59c5403a --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit3(module=commonjs).js @@ -0,0 +1,83 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit3.ts] //// + +//// [package.json] +{ + "type": "module" +} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [b.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [c.cjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [d.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [e.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [f.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [g.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [h.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [i.cjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [dummy.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/impliedNodeFormatEmit3(module=esnext).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit3(module=esnext).errors.txt new file mode 100644 index 0000000000000..5f8efe425b6c7 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit3(module=esnext).errors.txt @@ -0,0 +1,49 @@ +/g.ts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +/h.mts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +/i.cts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + + +==== /package.json (0 errors) ==== + { + "type": "module" + } + +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /h.mts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /i.cts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit3(module=esnext).js b/tests/baselines/reference/impliedNodeFormatEmit3(module=esnext).js new file mode 100644 index 0000000000000..1df2b11dbce13 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit3(module=esnext).js @@ -0,0 +1,61 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit3.ts] //// + +//// [package.json] +{ + "type": "module" +} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +export var _ = 0; +//// [b.mjs] +export var _ = 0; +//// [c.cjs] +export var _ = 0; +//// [d.js] +export var _ = 0; +//// [e.mjs] +export var _ = 0; +//// [f.mjs] +export var _ = 0; +//// [g.js] +export {}; +//// [h.mjs] +export {}; +//// [i.cjs] +export {}; +//// [dummy.js] +export {}; diff --git a/tests/baselines/reference/impliedNodeFormatEmit3(module=preserve).js b/tests/baselines/reference/impliedNodeFormatEmit3(module=preserve).js new file mode 100644 index 0000000000000..91cb7ffa16e6a --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit3(module=preserve).js @@ -0,0 +1,57 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit3.ts] //// + +//// [package.json] +{ + "type": "module" +} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +export var _ = 0; +//// [b.mjs] +export var _ = 0; +//// [c.cjs] +export var _ = 0; +//// [d.js] +export var _ = 0; +//// [e.mjs] +export var _ = 0; +//// [f.mjs] +export var _ = 0; +//// [g.js] +//// [h.mjs] +//// [i.cjs] +//// [dummy.js] diff --git a/tests/baselines/reference/impliedNodeFormatEmit4(module=commonjs).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit4(module=commonjs).errors.txt new file mode 100644 index 0000000000000..5229094dfa736 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit4(module=commonjs).errors.txt @@ -0,0 +1,42 @@ +error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. + + +!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. +==== /package.json (0 errors) ==== + { + "type": "commonjs" + } + +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /h.mts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /i.cts (0 errors) ==== + import {} from "./a"; + import a = require("./a"); + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit4(module=commonjs).js b/tests/baselines/reference/impliedNodeFormatEmit4(module=commonjs).js new file mode 100644 index 0000000000000..0d273c2e6c06d --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit4(module=commonjs).js @@ -0,0 +1,83 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit4.ts] //// + +//// [package.json] +{ + "type": "commonjs" +} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [b.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [c.cjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [d.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [e.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [f.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports._ = void 0; +exports._ = 0; +//// [g.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [h.mjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [i.cjs] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [dummy.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/impliedNodeFormatEmit4(module=esnext).errors.txt b/tests/baselines/reference/impliedNodeFormatEmit4(module=esnext).errors.txt new file mode 100644 index 0000000000000..996c1c41bad96 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit4(module=esnext).errors.txt @@ -0,0 +1,49 @@ +/g.ts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +/h.mts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +/i.cts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + + +==== /package.json (0 errors) ==== + { + "type": "commonjs" + } + +==== /a.ts (0 errors) ==== + export const _ = 0; + +==== /b.mts (0 errors) ==== + export const _ = 0; + +==== /c.cts (0 errors) ==== + export const _ = 0; + +==== /d.js (0 errors) ==== + export const _ = 0; + +==== /e.mjs (0 errors) ==== + export const _ = 0; + +==== /f.mjs (0 errors) ==== + export const _ = 0; + +==== /g.ts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /h.mts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /i.cts (1 errors) ==== + import {} from "./a"; + import a = require("./a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + +==== /dummy.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/impliedNodeFormatEmit4(module=esnext).js b/tests/baselines/reference/impliedNodeFormatEmit4(module=esnext).js new file mode 100644 index 0000000000000..0023d65f995a9 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit4(module=esnext).js @@ -0,0 +1,61 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit4.ts] //// + +//// [package.json] +{ + "type": "commonjs" +} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +export var _ = 0; +//// [b.mjs] +export var _ = 0; +//// [c.cjs] +export var _ = 0; +//// [d.js] +export var _ = 0; +//// [e.mjs] +export var _ = 0; +//// [f.mjs] +export var _ = 0; +//// [g.js] +export {}; +//// [h.mjs] +export {}; +//// [i.cjs] +export {}; +//// [dummy.js] +export {}; diff --git a/tests/baselines/reference/impliedNodeFormatEmit4(module=preserve).js b/tests/baselines/reference/impliedNodeFormatEmit4(module=preserve).js new file mode 100644 index 0000000000000..3de162effe8f8 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatEmit4(module=preserve).js @@ -0,0 +1,57 @@ +//// [tests/cases/compiler/impliedNodeFormatEmit4.ts] //// + +//// [package.json] +{ + "type": "commonjs" +} + +//// [a.ts] +export const _ = 0; + +//// [b.mts] +export const _ = 0; + +//// [c.cts] +export const _ = 0; + +//// [d.js] +export const _ = 0; + +//// [e.mjs] +export const _ = 0; + +//// [f.mjs] +export const _ = 0; + +//// [g.ts] +import {} from "./a"; +import a = require("./a"); + +//// [h.mts] +import {} from "./a"; +import a = require("./a"); + +//// [i.cts] +import {} from "./a"; +import a = require("./a"); + +//// [dummy.ts] +export {}; + + +//// [a.js] +export var _ = 0; +//// [b.mjs] +export var _ = 0; +//// [c.cjs] +export var _ = 0; +//// [d.js] +export var _ = 0; +//// [e.mjs] +export var _ = 0; +//// [f.mjs] +export var _ = 0; +//// [g.js] +//// [h.mjs] +//// [i.cjs] +//// [dummy.js] diff --git a/tests/baselines/reference/impliedNodeFormatInterop1.js b/tests/baselines/reference/impliedNodeFormatInterop1.js new file mode 100644 index 0000000000000..8f57e8dce3d80 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatInterop1.js @@ -0,0 +1,30 @@ +//// [tests/cases/compiler/impliedNodeFormatInterop1.ts] //// + +//// [package.json] +{ + "name": "highlight.js", + "type": "commonjs", + "types": "index.d.ts" +} + +//// [index.d.ts] +declare module "highlight.js" { + export interface HighlightAPI { + highlight(code: string): string; + } + const hljs: HighlightAPI; + export default hljs; +} + +//// [core.d.ts] +import hljs from "highlight.js"; +export default hljs; + +//// [index.ts] +import hljs from "highlight.js/lib/core"; +hljs.highlight("code"); + + +//// [index.js] +import hljs from "highlight.js/lib/core"; +hljs.highlight("code"); diff --git a/tests/baselines/reference/impliedNodeFormatInterop1.symbols b/tests/baselines/reference/impliedNodeFormatInterop1.symbols new file mode 100644 index 0000000000000..15b707874681b --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatInterop1.symbols @@ -0,0 +1,37 @@ +//// [tests/cases/compiler/impliedNodeFormatInterop1.ts] //// + +=== /node_modules/highlight.js/index.d.ts === +declare module "highlight.js" { +>"highlight.js" : Symbol("highlight.js", Decl(index.d.ts, 0, 0)) + + export interface HighlightAPI { +>HighlightAPI : Symbol(HighlightAPI, Decl(index.d.ts, 0, 31)) + + highlight(code: string): string; +>highlight : Symbol(HighlightAPI.highlight, Decl(index.d.ts, 1, 33)) +>code : Symbol(code, Decl(index.d.ts, 2, 14)) + } + const hljs: HighlightAPI; +>hljs : Symbol(hljs, Decl(index.d.ts, 4, 7)) +>HighlightAPI : Symbol(HighlightAPI, Decl(index.d.ts, 0, 31)) + + export default hljs; +>hljs : Symbol(hljs, Decl(index.d.ts, 4, 7)) +} + +=== /node_modules/highlight.js/lib/core.d.ts === +import hljs from "highlight.js"; +>hljs : Symbol(hljs, Decl(core.d.ts, 0, 6)) + +export default hljs; +>hljs : Symbol(hljs, Decl(core.d.ts, 0, 6)) + +=== /index.ts === +import hljs from "highlight.js/lib/core"; +>hljs : Symbol(hljs, Decl(index.ts, 0, 6)) + +hljs.highlight("code"); +>hljs.highlight : Symbol(HighlightAPI.highlight, Decl(index.d.ts, 1, 33)) +>hljs : Symbol(hljs, Decl(index.ts, 0, 6)) +>highlight : Symbol(HighlightAPI.highlight, Decl(index.d.ts, 1, 33)) + diff --git a/tests/baselines/reference/impliedNodeFormatInterop1.types b/tests/baselines/reference/impliedNodeFormatInterop1.types new file mode 100644 index 0000000000000..edf0ac628dde0 --- /dev/null +++ b/tests/baselines/reference/impliedNodeFormatInterop1.types @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/impliedNodeFormatInterop1.ts] //// + +=== /node_modules/highlight.js/index.d.ts === +declare module "highlight.js" { +>"highlight.js" : typeof import("highlight.js") +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + export interface HighlightAPI { + highlight(code: string): string; +>highlight : (code: string) => string +> : ^ ^^ ^^^^^ +>code : string +> : ^^^^^^ + } + const hljs: HighlightAPI; +>hljs : HighlightAPI +> : ^^^^^^^^^^^^ + + export default hljs; +>hljs : HighlightAPI +> : ^^^^^^^^^^^^ +} + +=== /node_modules/highlight.js/lib/core.d.ts === +import hljs from "highlight.js"; +>hljs : import("highlight.js").HighlightAPI +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +export default hljs; +>hljs : import("highlight.js").HighlightAPI +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +=== /index.ts === +import hljs from "highlight.js/lib/core"; +>hljs : import("highlight.js").HighlightAPI +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +hljs.highlight("code"); +>hljs.highlight("code") : string +> : ^^^^^^ +>hljs.highlight : (code: string) => string +> : ^ ^^ ^^^^^ +>hljs : import("highlight.js").HighlightAPI +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>highlight : (code: string) => string +> : ^ ^^ ^^^^^ +>"code" : "code" +> : ^^^^^^ + diff --git a/tests/baselines/reference/modulePreserve4.errors.txt b/tests/baselines/reference/modulePreserve4.errors.txt index fa8baeb0c390d..b94d7b89604a5 100644 --- a/tests/baselines/reference/modulePreserve4.errors.txt +++ b/tests/baselines/reference/modulePreserve4.errors.txt @@ -127,6 +127,9 @@ import g1 from "./g"; // { default: 0 } const g2 = require("./g"); // { default: 0 } +==== /main4.cjs (0 errors) ==== + exports.x = require("./g"); + ==== /dummy.ts (0 errors) ==== export {}; // Silly test harness \ No newline at end of file diff --git a/tests/baselines/reference/modulePreserve4.js b/tests/baselines/reference/modulePreserve4.js index e5e009d628b0c..536f52f3a4897 100644 --- a/tests/baselines/reference/modulePreserve4.js +++ b/tests/baselines/reference/modulePreserve4.js @@ -100,6 +100,9 @@ const f2 = require("./f.cjs"); // { default: 0 } import g1 from "./g"; // { default: 0 } const g2 = require("./g"); // { default: 0 } +//// [main4.cjs] +exports.x = require("./g"); + //// [dummy.ts] export {}; // Silly test harness @@ -185,6 +188,8 @@ import f1 from "./f.cjs"; // 0 const f2 = require("./f.cjs"); // { default: 0 } import g1 from "./g"; // { default: 0 } const g2 = require("./g"); // { default: 0 } +//// [main4.cjs] +exports.x = require("./g"); //// [dummy.js] export {}; // Silly test harness @@ -217,5 +222,7 @@ export {}; export {}; //// [main3.d.cts] export {}; +//// [main4.d.cts] +export const x: typeof import("./g"); //// [dummy.d.ts] export {}; diff --git a/tests/baselines/reference/modulePreserve4.symbols b/tests/baselines/reference/modulePreserve4.symbols index 05a7671af0235..e9b29a585d546 100644 --- a/tests/baselines/reference/modulePreserve4.symbols +++ b/tests/baselines/reference/modulePreserve4.symbols @@ -256,6 +256,14 @@ const g2 = require("./g"); // { default: 0 } >require : Symbol(require) >"./g" : Symbol(g1, Decl(g.js, 0, 0)) +=== /main4.cjs === +exports.x = require("./g"); +>exports.x : Symbol(x, Decl(main4.cjs, 0, 0)) +>exports : Symbol(x, Decl(main4.cjs, 0, 0)) +>x : Symbol(x, Decl(main4.cjs, 0, 0)) +>require : Symbol(require) +>"./g" : Symbol("/g", Decl(g.js, 0, 0)) + === /dummy.ts === export {}; // Silly test harness diff --git a/tests/baselines/reference/modulePreserve4.types b/tests/baselines/reference/modulePreserve4.types index 6d00a2d954e7a..ed61a6e2d5284 100644 --- a/tests/baselines/reference/modulePreserve4.types +++ b/tests/baselines/reference/modulePreserve4.types @@ -441,6 +441,23 @@ const g2 = require("./g"); // { default: 0 } >"./g" : "./g" > : ^^^^^ +=== /main4.cjs === +exports.x = require("./g"); +>exports.x = require("./g") : typeof import("/g") +> : ^^^^^^^^^^^^^^^^^^^ +>exports.x : typeof import("/g") +> : ^^^^^^^^^^^^^^^^^^^ +>exports : typeof import("/main4") +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>x : typeof import("/g") +> : ^^^^^^^^^^^^^^^^^^^ +>require("./g") : typeof import("/g") +> : ^^^^^^^^^^^^^^^^^^^ +>require : any +> : ^^^ +>"./g" : "./g" +> : ^^^^^ + === /dummy.ts === export {}; // Silly test harness diff --git a/tests/baselines/reference/nestedPackageJsonRedirect(moduleresolution=bundler).trace.json b/tests/baselines/reference/nestedPackageJsonRedirect(moduleresolution=bundler).trace.json index a6d17c4961116..7fc8b8ccbdea9 100644 --- a/tests/baselines/reference/nestedPackageJsonRedirect(moduleresolution=bundler).trace.json +++ b/tests/baselines/reference/nestedPackageJsonRedirect(moduleresolution=bundler).trace.json @@ -1,7 +1,7 @@ [ "======== Resolving module '@restart/hooks/useMergedRefs' from '/main.ts'. ========", "Explicitly specified module resolution kind: 'Bundler'.", - "Resolving in CJS mode with conditions 'import', 'types'.", + "Resolving in CJS mode with conditions 'require', 'types'.", "File '/package.json' does not exist.", "Loading module '@restart/hooks/useMergedRefs' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.", "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", diff --git a/tests/baselines/reference/nodeModulesDeclarationEmitDynamicImportWithPackageExports.js b/tests/baselines/reference/nodeModulesDeclarationEmitDynamicImportWithPackageExports.js index e790961aa706e..3afe5f2a3f639 100644 --- a/tests/baselines/reference/nodeModulesDeclarationEmitDynamicImportWithPackageExports.js +++ b/tests/baselines/reference/nodeModulesDeclarationEmitDynamicImportWithPackageExports.js @@ -157,8 +157,8 @@ export declare const e: typeof import("inner/mjs"); export declare const a: Promise<{ default: typeof import("./index.cjs"); }>; -export declare const b: Promise; -export declare const c: Promise; +export declare const b: Promise; +export declare const c: Promise; export declare const f: Promise<{ default: typeof import("inner"); cjsMain: true; diff --git a/tests/baselines/reference/nodeNextModuleResolution1.js b/tests/baselines/reference/nodeNextModuleResolution1.js index d76bd3acd7fb6..a006d7840c307 100644 --- a/tests/baselines/reference/nodeNextModuleResolution1.js +++ b/tests/baselines/reference/nodeNextModuleResolution1.js @@ -15,5 +15,4 @@ import {x} from "foo"; //// [app.js] -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +export {}; diff --git a/tests/baselines/reference/nodeNextModuleResolution2.js b/tests/baselines/reference/nodeNextModuleResolution2.js index 19475675a566b..e57c0f2575603 100644 --- a/tests/baselines/reference/nodeNextModuleResolution2.js +++ b/tests/baselines/reference/nodeNextModuleResolution2.js @@ -16,5 +16,4 @@ import {x} from "foo"; //// [app.mjs] -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +export {}; diff --git a/tests/baselines/reference/resolvesWithoutExportsDiagnostic1(moduleresolution=bundler).errors.txt b/tests/baselines/reference/resolvesWithoutExportsDiagnostic1(moduleresolution=bundler).errors.txt index befdfb5cd9df7..fe904ca69530b 100644 --- a/tests/baselines/reference/resolvesWithoutExportsDiagnostic1(moduleresolution=bundler).errors.txt +++ b/tests/baselines/reference/resolvesWithoutExportsDiagnostic1(moduleresolution=bundler).errors.txt @@ -1,4 +1,3 @@ -error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. error TS6504: File '/node_modules/bar/index.js' is a JavaScript file. Did you mean to enable the 'allowJs' option? The file is in the program because: Root file specified for compilation @@ -17,7 +16,6 @@ error TS6504: File '/node_modules/foo/index.mjs' is a JavaScript file. Did you m There are types at '/node_modules/@types/bar/index.d.ts', but this result could not be resolved when respecting package.json "exports". The '@types/bar' library may need to update its package.json or typings. -!!! error TS5095: Option 'bundler' can only be used when 'module' is set to 'preserve' or to 'es2015' or later. !!! error TS6504: File '/node_modules/bar/index.js' is a JavaScript file. Did you mean to enable the 'allowJs' option? !!! error TS6504: The file is in the program because: !!! error TS6504: Root file specified for compilation diff --git a/tests/baselines/reference/tsc/moduleResolution/alternateResult.js b/tests/baselines/reference/tsc/moduleResolution/alternateResult.js index c4cd0a925744b..2baf46187b384 100644 --- a/tests/baselines/reference/tsc/moduleResolution/alternateResult.js +++ b/tests/baselines/reference/tsc/moduleResolution/alternateResult.js @@ -383,7 +383,7 @@ Shape signatures in builder refreshed for:: //// [/home/src/projects/project/index.mjs] "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +export {}; //// [/home/src/projects/project/tsconfig.tsbuildinfo] diff --git a/tests/baselines/reference/tsc/projectReferences/default-import-interop-uses-referenced-project-settings.js b/tests/baselines/reference/tsc/projectReferences/default-import-interop-uses-referenced-project-settings.js new file mode 100644 index 0000000000000..cae334db82e54 --- /dev/null +++ b/tests/baselines/reference/tsc/projectReferences/default-import-interop-uses-referenced-project-settings.js @@ -0,0 +1,95 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Input:: +//// [/app/src/index.ts] + + import local from "./local"; // Error + import esm from "esm-package"; // Error + import referencedSource from "../../lib/src/a"; // Error + import referencedDeclaration from "../../lib/dist/a"; // Error + import ambiguous from "ambiguous-package"; // Ok + +//// [/app/src/local.ts] +export const local = 0; + +//// [/app/tsconfig.json] +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "rootDir": "src", + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../lib" + } + ] +} + +//// [/lib/dist/a.d.ts] +export declare const a = 0; + +//// [/lib/lib.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; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + +//// [/lib/src/a.ts] +export const a = 0; + +//// [/lib/tsconfig.json] +{ + "compilerOptions": { + "composite": true, + "declaration": true, + "rootDir": "src", + "outDir": "dist", + "module": "esnext", + "moduleResolution": "bundler" + }, + "include": [ + "src" + ] +} + +//// [/node_modules/ambiguous-package/index.d.ts] +export declare const ambiguous: number; + +//// [/node_modules/ambiguous-package/package.json] +{ "name": "ambiguous-package" } + +//// [/node_modules/esm-package/index.d.ts] +export declare const esm: number; + +//// [/node_modules/esm-package/package.json] +{ "name": "esm-package", "type": "module" } + + + +Output:: +/lib/tsc --p app --pretty false +app/src/index.ts(2,28): error TS2613: Module '"/app/src/local"' has no default export. Did you mean to use 'import { local } from "/app/src/local"' instead? +exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated + + +//// [/app/dist/index.js] +export {}; + + +//// [/app/dist/local.js] +export var local = 0; + + diff --git a/tests/baselines/reference/tscWatch/forceConsistentCasingInFileNames/with-nodeNext-resolution.js b/tests/baselines/reference/tscWatch/forceConsistentCasingInFileNames/with-nodeNext-resolution.js index 7b5d8c6952e42..d59303ac57b12 100644 --- a/tests/baselines/reference/tscWatch/forceConsistentCasingInFileNames/with-nodeNext-resolution.js +++ b/tests/baselines/reference/tscWatch/forceConsistentCasingInFileNames/with-nodeNext-resolution.js @@ -111,10 +111,8 @@ File '/package.json' does not exist according to earlier cached lookups. node_modules/@types/yargs/index.d.ts Imported via "yargs" from file 'src/bin.ts' with packageId 'yargs/index.d.ts@17.0.12' Entry point for implicit type library 'yargs' with packageId 'yargs/index.d.ts@17.0.12' - File is CommonJS module because 'node_modules/@types/yargs/package.json' does not have field "type" src/bin.ts Matched by default include pattern '**/*' - File is CommonJS module because 'package.json' was not found [HH:MM:SS AM] Found 1 error. Watching for file changes. diff --git a/tests/baselines/reference/tscWatch/moduleResolution/alternateResult.js b/tests/baselines/reference/tscWatch/moduleResolution/alternateResult.js index c9a1190333dc7..4d607e1c55178 100644 --- a/tests/baselines/reference/tscWatch/moduleResolution/alternateResult.js +++ b/tests/baselines/reference/tscWatch/moduleResolution/alternateResult.js @@ -375,7 +375,7 @@ Elapsed:: *ms DirectoryWatcher:: Triggered with /home/src/projects/project/tscon //// [/home/src/projects/project/index.mjs] "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +export {}; //// [/home/src/projects/project/tsconfig.tsbuildinfo] diff --git a/tests/baselines/reference/tscWatch/moduleResolution/diagnostics-from-cache.js b/tests/baselines/reference/tscWatch/moduleResolution/diagnostics-from-cache.js index 5ed903115a938..de2f785e9c58a 100644 --- a/tests/baselines/reference/tscWatch/moduleResolution/diagnostics-from-cache.js +++ b/tests/baselines/reference/tscWatch/moduleResolution/diagnostics-from-cache.js @@ -80,12 +80,9 @@ File '/package.json' does not exist. //// [/user/username/projects/myproject/dist/index.js] -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.thing = thing; -var me = require("@this/package"); +import * as me from "@this/package"; me.thing(); -function thing() { } +export function thing() { } //// [/user/username/projects/myproject/types/index.d.ts] @@ -93,10 +90,7 @@ export declare function thing(): void; //// [/user/username/projects/myproject/dist/index2.js] -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.thing = thing; -function thing() { } +export function thing() { } //// [/user/username/projects/myproject/types/index2.d.ts] diff --git a/tests/baselines/reference/tsserver/fourslashServer/completionsImport_jsModuleExportsAssignment.js b/tests/baselines/reference/tsserver/fourslashServer/completionsImport_jsModuleExportsAssignment.js index 1f718c607011b..6a8dc8740d6a9 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/completionsImport_jsModuleExportsAssignment.js +++ b/tests/baselines/reference/tsserver/fourslashServer/completionsImport_jsModuleExportsAssignment.js @@ -395,7 +395,7 @@ Info seq [hh:mm:ss:mss] getCompletionData: Is inside comment: * Info seq [hh:mm:ss:mss] getCompletionData: Get previous token: * Info seq [hh:mm:ss:mss] getExportInfoMap: cache miss or empty; calculating new results Info seq [hh:mm:ss:mss] getExportInfoMap: done in * ms -Info seq [hh:mm:ss:mss] collectAutoImports: resolved 0 module specifiers, plus 0 ambient and 3 from cache +Info seq [hh:mm:ss:mss] collectAutoImports: resolved 0 module specifiers, plus 0 ambient and 4 from cache Info seq [hh:mm:ss:mss] collectAutoImports: response is incomplete Info seq [hh:mm:ss:mss] collectAutoImports: * Info seq [hh:mm:ss:mss] getCompletionData: Semantic work: * @@ -1068,6 +1068,19 @@ Info seq [hh:mm:ss:mss] response: "fileName": "/third_party/marked/src/defaults.js" } }, + { + "name": "defaults", + "kind": "property", + "kindModifiers": "", + "sortText": "16", + "hasAction": true, + "source": "/third_party/marked/src/defaults", + "data": { + "exportName": "export=", + "exportMapKey": "8 * defaults ", + "fileName": "/third_party/marked/src/defaults.js" + } + }, { "name": "defaults", "kind": "alias", @@ -1288,7 +1301,7 @@ Info seq [hh:mm:ss:mss] getCompletionData: Get current token: * Info seq [hh:mm:ss:mss] getCompletionData: Is inside comment: * Info seq [hh:mm:ss:mss] getCompletionData: Get previous token: * Info seq [hh:mm:ss:mss] getExportInfoMap: cache hit -Info seq [hh:mm:ss:mss] collectAutoImports: resolved 0 module specifiers, plus 0 ambient and 3 from cache +Info seq [hh:mm:ss:mss] collectAutoImports: resolved 0 module specifiers, plus 0 ambient and 4 from cache Info seq [hh:mm:ss:mss] collectAutoImports: response is incomplete Info seq [hh:mm:ss:mss] collectAutoImports: * Info seq [hh:mm:ss:mss] getCompletionData: Semantic work: * @@ -1974,6 +1987,19 @@ Info seq [hh:mm:ss:mss] response: "fileName": "/third_party/marked/src/defaults.js" } }, + { + "name": "defaults", + "kind": "property", + "kindModifiers": "", + "sortText": "16", + "hasAction": true, + "source": "/third_party/marked/src/defaults", + "data": { + "exportName": "export=", + "exportMapKey": "8 * defaults ", + "fileName": "/third_party/marked/src/defaults.js" + } + }, { "name": "defaults", "kind": "alias", diff --git a/tests/baselines/reference/tsserver/moduleResolution/alternateResult.js b/tests/baselines/reference/tsserver/moduleResolution/alternateResult.js index d4ef9a801e623..7cf87089f7d8e 100644 --- a/tests/baselines/reference/tsserver/moduleResolution/alternateResult.js +++ b/tests/baselines/reference/tsserver/moduleResolution/alternateResult.js @@ -394,10 +394,8 @@ Info seq [hh:mm:ss:mss] Files (4) Default library for target 'es5' node_modules/foo2/index.d.ts Imported via "foo2" from file 'index.mts' with packageId 'foo2/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/foo2/package.json' does not have field "type" node_modules/@types/bar2/index.d.ts Imported via "bar2" from file 'index.mts' with packageId '@types/bar2/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/@types/bar2/package.json' does not have field "type" index.mts Part of 'files' list in tsconfig.json @@ -2157,13 +2155,10 @@ Info seq [hh:mm:ss:mss] Files (5) Default library for target 'es5' node_modules/@types/bar/index.d.ts Imported via "bar" from file 'index.mts' with packageId '@types/bar/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/@types/bar/package.json' does not have field "type" node_modules/foo2/index.d.ts Imported via "foo2" from file 'index.mts' with packageId 'foo2/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/foo2/package.json' does not have field "type" node_modules/@types/bar2/index.d.ts Imported via "bar2" from file 'index.mts' with packageId '@types/bar2/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/@types/bar2/package.json' does not have field "type" index.mts Part of 'files' list in tsconfig.json @@ -2480,16 +2475,12 @@ Info seq [hh:mm:ss:mss] Files (6) Default library for target 'es5' node_modules/foo/index.d.ts Imported via "foo" from file 'index.mts' with packageId 'foo/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/foo/package.json' does not have field "type" node_modules/@types/bar/index.d.ts Imported via "bar" from file 'index.mts' with packageId '@types/bar/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/@types/bar/package.json' does not have field "type" node_modules/foo2/index.d.ts Imported via "foo2" from file 'index.mts' with packageId 'foo2/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/foo2/package.json' does not have field "type" node_modules/@types/bar2/index.d.ts Imported via "bar2" from file 'index.mts' with packageId '@types/bar2/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/@types/bar2/package.json' does not have field "type" index.mts Part of 'files' list in tsconfig.json @@ -2874,13 +2865,10 @@ Info seq [hh:mm:ss:mss] Files (5) Default library for target 'es5' node_modules/foo/index.d.ts Imported via "foo" from file 'index.mts' with packageId 'foo/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/foo/package.json' does not have field "type" node_modules/@types/bar/index.d.ts Imported via "bar" from file 'index.mts' with packageId '@types/bar/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/@types/bar/package.json' does not have field "type" node_modules/foo2/index.d.ts Imported via "foo2" from file 'index.mts' with packageId 'foo2/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/foo2/package.json' does not have field "type" index.mts Part of 'files' list in tsconfig.json @@ -3253,10 +3241,8 @@ Info seq [hh:mm:ss:mss] Files (4) Default library for target 'es5' node_modules/foo/index.d.ts Imported via "foo" from file 'index.mts' with packageId 'foo/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/foo/package.json' does not have field "type" node_modules/@types/bar/index.d.ts Imported via "bar" from file 'index.mts' with packageId '@types/bar/index.d.ts@1.0.0' - File is CommonJS module because 'node_modules/@types/bar/package.json' does not have field "type" index.mts Part of 'files' list in tsconfig.json diff --git a/tests/cases/compiler/esmNoSynthesizedDefault.ts b/tests/cases/compiler/esmNoSynthesizedDefault.ts new file mode 100644 index 0000000000000..17fcea5f883c2 --- /dev/null +++ b/tests/cases/compiler/esmNoSynthesizedDefault.ts @@ -0,0 +1,18 @@ +// @target: esnext +// @module: preserve, esnext +// @moduleResolution: bundler + +// @Filename: /node_modules/mdast-util-to-string/package.json +{ "type": "module" } + +// @Filename: /node_modules/mdast-util-to-string/index.d.ts +export function toString(): string; + +// @Filename: /index.ts +import mdast, { toString } from 'mdast-util-to-string'; +mdast; +mdast.toString(); + +const mdast2 = await import('mdast-util-to-string'); +mdast2.toString(); +mdast2.default; diff --git a/tests/cases/compiler/impliedNodeFormatEmit1.ts b/tests/cases/compiler/impliedNodeFormatEmit1.ts new file mode 100644 index 0000000000000..6fd41c8c32ac4 --- /dev/null +++ b/tests/cases/compiler/impliedNodeFormatEmit1.ts @@ -0,0 +1,39 @@ +// @allowJs: true +// @checkJs: true +// @outDir: dist +// @module: esnext, commonjs, amd, system, umd, preserve +// @moduleResolution: bundler +// @noTypesAndSymbols: true + +// @Filename: /a.ts +export const _ = 0; + +// @Filename: /b.mts +export const _ = 0; + +// @Filename: /c.cts +export const _ = 0; + +// @Filename: /d.js +export const _ = 0; + +// @Filename: /e.mjs +export const _ = 0; + +// @Filename: /f.mjs +export const _ = 0; + +// @Filename: /g.ts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /h.mts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /i.cts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /dummy.ts +export {}; diff --git a/tests/cases/compiler/impliedNodeFormatEmit2.ts b/tests/cases/compiler/impliedNodeFormatEmit2.ts new file mode 100644 index 0000000000000..851fbd748a790 --- /dev/null +++ b/tests/cases/compiler/impliedNodeFormatEmit2.ts @@ -0,0 +1,42 @@ +// @allowJs: true +// @checkJs: true +// @outDir: dist +// @module: esnext, commonjs, preserve +// @moduleResolution: bundler +// @noTypesAndSymbols: true + +// @Filename: /package.json +{} + +// @Filename: /a.ts +export const _ = 0; + +// @Filename: /b.mts +export const _ = 0; + +// @Filename: /c.cts +export const _ = 0; + +// @Filename: /d.js +export const _ = 0; + +// @Filename: /e.mjs +export const _ = 0; + +// @Filename: /f.mjs +export const _ = 0; + +// @Filename: /g.ts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /h.mts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /i.cts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /dummy.ts +export {}; diff --git a/tests/cases/compiler/impliedNodeFormatEmit3.ts b/tests/cases/compiler/impliedNodeFormatEmit3.ts new file mode 100644 index 0000000000000..459d542e26e0d --- /dev/null +++ b/tests/cases/compiler/impliedNodeFormatEmit3.ts @@ -0,0 +1,44 @@ +// @allowJs: true +// @checkJs: true +// @outDir: dist +// @module: esnext, commonjs, preserve +// @moduleResolution: bundler +// @noTypesAndSymbols: true + +// @Filename: /package.json +{ + "type": "module" +} + +// @Filename: /a.ts +export const _ = 0; + +// @Filename: /b.mts +export const _ = 0; + +// @Filename: /c.cts +export const _ = 0; + +// @Filename: /d.js +export const _ = 0; + +// @Filename: /e.mjs +export const _ = 0; + +// @Filename: /f.mjs +export const _ = 0; + +// @Filename: /g.ts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /h.mts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /i.cts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /dummy.ts +export {}; diff --git a/tests/cases/compiler/impliedNodeFormatEmit4.ts b/tests/cases/compiler/impliedNodeFormatEmit4.ts new file mode 100644 index 0000000000000..769510c6c0ce9 --- /dev/null +++ b/tests/cases/compiler/impliedNodeFormatEmit4.ts @@ -0,0 +1,44 @@ +// @allowJs: true +// @checkJs: true +// @outDir: dist +// @module: esnext, commonjs, preserve +// @moduleResolution: bundler +// @noTypesAndSymbols: true + +// @Filename: /package.json +{ + "type": "commonjs" +} + +// @Filename: /a.ts +export const _ = 0; + +// @Filename: /b.mts +export const _ = 0; + +// @Filename: /c.cts +export const _ = 0; + +// @Filename: /d.js +export const _ = 0; + +// @Filename: /e.mjs +export const _ = 0; + +// @Filename: /f.mjs +export const _ = 0; + +// @Filename: /g.ts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /h.mts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /i.cts +import {} from "./a"; +import a = require("./a"); + +// @Filename: /dummy.ts +export {}; diff --git a/tests/cases/compiler/impliedNodeFormatInterop1.ts b/tests/cases/compiler/impliedNodeFormatInterop1.ts new file mode 100644 index 0000000000000..c4e18c0ddc0e9 --- /dev/null +++ b/tests/cases/compiler/impliedNodeFormatInterop1.ts @@ -0,0 +1,27 @@ +// @module: es2020 +// @moduleResolution: node10 +// @esModuleInterop: true + +// @Filename: /node_modules/highlight.js/package.json +{ + "name": "highlight.js", + "type": "commonjs", + "types": "index.d.ts" +} + +// @Filename: /node_modules/highlight.js/index.d.ts +declare module "highlight.js" { + export interface HighlightAPI { + highlight(code: string): string; + } + const hljs: HighlightAPI; + export default hljs; +} + +// @Filename: /node_modules/highlight.js/lib/core.d.ts +import hljs from "highlight.js"; +export default hljs; + +// @Filename: /index.ts +import hljs from "highlight.js/lib/core"; +hljs.highlight("code"); diff --git a/tests/cases/compiler/modulePreserve4.ts b/tests/cases/compiler/modulePreserve4.ts index 9eabe664bb88c..9a7014852eefa 100644 --- a/tests/cases/compiler/modulePreserve4.ts +++ b/tests/cases/compiler/modulePreserve4.ts @@ -106,5 +106,8 @@ const f2 = require("./f.cjs"); // { default: 0 } import g1 from "./g"; // { default: 0 } const g2 = require("./g"); // { default: 0 } +// @Filename: /main4.cjs +exports.x = require("./g"); + // @Filename: /dummy.ts export {}; // Silly test harness diff --git a/tests/cases/conformance/moduleResolution/conditionalExportsResolutionFallback.ts b/tests/cases/conformance/moduleResolution/conditionalExportsResolutionFallback.ts index d9a1d480b8ef3..26fe08e88fb11 100644 --- a/tests/cases/conformance/moduleResolution/conditionalExportsResolutionFallback.ts +++ b/tests/cases/conformance/moduleResolution/conditionalExportsResolutionFallback.ts @@ -1,3 +1,4 @@ +// @module: esnext // @moduleResolution: node16,nodenext,bundler // @traceResolution: true // @allowJs: true diff --git a/tests/cases/conformance/moduleResolution/customConditions.ts b/tests/cases/conformance/moduleResolution/customConditions.ts index 47fb048ac28bf..0533574c6c230 100644 --- a/tests/cases/conformance/moduleResolution/customConditions.ts +++ b/tests/cases/conformance/moduleResolution/customConditions.ts @@ -1,3 +1,4 @@ +// @module: preserve // @moduleResolution: bundler // @customConditions: webpack, browser // @resolvePackageJsonExports: true, false diff --git a/tests/cases/conformance/moduleResolution/resolvesWithoutExportsDiagnostic1.ts b/tests/cases/conformance/moduleResolution/resolvesWithoutExportsDiagnostic1.ts index d01bb47a75ca8..57430c902655d 100644 --- a/tests/cases/conformance/moduleResolution/resolvesWithoutExportsDiagnostic1.ts +++ b/tests/cases/conformance/moduleResolution/resolvesWithoutExportsDiagnostic1.ts @@ -1,3 +1,4 @@ +// @module: preserve // @moduleResolution: bundler,node16 // @strict: true // @noTypesAndSymbols: true diff --git a/tests/cases/fourslash/completionsImport_reExportDefault2.ts b/tests/cases/fourslash/completionsImport_reExportDefault2.ts new file mode 100644 index 0000000000000..85975f7f0d6ca --- /dev/null +++ b/tests/cases/fourslash/completionsImport_reExportDefault2.ts @@ -0,0 +1,39 @@ +/// + +// @module: preserve +// @checkJs: true + +// @Filename: /node_modules/example/package.json +//// { "name": "example", "version": "1.0.0", "main": "dist/index.js" } + +// @Filename: /node_modules/example/dist/nested/module.d.ts +//// declare const defaultExport: () => void; +//// declare const namedExport: () => void; +//// +//// export default defaultExport; +//// export { namedExport }; + +// @Filename: /node_modules/example/dist/index.d.ts +//// export { default, namedExport } from "./nested/module"; + +// @Filename: /index.mjs +//// import { namedExport } from "example"; +//// defaultExp/**/ + +verify.completions({ + marker: "", + exact: completion.globalsInJsPlus([ + "namedExport", + { + name: "defaultExport", + source: "example", + sourceDisplay: "example", + hasAction: true, + sortText: completion.SortText.AutoImportSuggestions + }, + ]), + preferences: { + includeCompletionsForModuleExports: true, + allowIncompleteCompletions: true, + }, +}); \ No newline at end of file