repl: handle stage-3 language features properly
This adds stage-3 language features to acorn so that the REPL is able to parse these features properly. Otherwise these would cause SyntaxErrors. PR-URL: https://github.com/nodejs/node/pull/27400 Fixes: https://github.com/nodejs/node/issues/27391 Fixes: https://github.com/nodejs/node/issues/25835 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
parent
f37e40af2b
commit
e939b8f13b
@ -1,6 +1,15 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const acorn = require('internal/deps/acorn/acorn/dist/acorn');
|
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;
|
const { tokTypes: tt, Parser: AcornParser } = acorn;
|
||||||
|
|
||||||
// If the error is that we've unexpectedly ended the input,
|
// 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,
|
// Note: `e` (the original exception) is not used by the current implementation,
|
||||||
// but may be needed in the future.
|
// but may be needed in the future.
|
||||||
function isRecoverableError(e, code) {
|
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;
|
let recoverable = false;
|
||||||
|
|
||||||
// Determine if the point of any error raised is at the end of the input.
|
// 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
|
// change these messages in the future, this will lead to a test
|
||||||
// failure, indicating that this code needs to be updated.
|
// failure, indicating that this code needs to be updated.
|
||||||
//
|
//
|
||||||
const RecoverableParser = AcornParser.extend((Parser) => {
|
const RecoverableParser = AcornParser
|
||||||
return class extends Parser {
|
.extend(
|
||||||
nextToken() {
|
privateMethods,
|
||||||
super.nextToken();
|
bigInt,
|
||||||
if (this.type === tt.eof) recoverable = true;
|
classFields,
|
||||||
}
|
numericSeparator,
|
||||||
raise(pos, message) {
|
staticClassFeatures,
|
||||||
switch (message) {
|
(Parser) => {
|
||||||
case 'Unterminated template':
|
return class extends Parser {
|
||||||
case 'Unterminated comment':
|
nextToken() {
|
||||||
recoverable = true;
|
super.nextToken();
|
||||||
break;
|
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':
|
case 'Unterminated string constant':
|
||||||
const token = this.input.slice(this.lastTokStart, this.pos);
|
const token = this.input.slice(this.lastTokStart, this.pos);
|
||||||
// See https://www.ecma-international.org/ecma-262/#sec-line-terminators
|
// See https://www.ecma-international.org/ecma-262/#sec-line-terminators
|
||||||
recoverable = /\\(?:\r\n?|\n|\u2028|\u2029)$/.test(token);
|
if (/\\(?:\r\n?|\n|\u2028|\u2029)$/.test(token)) {
|
||||||
}
|
recoverable = true;
|
||||||
super.raise(pos, message);
|
}
|
||||||
|
}
|
||||||
|
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
|
// Try to parse the code with acorn. If the parse fails, ignore the acorn
|
||||||
// error and return the recoverable status.
|
// error and return the recoverable status.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user