eslint-plugin-etc-misc 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +3 -0
  2. package/dist/configs/all-strict.d.ts +1 -0
  3. package/dist/configs/all-strict.d.ts.map +1 -1
  4. package/dist/configs/all-strict.js +1 -0
  5. package/dist/configs/all-strict.js.map +1 -1
  6. package/dist/configs/all.d.ts +1 -0
  7. package/dist/configs/all.d.ts.map +1 -1
  8. package/dist/configs/all.js +1 -0
  9. package/dist/configs/all.js.map +1 -1
  10. package/dist/configs/minimal.d.ts +3 -0
  11. package/dist/configs/minimal.d.ts.map +1 -1
  12. package/dist/configs/minimal.js +3 -0
  13. package/dist/configs/minimal.js.map +1 -1
  14. package/dist/configs/recommended.d.ts +3 -0
  15. package/dist/configs/recommended.d.ts.map +1 -1
  16. package/dist/configs/recommended.js +3 -0
  17. package/dist/configs/recommended.js.map +1 -1
  18. package/dist/configs/strict-type-checked.d.ts +1 -0
  19. package/dist/configs/strict-type-checked.d.ts.map +1 -1
  20. package/dist/configs/strict-type-checked.js +1 -0
  21. package/dist/configs/strict-type-checked.js.map +1 -1
  22. package/dist/configs/strict.d.ts +1 -0
  23. package/dist/configs/strict.d.ts.map +1 -1
  24. package/dist/configs/strict.js +1 -0
  25. package/dist/configs/strict.js.map +1 -1
  26. package/dist/configs.d.ts +8 -7
  27. package/dist/configs.d.ts.map +1 -1
  28. package/dist/configs.js +1 -0
  29. package/dist/configs.js.map +1 -1
  30. package/dist/plugin.cjs +967 -404
  31. package/dist/plugin.cjs.map +4 -4
  32. package/dist/rules/no-commented-out-code.d.ts.map +1 -1
  33. package/dist/rules/no-commented-out-code.js.map +1 -1
  34. package/dist/rules/no-function-declare-after-return.d.ts +19 -0
  35. package/dist/rules/no-function-declare-after-return.d.ts.map +1 -0
  36. package/dist/rules/no-function-declare-after-return.js +119 -0
  37. package/dist/rules/no-function-declare-after-return.js.map +1 -0
  38. package/dist/rules/no-use-extend-native.d.ts +9 -0
  39. package/dist/rules/no-use-extend-native.d.ts.map +1 -0
  40. package/dist/rules/no-use-extend-native.js +296 -0
  41. package/dist/rules/no-use-extend-native.js.map +1 -0
  42. package/dist/rules/no-vulnerable.d.ts +15 -0
  43. package/dist/rules/no-vulnerable.d.ts.map +1 -0
  44. package/dist/rules/no-vulnerable.js +182 -0
  45. package/dist/rules/no-vulnerable.js.map +1 -0
  46. package/dist/rules.d.ts.map +1 -1
  47. package/dist/rules.js +8 -0
  48. package/dist/rules.js.map +1 -1
  49. package/docs/docusaurus/package.json +5 -5
  50. package/docs/docusaurus/src/components/GitHubStats.jsx +2 -1
  51. package/docs/docusaurus/src/components/GitHubStats.module.css.d.ts +7 -0
  52. package/docs/docusaurus/src/css/custom.css.d.ts +3 -0
  53. package/docs/docusaurus/src/pages/index.module.css +23 -12
  54. package/docs/docusaurus/src/pages/index.module.css.d.ts +6 -11
  55. package/docs/rules/no-function-declare-after-return.md +143 -0
  56. package/docs/rules/no-use-extend-native.md +89 -0
  57. package/docs/rules/no-vulnerable.md +110 -0
  58. package/package.json +32 -221
