diff --git a/lib/internal/repl/utils.js b/lib/internal/repl/utils.js index 6830ebb08065e5..2ad78a8ab4dfaa 100644 --- a/lib/internal/repl/utils.js +++ b/lib/internal/repl/utils.js @@ -1,6 +1,15 @@ 'use strict'; const acorn = require('internal/deps/acorn/acorn/dist/acorn'); +const privateMethods = + require('internal/deps/acorn-plugins/acorn-private-methods/index'); +const bigInt = require('internal/deps/acorn-plugins/acorn-bigint/index'); +const classFields = + require('internal/deps/acorn-plugins/acorn-class-fields/index'); +const numericSeparator = + require('internal/deps/acorn-plugins/acorn-numeric-separator/index'); +const staticClassFeatures = + require('internal/deps/acorn-plugins/acorn-static-class-features/index'); const { tokTypes: tt, Parser: AcornParser } = acorn; // If the error is that we've unexpectedly ended the input, @@ -8,6 +17,12 @@ const { tokTypes: tt, Parser: AcornParser } = acorn; // Note: `e` (the original exception) is not used by the current implementation, // but may be needed in the future. function isRecoverableError(e, code) { + // For similar reasons as `defaultEval`, wrap expressions starting with a + // curly brace with parenthesis. Note: only the open parenthesis is added + // here as the point is to test for potentially valid but incomplete + // expressions. + if (/^\s*\{/.test(code) && isRecoverableError(e, `(${code}`)) return true; + let recoverable = false; // Determine if the point of any error raised is at the end of the input. @@ -26,34 +41,39 @@ function isRecoverableError(e, code) { // change these messages in the future, this will lead to a test // failure, indicating that this code needs to be updated. // - const RecoverableParser = AcornParser.extend((Parser) => { - return class extends Parser { - nextToken() { - super.nextToken(); - if (this.type === tt.eof) recoverable = true; - } - raise(pos, message) { - switch (message) { - case 'Unterminated template': - case 'Unterminated comment': - recoverable = true; - break; + const RecoverableParser = AcornParser + .extend( + privateMethods, + bigInt, + classFields, + numericSeparator, + staticClassFeatures, + (Parser) => { + return class extends Parser { + nextToken() { + super.nextToken(); + if (this.type === tt.eof) + recoverable = true; + } + raise(pos, message) { + switch (message) { + case 'Unterminated template': + case 'Unterminated comment': + recoverable = true; + break; - case 'Unterminated string constant': - const token = this.input.slice(this.lastTokStart, this.pos); - // See https://www.ecma-international.org/ecma-262/#sec-line-terminators - recoverable = /\\(?:\r\n?|\n|\u2028|\u2029)$/.test(token); - } - super.raise(pos, message); + case 'Unterminated string constant': + const token = this.input.slice(this.lastTokStart, this.pos); + // See https://www.ecma-international.org/ecma-262/#sec-line-terminators + if (/\\(?:\r\n?|\n|\u2028|\u2029)$/.test(token)) { + recoverable = true; + } + } + super.raise(pos, message); + } + }; } - }; - }); - - // For similar reasons as `defaultEval`, wrap expressions starting with a - // curly brace with parenthesis. Note: only the open parenthesis is added - // here as the point is to test for potentially valid but incomplete - // expressions. - if (/^\s*\{/.test(code) && isRecoverableError(e, `(${code}`)) return true; + ); // Try to parse the code with acorn. If the parse fails, ignore the acorn // error and return the recoverable status.