Skip to content

Commit 0f619db

Browse files
committed
Plain JS binder errors
Issue select errors from the binder in JS files that do not have checkJS explicitly turned on or off. These errors mirror runtime checks done by Javascript.
1 parent fe3e117 commit 0f619db

32 files changed

+776
-8
lines changed

src/compiler/program.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,22 @@ namespace ts {
818818
}
819819
}
820820

821+
/** @internal */
822+
export const plainJSErrors: Set<number> = new Set([
823+
Diagnostics.Cannot_redeclare_block_scoped_variable_0.code,
824+
Diagnostics.A_module_cannot_have_multiple_default_exports.code,
825+
Diagnostics.Another_export_default_is_here.code,
826+
Diagnostics.The_first_export_default_is_here.code,
827+
Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module.code,
828+
Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode.code,
829+
Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here.code,
830+
Diagnostics.constructor_is_a_reserved_word.code,
831+
Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode.code,
832+
Diagnostics.Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode.code,
833+
Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode.code,
834+
Diagnostics.Invalid_use_of_0_in_strict_mode.code,
835+
]);
836+
821837
/**
822838
* Determine if source file needs to be re-created even if its text hasn't changed
823839
*/
@@ -2004,15 +2020,22 @@ namespace ts {
20042020

20052021
Debug.assert(!!sourceFile.bindDiagnostics);
20062022

2007-
const isCheckJs = isCheckJsEnabledForFile(sourceFile, options);
2023+
const isCheckJs = !!isCheckJsEnabledForFile(sourceFile, options) && (sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX);
2024+
const isPlainJs = !sourceFile.checkJsDirective && options.checkJs === undefined && (sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX);
20082025
const isTsNoCheck = !!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false;
2026+
20092027
// By default, only type-check .ts, .tsx, 'Deferred' and 'External' files (external files are added by plugins)
2010-
const includeBindAndCheckDiagnostics = !isTsNoCheck && (sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX
2011-
|| sourceFile.scriptKind === ScriptKind.External || isCheckJs || sourceFile.scriptKind === ScriptKind.Deferred);
2012-
const bindDiagnostics: readonly Diagnostic[] = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray;
2013-
const checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray;
2028+
const includeBindAndCheckDiagnostics = !isTsNoCheck && (
2029+
sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX
2030+
|| sourceFile.scriptKind === ScriptKind.External || isPlainJs || isCheckJs || sourceFile.scriptKind === ScriptKind.Deferred);
2031+
let bindDiagnostics: readonly Diagnostic[] = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray;
2032+
let checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray;
2033+
if (isPlainJs) {
2034+
bindDiagnostics = bindDiagnostics.filter(d => plainJSErrors.has(d.code));
2035+
checkDiagnostics = checkDiagnostics.filter(d => plainJSErrors.has(d.code));
2036+
}
20142037

2015-
return getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined);
2038+
return getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics && !isPlainJs, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined);
20162039
});
20172040
}
20182041

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/a.js(18,9): error TS1210: Code contained in a class is evaluated in JavaScript's strict mode which does not allow this use of 'arguments'. For more information, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode.
2+
3+
4+
==== /a.js (1 errors) ====
5+
class A {
6+
/**
7+
* Constructor
8+
*
9+
* @param {object} [foo={}]
10+
*/
11+
constructor(foo = {}) {
12+
const key = "bar";
13+
14+
/**
15+
* @type object
16+
*/
17+
this.foo = foo;
18+
19+
/**
20+
* @type object
21+
*/
22+
const arguments = this.arguments;
23+
~~~~~~~~~
24+
!!! error TS1210: Code contained in a class is evaluated in JavaScript's strict mode which does not allow this use of 'arguments'. For more information, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode.
25+
26+
/**
27+
* @type object
28+
*/
29+
this.bar = arguments.bar;
30+
31+
/**
32+
* @type object
33+
*/
34+
this.baz = arguments[key];
35+
36+
/**
37+
* @type object
38+
*/
39+
this.options = arguments;
40+
}
41+
42+
get arguments() {
43+
return { bar: {} };
44+
}
45+
}
46+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/a.js(16,9): error TS1210: Code contained in a class is evaluated in JavaScript's strict mode which does not allow this use of 'arguments'. For more information, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode.
2+
3+
4+
==== /a.js (1 errors) ====
5+
class A {
6+
/**
7+
* @param {object} [foo={}]
8+
*/
9+
m(foo = {}) {
10+
const key = "bar";
11+
12+
/**
13+
* @type object
14+
*/
15+
this.foo = foo;
16+
17+
/**
18+
* @type object
19+
*/
20+
const arguments = this.arguments;
21+
~~~~~~~~~
22+
!!! error TS1210: Code contained in a class is evaluated in JavaScript's strict mode which does not allow this use of 'arguments'. For more information, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode.
23+
24+
/**
25+
* @type object
26+
*/
27+
this.bar = arguments.bar;
28+
29+
/**
30+
* @type object
31+
*/
32+
this.baz = arguments[key];
33+
34+
/**
35+
* @type object
36+
*/
37+
this.options = arguments;
38+
}
39+
40+
get arguments() {
41+
return { bar: {} };
42+
}
43+
}
44+
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1+
tests/cases/compiler/export.js(1,13): error TS2451: Cannot redeclare block-scoped variable 'foo'.
12
tests/cases/compiler/export.js(1,13): error TS8008: Type aliases can only be used in TypeScript files.
3+
tests/cases/compiler/export.js(6,14): error TS2451: Cannot redeclare block-scoped variable 'foo'.
24

