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

no-undef on AggregateError #14100

Closed
icecream17 opened this issue Feb 12, 2021 · 6 comments
Closed

no-undef on AggregateError #14100

icecream17 opened this issue Feb 12, 2021 · 6 comments
Assignees
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion core Relates to ESLint's core APIs and features new syntax This issue is related to new syntax that has reached stage 4
Projects

Comments

@icecream17
Copy link

Tell us about your environment

I'm using github-actions to run tests on my code.

--env-info got:

Environment Info:

Node version: v14.15.4
npm version: v6.14.10
Local ESLint version: v7.19.0 (Currently used)
Global ESLint version: Not found
  • Operating System: I'm using github actions, so it tests on all 3 of the following:
          - ubuntu-latest
          - macos-latest
          - windows-latest

However ubuntu-latest failed first, so github-actions skipped the other checks.

What parser (default, @babel/eslint-parser, @typescript-eslint/parser, etc.) are you using?
@babel/eslint-parser

Please show your full configuration:

Configuration

You can see the file here: https://github.com/icecream17/tic-tac-toe-grow-for-website/blob/main/.github/workflows/main.yml

      - uses: actions/setup-node@v2.1.4
        with:
          node-version: '14.15'

      - name: Install babel eslint
        run: npm install --save-dev eslint @babel/core @babel/eslint-parser @babel/eslint-plugin @babel/preset-env @babel/plugin-syntax-class-properties

What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.

https://github.com/icecream17/tic-tac-toe-grow-for-website/blob/e1040b4403f9236a3aa31e81602c0b383a392abb/game.js

// My code is 1446 lines long, so much of it isn't really important to this issue
// So here, you can see the basic structure and better understand where the error is happening.
//////////////////////////////////////

async function example() {
   // Simulates chance of error happening sometime in the future............
   // In the real code the error is inside an if statement too.
   if (Math.random()) {
      let promiseGroup = await Promise.allSettled([1, 2, 3])
      throw new AggregateError(promiseGroup);
   }
}

// Browser call
document.someElement.onclick = example();
      - name: Check game.js
        run: ./node_modules/.bin/eslint --format codeframe --color game.js

      - name: Check tournament.js
        run: ./node_modules/.bin/eslint --format codeframe --color tournament.js

Which corresponds to

./node_modules/.bin/eslint --format codeframe --color game.js

It failed at "game.js" so it didn't get to do "tournament.js".

What did you expect to happen?
No errors when using AggregateError

What actually happened? Please copy-paste the actual, raw output from ESLint.
no-undef: AggregateError is not defined

Better highlighting at: https://github.com/icecream17/tic-tac-toe-grow-for-website/runs/1888640229?check_suite_focus=true

Wow, raw output.

warning: Return values from promise executor functions cannot be read (no-promise-executor-return) at game.js:23:40:
  21 |  */
  22 | async function pause(ms) {
> 23 |    return await new Promise(resolve => setTimeout(resolve, ms, "Done!"));
     |                                        ^
  24 | }
  25 |
  26 | /**


warning: Missing semicolon (@babel/semi) at game.js:46:25:
  44 |       if (this[i] !== arr[i])
  45 |          if (!Array.isArray(this[i]) || !Array.isArray(arr[i]))
> 46 |             return false
     |                         ^
  47 |          else if (!this[i].valuesEqual(arr[i]))
  48 |             return false;
  49 |    return true;


warning: Missing semicolon (@babel/semi) at game.js:50:2:
  48 |             return false;
  49 |    return true;
> 50 | }
     |  ^
  51 |
  52 | /**
  53 |  * Represents an explicit and somewhat anticipated error


warning: This line has a length of 127. Maximum allowed is 120 (max-len) at game.js:72:1:
  70 |     * I'll just say it's not under the Apache License.
  71 |     *
> 72 |     * @param {...*} [args] - The args to the Error constructor. The only guaranteed argument is a string for the error message.
     | ^
  73 |     */
  74 |    constructor (...args) {
  75 |       super(...args);


warning: Unnecessary { after 'if' condition (curly) at game.js:79:7:
  77 |       // Maintains proper stack trace for where our error was thrown (only available on V8)
  78 |       // You must be pretty sure, and have a really good reason to pass this if statement
> 79 |       if (String(Error?.captureStackTrace).includes("native code")) {
     |       ^
  80 |          Error.captureStackTrace(this, CustomError);
  81 |       } else {
  82 |          this.stack = (new Error(...args)).stack;


warning: Unnecessary { after 'else' (curly) at game.js:81:9:
  79 |       if (String(Error?.captureStackTrace).includes("native code")) {
  80 |          Error.captureStackTrace(this, CustomError);
> 81 |       } else {
     |         ^
  82 |          this.stack = (new Error(...args)).stack;
  83 |       }
  84 |    }


warning: Operator '=' must be spaced (space-infix-ops) at game.js:98:20:
   96 |     * Derived from https://stackoverflow.com/a/42755876 by Matt
   97 |     */
>  98 |    rethrow (message=this.message, ...args) {
      |                    ^
   99 |       if (message !== this.message) {
  100 |          let newError = new (this.constructor)(message, ...args);
  101 |          newError.originalError = this;


warning: Unexpected negated condition (no-negated-condition) at game.js:99:7:
   97 |     */
   98 |    rethrow (message=this.message, ...args) {
>  99 |       if (message !== this.message) {
      |       ^
  100 |          let newError = new (this.constructor)(message, ...args);
  101 |          newError.originalError = this;
  102 |          newError.stack = `${newError.stack}\n${this.stack}`;


warning: Unnecessary parentheses around expression (no-extra-parens) at game.js:100:29:
   98 |    rethrow (message=this.message, ...args) {
   99 |       if (message !== this.message) {
> 100 |          let newError = new (this.constructor)(message, ...args);
      |                             ^
  101 |          newError.originalError = this;
  102 |          newError.stack = `${newError.stack}\n${this.stack}`;
  103 |          throw newError;


warning: Unnecessary parentheses around expression (no-extra-parens) at game.js:105:27:
  103 |          throw newError;
  104 |       } else {
> 105 |          this.stack = new (this.constructor)(message, ...args);
      |                           ^
  106 |          throw this;
  107 |       }
  108 |    }


warning: Expected an error object to be thrown (no-throw-literal) at game.js:106:10:
  104 |       } else {
  105 |          this.stack = new (this.constructor)(message, ...args);
> 106 |          throw this;
      |          ^
  107 |       }
  108 |    }
  109 | }


warning: This line has a length of 132. Maximum allowed is 120 (max-len) at game.js:124:1:
  122 |
  123 | class NothingDisabledError extends CustomError {
> 124 |    constructor (noun = "Nothing", plural = `${noun}s`, message = `Cannot enable ${noun} since all ${plural} are already enabled.`) {
      | ^
  125 |       super(message);
  126 |    }
  127 | }


warning: This line has a length of 134. Maximum allowed is 120 (max-len) at game.js:130:1:
  128 |
  129 | class NothingEnabledError extends CustomError {
> 130 |    constructor (noun = "Nothing", plural = `${noun}s`, message = `Cannot disable ${noun} since all ${plural} are already disabled.`) {
      | ^
  131 |       super(message);
  132 |    }
  133 | }


warning: 'NOT_DONE_YET' is assigned a value but never used (no-unused-vars) at game.js:220:7:
  218 |    EVIL_CHANGE: new EvilPlayerError("How did you do that"),
  219 | };
> 220 | const NOT_DONE_YET = "This feature is not finished yet. So it doesn't work";
      |       ^
  221 |
  222 | class Position {
  223 |    constructor (x, y) {


warning: Expected indentation of 6 spaces but found 9 (indent) at game.js:394:1:
  392 |       // Converted from an "if, else if, else" statement.
  393 |       switch (result[0]) {
> 394 |          case "win":
      | ^
  395 |             {
  396 |                notice("WINNNN", result);
  397 |                for (let cell of result[1].flat().concat(this.board[lastY][lastX]))


warning: Expected indentation of 9 spaces but found 12 (indent) at game.js:395:1:
  393 |       switch (result[0]) {
  394 |          case "win":
> 395 |             {
      | ^
  396 |                notice("WINNNN", result);
  397 |                for (let cell of result[1].flat().concat(this.board[lastY][lastX]))
  398 |                   cell.win = true;


warning: Expected indentation of 12 spaces but found 15 (indent) at game.js:396:1:
  394 |          case "win":
  395 |             {
> 396 |                notice("WINNNN", result);
      | ^
  397 |                for (let cell of result[1].flat().concat(this.board[lastY][lastX]))
  398 |                   cell.win = true;
  399 |


warning: Expected indentation of 12 spaces but found 15 (indent) at game.js:397:1:
  395 |             {
  396 |                notice("WINNNN", result);
> 397 |                for (let cell of result[1].flat().concat(this.board[lastY][lastX]))
      | ^
  398 |                   cell.win = true;
  399 |
  400 |                let winArray = [this.toMove, PLAYER_NAMES[this.toMove], players[this.toMove].player];


warning: Expected indentation of 15 spaces but found 18 (indent) at game.js:398:1:
  396 |                notice("WINNNN", result);
  397 |                for (let cell of result[1].flat().concat(this.board[lastY][lastX]))
> 398 |                   cell.win = true;
      | ^
  399 |
  400 |                let winArray = [this.toMove, PLAYER_NAMES[this.toMove], players[this.toMove].player];
  401 |                if (this.winners.every(array => !array.valuesEqual(winArray)))


warning: Expected indentation of 12 spaces but found 15 (indent) at game.js:400:1:
  398 |                   cell.win = true;
  399 |
> 400 |                let winArray = [this.toMove, PLAYER_NAMES[this.toMove], players[this.toMove].player];
      | ^
  401 |                if (this.winners.every(array => !array.valuesEqual(winArray)))
  402 |                   this.winners.push(winArray);
  403 |             }


warning: Expected indentation of 12 spaces but found 15 (indent) at game.js:401:1:
  399 |
  400 |                let winArray = [this.toMove, PLAYER_NAMES[this.toMove], players[this.toMove].player];
> 401 |                if (this.winners.every(array => !array.valuesEqual(winArray)))
      | ^
  402 |                   this.winners.push(winArray);
  403 |             }
  404 |             break;


warning: Expected indentation of 15 spaces but found 18 (indent) at game.js:402:1:
  400 |                let winArray = [this.toMove, PLAYER_NAMES[this.toMove], players[this.toMove].player];
  401 |                if (this.winners.every(array => !array.valuesEqual(winArray)))
> 402 |                   this.winners.push(winArray);
      | ^
  403 |             }
  404 |             break;
  405 |          case "draw":


warning: Expected indentation of 9 spaces but found 12 (indent) at game.js:403:1:
  401 |                if (this.winners.every(array => !array.valuesEqual(winArray)))
  402 |                   this.winners.push(winArray);
> 403 |             }
      | ^
  404 |             break;
  405 |          case "draw":
  406 |             notice(`*gasp*! Draw!\n${result[1]}`, result);


warning: Expected indentation of 9 spaces but found 12 (indent) at game.js:404:1:
  402 |                   this.winners.push(winArray);
  403 |             }
> 404 |             break;
      | ^
  405 |          case "draw":
  406 |             notice(`*gasp*! Draw!\n${result[1]}`, result);
  407 |             break;


warning: Expected indentation of 6 spaces but found 9 (indent) at game.js:405:1:
  403 |             }
  404 |             break;
> 405 |          case "draw":
      | ^
  406 |             notice(`*gasp*! Draw!\n${result[1]}`, result);
  407 |             break;
  408 |          default:


warning: Expected indentation of 9 spaces but found 12 (indent) at game.js:406:1:
  404 |             break;
  405 |          case "draw":
> 406 |             notice(`*gasp*! Draw!\n${result[1]}`, result);
      | ^
  407 |             break;
  408 |          default:
  409 |             ERRORS.INVALID_MOVE_FINISH.rethrow();


warning: Expected indentation of 9 spaces but found 12 (indent) at game.js:407:1:
  405 |          case "draw":
  406 |             notice(`*gasp*! Draw!\n${result[1]}`, result);
> 407 |             break;
      | ^
  408 |          default:
  409 |             ERRORS.INVALID_MOVE_FINISH.rethrow();
  410 |       }


warning: Expected indentation of 6 spaces but found 9 (indent) at game.js:408:1:
  406 |             notice(`*gasp*! Draw!\n${result[1]}`, result);
  407 |             break;
> 408 |          default:
      | ^
  409 |             ERRORS.INVALID_MOVE_FINISH.rethrow();
  410 |       }
  411 |    }


warning: Expected indentation of 9 spaces but found 12 (indent) at game.js:409:1:
  407 |             break;
  408 |          default:
> 409 |             ERRORS.INVALID_MOVE_FINISH.rethrow();
      | ^
  410 |       }
  411 |    }
  412 |


