diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f901db2ab4c5c..bf198f02e911b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1320,13 +1320,14 @@ namespace ts { else { // error const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum); const isEitherBlockScoped = !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable); - const message = isEitherEnum - ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations - : isEitherBlockScoped - ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : Diagnostics.Duplicate_identifier_0; + const message = isEitherEnum ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations + : isEitherBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : Diagnostics.Duplicate_identifier_0; const sourceSymbolFile = source.declarations && getSourceFileOfNode(source.declarations[0]); const targetSymbolFile = target.declarations && getSourceFileOfNode(target.declarations[0]); + + const isSourcePlainJs = isPlainJsFile(sourceSymbolFile, compilerOptions.checkJs); + const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs); const symbolName = symbolToString(source); // Collect top-level duplicate identifier errors into one mapping, so we can then merge their diagnostics if there are a bunch @@ -1337,12 +1338,12 @@ namespace ts { ({ firstFile, secondFile, conflictingSymbols: new Map() } as DuplicateInfoForFiles)); const conflictingSymbolInfo = getOrUpdate(filesDuplicates.conflictingSymbols, symbolName, () => ({ isBlockScoped: isEitherBlockScoped, firstFileLocations: [], secondFileLocations: [] } as DuplicateInfoForSymbol)); - addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source); - addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target); + if (!isSourcePlainJs) addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source); + if (!isTargetPlainJs) addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target); } else { - addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target); - addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source); + if (!isSourcePlainJs) addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target); + if (!isTargetPlainJs) addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source); } } return target; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f6cacfe719881..d8d22046674dc 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2102,7 +2102,7 @@ namespace ts { const isJs = sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX; const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options); - const isPlainJs = isJs && !sourceFile.checkJsDirective && options.checkJs === undefined; + const isPlainJs = isPlainJsFile(sourceFile, options.checkJs); const isTsNoCheck = !!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false; // By default, only type-check .ts, .tsx, Deferred, plain JS, checked JS and External diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index cabcb2f9b6cac..186df09456d14 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -271,6 +271,10 @@ namespace ts { return getSourceFileOfNode(module.valueDeclaration || getNonAugmentationDeclaration(module)); } + export function isPlainJsFile(file: SourceFile | undefined, checkJs: boolean | undefined): boolean { + return !!file && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX) && !file.checkJsDirective && checkJs === undefined; + } + export function isStatementWithLocals(node: Node) { switch (node.kind) { case SyntaxKind.Block: diff --git a/tests/baselines/reference/plainJSReservedStrict.errors.txt b/tests/baselines/reference/plainJSReservedStrict.errors.txt index a040fce591c17..db4714a10c194 100644 --- a/tests/baselines/reference/plainJSReservedStrict.errors.txt +++ b/tests/baselines/reference/plainJSReservedStrict.errors.txt @@ -1,16 +1,12 @@ tests/cases/conformance/salsa/plainJSReservedStrict.js(2,7): error TS1100: Invalid use of 'eval' in strict mode. -tests/cases/conformance/salsa/plainJSReservedStrict.js(2,7): error TS2451: Cannot redeclare block-scoped variable 'eval'. tests/cases/conformance/salsa/plainJSReservedStrict.js(3,7): error TS1100: Invalid use of 'arguments' in strict mode. -==== tests/cases/conformance/salsa/plainJSReservedStrict.js (3 errors) ==== +==== tests/cases/conformance/salsa/plainJSReservedStrict.js (2 errors) ==== "use strict" const eval = 1 ~~~~ !!! error TS1100: Invalid use of 'eval' in strict mode. - ~~~~ -!!! error TS2451: Cannot redeclare block-scoped variable 'eval'. -!!! related TS6203 /.ts/lib.es5.d.ts:32:18: 'eval' was also declared here. const arguments = 2 ~~~~~~~~~ !!! error TS1100: Invalid use of 'arguments' in strict mode.