diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7a6aaa1861859..b55edb31276eb 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -248,6 +248,16 @@ namespace ts { if (!file.locals) { bind(file); + // `bindSourceFileAsExternalModule` is called in `setCommonJsModuleIndicator`, + // but if `setCommonJsModuleIndicator` was not called, as it won't be for `.cjs` + // files with no imports or exports, then `bindSourceFileAsExternalModule` + // will not have been called, which would cause the checker to crash. + + // This also can't be moved to `bindSourceFileIfExternalModule`, + // as that gets called after CommonJS exports are bound. + if (isCommonJsModule(file) && !file.commonJsModuleIndicator) { + bindSourceFileAsExternalModule(); + } file.symbolCount = symbolCount; file.classifiableNames = classifiableNames; delayedBindJSDocTypedefTag(); @@ -283,7 +293,7 @@ namespace ts { return true; } else { - return !!file.externalModuleIndicator; + return isExternalModule(file); } } @@ -2154,7 +2164,7 @@ namespace ts { return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; } - if (file.externalModuleIndicator) { + if (isExternalModule(file)) { return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; } @@ -2223,7 +2233,7 @@ namespace ts { return Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; } - if (file.externalModuleIndicator) { + if (isExternalModule(file)) { return Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; } @@ -2244,7 +2254,7 @@ namespace ts { return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; } - if (file.externalModuleIndicator) { + if (isExternalModule(file)) { return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; } @@ -2460,7 +2470,7 @@ namespace ts { bindSpecialPropertyDeclaration(expr); } if (isInJSFile(expr) && - file.commonJsModuleIndicator && + isCommonJsModule(file) && isModuleExportsAccessExpression(expr) && !lookupSymbolForNameWorker(blockScopeContainer, "module" as __String)) { declareSymbol(file.locals!, /*parent*/ undefined, expr.expression, @@ -2743,7 +2753,7 @@ namespace ts { } function setCommonJsModuleIndicator(node: Node) { - if (file.externalModuleIndicator) { + if (isExternalModule(file)) { return false; } if (!file.commonJsModuleIndicator) { @@ -2866,7 +2876,7 @@ namespace ts { if (hasDynamicName(node)) { break; } - else if ((thisContainer as SourceFile).commonJsModuleIndicator) { + else if (isCommonJsModule(thisContainer as SourceFile)) { declareSymbol(thisContainer.symbol.exports!, thisContainer.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None); } else { @@ -3133,7 +3143,7 @@ namespace ts { function bindCallExpression(node: CallExpression) { // We're only inspecting call expressions to detect CommonJS modules, so we can skip // this check if we've already seen the module indicator - if (!file.commonJsModuleIndicator && isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ false)) { + if (!file.commonJsModuleIndicator && !fileExtensionIs(file.fileName, Extension.Mjs) && isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ false)) { setCommonJsModuleIndicator(node); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62994a8f464dd..c403f9a660a2c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1382,7 +1382,7 @@ namespace ts { const useFile = getSourceFileOfNode(usage); const declContainer = getEnclosingBlockScopeContainer(declaration); if (declarationFile !== useFile) { - if ((moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || + if ((moduleKind && (isExternalModule(declarationFile) || isExternalModule(useFile))) || (!outFile(compilerOptions)) || isInTypeQuery(usage) || declaration.flags & NodeFlags.Ambient) { @@ -1717,7 +1717,7 @@ namespace ts { isInExternalModule = true; // falls through case SyntaxKind.ModuleDeclaration: - const moduleExports = getSymbolOfNode(location as SourceFile | ModuleDeclaration).exports || emptySymbols; + const moduleExports = getSymbolOfNode(location as SourceFile | ModuleDeclaration)?.exports || emptySymbols; if (location.kind === SyntaxKind.SourceFile || (isModuleDeclaration(location) && location.flags & NodeFlags.Ambient && !isGlobalScopeAugmentation(location))) { // It's an external module. First see if the module has an export default and if the local @@ -1751,7 +1751,7 @@ namespace ts { // ES6 exports are also visible locally (except for 'default'), but commonjs exports are not (except typedefs) if (name !== InternalSymbolName.Default && (result = lookup(moduleExports, name, meaning & SymbolFlags.ModuleMember))) { - if (isSourceFile(location) && location.commonJsModuleIndicator && !result.declarations.some(isJSDocTypeAlias)) { + if (isSourceFile(location) && isCommonJsModule(location) && !result.declarations.some(isJSDocTypeAlias)) { result = undefined; } else { @@ -1945,7 +1945,7 @@ namespace ts { if (!result) { if (lastLocation) { Debug.assert(lastLocation.kind === SyntaxKind.SourceFile); - if ((lastLocation as SourceFile).commonJsModuleIndicator && name === "exports" && meaning & lastLocation.symbol.flags) { + if (isCommonJsModule(lastLocation as SourceFile) && name === "exports" && meaning & lastLocation.symbol.flags) { return lastLocation.symbol; } } @@ -2467,7 +2467,7 @@ namespace ts { return hasExportAssignmentSymbol(moduleSymbol); } // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker - return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias); + return !isExternalModule(file) && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias); } function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol | undefined { @@ -8568,7 +8568,7 @@ namespace ts { declaration.parent.kind === SyntaxKind.BinaryExpression)) { return getWidenedTypeForAssignmentDeclaration(symbol); } - else if (symbol.flags & SymbolFlags.ValueModule && declaration && isSourceFile(declaration) && declaration.commonJsModuleIndicator) { + else if (symbol.flags & SymbolFlags.ValueModule && declaration && isSourceFile(declaration) && isCommonJsModule(declaration)) { const resolvedModule = resolveExternalModuleSymbol(symbol); if (resolvedModule !== symbol) { if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { @@ -22523,11 +22523,11 @@ namespace ts { if (isSourceFile(container)) { // look up in the source file's locals or exports - if (container.commonJsModuleIndicator) { + if (isCommonJsModule(container)) { const fileSymbol = getSymbolOfNode(container); return fileSymbol && getTypeOfSymbol(fileSymbol); } - else if (container.externalModuleIndicator) { + else if (isExternalModule(container)) { // TODO: Maybe issue a better error than 'object is possibly undefined' return undefinedType; } @@ -22893,7 +22893,7 @@ namespace ts { // Don't contextually type `this` as `exports` in `exports.Point = function(x, y) { this.x = x; this.y = y; }` if (inJs && isIdentifier(expression)) { const sourceFile = getSourceFileOfNode(parent); - if (sourceFile.commonJsModuleIndicator && getResolvedSymbol(expression) === sourceFile.symbol) { + if (isCommonJsModule(sourceFile) && getResolvedSymbol(expression) === sourceFile.symbol) { return undefined; } } @@ -27788,12 +27788,18 @@ namespace ts { } function checkImportMetaProperty(node: MetaProperty) { - if (moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.System) { - error(node, Diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_esnext_or_system); - } const file = getSourceFileOfNode(node); + if (fileExtensionIs(file.fileName, Extension.Cjs)) { + error(node, Diagnostics.The_import_meta_meta_property_is_not_allowed_in_CommonJS_module_files); + Debug.assert(file.externalModuleIndicator === undefined, "Containing `.cjs` file should not be a module."); + } + else { + if (moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.System) { + error(node, Diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_esnext_or_system); + } + Debug.assert(!!file.externalModuleIndicator, "Containing file should be a module."); + } Debug.assert(!!(file.flags & NodeFlags.PossiblyContainsImportMeta), "Containing file is missing import meta node flag."); - Debug.assert(!!file.externalModuleIndicator, "Containing file should be a module."); return node.name.escapedText === "meta" ? getGlobalImportMetaType() : errorType; } @@ -35466,7 +35472,8 @@ namespace ts { } function checkGrammarModuleElementContext(node: Statement, errorMessage: DiagnosticMessage): boolean { - const isInAppropriateContext = node.parent.kind === SyntaxKind.SourceFile || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.ModuleDeclaration; + const isInAppropriateContext = (node.parent.kind === SyntaxKind.SourceFile && !fileExtensionIs((node.parent).fileName, Extension.Cjs)) + || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.ModuleDeclaration; if (!isInAppropriateContext) { grammarErrorOnFirstToken(node, errorMessage); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 82f3cb4ce579b..5ae62939a24d3 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1180,6 +1180,10 @@ "category": "Error", "code": 1388 }, + "The 'import.meta' meta-property is not allowed in CommonJS module files.": { + "category": "Error", + "code": 1389 + }, "The types of '{0}' are incompatible between these types.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index f976c38ea6af8..54ef9a6d29ca0 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -116,9 +116,11 @@ namespace ts { return Extension.Json; } + const { fileName } = sourceFile; + if (options.jsx === JsxEmit.Preserve) { if (isSourceFileJS(sourceFile)) { - if (fileExtensionIs(sourceFile.fileName, Extension.Jsx)) { + if (fileExtensionIs(fileName, Extension.Jsx)) { return Extension.Jsx; } } @@ -127,6 +129,16 @@ namespace ts { return Extension.Jsx; } } + + // Preserve the output extension for `.cjs` and `.mjs` files + if (fileExtensionIs(fileName, Extension.Cjs)) { + return Extension.Cjs; + } + + if (fileExtensionIs(fileName, Extension.Mjs)) { + return Extension.Mjs; + } + return Extension.Js; } diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index ad331c60be7f2..1610f2def199b 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -65,7 +65,7 @@ namespace ts { */ enum Extensions { TypeScript, /** '.ts', '.tsx', or '.d.ts' */ - JavaScript, /** '.js' or '.jsx' */ + JavaScript, /** '.js', '.cjs', '.mjs' or '.jsx' */ Json, /** '.json' */ TSConfig, /** '.json' with `tsconfig` used instead of `index` */ DtsOnly /** Only '.d.ts' */ @@ -1096,6 +1096,7 @@ namespace ts { case Extensions.TypeScript: return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || tryExtension(Extension.Dts); case Extensions.JavaScript: + // `.cjs` and `.mjs` file extensions must always have the file extension return tryExtension(Extension.Js) || tryExtension(Extension.Jsx); case Extensions.TSConfig: case Extensions.Json: @@ -1235,7 +1236,7 @@ namespace ts { function extensionIsOk(extensions: Extensions, extension: Extension): boolean { switch (extensions) { case Extensions.JavaScript: - return extension === Extension.Js || extension === Extension.Jsx; + return extension === Extension.Js || extension === Extension.Cjs || extension === Extension.Mjs || extension === Extension.Jsx; case Extensions.TSConfig: case Extensions.Json: return extension === Extension.Json; diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 54be63be022fa..edc94b7ff8ac0 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -17,6 +17,10 @@ namespace ts.moduleSpecifiers { ending: getEnding(), }; function getEnding(): Ending { + // `.mjs` files must always use file extensions in import specifiers + if (fileExtensionIs(importingSourceFile.fileName, Extension.Mjs)) { + return Ending.JsExtension; + } switch (importModuleSpecifierEnding) { case "minimal": return Ending.Minimal; case "index": return Ending.Index; @@ -309,6 +313,8 @@ namespace ts.moduleSpecifiers { const relativePath = normalizedSourcePath !== undefined ? ensurePathIsNonModuleName(getRelativePathFromDirectory(normalizedSourcePath, normalizedTargetPath, getCanonicalFileName)) : normalizedTargetPath; return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs ? removeExtensionAndIndexPostFix(relativePath, ending, compilerOptions) + // `.cjs` and `.mjs` files must always be imported with the file extension: + : fileExtensionIsOneOf(relativePath, [Extension.Cjs, Extension.Mjs]) ? relativePath : removeFileExtension(relativePath); } @@ -490,7 +496,8 @@ namespace ts.moduleSpecifiers { } function removeExtensionAndIndexPostFix(fileName: string, ending: Ending, options: CompilerOptions): string { - if (fileExtensionIs(fileName, Extension.Json)) return fileName; + // `.cjs` and `.mjs` files must always be imported with the file extension, as Node doesn't resolve them by default: + if (fileExtensionIsOneOf(fileName, [Extension.Cjs, Extension.Mjs, Extension.Json])) return fileName; const noExtension = removeFileExtension(fileName); switch (ending) { case Ending.Minimal: @@ -513,6 +520,8 @@ namespace ts.moduleSpecifiers { case Extension.Tsx: return options.jsx === JsxEmit.Preserve ? Extension.Jsx : Extension.Js; case Extension.Js: + case Extension.Cjs: + case Extension.Mjs: case Extension.Jsx: case Extension.Json: return ext; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1729e3a810c4a..4cb6e485e1026 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -636,7 +636,11 @@ namespace ts { // See also `isExternalOrCommonJsModule` in utilities.ts export function isExternalModule(file: SourceFile): boolean { - return file.externalModuleIndicator !== undefined; + return file.externalModuleIndicator !== undefined || fileExtensionIs(file.fileName, Extension.Mjs); + } + + export function isCommonJsModule(file: SourceFile): boolean { + return file.commonJsModuleIndicator !== undefined || fileExtensionIs(file.fileName, Extension.Cjs); } // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter @@ -1157,6 +1161,8 @@ namespace ts { // this is quite rare comparing to other nodes and createNode should be as fast as possible let sourceFile = factory.createSourceFile(statements, endOfFileToken, flags); setTextRangePosWidth(sourceFile, 0, sourceText.length); + + sourceFile.fileName = fileName; setExternalModuleIndicator(sourceFile); // If we parsed this as an external module, it may contain top-level await @@ -1168,7 +1174,6 @@ namespace ts { sourceFile.bindDiagnostics = []; sourceFile.bindSuggestionDiagnostics = undefined; sourceFile.languageVersion = languageVersion; - sourceFile.fileName = fileName; sourceFile.languageVariant = getLanguageVariant(scriptKind); sourceFile.isDeclarationFile = isDeclarationFile; sourceFile.scriptKind = scriptKind; @@ -7047,6 +7052,9 @@ namespace ts { } function setExternalModuleIndicator(sourceFile: SourceFile) { + // `.cjs` files are never ECMAScript modules + if (fileExtensionIs(sourceFile.fileName, Extension.Cjs)) return; + // Try to use the first top-level import/export when available, then // fall back to looking for an 'import.meta' somewhere in the tree if necessary. sourceFile.externalModuleIndicator = diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 87f4637258cb0..96ebc35745248 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -3119,7 +3119,10 @@ namespace ts { const languageVersion = options.target || ScriptTarget.ES3; - const firstNonAmbientExternalModuleSourceFile = find(files, f => isExternalModule(f) && !f.isDeclarationFile); + const firstNonAmbientExternalModuleSourceFile = find(files, f => + // This can't use `isExternalModule(f)`, as that can return `.mjs` files that have an undefined `externalModuleIndicator`, + // and `firstNonAmbientExternalModuleSourceFile` is only used for `externalModuleIndicator`. + f.externalModuleIndicator !== undefined && !f.isDeclarationFile); if (options.isolatedModules) { if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES2015) { createDiagnosticForOptionName(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, "isolatedModules", "target"); @@ -3782,6 +3785,8 @@ namespace ts { case Extension.Jsx: return needJsx() || needAllowJs(); case Extension.Js: + case Extension.Cjs: + case Extension.Mjs: return needAllowJs(); case Extension.Json: return needResolveJsonModule(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 30a0dc4e7e952..2858631e42897 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6176,6 +6176,8 @@ namespace ts { Tsx = ".tsx", Dts = ".d.ts", Js = ".js", + Cjs = ".cjs", + Mjs = ".mjs", Jsx = ".jsx", Json = ".json", TsBuildInfo = ".tsbuildinfo" diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index d7c00dbcc14c9..cc1e697132080 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -697,7 +697,7 @@ namespace ts { } export function isEffectiveExternalModule(node: SourceFile, compilerOptions: CompilerOptions) { - return isExternalModule(node) || compilerOptions.isolatedModules || ((getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS) && !!node.commonJsModuleIndicator); + return isExternalModule(node) || compilerOptions.isolatedModules || ((getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS) && isCommonJsModule(node)); } /** @@ -1023,7 +1023,7 @@ namespace ts { } export function isExternalOrCommonJsModule(file: SourceFile): boolean { - return (file.externalModuleIndicator || file.commonJsModuleIndicator) !== undefined; + return (file.externalModuleIndicator || file.commonJsModuleIndicator) !== undefined || fileExtensionIsOneOf(file.fileName || "", [Extension.Mjs, Extension.Cjs]); } @@ -6325,6 +6325,8 @@ namespace ts { const ext = fileName.substr(fileName.lastIndexOf(".")); switch (ext.toLowerCase()) { case Extension.Js: + case Extension.Cjs: + case Extension.Mjs: return ScriptKind.JS; case Extension.Jsx: return ScriptKind.JSX; @@ -6346,8 +6348,8 @@ namespace ts { export const supportedTSExtensionsWithJson: readonly Extension[] = [Extension.Ts, Extension.Tsx, Extension.Dts, Extension.Json]; /** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */ export const supportedTSExtensionsForExtractExtension: readonly Extension[] = [Extension.Dts, Extension.Ts, Extension.Tsx]; - export const supportedJSExtensions: readonly Extension[] = [Extension.Js, Extension.Jsx]; - export const supportedJSAndJsonExtensions: readonly Extension[] = [Extension.Js, Extension.Jsx, Extension.Json]; + export const supportedJSExtensions: readonly Extension[] = [Extension.Js, Extension.Jsx, Extension.Cjs, Extension.Mjs]; + export const supportedJSAndJsonExtensions: readonly Extension[] = [Extension.Js, Extension.Jsx, Extension.Cjs, Extension.Mjs, Extension.Json]; const allSupportedExtensions: readonly Extension[] = [...supportedTSExtensions, ...supportedJSExtensions]; const allSupportedExtensionsWithJson: readonly Extension[] = [...supportedTSExtensions, ...supportedJSExtensions, Extension.Json]; @@ -6451,7 +6453,7 @@ namespace ts { } } - const extensionsToRemove = [Extension.Dts, Extension.Ts, Extension.Js, Extension.Tsx, Extension.Jsx, Extension.Json]; + const extensionsToRemove = [Extension.Dts, Extension.Ts, Extension.Js, Extension.Cjs, Extension.Mjs, Extension.Tsx, Extension.Jsx, Extension.Json]; export function removeFileExtension(path: string): string { for (const ext of extensionsToRemove) { const extensionless = tryRemoveExtension(path, ext); diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 2adcba0a9eec0..e308d9fbf3b8b 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -363,9 +363,8 @@ namespace ts.codefix { } function shouldUseRequire(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean { - return isSourceFileJS(sourceFile) - && !sourceFile.externalModuleIndicator - && (!!sourceFile.commonJsModuleIndicator || getEmitModuleKind(compilerOptions) < ModuleKind.ES2015); + if (!isSourceFileJS(sourceFile) || isExternalModule(sourceFile)) return false; + return isCommonJsModule(sourceFile) || getEmitModuleKind(compilerOptions) < ModuleKind.ES2015; } function getNewImportInfos( diff --git a/src/services/completions.ts b/src/services/completions.ts index 67b9f0d94ce80..6db8c2d0c4fa8 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1442,7 +1442,7 @@ namespace ts.Completions { // If not already a module, must have modules enabled. if (!preferences.includeCompletionsForModuleExports) return false; // If already using ES6 modules, OK to continue using them. - if (sourceFile.externalModuleIndicator || sourceFile.commonJsModuleIndicator) return true; + if (isExternalOrCommonJsModule(sourceFile)) return true; // If module transpilation is enabled or we're targeting es6 or above, or not emitting, OK. if (compilerOptionsIndicateEs6Modules(program.getCompilerOptions())) return true; // If some file is using ES6 modules, assume that it's OK to add more. diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index c2234a891dd67..79d78aec45870 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -481,7 +481,7 @@ namespace ts.refactor.extractSymbol { // falls through case SyntaxKind.ClassDeclaration: case SyntaxKind.FunctionDeclaration: - if (isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) { + if (isSourceFile(node.parent) && !isExternalModule(node.parent)) { // You cannot extract global declarations (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); } @@ -772,7 +772,7 @@ namespace ts.refactor.extractSymbol { function getDescriptionForModuleLikeDeclaration(scope: SourceFile | ModuleBlock): string | SpecialScope { return scope.kind === SyntaxKind.ModuleBlock ? `namespace '${scope.parent.name.getText()}'` - : scope.externalModuleIndicator ? SpecialScope.Module : SpecialScope.Global; + : isExternalModule(scope) ? SpecialScope.Module : SpecialScope.Global; } const enum SpecialScope { diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index fb151d6dba9f3..d1b9d8340d497 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -112,12 +112,12 @@ namespace ts.refactor { ) { const checker = program.getTypeChecker(); - if (!oldFile.externalModuleIndicator && !oldFile.commonJsModuleIndicator) { + if (!isExternalOrCommonJsModule(oldFile)) { deleteMovedStatements(oldFile, toMove.ranges, changes); return toMove.all; } - const useEs6ModuleSyntax = !!oldFile.externalModuleIndicator; + const useEs6ModuleSyntax = isExternalModule(oldFile); const quotePreference = getQuotePreference(oldFile, preferences); const importsFromNewFile = createOldFileImportsFromNewFile(usage.oldFileImportsFromNewFile, newModuleName, useEs6ModuleSyntax, quotePreference); if (importsFromNewFile) { diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index c3473b6251eae..48ad2d3980dd0 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -84,6 +84,8 @@ namespace ts.Completions.StringCompletions { switch (extension) { case Extension.Dts: return ScriptElementKindModifier.dtsModifier; case Extension.Js: return ScriptElementKindModifier.jsModifier; + case Extension.Cjs: return ScriptElementKindModifier.cjsModifier; + case Extension.Mjs: return ScriptElementKindModifier.mjsModifier; case Extension.Json: return ScriptElementKindModifier.jsonModifier; case Extension.Jsx: return ScriptElementKindModifier.jsxModifier; case Extension.Ts: return ScriptElementKindModifier.tsModifier; diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index a8c50322522a1..580f82d10ce7f 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -8,6 +8,8 @@ namespace ts { const checker = program.getTypeChecker(); if (sourceFile.commonJsModuleIndicator && + // ES6 module syntax is illegal in `.cjs` files, which are always CommonJS files + !fileExtensionIs(sourceFile.fileName, Extension.Cjs) && (programContainsEs6Modules(program) || compilerOptionsIndicateEs6Modules(program.getCompilerOptions())) && containsTopLevelCommonjs(sourceFile)) { diags.push(createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module)); diff --git a/src/services/types.ts b/src/services/types.ts index 0ebd80372cbea..1f18f3795cb8c 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -1337,6 +1337,8 @@ namespace ts { dtsModifier = ".d.ts", tsModifier = ".ts", tsxModifier = ".tsx", + cjsModifier = ".cjs", + mjsModifier = ".mjs", jsModifier = ".js", jsxModifier = ".jsx", jsonModifier = ".json", diff --git a/src/services/utilities.ts b/src/services/utilities.ts index c11c65d076dd6..bab3b2039caf3 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1743,10 +1743,10 @@ namespace ts { } export function programContainsModules(program: Program): boolean { - return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!(s.externalModuleIndicator || s.commonJsModuleIndicator)); + return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && isExternalOrCommonJsModule(s)); } export function programContainsEs6Modules(program: Program): boolean { - return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!s.externalModuleIndicator); + return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && isExternalModule(s)); } export function compilerOptionsIndicateEs6Modules(compilerOptions: CompilerOptions): boolean { return !!compilerOptions.module || compilerOptions.target! >= ScriptTarget.ES2015 || !!compilerOptions.noEmit; @@ -2924,7 +2924,7 @@ namespace ts { export function isNonGlobalDeclaration(declaration: Declaration) { const sourceFile = declaration.getSourceFile(); // If the file is not a module, the declaration is global - if (!sourceFile.externalModuleIndicator && !sourceFile.commonJsModuleIndicator) { + if (!isExternalOrCommonJsModule(sourceFile)) { return false; } // If the file is a module written in TypeScript, it still might be in a `declare global` augmentation diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5a803b4c659ed..943ea8ed66e25 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3006,6 +3006,8 @@ declare namespace ts { Tsx = ".tsx", Dts = ".d.ts", Js = ".js", + Cjs = ".cjs", + Mjs = ".mjs", Jsx = ".jsx", Json = ".json", TsBuildInfo = ".tsbuildinfo" @@ -4481,6 +4483,7 @@ declare namespace ts { */ export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile; export function isExternalModule(file: SourceFile): boolean; + export function isCommonJsModule(file: SourceFile): boolean; export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; export {}; } @@ -6162,6 +6165,8 @@ declare namespace ts { dtsModifier = ".d.ts", tsModifier = ".ts", tsxModifier = ".tsx", + cjsModifier = ".cjs", + mjsModifier = ".mjs", jsModifier = ".js", jsxModifier = ".jsx", jsonModifier = ".json" diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index bb9aa1f2d2537..6868c7f4b35d4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3006,6 +3006,8 @@ declare namespace ts { Tsx = ".tsx", Dts = ".d.ts", Js = ".js", + Cjs = ".cjs", + Mjs = ".mjs", Jsx = ".jsx", Json = ".json", TsBuildInfo = ".tsbuildinfo" @@ -4481,6 +4483,7 @@ declare namespace ts { */ export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile; export function isExternalModule(file: SourceFile): boolean; + export function isCommonJsModule(file: SourceFile): boolean; export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; export {}; } @@ -6162,6 +6165,8 @@ declare namespace ts { dtsModifier = ".d.ts", tsModifier = ".ts", tsxModifier = ".tsx", + cjsModifier = ".cjs", + mjsModifier = ".mjs", jsModifier = ".js", jsxModifier = ".jsx", jsonModifier = ".json" diff --git a/tests/baselines/reference/declarationEmitInvalidReferenceAllowJs.errors.txt b/tests/baselines/reference/declarationEmitInvalidReferenceAllowJs.errors.txt index 79f9afa5f34cb..5caaa4a8aedb6 100644 --- a/tests/baselines/reference/declarationEmitInvalidReferenceAllowJs.errors.txt +++ b/tests/baselines/reference/declarationEmitInvalidReferenceAllowJs.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/declarationEmitInvalidReferenceAllowJs.ts(1,22): error TS6231: Could not resolve the path 'tests/cases/compiler/invalid' with the extensions: '.ts', '.tsx', '.d.ts', '.js', '.jsx'. +tests/cases/compiler/declarationEmitInvalidReferenceAllowJs.ts(1,22): error TS6231: Could not resolve the path 'tests/cases/compiler/invalid' with the extensions: '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cjs', '.mjs'. ==== tests/cases/compiler/declarationEmitInvalidReferenceAllowJs.ts (1 errors) ==== /// ~~~~~~~ -!!! error TS6231: Could not resolve the path 'tests/cases/compiler/invalid' with the extensions: '.ts', '.tsx', '.d.ts', '.js', '.jsx'. +!!! error TS6231: Could not resolve the path 'tests/cases/compiler/invalid' with the extensions: '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cjs', '.mjs'. var x = 0; \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilationWithMapFileAsJs.errors.txt b/tests/baselines/reference/jsFileCompilationWithMapFileAsJs.errors.txt index 4dced529edf10..4ef8f6c524f95 100644 --- a/tests/baselines/reference/jsFileCompilationWithMapFileAsJs.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithMapFileAsJs.errors.txt @@ -1,11 +1,11 @@ error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. -error TS6054: File 'tests/cases/compiler/b.js.map' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'. +error TS6054: File 'tests/cases/compiler/b.js.map' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cjs', '.mjs'. !!! error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. !!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. -!!! error TS6054: File 'tests/cases/compiler/b.js.map' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'. +!!! error TS6054: File 'tests/cases/compiler/b.js.map' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cjs', '.mjs'. ==== tests/cases/compiler/a.ts (0 errors) ==== class c { } diff --git a/tests/baselines/reference/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.errors.txt b/tests/baselines/reference/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.errors.txt index 4dced529edf10..4ef8f6c524f95 100644 --- a/tests/baselines/reference/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.errors.txt +++ b/tests/baselines/reference/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.errors.txt @@ -1,11 +1,11 @@ error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. -error TS6054: File 'tests/cases/compiler/b.js.map' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'. +error TS6054: File 'tests/cases/compiler/b.js.map' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cjs', '.mjs'. !!! error TS5055: Cannot write file 'tests/cases/compiler/b.js' because it would overwrite input file. !!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. -!!! error TS6054: File 'tests/cases/compiler/b.js.map' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'. +!!! error TS6054: File 'tests/cases/compiler/b.js.map' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx', '.cjs', '.mjs'. ==== tests/cases/compiler/a.ts (0 errors) ==== class c { } diff --git a/tests/baselines/reference/jsFileCompilation_cjs.errors.txt b/tests/baselines/reference/jsFileCompilation_cjs.errors.txt new file mode 100644 index 0000000000000..de46607d7c081 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_cjs.errors.txt @@ -0,0 +1,29 @@ +tests/cases/compiler/a.cjs(1,1): error TS1233: An export declaration can only be used in a module. +tests/cases/compiler/a.cjs(2,1): error TS1389: The 'import.meta' meta-property is not allowed in CommonJS module files. +tests/cases/compiler/c.cjs(4,7): error TS1210: Invalid use of 'eval'. Class definitions are automatically in strict mode. +tests/cases/compiler/c.cjs(7,13): error TS1213: Identifier expected. 'let' is a reserved word in strict mode. Class definitions are automatically in strict mode. + + +==== tests/cases/compiler/a.cjs (2 errors) ==== + export {}; // error + ~~~~~~ +!!! error TS1233: An export declaration can only be used in a module. + import.meta; // error + ~~~~~~~~~~~ +!!! error TS1389: The 'import.meta' meta-property is not allowed in CommonJS module files. + +==== tests/cases/compiler/c.cjs (2 errors) ==== + // this is not in strict mode but class definitions are always in strict mode + + class c { + a(eval) { //error + ~~~~ +!!! error TS1210: Invalid use of 'eval'. Class definitions are automatically in strict mode. + } + method() { + var let = 10; // error + ~~~ +!!! error TS1213: Identifier expected. 'let' is a reserved word in strict mode. Class definitions are automatically in strict mode. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilation_cjs.symbols b/tests/baselines/reference/jsFileCompilation_cjs.symbols new file mode 100644 index 0000000000000..84bd9cc9d5ebb --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_cjs.symbols @@ -0,0 +1,22 @@ +=== tests/cases/compiler/a.cjs === +export {}; // error +No type information for this code.import.meta; // error +No type information for this code. +No type information for this code.=== tests/cases/compiler/c.cjs === +// this is not in strict mode but class definitions are always in strict mode + +class c { +>c : Symbol(c, Decl(c.cjs, 0, 0)) + + a(eval) { //error +>a : Symbol(c.a, Decl(c.cjs, 2, 9)) +>eval : Symbol(eval, Decl(c.cjs, 3, 6)) + } + method() { +>method : Symbol(c.method, Decl(c.cjs, 4, 5)) + + var let = 10; // error +>let : Symbol(let, Decl(c.cjs, 6, 11)) + } +} + diff --git a/tests/baselines/reference/jsFileCompilation_cjs.types b/tests/baselines/reference/jsFileCompilation_cjs.types new file mode 100644 index 0000000000000..ba8d39924c75a --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_cjs.types @@ -0,0 +1,25 @@ +=== tests/cases/compiler/a.cjs === +export {}; // error +import.meta; // error +>import.meta : ImportMeta +>meta : any + +=== tests/cases/compiler/c.cjs === +// this is not in strict mode but class definitions are always in strict mode + +class c { +>c : c + + a(eval) { //error +>a : (eval: any) => void +>eval : any + } + method() { +>method : () => void + + var let = 10; // error +>let : number +>10 : 10 + } +} + diff --git a/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.errors.txt b/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.errors.txt new file mode 100644 index 0000000000000..da6db8c4ec38c --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/index.cjs(1,22): error TS2792: Cannot find module './blah'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? +tests/cases/compiler/index.cjs(2,34): error TS2792: Cannot find module './utils'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + + +==== tests/cases/compiler/index.cjs (2 errors) ==== + const Blah = require("./blah"); + ~~~~~~~~ +!!! error TS2792: Cannot find module './blah'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + const { util1, util2 } = require("./utils"); + ~~~~~~~~~ +!!! error TS2792: Cannot find module './utils'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + +==== tests/cases/compiler/blah.mjs (0 errors) ==== + export default class Blah {} + +==== tests/cases/compiler/utils.cjs (0 errors) ==== + function util1() {} + function util2() {} + module.exports = { util1, util2 }; + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.symbols b/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.symbols new file mode 100644 index 0000000000000..06707917e1239 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/index.cjs === +const Blah = require("./blah"); +>Blah : Symbol(Blah, Decl(index.cjs, 0, 5)) +>require : Symbol(require) + +const { util1, util2 } = require("./utils"); +>util1 : Symbol(util1, Decl(index.cjs, 1, 7)) +>util2 : Symbol(util2, Decl(index.cjs, 1, 14)) +>require : Symbol(require) + diff --git a/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.types b/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.types new file mode 100644 index 0000000000000..6f23e94ea5b51 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/index.cjs === +const Blah = require("./blah"); +>Blah : any +>require("./blah") : any +>require : any +>"./blah" : "./blah" + +const { util1, util2 } = require("./utils"); +>util1 : any +>util2 : any +>require("./utils") : any +>require : any +>"./utils" : "./utils" + diff --git a/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.errors.txt b/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.errors.txt new file mode 100644 index 0000000000000..395c8552d90d5 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/index.js(1,18): error TS2792: Cannot find module './blah'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? +tests/cases/compiler/index.js(2,30): error TS2792: Cannot find module './utils'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + + +==== tests/cases/compiler/blah.mjs (0 errors) ==== + export default class Blah {} + +==== tests/cases/compiler/utils.cjs (0 errors) ==== + function util1() {} + function util2() {} + module.exports = { util1, util2 }; + +==== tests/cases/compiler/index.js (2 errors) ==== + import Blah from "./blah"; + ~~~~~~~~ +!!! error TS2792: Cannot find module './blah'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + import { util1, util2 } from "./utils"; + ~~~~~~~~~ +!!! error TS2792: Cannot find module './utils'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.symbols b/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.symbols new file mode 100644 index 0000000000000..9e1ba6c0b4e15 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/blah.mjs === +export default class Blah {} +>Blah : Symbol(Blah, Decl(blah.mjs, 0, 0)) + +=== tests/cases/compiler/utils.cjs === +function util1() {} +>util1 : Symbol(util1, Decl(utils.cjs, 0, 0)) + +function util2() {} +>util2 : Symbol(util2, Decl(utils.cjs, 0, 19)) + +module.exports = { util1, util2 }; +>module.exports : Symbol("tests/cases/compiler/utils", Decl(utils.cjs, 0, 0)) +>module : Symbol(export=, Decl(utils.cjs, 1, 19)) +>exports : Symbol(export=, Decl(utils.cjs, 1, 19)) +>util1 : Symbol(util1, Decl(utils.cjs, 2, 18)) +>util2 : Symbol(util2, Decl(utils.cjs, 2, 25)) + +=== tests/cases/compiler/index.js === +import Blah from "./blah"; +>Blah : Symbol(Blah, Decl(index.js, 0, 6)) + +import { util1, util2 } from "./utils"; +>util1 : Symbol(util1, Decl(index.js, 1, 8)) +>util2 : Symbol(util2, Decl(index.js, 1, 15)) + diff --git a/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.types b/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.types new file mode 100644 index 0000000000000..fc323eefacabd --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/blah.mjs === +export default class Blah {} +>Blah : Blah + +=== tests/cases/compiler/utils.cjs === +function util1() {} +>util1 : () => void + +function util2() {} +>util2 : () => void + +module.exports = { util1, util2 }; +>module.exports = { util1, util2 } : { util1: () => void; util2: () => void; } +>module.exports : { util1: () => void; util2: () => void; } +>module : { "\"tests/cases/compiler/utils\"": { util1: () => void; util2: () => void; }; } +>exports : { util1: () => void; util2: () => void; } +>{ util1, util2 } : { util1: () => void; util2: () => void; } +>util1 : () => void +>util2 : () => void + +=== tests/cases/compiler/index.js === +import Blah from "./blah"; +>Blah : any + +import { util1, util2 } from "./utils"; +>util1 : any +>util2 : any + diff --git a/tests/baselines/reference/jsFileCompilation_mjs.errors.txt b/tests/baselines/reference/jsFileCompilation_mjs.errors.txt new file mode 100644 index 0000000000000..f2b33f25a63b6 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_mjs.errors.txt @@ -0,0 +1,84 @@ +tests/cases/compiler/a.mjs(6,5): error TS1117: An object literal cannot have multiple properties with the same name in strict mode. +tests/cases/compiler/a.mjs(6,5): error TS2300: Duplicate identifier 'a'. +tests/cases/compiler/a.mjs(8,5): error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. +tests/cases/compiler/a.mjs(9,8): error TS1102: 'delete' cannot be called on an identifier in strict mode. +tests/cases/compiler/a.mjs(9,8): error TS2703: The operand of a 'delete' operator must be a property reference. +tests/cases/compiler/a.mjs(11,10): error TS1215: Invalid use of 'eval'. Modules are automatically in strict mode. +tests/cases/compiler/a.mjs(13,10): error TS1215: Invalid use of 'arguments'. Modules are automatically in strict mode. +tests/cases/compiler/a.mjs(16,1): error TS1101: 'with' statements are not allowed in strict mode. +tests/cases/compiler/a.mjs(16,1): error TS2410: The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'. +tests/cases/compiler/b.mjs(2,7): error TS1210: Invalid use of 'eval'. Class definitions are automatically in strict mode. +tests/cases/compiler/b.mjs(5,13): error TS1213: Identifier expected. 'let' is a reserved word in strict mode. Class definitions are automatically in strict mode. +tests/cases/compiler/c.mjs(1,5): error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. +tests/cases/compiler/c.mjs(2,5): error TS1215: Invalid use of 'eval'. Modules are automatically in strict mode. +tests/cases/compiler/d.mjs(1,9): error TS1121: Octal literals are not allowed in strict mode. +tests/cases/compiler/d.mjs(1,11): error TS1005: ',' expected. + + +==== tests/cases/compiler/a.mjs (9 errors) ==== + // `.mjs` files are automatically external modules, and thus in strict mode + + var a = { + a: "hello", // error + b: 10, + a: 10 // error + ~ +!!! error TS1117: An object literal cannot have multiple properties with the same name in strict mode. + ~ +!!! error TS2300: Duplicate identifier 'a'. + }; + var let = 10; // error + ~~~ +!!! error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. + delete a; // error + ~ +!!! error TS1102: 'delete' cannot be called on an identifier in strict mode. + ~ +!!! error TS2703: The operand of a 'delete' operator must be a property reference. + try { + } catch (eval) { // error + ~~~~ +!!! error TS1215: Invalid use of 'eval'. Modules are automatically in strict mode. + } + function arguments() { // error + ~~~~~~~~~ +!!! error TS1215: Invalid use of 'arguments'. Modules are automatically in strict mode. + } + + with (a) { + ~~~~ +!!! error TS1101: 'with' statements are not allowed in strict mode. + ~~~~~~~~ +!!! error TS2410: The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'. + b = 10; + } + +==== tests/cases/compiler/b.mjs (2 errors) ==== + class c { + a(eval) { //error + ~~~~ +!!! error TS1210: Invalid use of 'eval'. Class definitions are automatically in strict mode. + } + method() { + var let = 10; // error + ~~~ +!!! error TS1213: Identifier expected. 'let' is a reserved word in strict mode. Class definitions are automatically in strict mode. + } + } + +==== tests/cases/compiler/c.mjs (2 errors) ==== + var let = 10; + ~~~ +!!! error TS1214: Identifier expected. 'let' is a reserved word in strict mode. Modules are automatically in strict mode. + var eval = function () { + ~~~~ +!!! error TS1215: Invalid use of 'eval'. Modules are automatically in strict mode. + }; + +==== tests/cases/compiler/d.mjs (2 errors) ==== + var x = 009; // error + ~~ +!!! error TS1121: Octal literals are not allowed in strict mode. + ~ +!!! error TS1005: ',' expected. + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilation_mjs.symbols b/tests/baselines/reference/jsFileCompilation_mjs.symbols new file mode 100644 index 0000000000000..229da71ad7aec --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_mjs.symbols @@ -0,0 +1,65 @@ +=== tests/cases/compiler/a.mjs === +// `.mjs` files are automatically external modules, and thus in strict mode + +var a = { +>a : Symbol(a, Decl(a.mjs, 2, 3)) + + a: "hello", // error +>a : Symbol(a, Decl(a.mjs, 2, 9), Decl(a.mjs, 4, 10)) + + b: 10, +>b : Symbol(b, Decl(a.mjs, 3, 15)) + + a: 10 // error +>a : Symbol(a, Decl(a.mjs, 2, 9), Decl(a.mjs, 4, 10)) + +}; +var let = 10; // error +>let : Symbol(let, Decl(a.mjs, 7, 3)) + +delete a; // error +>a : Symbol(a, Decl(a.mjs, 2, 3)) + +try { +} catch (eval) { // error +>eval : Symbol(eval, Decl(a.mjs, 10, 9)) +} +function arguments() { // error +>arguments : Symbol(arguments, Decl(a.mjs, 11, 1)) +} + +with (a) { +>a : Symbol(a, Decl(a.mjs, 2, 3)) + + b = 10; +} + +=== tests/cases/compiler/b.mjs === +class c { +>c : Symbol(c, Decl(b.mjs, 0, 0)) + + a(eval) { //error +>a : Symbol(c.a, Decl(b.mjs, 0, 9)) +>eval : Symbol(eval, Decl(b.mjs, 1, 6)) + } + method() { +>method : Symbol(c.method, Decl(b.mjs, 2, 5)) + + var let = 10; // error +>let : Symbol(let, Decl(b.mjs, 4, 11)) + } +} + +=== tests/cases/compiler/c.mjs === +var let = 10; +>let : Symbol(let, Decl(c.mjs, 0, 3)) + +var eval = function () { +>eval : Symbol(eval, Decl(c.mjs, 1, 3)) + +}; + +=== tests/cases/compiler/d.mjs === +var x = 009; // error +>x : Symbol(x, Decl(d.mjs, 0, 3)) + diff --git a/tests/baselines/reference/jsFileCompilation_mjs.types b/tests/baselines/reference/jsFileCompilation_mjs.types new file mode 100644 index 0000000000000..5e81cbfd3a37b --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_mjs.types @@ -0,0 +1,79 @@ +=== tests/cases/compiler/a.mjs === +// `.mjs` files are automatically external modules, and thus in strict mode + +var a = { +>a : { a: number; b: number; } +>{ a: "hello", // error b: 10, a: 10 // error} : { a: number; b: number; } + + a: "hello", // error +>a : string +>"hello" : "hello" + + b: 10, +>b : number +>10 : 10 + + a: 10 // error +>a : string +>10 : 10 + +}; +var let = 10; // error +>let : number +>10 : 10 + +delete a; // error +>delete a : boolean +>a : { a: number; b: number; } + +try { +} catch (eval) { // error +>eval : any +} +function arguments() { // error +>arguments : () => void +} + +with (a) { +>a : { a: number; b: number; } + + b = 10; +>b = 10 : any +>b : any +>10 : any +} + +=== tests/cases/compiler/b.mjs === +class c { +>c : c + + a(eval) { //error +>a : (eval: any) => void +>eval : any + } + method() { +>method : () => void + + var let = 10; // error +>let : number +>10 : 10 + } +} + +=== tests/cases/compiler/c.mjs === +var let = 10; +>let : number +>10 : 10 + +var eval = function () { +>eval : () => void +>function () {} : () => void + +}; + +=== tests/cases/compiler/d.mjs === +var x = 009; // error +>x : number +>00 : 0 +>9 : 9 + diff --git a/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.errors.txt b/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.errors.txt new file mode 100644 index 0000000000000..3219bb96545a8 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/index.mjs(1,18): error TS2792: Cannot find module './blah'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? +tests/cases/compiler/index.mjs(2,30): error TS2792: Cannot find module './utils'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + + +==== tests/cases/compiler/blah.mjs (0 errors) ==== + export default class Blah {} + +==== tests/cases/compiler/utils.cjs (0 errors) ==== + function util1() {} + function util2() {} + module.exports = { util1, util2 }; + +==== tests/cases/compiler/index.mjs (2 errors) ==== + import Blah from "./blah"; + ~~~~~~~~ +!!! error TS2792: Cannot find module './blah'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + import { util1, util2 } from "./utils"; + ~~~~~~~~~ +!!! error TS2792: Cannot find module './utils'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option? + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.symbols b/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.symbols new file mode 100644 index 0000000000000..039028c31beb2 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/blah.mjs === +export default class Blah {} +>Blah : Symbol(Blah, Decl(blah.mjs, 0, 0)) + +=== tests/cases/compiler/utils.cjs === +function util1() {} +>util1 : Symbol(util1, Decl(utils.cjs, 0, 0)) + +function util2() {} +>util2 : Symbol(util2, Decl(utils.cjs, 0, 19)) + +module.exports = { util1, util2 }; +>module.exports : Symbol("tests/cases/compiler/utils", Decl(utils.cjs, 0, 0)) +>module : Symbol(export=, Decl(utils.cjs, 1, 19)) +>exports : Symbol(export=, Decl(utils.cjs, 1, 19)) +>util1 : Symbol(util1, Decl(utils.cjs, 2, 18)) +>util2 : Symbol(util2, Decl(utils.cjs, 2, 25)) + +=== tests/cases/compiler/index.mjs === +import Blah from "./blah"; +>Blah : Symbol(Blah, Decl(index.mjs, 0, 6)) + +import { util1, util2 } from "./utils"; +>util1 : Symbol(util1, Decl(index.mjs, 1, 8)) +>util2 : Symbol(util2, Decl(index.mjs, 1, 15)) + diff --git a/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.types b/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.types new file mode 100644 index 0000000000000..3a1ffc5890808 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/blah.mjs === +export default class Blah {} +>Blah : Blah + +=== tests/cases/compiler/utils.cjs === +function util1() {} +>util1 : () => void + +function util2() {} +>util2 : () => void + +module.exports = { util1, util2 }; +>module.exports = { util1, util2 } : { util1: () => void; util2: () => void; } +>module.exports : { util1: () => void; util2: () => void; } +>module : { "\"tests/cases/compiler/utils\"": { util1: () => void; util2: () => void; }; } +>exports : { util1: () => void; util2: () => void; } +>{ util1, util2 } : { util1: () => void; util2: () => void; } +>util1 : () => void +>util2 : () => void + +=== tests/cases/compiler/index.mjs === +import Blah from "./blah"; +>Blah : any + +import { util1, util2 } from "./utils"; +>util1 : any +>util2 : any + diff --git a/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.errors.txt b/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.errors.txt new file mode 100644 index 0000000000000..e21cbb16ad426 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/index.cjs(1,22): error TS2307: Cannot find module './blah' or its corresponding type declarations. +tests/cases/compiler/index.cjs(2,34): error TS2307: Cannot find module './utils' or its corresponding type declarations. + + +==== tests/cases/compiler/index.cjs (2 errors) ==== + const Blah = require("./blah"); + ~~~~~~~~ +!!! error TS2307: Cannot find module './blah' or its corresponding type declarations. + const { util1, util2 } = require("./utils"); + ~~~~~~~~~ +!!! error TS2307: Cannot find module './utils' or its corresponding type declarations. + +==== tests/cases/compiler/blah.mjs (0 errors) ==== + export default class Blah {} + +==== tests/cases/compiler/utils.cjs (0 errors) ==== + function util1() {} + function util2() {} + module.exports = { util1, util2 }; + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.symbols b/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.symbols new file mode 100644 index 0000000000000..06707917e1239 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/index.cjs === +const Blah = require("./blah"); +>Blah : Symbol(Blah, Decl(index.cjs, 0, 5)) +>require : Symbol(require) + +const { util1, util2 } = require("./utils"); +>util1 : Symbol(util1, Decl(index.cjs, 1, 7)) +>util2 : Symbol(util2, Decl(index.cjs, 1, 14)) +>require : Symbol(require) + diff --git a/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.types b/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.types new file mode 100644 index 0000000000000..6f23e94ea5b51 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/index.cjs === +const Blah = require("./blah"); +>Blah : any +>require("./blah") : any +>require : any +>"./blah" : "./blah" + +const { util1, util2 } = require("./utils"); +>util1 : any +>util2 : any +>require("./utils") : any +>require : any +>"./utils" : "./utils" + diff --git a/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.errors.txt b/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.errors.txt new file mode 100644 index 0000000000000..1de0b8b097f6f --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/index.js(1,18): error TS2307: Cannot find module './blah' or its corresponding type declarations. +tests/cases/compiler/index.js(2,30): error TS2307: Cannot find module './utils' or its corresponding type declarations. + + +==== tests/cases/compiler/blah.mjs (0 errors) ==== + export default class Blah {} + +==== tests/cases/compiler/utils.cjs (0 errors) ==== + function util1() {} + function util2() {} + module.exports = { util1, util2 }; + +==== tests/cases/compiler/index.js (2 errors) ==== + import Blah from "./blah"; + ~~~~~~~~ +!!! error TS2307: Cannot find module './blah' or its corresponding type declarations. + import { util1, util2 } from "./utils"; + ~~~~~~~~~ +!!! error TS2307: Cannot find module './utils' or its corresponding type declarations. + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.symbols b/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.symbols new file mode 100644 index 0000000000000..9e1ba6c0b4e15 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/blah.mjs === +export default class Blah {} +>Blah : Symbol(Blah, Decl(blah.mjs, 0, 0)) + +=== tests/cases/compiler/utils.cjs === +function util1() {} +>util1 : Symbol(util1, Decl(utils.cjs, 0, 0)) + +function util2() {} +>util2 : Symbol(util2, Decl(utils.cjs, 0, 19)) + +module.exports = { util1, util2 }; +>module.exports : Symbol("tests/cases/compiler/utils", Decl(utils.cjs, 0, 0)) +>module : Symbol(export=, Decl(utils.cjs, 1, 19)) +>exports : Symbol(export=, Decl(utils.cjs, 1, 19)) +>util1 : Symbol(util1, Decl(utils.cjs, 2, 18)) +>util2 : Symbol(util2, Decl(utils.cjs, 2, 25)) + +=== tests/cases/compiler/index.js === +import Blah from "./blah"; +>Blah : Symbol(Blah, Decl(index.js, 0, 6)) + +import { util1, util2 } from "./utils"; +>util1 : Symbol(util1, Decl(index.js, 1, 8)) +>util2 : Symbol(util2, Decl(index.js, 1, 15)) + diff --git a/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.types b/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.types new file mode 100644 index 0000000000000..fc323eefacabd --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/blah.mjs === +export default class Blah {} +>Blah : Blah + +=== tests/cases/compiler/utils.cjs === +function util1() {} +>util1 : () => void + +function util2() {} +>util2 : () => void + +module.exports = { util1, util2 }; +>module.exports = { util1, util2 } : { util1: () => void; util2: () => void; } +>module.exports : { util1: () => void; util2: () => void; } +>module : { "\"tests/cases/compiler/utils\"": { util1: () => void; util2: () => void; }; } +>exports : { util1: () => void; util2: () => void; } +>{ util1, util2 } : { util1: () => void; util2: () => void; } +>util1 : () => void +>util2 : () => void + +=== tests/cases/compiler/index.js === +import Blah from "./blah"; +>Blah : any + +import { util1, util2 } from "./utils"; +>util1 : any +>util2 : any + diff --git a/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.errors.txt b/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.errors.txt new file mode 100644 index 0000000000000..86f054233ed87 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/index.mjs(1,18): error TS2307: Cannot find module './blah' or its corresponding type declarations. +tests/cases/compiler/index.mjs(2,30): error TS2307: Cannot find module './utils' or its corresponding type declarations. + + +==== tests/cases/compiler/blah.mjs (0 errors) ==== + export default class Blah {} + +==== tests/cases/compiler/utils.cjs (0 errors) ==== + function util1() {} + function util2() {} + module.exports = { util1, util2 }; + +==== tests/cases/compiler/index.mjs (2 errors) ==== + import Blah from "./blah"; + ~~~~~~~~ +!!! error TS2307: Cannot find module './blah' or its corresponding type declarations. + import { util1, util2 } from "./utils"; + ~~~~~~~~~ +!!! error TS2307: Cannot find module './utils' or its corresponding type declarations. + \ No newline at end of file diff --git a/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.symbols b/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.symbols new file mode 100644 index 0000000000000..039028c31beb2 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/blah.mjs === +export default class Blah {} +>Blah : Symbol(Blah, Decl(blah.mjs, 0, 0)) + +=== tests/cases/compiler/utils.cjs === +function util1() {} +>util1 : Symbol(util1, Decl(utils.cjs, 0, 0)) + +function util2() {} +>util2 : Symbol(util2, Decl(utils.cjs, 0, 19)) + +module.exports = { util1, util2 }; +>module.exports : Symbol("tests/cases/compiler/utils", Decl(utils.cjs, 0, 0)) +>module : Symbol(export=, Decl(utils.cjs, 1, 19)) +>exports : Symbol(export=, Decl(utils.cjs, 1, 19)) +>util1 : Symbol(util1, Decl(utils.cjs, 2, 18)) +>util2 : Symbol(util2, Decl(utils.cjs, 2, 25)) + +=== tests/cases/compiler/index.mjs === +import Blah from "./blah"; +>Blah : Symbol(Blah, Decl(index.mjs, 0, 6)) + +import { util1, util2 } from "./utils"; +>util1 : Symbol(util1, Decl(index.mjs, 1, 8)) +>util2 : Symbol(util2, Decl(index.mjs, 1, 15)) + diff --git a/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.types b/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.types new file mode 100644 index 0000000000000..3a1ffc5890808 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/blah.mjs === +export default class Blah {} +>Blah : Blah + +=== tests/cases/compiler/utils.cjs === +function util1() {} +>util1 : () => void + +function util2() {} +>util2 : () => void + +module.exports = { util1, util2 }; +>module.exports = { util1, util2 } : { util1: () => void; util2: () => void; } +>module.exports : { util1: () => void; util2: () => void; } +>module : { "\"tests/cases/compiler/utils\"": { util1: () => void; util2: () => void; }; } +>exports : { util1: () => void; util2: () => void; } +>{ util1, util2 } : { util1: () => void; util2: () => void; } +>util1 : () => void +>util2 : () => void + +=== tests/cases/compiler/index.mjs === +import Blah from "./blah"; +>Blah : any + +import { util1, util2 } from "./utils"; +>util1 : any +>util2 : any + diff --git a/tests/cases/compiler/jsFileCompilation_cjs.ts b/tests/cases/compiler/jsFileCompilation_cjs.ts new file mode 100644 index 0000000000000..4df902dc9da9a --- /dev/null +++ b/tests/cases/compiler/jsFileCompilation_cjs.ts @@ -0,0 +1,17 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @filename: a.cjs +export {}; // error +import.meta; // error + +// @filename: c.cjs +// this is not in strict mode but class definitions are always in strict mode + +class c { + a(eval) { //error + } + method() { + var let = 10; // error + } +} diff --git a/tests/cases/compiler/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.ts b/tests/cases/compiler/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.ts new file mode 100644 index 0000000000000..f3ee1a959b3d2 --- /dev/null +++ b/tests/cases/compiler/jsFileCompilation_cjs_importMissingFileExtension_cjs_mjs.ts @@ -0,0 +1,16 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @target: es6 + +// @filename: blah.mjs +export default class Blah {} + +// @filename: utils.cjs +function util1() {} +function util2() {} +module.exports = { util1, util2 }; + +// @filename: index.cjs +const Blah = require("./blah"); +const { util1, util2 } = require("./utils"); diff --git a/tests/cases/compiler/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.ts b/tests/cases/compiler/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.ts new file mode 100644 index 0000000000000..f9e0376be64cc --- /dev/null +++ b/tests/cases/compiler/jsFileCompilation_js_importMissingFileExtension_cjs_mjs.ts @@ -0,0 +1,16 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @target: es6 + +// @filename: blah.mjs +export default class Blah {} + +// @filename: utils.cjs +function util1() {} +function util2() {} +module.exports = { util1, util2 }; + +// @filename: index.js +import Blah from "./blah"; +import { util1, util2 } from "./utils"; diff --git a/tests/cases/compiler/jsFileCompilation_mjs.ts b/tests/cases/compiler/jsFileCompilation_mjs.ts new file mode 100644 index 0000000000000..a01ac999a3f08 --- /dev/null +++ b/tests/cases/compiler/jsFileCompilation_mjs.ts @@ -0,0 +1,40 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @target: es6 +// @filename: a.mjs +// `.mjs` files are automatically external modules, and thus in strict mode + +var a = { + a: "hello", // error + b: 10, + a: 10 // error +}; +var let = 10; // error +delete a; // error +try { +} catch (eval) { // error +} +function arguments() { // error +} + +with (a) { + b = 10; +} + +// @filename: b.mjs +class c { + a(eval) { //error + } + method() { + var let = 10; // error + } +} + +// @filename: c.mjs +var let = 10; +var eval = function () { +}; + +//@filename: d.mjs +var x = 009; // error diff --git a/tests/cases/compiler/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.ts b/tests/cases/compiler/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.ts new file mode 100644 index 0000000000000..eef7c75a9fa69 --- /dev/null +++ b/tests/cases/compiler/jsFileCompilation_mjs_importMissingFileExtension_cjs_mjs.ts @@ -0,0 +1,16 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @target: es6 + +// @filename: blah.mjs +export default class Blah {} + +// @filename: utils.cjs +function util1() {} +function util2() {} +module.exports = { util1, util2 }; + +// @filename: index.mjs +import Blah from "./blah"; +import { util1, util2 } from "./utils"; diff --git a/tests/cases/compiler/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.ts b/tests/cases/compiler/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.ts new file mode 100644 index 0000000000000..0dee2a24e1b66 --- /dev/null +++ b/tests/cases/compiler/jsFileCompilation_node_cjs_importMissingFileExtension_cjs_mjs.ts @@ -0,0 +1,17 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @target: es6 +// @moduleResolution: node + +// @filename: blah.mjs +export default class Blah {} + +// @filename: utils.cjs +function util1() {} +function util2() {} +module.exports = { util1, util2 }; + +// @filename: index.cjs +const Blah = require("./blah"); +const { util1, util2 } = require("./utils"); diff --git a/tests/cases/compiler/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.ts b/tests/cases/compiler/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.ts new file mode 100644 index 0000000000000..e10bdfffe4904 --- /dev/null +++ b/tests/cases/compiler/jsFileCompilation_node_js_importMissingFileExtension_cjs_mjs.ts @@ -0,0 +1,17 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @target: es6 +// @moduleResolution: node + +// @filename: blah.mjs +export default class Blah {} + +// @filename: utils.cjs +function util1() {} +function util2() {} +module.exports = { util1, util2 }; + +// @filename: index.js +import Blah from "./blah"; +import { util1, util2 } from "./utils"; diff --git a/tests/cases/compiler/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.ts b/tests/cases/compiler/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.ts new file mode 100644 index 0000000000000..c07b23caaf0f9 --- /dev/null +++ b/tests/cases/compiler/jsFileCompilation_node_mjs_importMissingFileExtension_cjs_mjs.ts @@ -0,0 +1,17 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @target: es6 +// @moduleResolution: node + +// @filename: blah.mjs +export default class Blah {} + +// @filename: utils.cjs +function util1() {} +function util2() {} +module.exports = { util1, util2 }; + +// @filename: index.mjs +import Blah from "./blah"; +import { util1, util2 } from "./utils"; diff --git a/tests/cases/fourslash/importNameCodeFix_cjs.ts b/tests/cases/fourslash/importNameCodeFix_cjs.ts new file mode 100644 index 0000000000000..7c82ba35a25f1 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_cjs.ts @@ -0,0 +1,36 @@ +/// + +// @allowJs: true +// @checkJs: true + +// @Filename: foo.cjs +////module.exports = function foo() {} + +// @Filename: utils.cjs +////function util1() {} +////function util2() {} +////module.exports = { util1, util2 }; + +// @Filename: blah.js +////export default class Blah {} + +// @Filename: index.cjs +////foo(); +////util1(); +////util2(); +////new Blah; + +goTo.file("index.cjs"); +verify.codeFixAll({ + fixId: "fixMissingImport", + fixAllDescription: "Add all missing imports", + newFileContent: +`const { default: Blah } = require("./blah"); +const foo = require("./foo.cjs"); +const { util1, util2 } = require("./utils.cjs"); + +foo(); +util1(); +util2(); +new Blah;` +}); diff --git a/tests/cases/fourslash/importNameCodeFix_mjs.ts b/tests/cases/fourslash/importNameCodeFix_mjs.ts new file mode 100644 index 0000000000000..85437e9059559 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_mjs.ts @@ -0,0 +1,36 @@ +/// + +// @allowJs: true +// @checkJs: true + +// @Filename: foo.js +////module.exports = function foo() {} + +// @Filename: utils.cjs +////function util1() {} +////function util2() {} +////module.exports = { util1, util2 }; + +// @Filename: blah.mjs +////export default class Blah {} + +// @Filename: index.mjs +////foo(); +////util1(); +////util2(); +////new Blah; + +goTo.file("index.mjs"); +verify.codeFixAll({ + fixId: "fixMissingImport", + fixAllDescription: "Add all missing imports", + newFileContent: +`import Blah from "./blah.mjs"; +import foo from "./foo.js"; +import { util1, util2 } from "./utils.cjs"; + +foo(); +util1(); +util2(); +new Blah;` +}); diff --git a/tests/cases/fourslash/importNameCodeFix_require_cjs_and_mjs.ts b/tests/cases/fourslash/importNameCodeFix_require_cjs_and_mjs.ts new file mode 100644 index 0000000000000..dd8f4cc903e0b --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_require_cjs_and_mjs.ts @@ -0,0 +1,36 @@ +/// + +// @allowJs: true +// @checkJs: true + +// @Filename: foo.js +////module.exports = function foo() {} + +// @Filename: utils.cjs +////function util1() {} +////function util2() {} +////module.exports = { util1, util2 }; + +// @Filename: blah.mjs +////export default class Blah {} + +// @Filename: index.js +////foo(); +////util1(); +////util2(); +////new Blah; + +goTo.file("index.js"); +verify.codeFixAll({ + fixId: "fixMissingImport", + fixAllDescription: "Add all missing imports", + newFileContent: +`const { default: Blah } = require("./blah.mjs"); +const foo = require("./foo"); +const { util1, util2 } = require("./utils.cjs"); + +foo(); +util1(); +util2(); +new Blah;` +});