Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: detect variable usage before initialization #458

Open
bunglegrind opened this issue Mar 16, 2024 · 9 comments
Open

Regression: detect variable usage before initialization #458

bunglegrind opened this issue Mar 16, 2024 · 9 comments

Comments

@bunglegrind
Copy link

As the title stated:

no error/warning in jslint

const a = b + 3;
const b = 1;

but, of course, when executed (node 20):


const a = b + 3;
          ^

ReferenceError: Cannot access 'b' before initialization

Is it possible to detect such kind of mistakes via linting?

@bunglegrind
Copy link
Author

bunglegrind commented Mar 16, 2024

Well, just tested on the branch-v2014.7.8 version (with var instead of const obviously) and jslint warns about the uninitialized variable. So, I'm assuming it's a regression, not a new feature... (version 2020.11.6 however does not warn).

@bunglegrind bunglegrind changed the title Feature request: detect variable usage before initialization Regression (?): detect variable usage before initialization Mar 16, 2024
@kaizhu256
Copy link
Member

@@ -3220,7 +3241,9 @@ function do_var() {
             }
             enroll(name, "variable", is_const);
             if (next_token.id === "=" || is_const) {
+                implied_strict = true;
                 advance("=");
+                name.dead = false;
                 name.init = true;
                 name.expression = expression(0);
             }
  • am hesitant to revert, since i don't fully understand its side-effects

@bunglegrind
Copy link
Author

Sorry, I don't have any clue.
The only suggestion I have is to write tests (many?) in order to reduce other regressions chance

@bunglegrind
Copy link
Author

jamesdiacono/JSLint@5170d8e

@jamesdiacono
Same bug?

@jamesdiacono
Copy link

Yes. Funny that nobody noticed it for 4 years?

@bunglegrind bunglegrind changed the title Regression (?): detect variable usage before initialization Regression: detect variable usage before initialization Mar 19, 2024
@kaizhu256
Copy link
Member

  • @jamesdiacono can you submit a patch to beta branch and take credit for work already done?

  • here's a starting point to apply to current jslint.mjs (admittedly, i don't fully understand it ^^;;;)

git diff
diff --git a/jslint.mjs b/jslint.mjs
index 8abd882..d8f7413 100644
--- a/jslint.mjs
+++ b/jslint.mjs
@@ -5147,6 +5147,7 @@ function jslint_phase3_parse(state) {
                 the_label.dead = false;
                 the_label.init = true;
                 the_statement = parse_statement();
+                the_label.dead = true;
                 functionage.statement_prv = the_statement;
                 the_statement.label = the_label;
                 the_statement.statement = true;
@@ -5193,9 +5194,6 @@ function jslint_phase3_parse(state) {
             }
             semicolon();
         }
-        if (the_label !== undefined) {
-            the_label.dead = true;
-        }
         return the_statement;
     }

@@ -6976,7 +6974,6 @@ function jslint_phase3_parse(state) {
                         the_variable.names.push(name);
                         enroll(name, "variable", mode_const);
                     }
-                    name.dead = false;
                     name.init = true;
                     if (token_nxt.id === "=") {

@@ -7028,7 +7025,6 @@ function jslint_phase3_parse(state) {
                     advance();
                     the_variable.names.push(name);
                     enroll(name, "variable", mode_const);
-                    name.dead = false;
                     name.init = true;
                     if (ellipsis) {
                         name.ellipsis = true;
@@ -7062,7 +7058,6 @@ function jslint_phase3_parse(state) {
                 enroll(name, "variable", mode_const);
                 if (token_nxt.id === "=" || mode_const) {
                     advance("=");
-                    name.dead = false;
                     name.init = true;
                     name.expression = parse_expression(0);
                 }
  • can help on writing / fixing tests once the initial pr is created

@jamesdiacono
Copy link

You are absolutely welcome to use any of the commits from my fork, no need to credit me.

@bunglegrind
Copy link
Author

@kaizhu256 about the tests...I don't understand how they work. I couldn't find any hint in the documentation.

For instance, how I write that

const a = b;
const b = 1;

should raise an error?

@kaizhu256
Copy link
Member

kaizhu256 commented Apr 1, 2024

  • the following patch would add test-cases for const

  • EDIT: sorry for lack of documentation, but but here's general signature:

// test_cause:
[
    "<expression>",
    "<calling function>",
    "<warning_code>",
    "<warning_argument>",
    <column where error occurred>
]
--- a/jslint.mjs
+++ b/jslint.mjs
@@ -5147,6 +5147,7 @@ function jslint_phase3_parse(state) {
                 the_label.dead = false;
                 the_label.init = true;
                 the_statement = parse_statement();
+                the_label.dead = true;
                 functionage.statement_prv = the_statement;
                 the_statement.label = the_label;
                 the_statement.statement = true;
@@ -5193,9 +5194,6 @@ function jslint_phase3_parse(state) {
             }
             semicolon();
         }
-        if (the_label !== undefined) {
-            the_label.dead = true;
-        }
         return the_statement;
     }

@@ -6969,15 +6967,17 @@ function jslint_phase3_parse(state) {
                         the_variable.names.push(name);
                         survey(name);
                         enroll(name, "variable", mode_const);
-
                         advance();
                         the_brace.open = true;
                     } else {
                         the_variable.names.push(name);
                         enroll(name, "variable", mode_const);
                     }
-                    name.dead = false;
                     name.init = true;
+
+// test_cause:
+// ["const {aa}=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 12]
+
                     if (token_nxt.id === "=") {

 // test_cause:
@@ -7028,8 +7028,11 @@ function jslint_phase3_parse(state) {
                     advance();
                     the_variable.names.push(name);
                     enroll(name, "variable", mode_const);
-                    name.dead = false;
                     name.init = true;
+
+// test_cause:
+// ["const [aa]=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 12]
+
                     if (ellipsis) {
                         name.ellipsis = true;
                         break;
@@ -7062,8 +7065,11 @@ function jslint_phase3_parse(state) {
                 enroll(name, "variable", mode_const);
                 if (token_nxt.id === "=" || mode_const) {
                     advance("=");
-                    name.dead = false;
                     name.init = true;
+
+// test_cause:
+// ["const aa=bb;\nconst bb=0;", "lookup", "out_of_scope_a", "bb", 10]
+
                     name.expression = parse_expression(0);
                 }
                 the_variable.names.push(name);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants