eslint 9.39.0 → 10.0.0-alpha.0

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 (42) hide show
  1. package/README.md +3 -3
  2. package/bin/eslint.js +1 -2
  3. package/lib/api.js +4 -15
  4. package/lib/cli.js +14 -56
  5. package/lib/config/config-loader.js +6 -154
  6. package/lib/eslint/eslint-helpers.js +5 -8
  7. package/lib/eslint/eslint.js +1 -1
  8. package/lib/eslint/index.js +0 -2
  9. package/lib/languages/js/source-code/source-code.js +41 -89
  10. package/lib/languages/js/source-code/token-store/utils.js +29 -8
  11. package/lib/linter/apply-disable-directives.js +0 -1
  12. package/lib/linter/file-context.js +0 -56
  13. package/lib/linter/file-report.js +0 -4
  14. package/lib/linter/linter.js +45 -1086
  15. package/lib/linter/rule-fixer.js +30 -0
  16. package/lib/options.js +62 -182
  17. package/lib/rule-tester/rule-tester.js +255 -194
  18. package/lib/rules/dot-notation.js +2 -2
  19. package/lib/rules/func-names.js +2 -0
  20. package/lib/rules/no-eval.js +1 -1
  21. package/lib/rules/no-invalid-regexp.js +1 -0
  22. package/lib/rules/no-shadow-restricted-names.js +1 -1
  23. package/lib/rules/no-unassigned-vars.js +1 -1
  24. package/lib/rules/no-useless-assignment.js +1 -1
  25. package/lib/rules/preserve-caught-error.js +1 -1
  26. package/lib/rules/radix.js +25 -48
  27. package/lib/services/parser-service.js +0 -1
  28. package/lib/services/processor-service.js +0 -1
  29. package/lib/services/warning-service.js +0 -11
  30. package/lib/shared/flags.js +0 -19
  31. package/lib/shared/translate-cli-options.js +106 -164
  32. package/lib/types/index.d.ts +7 -60
  33. package/lib/types/rules.d.ts +11 -2
  34. package/lib/types/use-at-your-own-risk.d.ts +1 -54
  35. package/lib/unsupported-api.js +3 -6
  36. package/package.json +14 -19
  37. package/conf/default-cli-options.js +0 -32
  38. package/lib/cli-engine/cli-engine.js +0 -1109
  39. package/lib/cli-engine/file-enumerator.js +0 -541
  40. package/lib/cli-engine/index.js +0 -7
  41. package/lib/cli-engine/load-rules.js +0 -46
  42. package/lib/eslint/legacy-eslint.js +0 -786
@@ -18,7 +18,8 @@ const assert = require("node:assert"),
18
18
  { Config } = require("../config/config"),
19
19
  { Linter, SourceCodeFixer } = require("../linter"),
20
20
  { interpolate, getPlaceholderMatcher } = require("../linter/interpolate"),
21
- stringify = require("json-stable-stringify-without-jsonify");
21
+ stringify = require("json-stable-stringify-without-jsonify"),
22
+ { isSerializable } = require("../shared/serialization");
22
23
 
23
24
  const { FlatConfigArray } = require("../config/flat-config-array");