warning: Missing semicolon (@babel/semi) at game.js:454:8:
  452 |
  453 |          return diag;
> 454 |       }
      |        ^
  455 |
  456 |       for (let i = 0; i < 4; i++) {
  457 |          const orthogonalStep = [


warning: Missing semicolon (@babel/semi) at game.js:554:8:
  552 |
  553 |          return newWins;
> 554 |       }
      |        ^
  555 |
  556 |       wins.push(...checkmarks(diagonal[0], diagonal[3], new Step(1, -1), new Step(-1, 1)));
  557 |       wins.push(...checkmarks(diagonal[1], diagonal[2], new Step(1, 1), new Step(-1, -1)));


warning: Missing semicolon (@babel/semi) at game.js:600:26:
  598 |          for (let x = 0; x < this.board.width; x++) {
  599 |             let char = this.board[y][x].value;
> 600 |             ascii += '%c'
      |                          ^
  601 |             if (char === '') {
  602 |                ascii += ' ';
  603 |                css.push('background-color:gray');


warning: Unexpected string concatenation (prefer-template) at game.js:610:19:
  608 |                ascii += char;
  609 |                css.push(
> 610 |                   "color:"
      |                   ^
  611 |                   + ['red', 'blue', 'green', 'orange', 'purple'][PLAYER_CHARS.indexOf(char)]
  612 |                   + (this.board[y][x].win ? ';background-color:#CFC' : '')
  613 |                );


warning: Missing semicolon (@babel/semi) at game.js:625:8:
  623 |          'background-color:gray;color:gray',
  624 |          'color:white'
> 625 |       )
      |        ^
  626 |
  627 |       if (verbose) console.debug(ascii, ...css);
  628 |       else console.log(ascii, ...css);


warning: '=' should be placed at the beginning of the line (operator-linebreak) at game.js:750:41:
  748 |
  749 |    updateVisualStats() {
> 750 |       ELEMENTS.statsParagraph.innerText =
      |                                         ^
  751 | `Width: ${this.board.width}
  752 | Height: ${this.board.height}
  753 | Turns: ${this.turn}`;


warning: 'args' is defined but never used (no-unused-vars) at game.js:823:20:
  821 | }
  822 |
> 823 | function notice(...args) {
      |                    ^
  824 |    // TODO: do something
  825 | }
  826 |


warning: Missing semicolon (@babel/semi) at game.js:921:2:
  919 |    currentGame.updateVisual();
  920 |    currentGame.updateVisualStats();
> 921 | }
      |  ^
  922 |
  923 | // Assumes that the enable and disable buttons are disabled / enabled when appropriate.
  924 | // For example, the enable button should not be enabled if the element is already enabled.


warning: Unnecessary parentheses around expression (no-extra-parens) at game.js:1053:32:
  1051 |          bot_mechanics.random_move.apply(this);
  1052 |       else {
> 1053 |          let indexOfLastMove = (
       |                                ^
  1054 |             lastMove.gameState
  1055 |                .originalMoves
  1056 |                .findIndex(


warning: Missing semicolon (@babel/semi) at game.js:1071:39:
  1069 |    avoider() {
  1070 |       let moves = this.getMoves();
> 1071 |       let best_moves = [-Infinity, []]
       |                                       ^
  1072 |       for (let move of moves) {
  1073 |          let score = 0;
  1074 |          for (let historicalMove of this.moveHistory)


warning: Unnecessary parentheses around expression (no-extra-parens) at game.js:1110:50:
  1108 |       } else positionOnDiagonal = new Position(0, 0);
  1109 |
> 1110 |       let moves = this.getMoves().filter(move => (
       |                                                  ^
  1111 |          (positionOnDiagonal.x + positionOnDiagonal.y + move.x + move.y) % 2 === 0
  1112 |       ));
  1113 |       if (moves.length === 0)


warning: A function with a name starting with an uppercase letter should only be used as a constructor (@babel/new-cap) at game.js:1220:33:
  1218 |
  1219 |    let localIndex = Array.prototype.indexOf.call(option.parentElement.children, option);
> 1220 |    if (localIndex === -1) throw ReferenceError("No player is selected!??");
       |                                 ^
  1221 |
  1222 |    players[playerIndex] = new PlayerReference(type, localIndex);
  1223 |    currentGame.playBots();


warning: Operator '=' must be spaced (space-infix-ops) at game.js:1239:45:
  1237 |
  1238 | // this = <input>
> 1239 | async function enablePerson(fromEnablePeople=false) {
       |                                             ^
  1240 |    // MAX_PLAYERS_REACHED and EVERYONEs_ENABLED both fit...
  1241 |    if (activePeople === 4) ERRORS.EVERYONEs_ENABLED.rethrow();
  1242 |    activePeople++;


warning: Operator '=' must be spaced (space-infix-ops) at game.js:1260:47:
  1258 |
  1259 | // Bug, probably feature: Player not changed when disabled
> 1260 | async function disablePerson(fromDisablePeople=false) {
       |                                               ^
  1261 |    if (activePeople === 0) ERRORS.NO_ONEs_ENABLED.rethrow();
  1262 |    activePeople--;
  1263 |


error: 'AggregateError' is not defined (no-undef) at game.js:1294:52:
  1292 |    let promiseGroup = await Promise.allSettled(clickPromises);
  1293 |    for (let promise of promiseGroup)
> 1294 |       if (promise.status === 'rejected') throw new AggregateError(promiseGroup);
       |                                                    ^
  1295 |
  1296 |    if (counter !== num)
  1297 |       console.warn(`Failed to enable the correct amount: ${counter} !== ${num}`);


error: 'AggregateError' is not defined (no-undef) at game.js:1317:52:
  1315 |    let promiseGroup = await Promise.allSettled(clickPromises);
  1316 |    for (let promise of promiseGroup)
> 1317 |       if (promise.status === 'rejected') throw new AggregateError(promiseGroup);
       |                                                    ^
  1318 |
  1319 |    activePeople = counter;
  1320 |    if (counter !== num)


warning: Possible race condition: `activePeople` might be reassigned based on an outdated value of `activePeople` (require-atomic-updates) at game.js:1319:4:
  1317 |       if (promise.status === 'rejected') throw new AggregateError(promiseGroup);
  1318 |
> 1319 |    activePeople = counter;
       |    ^
  1320 |    if (counter !== num)
  1321 |       console.warn(`Failed to disable the correct amount: ${counter} !== ${num}`);
  1322 |


warning: Operator '=' must be spaced (space-infix-ops) at game.js:1327:46:
  1325 |
  1326 | // this = <select disabled>
> 1327 | async function enablePlayer(fromEnablePlayers=false) {
       |                                              ^
  1328 |    if (activePlayers === 4) ERRORS.MAX_PLAYERS_REACHED.rethrow();
  1329 |
  1330 |    let playerIndex = this.parentElement.id[8] - 1;


warning: 'fromDisablePlayers' is assigned a value but never used (no-unused-vars) at game.js:1358:30:
  1356 | // Min players: !1 (apparently it's 0)
  1357 | // this = <input (not:disabled)>
> 1358 | async function disablePlayer(fromDisablePlayers=false) {
       |                              ^
  1359 |    if (activePlayers === 0) ERRORS.NO_ONEs_ENABLED.rethrow();
  1360 |
  1361 |    let option = this.selectedOptions[0];


warning: Operator '=' must be spaced (space-infix-ops) at game.js:1358:48:
  1356 | // Min players: !1 (apparently it's 0)
  1357 | // this = <input (not:disabled)>
> 1358 | async function disablePlayer(fromDisablePlayers=false) {
       |                                                ^
  1359 |    if (activePlayers === 0) ERRORS.NO_ONEs_ENABLED.rethrow();
  1360 |
  1361 |    let option = this.selectedOptions[0];


warning: Missing semicolon (@babel/semi) at game.js:1373:88:
  1371 |       ELEMENTS.playerSelects[playerIndexPlusOne].dispatchEvent(new Event("change"));
  1372 |
> 1373 |       return await disablePlayer.call(ELEMENTS.playerSelects[playerIndexPlusOne], true)
       |                                                                                        ^
  1374 |    } else {
  1375 |       this.disabled = true;
  1376 |       this.parentElement.nextElementSibling.disabled = false;


warning: 'activeBots' is assigned a value but never used (no-unused-vars) at game.js:1383:50:
  1381 |
  1382 |       // <optgroup> label
> 1383 |       if (option.parentElement.label === "Bots") activeBots--;
       |                                                  ^
  1384 |       else activePeople--;
  1385 |
  1386 |       if (currentGame.toMove === playerIndexPlusOne - 1) {


error: 'AggregateError' is not defined (no-undef) at game.js:1411:52:
  1409 |    let promiseGroup = await Promise.allSettled(clickPromises);
  1410 |    for (let promise of promiseGroup)
> 1411 |       if (promise.status === 'rejected') throw new AggregateError(promiseGroup);
       |                                                    ^
  1412 |
  1413 |    if (counter !== num)
  1414 |       console.warn(`Failed to enable the correct amount: ${counter} !== ${num}`);


error: 'AggregateError' is not defined (no-undef) at game.js:1433:52:
  1431 |    let promiseGroup = await Promise.allSettled(clickPromises);
  1432 |    for (let promise of promiseGroup)
> 1433 |       if (promise.status === 'rejected') throw new AggregateError(promiseGroup);
       |                                                    ^
  1434 |
  1435 |    if (counter !== num)
  1436 |       console.warn(`Failed to disable the correct amount: ${counter} !== ${num}`);


4 errors and 49 warnings found.
37 warnings potentially fixable with the `--fix` option.
Error: Process completed with exit code 1.

Steps to reproduce this issue:

  1. Use AggregateError in your code
  2. Watch as your tests fail because AggregateError is not defined

Are you willing to submit a pull request to fix this bug?
No

@icecream17 icecream17 added bug ESLint is working incorrectly triage An ESLint team member will look at this issue soon labels Feb 12, 2021
@ljharb
Copy link
Sponsor Contributor

ljharb commented Feb 12, 2021

Does your eslint config have env: { es2020: true } anywhere in it?

@icecream17
Copy link
Author

I think env: { es2021: true } counts.

By the way, here's my .eslintrc
https://github.com/icecream17/tic-tac-toe-grow-for-website/blob/e1040b4403f9236a3aa31e81602c0b383a392abb/.eslintrc.json

@mdjermanovic mdjermanovic added accepted There is consensus among the team that this change meets the criteria for inclusion core Relates to ESLint's core APIs and features new syntax This issue is related to new syntax that has reached stage 4 and removed triage An ESLint team member will look at this issue soon bug ESLint is working incorrectly labels Feb 12, 2021
@mdjermanovic
Copy link
Member

Hi @icecream17, thanks for the issue!

I can see you fixed the issue for now by adding "AggregateError" to globals 👍

It seems that we missed adding this to built-in environments. By the finished proposals list, it looks like this should be in the es2021 environment (the expected publication year for https://github.com/tc39/proposal-promise-any is 2021).

@mdjermanovic mdjermanovic added this to Ready to Implement in Triage Feb 12, 2021
@ljharb
Copy link
Sponsor Contributor

ljharb commented Feb 12, 2021

When making this change, it'd be great to also ensure WeakRef and FinalizationRegistry are in the es2021 list.

@mdjermanovic
Copy link
Member

When making this change, it'd be great to also ensure WeakRef and FinalizationRegistry are in the es2021 list.

Those two should be already there.

@mdjermanovic
Copy link
Member

Fixed by eslint/eslintrc#28 and #14147.

Triage automation moved this from Ready to Implement to Complete Feb 27, 2021
@eslint-github-bot eslint-github-bot bot locked and limited conversation to collaborators Aug 27, 2021
@eslint-github-bot eslint-github-bot bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Aug 27, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion core Relates to ESLint's core APIs and features new syntax This issue is related to new syntax that has reached stage 4
Projects
Archived in project
Triage
Complete
Development

No branches or pull requests

3 participants