]> git.proxmox.com Git - pve-eslint.git/blobdiff - eslint/tests/lib/rules/no-use-before-define.js
import 8.3.0 source
[pve-eslint.git] / eslint / tests / lib / rules / no-use-before-define.js
index 152fa991b9f7c96e7259fc8da243d9c7e81cf0d1..ba80e4075c24ce83273ec3825c8b4310d2730cc7 100644 (file)
@@ -20,6 +20,9 @@ const ruleTester = new RuleTester();
 
 ruleTester.run("no-use-before-define", rule, {
     valid: [
+        "unresolved",
+        "Array",
+        "function foo () { arguments; }",
         "var a=10; alert(a);",
         "function b(a) { alert(a); }",
         "Object.hasOwnProperty.call(a);",
@@ -35,6 +38,8 @@ ruleTester.run("no-use-before-define", rule, {
         "var foo = function() { foo(); };",
         "var a; for (a in a) {}",
         { code: "var a; for (a of a) {}", parserOptions: { ecmaVersion: 6 } },
+        { code: "let a; class C { static { a; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { let a; a; } }", parserOptions: { ecmaVersion: 2022 } },
 
         // Block-level bindings
         { code: "\"use strict\"; a(); { function a() {} }", parserOptions: { ecmaVersion: 6 } },
@@ -56,6 +61,154 @@ ruleTester.run("no-use-before-define", rule, {
             code: "var foo = () => bar; var bar;",
             options: [{ variables: false }],
             parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "class C { static { () => foo; let foo; } }",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+
+        // Tests related to class definition evaluation. These are not TDZ errors.
+        { code: "class C extends (class { method() { C; } }) {}", parserOptions: { ecmaVersion: 6 } },
+        { code: "(class extends (class { method() { C; } }) {});", parserOptions: { ecmaVersion: 6 } },
+        { code: "const C = (class extends (class { method() { C; } }) {});", parserOptions: { ecmaVersion: 6 } },
+        { code: "class C extends (class { field = C; }) {}", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class extends (class { field = C; }) {});", parserOptions: { ecmaVersion: 2022 } },
+        { code: "const C = (class extends (class { field = C; }) {});", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { [() => C](){} }", parserOptions: { ecmaVersion: 6 } },
+        { code: "(class C { [() => C](){} });", parserOptions: { ecmaVersion: 6 } },
+        { code: "const C = class { [() => C](){} };", parserOptions: { ecmaVersion: 6 } },
+        { code: "class C { static [() => C](){} }", parserOptions: { ecmaVersion: 6 } },
+        { code: "(class C { static [() => C](){} });", parserOptions: { ecmaVersion: 6 } },
+        { code: "const C = class { static [() => C](){} };", parserOptions: { ecmaVersion: 6 } },
+        { code: "class C { [() => C]; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { [() => C]; });", parserOptions: { ecmaVersion: 2022 } },
+        { code: "const C = class { [() => C]; };", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static [() => C]; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { static [() => C]; });", parserOptions: { ecmaVersion: 2022 } },
+        { code: "const C = class { static [() => C]; };", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { method() { C; } }", parserOptions: { ecmaVersion: 6 } },
+        { code: "(class C { method() { C; } });", parserOptions: { ecmaVersion: 6 } },
+        { code: "const C = class { method() { C; } };", parserOptions: { ecmaVersion: 6 } },
+        { code: "class C { static method() { C; } }", parserOptions: { ecmaVersion: 6 } },
+        { code: "(class C { static method() { C; } });", parserOptions: { ecmaVersion: 6 } },
+        { code: "const C = class { static method() { C; } };", parserOptions: { ecmaVersion: 6 } },
+        { code: "class C { field = C; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { field = C; });", parserOptions: { ecmaVersion: 2022 } },
+        { code: "const C = class { field = C; };", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static field = C; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { static field = C; });", parserOptions: { ecmaVersion: 2022 } }, // `const C = class { static field = C; };` is TDZ error
+        { code: "class C { static field = class { static field = C; }; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { static field = class { static field = C; }; });", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { field = () => C; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { field = () => C; });", parserOptions: { ecmaVersion: 2022 } },
+        { code: "const C = class { field = () => C; };", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static field = () => C; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { static field = () => C; });", parserOptions: { ecmaVersion: 2022 } },
+        { code: "const C = class { static field = () => C; };", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { field = class extends C {}; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { field = class extends C {}; });", parserOptions: { ecmaVersion: 2022 } },
+        { code: "const C = class { field = class extends C {}; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static field = class extends C {}; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { static field = class extends C {}; });", parserOptions: { ecmaVersion: 2022 } }, // `const C = class { static field = class extends C {}; };` is TDZ error
+        { code: "class C { static field = class { [C]; }; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "(class C { static field = class { [C]; }; });", parserOptions: { ecmaVersion: 2022 } }, // `const C = class { static field = class { [C]; } };` is TDZ error
+        { code: "const C = class { static field = class { field = C; }; };", parserOptions: { ecmaVersion: 2022 } },
+        {
+            code: "class C { method() { a; } } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "class C { static method() { a; } } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "class C { field = a; } let a;", // `class C { static field = a; } let a;` is TDZ error
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { field = D; } class D {}", // `class C { static field = D; } class D {}` is TDZ error
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { field = class extends D {}; } class D {}", // `class C { static field = class extends D {}; } class D {}` is TDZ error
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { field = () => a; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static field = () => a; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { field = () => D; } class D {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static field = () => D; } class D {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static field = class { field = a; }; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { C; } }", // `const C = class { static { C; } }` is TDZ error
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { C; } static {} static { C; } }",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "(class C { static { C; } })",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { class D extends C {} } }",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { (class { static { C } }) } }",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { () => C; } }",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "(class C { static { () => C; } })",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "const C = class { static { () => C; } }",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { () => D; } } class D {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { () => a; } } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "const C = class C { static { C.x; } }",
+            parserOptions: { ecmaVersion: 2022 }
         }
     ],
     invalid: [
@@ -495,6 +648,480 @@ ruleTester.run("no-use-before-define", rule, {
                 messageId: "usedBeforeDefined",
                 data: { name: "x" }
             }]
+        },
+
+        // Tests related to class definition evaluation. These are TDZ errors.
+        {
+            code: "class C extends C {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class extends C {};",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C extends (class { [C](){} }) {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class extends (class { [C](){} }) {};",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C extends (class { static field = C; }) {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class extends (class { static field = C; }) {};",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C { [C](){} }",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "(class C { [C](){} });",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { [C](){} };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C { static [C](){} }",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "(class C { static [C](){} });",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { static [C](){} };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C { [C]; }",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "(class C { [C]; });",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { [C]; };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C { [C] = foo; }",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "(class C { [C] = foo; });",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { [C] = foo; };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C { static [C]; }",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "(class C { static [C]; });",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { static [C]; };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C { static [C] = foo; }",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "(class C { static [C] = foo; });",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { static [C] = foo; };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { static field = C; };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { static field = class extends C {}; };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { static field = class { [C]; } };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { static field = class { static field = C; }; };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C extends D {} class D {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "D" }
+            }]
+        },
+        {
+            code: "class C extends (class { [a](){} }) {} let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C extends (class { static field = a; }) {} let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { [a]() {} } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { static [a]() {} } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { [a]; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { static [a]; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { [a] = foo; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { static [a] = foo; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { static field = a; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { static field = D; } class D {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "D" }
+            }]
+        },
+        {
+            code: "class C { static field = class extends D {}; } class D {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "D" }
+            }]
+        },
+        {
+            code: "class C { static field = class { [a](){} } } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { static field = class { static field = a; }; } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "const C = class { static { C; } };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "const C = class { static { (class extends C {}); } };",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "C" }
+            }]
+        },
+        {
+            code: "class C { static { a; } } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { static { D; } } class D {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "D" }
+            }]
+        },
+        {
+            code: "class C { static { (class extends D {}); } } class D {}",
+            options: [{ classes: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "D" }
+            }]
+        },
+        {
+            code: "class C { static { (class { [a](){} }); } } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
+        },
+        {
+            code: "class C { static { (class { static field = a; }); } } let a;",
+            options: [{ variables: false }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "usedBeforeDefined",
+                data: { name: "a" }
+            }]
         }
+
+        /*
+         * TODO(mdjermanovic): Add the following test cases once https://github.com/eslint/eslint-scope/issues/59 gets fixed:
+         * {
+         *  code: "(class C extends C {});",
+         *  options: [{ classes: false }],
+         *  parserOptions: { ecmaVersion: 6 },
+         *  errors: [{
+         *      messageId: "usedBeforeDefined",
+         *      data: { name: "C" }
+         *  }]
+         * },
+         * {
+         *  code: "(class C extends (class { [C](){} }) {});",
+         *  options: [{ classes: false }],
+         *  parserOptions: { ecmaVersion: 6 },
+         *  errors: [{
+         *      messageId: "usedBeforeDefined",
+         *      data: { name: "C" }
+         *  }]
+         * },
+         * {
+         *  code: "(class C extends (class { static field = C; }) {});",
+         *  options: [{ classes: false }],
+         *  parserOptions: { ecmaVersion: 2022 },
+         *  errors: [{
+         *      messageId: "usedBeforeDefined",
+         *      data: { name: "C" }
+         *  }]
+         * }
+         */
     ]
 });