35

4-
==== tests/cases/compiler/export.js (1 errors) ====
6+
==== tests/cases/compiler/export.js (3 errors) ====
57
export type foo = 5;
68
~~~
9+
!!! error TS2451: Cannot redeclare block-scoped variable 'foo'.
10+
~~~
711
!!! error TS8008: Type aliases can only be used in TypeScript files.
812
/**
913
* @typedef {{
1014
* }}
1115
*/
12-
export const foo = 5;
16+
export const foo = 5;
17+
~~~
18+
!!! error TS2451: Cannot redeclare block-scoped variable 'foo'.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js(1,1): error TS2528: A module cannot have multiple default exports.
2+
tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js(2,1): error TS2528: A module cannot have multiple default exports.
3+
tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js(3,7): error TS1262: Identifier expected. 'await' is a reserved word at the top-level of a module.
4+
tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js(4,7): error TS1214: Identifier expected. 'yield' is a reserved word in strict mode. Modules are automatically in strict mode.
5+
tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js(6,11): error TS1359: Identifier expected. 'await' is a reserved word that cannot be used here.
6+
tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js(9,11): error TS1214: Identifier expected. 'yield' is a reserved word in strict mode. Modules are automatically in strict mode.
7+
8+
9+
==== tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js (6 errors) ====
10+
export default 12
11+
~~~~~~~~~~~~~~~~~
12+
!!! error TS2528: A module cannot have multiple default exports.
13+
!!! related TS2753 tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js:2:1: Another export default is here.
14+
export default 13
15+
~~~~~~~~~~~~~~~~~
16+
!!! error TS2528: A module cannot have multiple default exports.
17+
!!! related TS2752 tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js:1:1: The first export default is here.
18+
const await = 1
19+
~~~~~
20+
!!! error TS1262: Identifier expected. 'await' is a reserved word at the top-level of a module.
21+
const yield = 2
22+
~~~~~
23+
!!! error TS1214: Identifier expected. 'yield' is a reserved word in strict mode. Modules are automatically in strict mode.
24+
async function f() {
25+
const await = 3
26+
~~~~~
27+
!!! error TS1359: Identifier expected. 'await' is a reserved word that cannot be used here.
28+
}
29+
function* g() {
30+
const yield = 4
31+
~~~~~
32+
!!! error TS1214: Identifier expected. 'yield' is a reserved word in strict mode. Modules are automatically in strict mode.
33+
}
34+
class C {
35+
#constructor = 1
36+
}
37+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//// [plainJSMultipleDefaultExport.js]
2+
export default 12
3+
export default 13
4+
const await = 1
5+
const yield = 2
6+
async function f() {
7+
const await = 3
8+
}
9+
function* g() {
10+
const yield = 4
11+
}
12+
class C {
13+
#constructor = 1
14+
}
15+
16+
17+
//// [plainJSMultipleDefaultExport.js]
18+
export default 12;
19+
export default 13;
20+
const await = 1;
21+
const yield = 2;
22+
async function f() {
23+
const await = 3;
24+
}
25+
function* g() {
26+
const yield = 4;
27+
}
28+
class C {
29+
#constructor = 1;
30+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
=== tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js ===
2+
export default 12
3+
export default 13
4+
const await = 1
5+
>await : Symbol(await, Decl(plainJSMultipleDefaultExport.js, 2, 5))
6+
7+
const yield = 2
8+
>yield : Symbol(yield, Decl(plainJSMultipleDefaultExport.js, 3, 5))
9+
10+
async function f() {
11+
>f : Symbol(f, Decl(plainJSMultipleDefaultExport.js, 3, 15))
12+
13+
const await = 3
14+
>await : Symbol(await, Decl(plainJSMultipleDefaultExport.js, 5, 9))
15+
}
16+
function* g() {
17+
>g : Symbol(g, Decl(plainJSMultipleDefaultExport.js, 6, 1))
18+
19+
const yield = 4
20+
>yield : Symbol(yield, Decl(plainJSMultipleDefaultExport.js, 8, 9))
21+
}
22+
class C {
23+
>C : Symbol(C, Decl(plainJSMultipleDefaultExport.js, 9, 1))
24+
25+
#constructor = 1
26+
>#constructor : Symbol(C.#constructor, Decl(plainJSMultipleDefaultExport.js, 10, 9))
27+
}
28+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/conformance/salsa/plainJSMultipleDefaultExport.js ===
2+
export default 12
3+
export default 13
4+
const await = 1
5+
>await : 1
6+
>1 : 1
7+
8+
const yield = 2
9+
>yield : 2
10+
>2 : 2
11+
12+
async function f() {
13+
>f : () => Promise<void>
14+
15+
const await = 3
16+
>await : 3
17+
>3 : 3
18+
}
19+
function* g() {
20+
>g : () => Generator<never, void, unknown>
21+
22+
const yield = 4
23+
>yield : 4
24+
>4 : 4
25+
}
26+
class C {
27+
>C : C
28+
29+
#constructor = 1
30+
>#constructor : number
31+
>1 : 1
32+
}
33+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
tests/cases/conformance/salsa/plainJSRedeclare.js(1,7): error TS2451: Cannot redeclare block-scoped variable 'orbitol'.
2+
tests/cases/conformance/salsa/plainJSRedeclare.js(2,5): error TS2451: Cannot redeclare block-scoped variable 'orbitol'.
3+
4+
5+
==== tests/cases/conformance/salsa/plainJSRedeclare.js (2 errors) ====
6+
const orbitol = 1
7+
~~~~~~~
8+
!!! error TS2451: Cannot redeclare block-scoped variable 'orbitol'.
9+
var orbitol = 1 + false
10+
~~~~~~~
11+
!!! error TS2451: Cannot redeclare block-scoped variable 'orbitol'.
12+
orbitol.toExponential()
13+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//// [plainJSRedeclare.js]
2+
const orbitol = 1
3+
var orbitol = 1 + false
4+
orbitol.toExponential()
5+
6+
7+
//// [plainJSRedeclare.js]
8+
var orbitol = 1;
9+
var orbitol = 1 + false;
10+
orbitol.toExponential();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=== tests/cases/conformance/salsa/plainJSRedeclare.js ===
2+
const orbitol = 1
3+
>orbitol : Symbol(orbitol, Decl(plainJSRedeclare.js, 0, 5))
4+
5+
var orbitol = 1 + false
6+
>orbitol : Symbol(orbitol, Decl(plainJSRedeclare.js, 1, 3))
7+
8+
orbitol.toExponential()
9+
>orbitol.toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
10+
>orbitol : Symbol(orbitol, Decl(plainJSRedeclare.js, 0, 5))
11+
>toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
12+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
=== tests/cases/conformance/salsa/plainJSRedeclare.js ===
2+
const orbitol = 1
3+
>orbitol : 1
4+
>1 : 1
5+
6+
var orbitol = 1 + false
7+
>orbitol : any
8+
>1 + false : any
9+
>1 : 1
10+
>false : false
11+
12+
orbitol.toExponential()
13+
>orbitol.toExponential() : string
14+
>orbitol.toExponential : (fractionDigits?: number) => string
15+
>orbitol : 1
16+
>toExponential : (fractionDigits?: number) => string
17+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
tests/cases/conformance/salsa/plainJSRedeclare.js(1,7): error TS2451: Cannot redeclare block-scoped variable 'orbitol'.
2+
tests/cases/conformance/salsa/plainJSRedeclare.js(2,5): error TS2451: Cannot redeclare block-scoped variable 'orbitol'.
3+
tests/cases/conformance/salsa/plainJSRedeclare.js(2,15): error TS2365: Operator '+' cannot be applied to types 'number' and 'boolean'.
4+
5+
6+
==== tests/cases/conformance/salsa/plainJSRedeclare.js (3 errors) ====
7+
const orbitol = 1
8+
~~~~~~~
9+
!!! error TS2451: Cannot redeclare block-scoped variable 'orbitol'.
10+
var orbitol = 1 + false
11+
~~~~~~~
12+
!!! error TS2451: Cannot redeclare block-scoped variable 'orbitol'.
13+
~~~~~~~~~
14+
!!! error TS2365: Operator '+' cannot be applied to types 'number' and 'boolean'.
15+
orbitol.toExponential()
16+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//// [plainJSRedeclare.js]
2+
const orbitol = 1
3+
var orbitol = 1 + false
4+
orbitol.toExponential()
5+
6+
7+
//// [plainJSRedeclare.js]
8+
var orbitol = 1;
9+
var orbitol = 1 + false;
10+
orbitol.toExponential();

0 commit comments

Comments
 (0)