@@ -0,0 +1,143 @@
1
+ # no-function-declare-after-return
2
+
3
+ Disallow function declarations that appear after a `return` statement in the same block scope.
4
+
5
+ ## Rule details
6
+
7
+ JavaScript hoists `function` declarations to the top of their enclosing scope,
8
+ which means the following code is syntactically valid and runs without errors:
9
+
10
+ ```ts
11
+ function publicMethods(obj) {
12
+ if (obj instanceof CustomClass) {
13
+ return {
14
+ get: methodGetter(obj), // ← called before its declaration ❌
15
+ };
16
+ }
17
+ function methodGetter(obj) { // ← declared after the return
18
+ // …
19
+ }
20
+ }
21
+ ```
22
+
23
+ Even though this works at runtime, it is a readability trap:
24
+
25
+ - A reader scanning the function top-to-bottom will encounter the call to
26
+ `methodGetter` before they see its definition.
27
+ - Newcomers unfamiliar with hoisting may not realize `methodGetter` is even in
28
+ scope at the call site.
29
+ - Linters such as `no-unreachable` do not flag this because the declaration is
30
+ not unreachable — it is hoisted.
31
+
32
+ This rule enforces that every `FunctionDeclaration` is placed **before** any
33
+ `ReturnStatement` in the same block scope, making hoisting irrelevant from a
34
+ readability perspective.
35
+
36
+ ### Scope boundaries
37
+
38
+ This rule reports only when the function declaration is a **direct sibling** of
39
+ the `return` statement in the same statement list (`BlockStatement` or
40
+ `Program`).
41
+
42
+ - `return` inside `switch` cases is out of scope for this rule.
43
+ - Function declarations nested inside later `if`/`try`/`for` blocks are not directly targeted by this rule.
44
+
45
+ > **Note:** This rule targets only `FunctionDeclaration` nodes. Arrow functions,
46
+ > function expressions, generator functions, and async function expressions
47
+ > assigned to variables are **not** flagged — those are expression statements and
48
+ > are genuinely unreachable. Use `no-unreachable` for those cases.
49
+
50
+ ## ❌ Incorrect
51
+
52
+ ```ts
53
+ function outer() {
54
+ return 42;
55
+ function helper() {} // ← 'helper' should be moved before the return
56
+ }
57
+ ```
58
+
59
+ ```ts
60
+ function publicMethods(obj) {
61
+ if (obj) {
62
+ return {
63
+ set: methodSetter(obj),
64
+ get: methodGetter(obj),
65
+ };
66
+ function methodSetter(obj) { /* … */ } // ← should be before return
67
+ function methodGetter(obj) { /* … */ } // ← should be before return
68
+ }
69
+ }
70
+ ```
71
+
72
+ ## ✅ Correct
73
+
74
+ ```ts
75
+ function outer() {
76
+ function helper() {} // ← declared before the return
77
+ return helper();
78
+ }
79
+ ```
80
+
81
+ ```ts
82
+ function publicMethods(obj) {
83
+ function methodSetter(obj) { /* … */ } // ← before the return
84
+ function methodGetter(obj) { /* … */ } // ← before the return
85
+ if (obj) {
86
+ return {
87
+ set: methodSetter(obj),
88
+ get: methodGetter(obj),
89
+ };
90
+ }
91
+ }
92
+ ```
93
+
94
+ ```ts
95
+ // Arrow functions and function expressions after return are NOT flagged —
96
+ // use no-unreachable for those.
97
+ function outer() {
98
+ return 1;
99
+ const arrow = () => {}; // not a FunctionDeclaration — not flagged here
100
+ }
101
+ ```
102
+
103
+ ## Autofix
104
+
105
+ This rule provides an **autofix**. When triggered, it moves the offending
106
+ `FunctionDeclaration` to immediately before the `ReturnStatement`, preserving
107
+ the correct indentation level.
108
+
109
+ When a function declaration has leading comments (including JSDoc), the fixer
110
+ moves those comments together with the declaration.
111
+
112
+ ## Options
113
+
114
+ This rule has no options.
115
+
116
+ ## When not to use it
117
+
118
+ - If your team relies on intentional hoisting patterns with thorough documentation,
119
+ you may disable this rule.
120
+ - If the function declaration lives in a different block scope from the return
121
+ statement (e.g., hoisted to the outer function while the return is inside an
122
+ `if`-block), the fix may require manual review to confirm the intended
123
+ placement.
124
+
125
+ ## Further reading
126
+
127
+ - [MDN: Function declarations — Hoisting](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#hoisting)
128
+ - [ESLint built-in: `no-unreachable`](https://eslint.org/docs/rules/no-unreachable)
129
+
130
+ ## ESLint flat config example
131
+
132
+ ```ts
133
+ import etcMisc from "eslint-plugin-etc-misc";
134
+
135
+ export default [
136
+ {
137
+ plugins: { "etc-misc": etcMisc },
138
+ rules: {
139
+ "etc-misc/no-function-declare-after-return": "warn",
140
+ },
141
+ },
142
+ ];
143
+ ```
@@ -0,0 +1,89 @@
1
+ # no-use-extend-native
2
+
3
+ Disallow usage of non-native members on built-in JavaScript objects.
4
+
5
+ ## Rule details
6
+
7
+ This rule helps prevent implicit reliance on monkey-patched native prototypes (for example from legacy libraries that add methods like `String.prototype.green`).
8
+
9
+ Relying on extended native objects can make code unpredictable across runtimes, bundling targets, and dependency versions.
10
+
11
+ This rule reports member usage on obvious built-in values when the accessed member is not part of the native API.
12
+
13
+ ## Targeted pattern scope
14
+
15
+ This rule is intentionally conservative and focuses on obvious built-in object shapes such as:
16
+
17
+ - String/number/boolean/regexp literals.
18
+ - Array/object literals.
19
+ - `new` expressions for built-ins.
20
+ - `String.prototype.<member>` / `Array.prototype.<member>` style accesses.
21
+
22
+ It does **not** attempt full-flow inference for arbitrary identifiers.
23
+
24
+ ## ❌ Incorrect
25
+
26
+ ```ts
27
+ const value = "unicorn".green;
28
+ ```
29
+
30
+ ```ts
31
+ const value = [].customFunction();
32
+ ```
33
+
34
+ ```ts
35
+ const value = String.prototype.shortHash();
36
+ ```
37
+
38
+ ## ✅ Correct
39
+
40
+ ```ts
41
+ const value = "unicorn".toUpperCase();
42
+ ```
43
+
44
+ ```ts
45
+ const value = [].map((entry) => entry);
46
+ ```
47
+
48
+ ```ts
49
+ const value = String.prototype.toLowerCase.call("ABC");
50
+ ```
51
+
52
+ ## Options
53
+
54
+ This rule has no options.
55
+
56
+ ## Relationship to ESLint `no-extend-native`
57
+
58
+ - ESLint core [`no-extend-native`](https://eslint.org/docs/latest/rules/no-extend-native) prevents adding properties to native prototypes.
59
+ - This rule prevents consuming non-native members when they appear in code.
60
+
61
+ Using both rules together gives better protection:
62
+
63
+ 1. Prevent introducing prototype extension.
64
+ 2. Prevent relying on prototype extension from third-party code.
65
+
66
+ ## When not to use it
67
+
68
+ - If your project intentionally and explicitly relies on controlled prototype extension.
69
+ - If your runtime environment guarantees specific prototype patches and that dependency is accepted in your architecture.
70
+
71
+ ## Further reading
72
+
73
+ - [ESLint `no-extend-native`](https://eslint.org/docs/latest/rules/no-extend-native)
74
+ - [MDN: Inheritance and the prototype chain](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)
75
+
76
+ ## ESLint flat config example
77
+
78
+ ```ts
79
+ import etcMisc from "eslint-plugin-etc-misc";
80
+
81
+ export default [
82
+ {
83
+ plugins: { "etc-misc": etcMisc },
84
+ rules: {
85
+ "etc-misc/no-use-extend-native": "error",
86
+ },
87
+ },
88
+ ];
89
+ ```
@@ -0,0 +1,110 @@
1
+ # no-vulnerable
2
+
3
+ Disallow regular expressions that are potentially vulnerable to ReDoS (Regular Expression Denial of Service).
4
+
5
+ ## Rule details
6
+
7
+ This rule analyzes regular expression literals and statically-resolvable `RegExp(...)` constructor calls using [`recheck`](https://www.npmjs.com/package/recheck).
8
+
9
+ Catastrophic backtracking can make an application spend excessive CPU time on crafted inputs. In server contexts, that can become an availability issue.
10
+
11
+ This rule reports patterns that `recheck` identifies as vulnerable with polynomial or exponential complexity.
12
+
13
+ ## What this rule checks
14
+
15
+ This rule checks:
16
+
17
+ - `/(...)/flags` literals.
18
+ - `RegExp("...")` and `new RegExp("...", "flags")` when both arguments are statically-known strings.
19
+
20
+ This rule intentionally skips dynamic patterns/flags it cannot resolve safely at lint time.
21
+
22
+ ## ❌ Incorrect
23
+
24
+ ```ts
25
+ const unsafe = /(a+)+$/;
26
+ ```
27
+
28
+ ```ts
29
+ const unsafe = RegExp("(a+)+$");
30
+ ```
31
+
32
+ ```ts
33
+ const unsafe = new RegExp("(a+)+$", "u");
34
+ ```
35
+
36
+ ## ✅ Correct
37
+
38
+ ```ts
39
+ const safe = /^a+$/;
40
+ ```
41
+
42
+ ```ts
43
+ const source = getPatternFromConfig();
44
+ const maybeUnsafe = RegExp(source); // Dynamic value: intentionally not analyzed.
45
+ ```
46
+
47
+ ## Options
48
+
49
+ ```ts
50
+ type Options = [
51
+ {
52
+ ignoreErrors?: boolean;
53
+ permittableComplexities?: Array<"polynomial" | "exponential">;
54
+ timeout?: number | null;
55
+ }?,
56
+ ];
57
+ ```
58
+
59
+ ### Default options
60
+
61
+ ```ts
62
+ {
63
+ ignoreErrors: true,
64
+ permittableComplexities: [],
65
+ }
66
+ ```
67
+
68
+ ### `ignoreErrors`
69
+
70
+ When `true` (default), analysis failures from `recheck` are ignored.
71
+ When `false`, analysis failures are reported.
72
+
73
+ ### `permittableComplexities`
74
+
75
+ Allows selected vulnerable complexity classes to pass.
76
+
77
+ For example, to allow polynomial but still report exponential:
78
+
79
+ ```ts
80
+ {
81
+ permittableComplexities: ["polynomial"],
82
+ }
83
+ ```
84
+
85
+ ## When not to use it
86
+
87
+ - If your codebase never handles untrusted input with regexes.
88
+ - If lint-time regex analysis cost is unacceptable for your workflow.
89
+ - If you prefer running ReDoS scanning as a separate CI security step rather than as an ESLint rule.
90
+
91
+ ## Further reading
92
+
93
+ - [OWASP: Regular expression Denial of Service (ReDoS)](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
94
+ - [`recheck` package](https://www.npmjs.com/package/recheck)
95
+ - [MDN: Regular expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions)
96
+
97
+ ## ESLint flat config example
98
+
99
+ ```ts
100
+ import etcMisc from "eslint-plugin-etc-misc";
101
+
102
+ export default [
103
+ {
104
+ plugins: { "etc-misc": etcMisc },
105
+ rules: {
106
+ "etc-misc/no-vulnerable": "error",
107
+ },
108
+ },
109
+ ];
110
+ ```