24
25
  const {
@@ -30,7 +31,6 @@ const ajv = require("../shared/ajv")({ strictDefaults: true });
30
31
 
31
32
  const parserSymbol = Symbol.for("eslint.RuleTester.parser");
32
33
  const { ConfigArraySymbol } = require("@eslint/config-array");
33
- const { isSerializable } = require("../shared/serialization");
34
34
 
35
35
  const jslang = require("../languages/js");
36
36
  const { SourceCode } = require("../languages/js/source-code");
@@ -78,7 +78,6 @@ const { SourceCode } = require("../languages/js/source-code");
78
78
  * @typedef {Object} TestCaseError
79
79
  * @property {string | RegExp} [message] Message.
80
80
  * @property {string} [messageId] Message ID.
81
- * @property {string} [type] The type of the reported AST node.
82
81
  * @property {{ [name: string]: string }} [data] The data used to fill the message template.
83
82
  * @property {number} [line] The 1-based line number of the reported start location.
84
83
  * @property {number} [column] The 1-based column number of the reported start location.
@@ -125,7 +124,6 @@ const errorObjectParameters = new Set([
125
124
  "message",
126
125
  "messageId",
127
126
  "data",
128
- "type",
129
127
  "line",
130
128
  "column",
131
129
  "endLine",
@@ -145,11 +143,6 @@ const suggestionObjectParameters = new Set([
145
143
  ]);
146
144
  const friendlySuggestionObjectParameterList = `[${[...suggestionObjectParameters].map(key => `'${key}'`).join(", ")}]`;
147
145
 
148
- /*
149
- * Ignored test case properties when checking for test case duplicates.
150
- */
151
- const duplicationIgnoredParameters = new Set(["name", "errors", "output"]);
152
-
153
146
  const forbiddenMethods = [
154
147
  "applyInlineConfig",
155
148
  "applyLanguageOptions",
@@ -375,6 +368,211 @@ const metaSchemaDescription = `
375
368
  \thttps://eslint.org/docs/latest/extend/custom-rules#options-schemas
376
369
  `;
377
370
 
371
+ /*
372
+ * Ignored test case properties when checking for test case duplicates.
373
+ */
374
+ const duplicationIgnoredParameters = new Set(["name", "errors", "output"]);
375
+
376
+ /**
377
+ * Normalizes a test case item, ensuring it is an object with a 'code' property.
378
+ * If the item is not an object, it returns an object with the 'code' property set to the item.
379
+ * @param {any} item The test case item to normalize.
380
+ * @returns {Object} The normalized test case object.
381
+ */
382
+ function normalizeTestCase(item) {
383
+ return item && typeof item === "object" ? item : { code: item };
384
+ }
385
+
386
+ /**
387
+ * Asserts that the `errors` property of an invalid test case is valid.
388
+ * @param {number | string[]} errors The `errors` property of the invalid test case.
389
+ * @param {string} ruleName The name of the rule being tested.
390
+ * @returns {void}
391
+ */
392
+ function assertErrorsProperty(errors, ruleName) {
393
+ const isNumber = typeof errors === "number";
394
+ const isArray = Array.isArray(errors);
395
+
396
+ if (!isNumber && !isArray) {
397
+ if (errors === void 0) {
398
+ assert.fail(
399
+ `Did not specify errors for an invalid test of ${ruleName}`,
400
+ );
401
+ } else {
402
+ assert.fail(
403
+ `Invalid 'errors' property for invalid test of ${ruleName}: expected a number or an array but got ${
404
+ errors === null ? "null" : typeof errors
405
+ }`,
406
+ );
407
+ }
408
+ }
409
+
410
+ if (isArray) {
411
+ assert.ok(
412
+ errors.length !== 0,
413
+ "Invalid cases must have at least one error",
414
+ );
415
+ } else {
416
+ assert.ok(
417
+ errors > 0,
418
+ "Invalid cases must have 'error' value greater than 0",
419
+ );
420
+ }
421
+ }
422
+
423
+ /**
424
+ * Check if this test case is a duplicate of one we have seen before.
425
+ * @param {Object} item test case object
426
+ * @param {Set<string>} seenTestCases set of serialized test cases we have seen so far (managed by this function)
427
+ * @returns {void}
428
+ */
429
+ function checkDuplicateTestCase(item, seenTestCases) {
430
+ if (!isSerializable(item)) {
431
+ /*
432
+ * If we can't serialize a test case (because it contains a function, RegExp, etc), skip the check.
433
+ * This might happen with properties like: options, plugins, settings, languageOptions.parser, languageOptions.parserOptions.
434
+ */
435
+ return;
436
+ }
437
+
438
+ const serializedTestCase = stringify(item, {
439
+ replacer(key, value) {
440
+ // "this" is the currently stringified object --> only ignore top-level properties
441
+ return item !== this || !duplicationIgnoredParameters.has(key)
442
+ ? value
443
+ : void 0;
444
+ },
445
+ });
446
+
447
+ assert(
448
+ !seenTestCases.has(serializedTestCase),
449
+ "detected duplicate test case",
450
+ );
451
+ seenTestCases.add(serializedTestCase);
452
+ }
453
+
454
+ /**
455
+ * Asserts that a rule is valid.
456
+ * A valid rule must be an object with a `create` method.
457
+ * @param {Object} rule The rule to check.
458
+ * @param {string} ruleName The name of the rule.
459
+ * @returns {void}
460
+ * @throws {AssertionError} If the rule is not valid.
461
+ */
462
+ function assertRule(rule, ruleName) {
463
+ assert.ok(
464
+ rule && typeof rule === "object" && typeof rule.create === "function",
465
+ `Rule ${ruleName} must be an object with a \`create\` method`,
466
+ );
467
+ }
468
+
469
+ /**
470
+ * Asserts that a test scenario object is valid.
471
+ * A valid test scenario object must have `valid` and `invalid` properties, both of
472
+ * which must be arrays.
473
+ * @param {Object} test The test scenario object to check.
474
+ * @param {string} ruleName The name of the rule being tested.
475
+ * @returns {void}
476
+ * @throws {AssertionError} If the test scenario object is not valid.
477
+ */
478
+ function assertTest(test, ruleName) {
479
+ assert.ok(
480
+ test && typeof test === "object",
481
+ `Test Scenarios for rule ${ruleName} : Could not find test scenario object`,
482
+ );
483
+
484
+ const hasValid = Array.isArray(test.valid);
485
+ const hasInvalid = Array.isArray(test.invalid);
486
+
487
+ assert.ok(
488
+ hasValid,
489
+ `Test Scenarios for rule ${ruleName} is invalid: Could not find any valid test scenarios`,
490
+ );
491
+
492
+ assert.ok(
493
+ hasInvalid,
494
+ `Test Scenarios for rule ${ruleName} is invalid: Could not find any invalid test scenarios`,
495
+ );
496
+ }
497
+
498
+ /**
499
+ * Asserts that the common properties of a valid/invalid test case have the correct types.
500
+ * @param {Object} item The test case object to check.
501
+ * @returns {void}
502
+ */
503
+ function assertTestCommonProperties(item) {
504
+ assert.ok(
505
+ typeof item.code === "string",
506
+ "Test case must specify a string value for 'code'",
507
+ );
508
+
509
+ // optional properties
510
+ if (item.name) {
511
+ assert.ok(
512
+ typeof item.name === "string",
513
+ "Optional test case property 'name' must be a string",
514
+ );
515
+ }
516
+ if (hasOwnProperty(item, "only")) {
517
+ assert.ok(
518
+ typeof item.only === "boolean",
519
+ "Optional test case property 'only' must be a boolean",
520
+ );
521
+ }
522
+ if (hasOwnProperty(item, "filename")) {
523
+ assert.ok(
524
+ typeof item.filename === "string",
525
+ "Optional test case property 'filename' must be a string",
526
+ );
527
+ }
528
+ if (hasOwnProperty(item, "options")) {
529
+ assert.ok(
530
+ Array.isArray(item.options),
531
+ "Optional test case property 'options' must be an array",
532
+ );
533
+ }
534
+ }
535
+
536
+ /**
537
+ * Asserts that a valid test case object is valid.
538
+ * A valid test case must specify a string value for 'code'.
539
+ * Optional properties are checked for correct types.
540
+ * @param {Object} item The valid test case object to check.
541
+ * @param {Set<string>} seenTestCases Set of serialized test cases to check for duplicates.
542
+ * @returns {void}
543
+ * @throws {AssertionError} If the test case is not valid.
544
+ */
545
+ function assertValidTestCase(item, seenTestCases) {
546
+ assertTestCommonProperties(item);
547
+ checkDuplicateTestCase(item, seenTestCases);
548
+ }
549
+
550
+ /**
551
+ * Asserts that the invalid test case object is valid.
552
+ * An invalid test case must specify a string value for 'code' and must have 'errors' property.
553
+ * Optional properties are checked for correct types.
554
+ * @param {Object} item The invalid test case object to check.
555
+ * @param {Set<string>} seenTestCases Set of serialized test cases to check for duplicates.
556
+ * @param {string} ruleName The name of the rule being tested.
557
+ * @returns {void}
558
+ * @throws {AssertionError} If the test case is not valid.
559
+ */
560
+ function assertInvalidTestCase(item, seenTestCases, ruleName) {
561
+ assertTestCommonProperties(item);
562
+
563
+ assertErrorsProperty(item.errors, ruleName);
564
+
565
+ // 'output' is optional, but if it exists it must be a string or null
566
+ if (hasOwnProperty(item, "output")) {
567
+ assert.ok(
568
+ item.output === null || typeof item.output === "string",
569
+ "Test property 'output', if specified, must be a string or null. If no autofix is expected, then omit the 'output' property or set it to null.",
570
+ );
571
+ }
572
+
573
+ checkDuplicateTestCase(item, seenTestCases);
574
+ }
575
+
378
576
  //------------------------------------------------------------------------------
379
577
  // Public Interface
380
578
  //------------------------------------------------------------------------------
@@ -564,45 +762,11 @@ class RuleTester {
564
762
  */
565
763
  run(ruleName, rule, test) {
566
764
  const testerConfig = this.testerConfig,
567
- requiredScenarios = ["valid", "invalid"],
568
- scenarioErrors = [],
569
765
  linter = this.linter,
570
766
  ruleId = `rule-to-test/${ruleName}`;
571
767
 
572
- const seenValidTestCases = new Set();
573
- const seenInvalidTestCases = new Set();
574
-
575
- if (
576
- !rule ||
577
- typeof rule !== "object" ||
578
- typeof rule.create !== "function"
579
- ) {
580
- throw new TypeError(
581
- "Rule must be an object with a `create` method",
582
- );
583
- }
584
-
585
- if (!test || typeof test !== "object") {
586
- throw new TypeError(
587
- `Test Scenarios for rule ${ruleName} : Could not find test scenario object`,
588
- );
589
- }
590
-
591
- requiredScenarios.forEach(scenarioType => {
592
- if (!test[scenarioType]) {
593
- scenarioErrors.push(
594
- `Could not find any ${scenarioType} test scenarios`,
595
- );
596
- }
597
- });
598
-
599
- if (scenarioErrors.length > 0) {
600
- throw new Error(
601
- [`Test Scenarios for rule ${ruleName} is invalid:`]
602
- .concat(scenarioErrors)
603
- .join("\n"),
604
- );
605
- }
768
+ assertRule(rule, ruleName);
769
+ assertTest(test, ruleName);
606
770
 
607
771
  const baseConfig = [
608
772
  {
@@ -651,14 +815,14 @@ class RuleTester {
651
815
 
652
816
  /**
653
817
  * Runs a hook on the given item when it's assigned to the given property
654
- * @param {string|Object} item Item to run the hook on
818
+ * @param {Object} item Item to run the hook on
655
819
  * @param {string} prop The property having the hook assigned to
656
820
  * @throws {Error} If the property is not a function or that function throws an error
657
821
  * @returns {void}
658
822
  * @private
659
823
  */
660
824
  function runHook(item, prop) {
661
- if (typeof item === "object" && hasOwnProperty(item, prop)) {
825
+ if (hasOwnProperty(item, prop)) {
662
826
  assert.strictEqual(
663
827
  typeof item[prop],
664
828
  "function",
@@ -667,22 +831,26 @@ class RuleTester {
667
831
  item[prop]();
668
832
  }
669
833
  }
670
-
671
834
  /**
672
835
  * Run the rule for the given item
673
- * @param {string|Object} item Item to run the rule against
836
+ * @param {Object} item Item to run the rule against
674
837
  * @throws {Error} If an invalid schema.
675
838
  * @returns {Object} Eslint run result
676
839
  * @private
677
840
  */
678
841
  function runRuleForItem(item) {
842
+ const code = item.code;
843
+ const filename = hasOwnProperty(item, "filename")
844
+ ? item.filename
845
+ : void 0;
846
+ const options = hasOwnProperty(item, "options") ? item.options : [];
679
847
  const flatConfigArrayOptions = {
680
848
  baseConfig,
681
849
  };
682
850
 
683
- if (item.filename) {
851
+ if (filename) {
684
852
  flatConfigArrayOptions.basePath =
685
- path.parse(item.filename).root || void 0;
853
+ path.parse(filename).root || void 0;
686
854
  }
687
855
 
688
856
  const configs = new FlatConfigArray(
@@ -713,54 +881,27 @@ class RuleTester {
713
881
  return calculatedConfig;
714
882
  };
715
883
 
716
- let code, filename, output, beforeAST, afterAST;
717
-
718
- if (typeof item === "string") {
719
- code = item;
720
- } else {
721
- code = item.code;
884
+ let output, beforeAST, afterAST;
722
885
 
723
- /*
724
- * Assumes everything on the item is a config except for the
725
- * parameters used by this tester
726
- */
727
- const itemConfig = { ...item };
728
-
729
- for (const parameter of RuleTesterParameters) {
730
- delete itemConfig[parameter];
731
- }
732
-
733
- /*
734
- * Create the config object from the tester config and this item
735
- * specific configurations.
736
- */
737
- configs.push(itemConfig);
738
- }
886
+ /*
887
+ * Assumes everything on the item is a config except for the
888
+ * parameters used by this tester
889
+ */
890
+ const itemConfig = { ...item };
739
891
 
740
- if (hasOwnProperty(item, "only")) {
741
- assert.ok(
742
- typeof item.only === "boolean",
743
- "Optional test case property 'only' must be a boolean",
744
- );
745
- }
746
- if (hasOwnProperty(item, "filename")) {
747
- assert.ok(
748
- typeof item.filename === "string",
749
- "Optional test case property 'filename' must be a string",
750
- );
751
- filename = item.filename;
892
+ for (const parameter of RuleTesterParameters) {
893
+ delete itemConfig[parameter];
752
894
  }
753
895
 
754
- let ruleConfig = 1;
755
-
756
- if (hasOwnProperty(item, "options")) {
757
- assert(Array.isArray(item.options), "options must be an array");
758
- ruleConfig = [1, ...item.options];
759
- }
896
+ /*
897
+ * Create the config object from the tester config and this item
898
+ * specific configurations.
899
+ */
900
+ configs.push(itemConfig);
760
901
 
761
902
  configs.push({
762
903
  rules: {
763
- [ruleId]: ruleConfig,
904
+ [ruleId]: [1, ...options],
764
905
  },
765
906
  });
766
907
 
@@ -939,64 +1080,14 @@ class RuleTester {
939
1080
  }
940
1081
  }
941
1082
 
942
- /**
943
- * Check if this test case is a duplicate of one we have seen before.
944
- * @param {string|Object} item test case object
945
- * @param {Set<string>} seenTestCases set of serialized test cases we have seen so far (managed by this function)
946
- * @returns {void}
947
- * @private
948
- */
949
- function checkDuplicateTestCase(item, seenTestCases) {
950
- if (!isSerializable(item)) {
951
- /*
952
- * If we can't serialize a test case (because it contains a function, RegExp, etc), skip the check.
953
- * This might happen with properties like: options, plugins, settings, languageOptions.parser, languageOptions.parserOptions.
954
- */
955
- return;
956
- }
957
-
958
- const normalizedItem =
959
- typeof item === "string" ? { code: item } : item;
960
- const serializedTestCase = stringify(normalizedItem, {
961
- replacer(key, value) {
962
- // "this" is the currently stringified object --> only ignore top-level properties
963
- return normalizedItem !== this ||
964
- !duplicationIgnoredParameters.has(key)
965
- ? value
966
- : void 0;
967
- },
968
- });
969
-
970
- assert(
971
- !seenTestCases.has(serializedTestCase),
972
- "detected duplicate test case",
973
- );
974
- seenTestCases.add(serializedTestCase);
975
- }
976
-
977
1083
  /**
978
1084
  * Check if the template is valid or not
979
1085
  * all valid cases go through this
980
- * @param {string|Object} item Item to run the rule against
1086
+ * @param {Object} item Item to run the rule against
981
1087
  * @returns {void}
982
1088
  * @private
983
1089
  */
984
1090
  function testValidTemplate(item) {
985
- const code = typeof item === "object" ? item.code : item;
986
-
987
- assert.ok(
988
- typeof code === "string",
989
- "Test case must specify a string value for 'code'",
990
- );
991
- if (item.name) {
992
- assert.ok(
993
- typeof item.name === "string",
994
- "Optional test case property 'name' must be a string",
995
- );
996
- }
997
-
998
- checkDuplicateTestCase(item, seenValidTestCases);
999
-
1000
1091
  const result = runRuleForItem(item);
1001
1092
  const messages = result.messages;
1002
1093
 
@@ -1037,32 +1128,11 @@ class RuleTester {
1037
1128
  /**
1038
1129
  * Check if the template is invalid or not
1039
1130
  * all invalid cases go through this.
1040
- * @param {string|Object} item Item to run the rule against
1131
+ * @param {Object} item Item to run the rule against
1041
1132
  * @returns {void}
1042
1133
  * @private
1043
1134
  */
1044
1135
  function testInvalidTemplate(item) {
1045
- assert.ok(
1046
- typeof item.code === "string",
1047
- "Test case must specify a string value for 'code'",
1048
- );
1049
- if (item.name) {
1050
- assert.ok(
1051
- typeof item.name === "string",
1052
- "Optional test case property 'name' must be a string",
1053
- );
1054
- }
1055
- assert.ok(
1056
- item.errors || item.errors === 0,
1057
- `Did not specify errors for an invalid test of ${ruleName}`,
1058
- );
1059
-
1060
- if (Array.isArray(item.errors) && item.errors.length === 0) {
1061
- assert.fail("Invalid cases must have at least one error");
1062
- }
1063
-
1064
- checkDuplicateTestCase(item, seenInvalidTestCases);
1065
-
1066
1136
  const ruleHasMetaMessages =
1067
1137
  hasOwnProperty(rule, "meta") &&
1068
1138
  hasOwnProperty(rule.meta, "messages");
@@ -1095,12 +1165,6 @@ class RuleTester {
1095
1165
  }
1096
1166
 
1097
1167
  if (typeof item.errors === "number") {
1098
- if (item.errors === 0) {
1099
- assert.fail(
1100
- "Invalid cases must have 'error' value greater than 0",
1101
- );
1102
- }
1103
-
1104
1168
  assert.strictEqual(
1105
1169
  messages.length,
1106
1170
  item.errors,
@@ -1148,8 +1212,7 @@ class RuleTester {
1148
1212
  } else if (typeof error === "object" && error !== null) {
1149
1213
  /*
1150
1214
  * Error object.
1151
- * This may have a message, messageId, data, node type, line, and/or
1152
- * column.
1215
+ * This may have a message, messageId, data, line, and/or column.
1153
1216
  */
1154
1217
 
1155
1218
  Object.keys(error).forEach(propertyName => {
@@ -1231,14 +1294,6 @@ class RuleTester {
1231
1294
  );
1232
1295
  }
1233
1296
 
1234
- if (error.type) {
1235
- assert.strictEqual(
1236
- message.nodeType,
1237
- error.type,
1238
- `Error type should be ${error.type}, found ${message.nodeType}`,
1239
- );
1240
- }
1241
-
1242
1297
  const actualLocation = {};
1243
1298
  const expectedLocation = {};
1244
1299
 
@@ -1533,19 +1588,18 @@ class RuleTester {
1533
1588
  this.constructor.describe(ruleName, () => {
1534
1589
  if (test.valid.length > 0) {
1535
1590
  this.constructor.describe("valid", () => {
1591
+ const seenTestCases = new Set();
1536
1592
  test.valid.forEach(valid => {
1593
+ const item = normalizeTestCase(valid);
1537
1594
  this.constructor[valid.only ? "itOnly" : "it"](
1538
- sanitize(
1539
- typeof valid === "object"
1540
- ? valid.name || valid.code
1541
- : valid,
1542
- ),
1595
+ sanitize(item.name || item.code),
1543
1596
  () => {
1544
1597
  try {
1545
- runHook(valid, "before");
1546
- testValidTemplate(valid);
1598
+ runHook(item, "before");
1599
+ assertValidTestCase(item, seenTestCases);
1600
+ testValidTemplate(item);
1547
1601
  } finally {
1548
- runHook(valid, "after");
1602
+ runHook(item, "after");
1549
1603
  }
1550
1604
  },
1551
1605
  );
@@ -1555,15 +1609,22 @@ class RuleTester {
1555
1609
 
1556
1610
  if (test.invalid.length > 0) {
1557
1611
  this.constructor.describe("invalid", () => {
1612
+ const seenTestCases = new Set();
1558
1613
  test.invalid.forEach(invalid => {
1559
- this.constructor[invalid.only ? "itOnly" : "it"](
1560
- sanitize(invalid.name || invalid.code),
1614
+ const item = normalizeTestCase(invalid);
1615
+ this.constructor[item.only ? "itOnly" : "it"](
1616
+ sanitize(item.name || item.code),
1561
1617
  () => {
1562
1618
  try {
1563
- runHook(invalid, "before");
1564
- testInvalidTemplate(invalid);
1619
+ runHook(item, "before");
1620
+ assertInvalidTestCase(
1621
+ item,
1622
+ seenTestCases,
1623
+ ruleName,
1624
+ );
1625
+ testInvalidTemplate(item);
1565
1626
  } finally {
1566
- runHook(invalid, "after");
1627
+ runHook(item, "after");
1567
1628
  }
1568
1629
  },
1569
1630
  );
@@ -76,7 +76,7 @@ module.exports = {
76
76
  /**
77
77
  * Check if the property is valid dot notation
78
78
  * @param {ASTNode} node The dot notation node
79
- * @param {string} value Value which is to be checked
79
+ * @param {string|boolean|null} value Value which is to be checked
80
80
  * @returns {void}
81
81
  */
82
82
  function checkComputedProperty(node, value) {
@@ -125,7 +125,7 @@ module.exports = {
125
125
  }
126
126
  yield fixer.replaceTextRange(
127
127
  [leftBracket.range[0], rightBracket.range[1]],
128
- value,
128
+ String(value),
129
129
  );
130
130
 
131
131
  // Insert a space after the property if it will be connected to the next token.
@@ -43,6 +43,7 @@ module.exports = {
43
43
  enum: ["always", "as-needed", "never"],
44
44
  },
45
45
  },
46
+ type: "array",
46
47
  items: [
47
48
  {
48
49
  $ref: "#/definitions/value",
@@ -57,6 +58,7 @@ module.exports = {
57
58
  additionalProperties: false,
58
59
  },
59
60
  ],
61
+ additionalItems: false,
60
62
  },
61
63
 
62
64
  messages: {
@@ -65,7 +65,7 @@ module.exports = {
65
65
  ],
66
66
 
67
67
  messages: {
68
- unexpected: "eval can be harmful.",
68
+ unexpected: "`eval` can be harmful.",
69
69
  },
70
70
  },
71
71
 
@@ -40,6 +40,7 @@ module.exports = {
40
40
  items: {
41
41
  type: "string",
42
42
  },
43
+ uniqueItems: true,
43
44
  },
44
45
  },
45
46
  additionalProperties: false,
@@ -34,7 +34,7 @@ module.exports = {
34
34
 
35
35
  defaultOptions: [
36
36
  {
37
- reportGlobalThis: false,
37
+ reportGlobalThis: true,
38
38
  },
39
39
  ],
40
40
 
@@ -18,7 +18,7 @@ module.exports = {
18
18
  docs: {
19
19
  description:
20
20
  "Disallow `let` or `var` variables that are read but never assigned",
21
- recommended: false,
21
+ recommended: true,
22
22
  url: "https://eslint.org/docs/latest/rules/no-unassigned-vars",
23
23
  },
24
24
 
@@ -130,7 +130,7 @@ module.exports = {
130
130
  docs: {
131
131
  description:
132
132
  "Disallow variable assignments when the value is not used",
133
- recommended: false,
133
+ recommended: true,
134
134
  url: "https://eslint.org/docs/latest/rules/no-useless-assignment",
135
135
  },
136
136
 
@@ -158,7 +158,7 @@ module.exports = {
158
158
  docs: {
159
159
  description:
160
160
  "Disallow losing originally caught error when re-throwing custom errors",
161
- recommended: false,
161
+ recommended: true,
162
162
  url: "https://eslint.org/docs/latest/rules/preserve-caught-error", // URL to the documentation page for this rule
163
163
  },
164
164
  /*