@@ -73,6 +73,7 @@ const {
7373} = require ( 'internal/errors' ) . codes ;
7474const { sendInspectorCommand } = require ( 'internal/util/inspector' ) ;
7575const { experimentalREPLAwait } = process . binding ( 'config' ) ;
76+ const { isRecoverableError } = require ( 'internal/repl/recoverable' ) ;
7677
7778// Lazy-loaded.
7879let processTopLevelAwait ;
@@ -227,7 +228,8 @@ function REPLServer(prompt,
227228 // It's confusing for `{ a : 1 }` to be interpreted as a block
228229 // statement rather than an object literal. So, we first try
229230 // to wrap it in parentheses, so that it will be interpreted as
230- // an expression.
231+ // an expression. Note that if the above condition changes,
232+ // lib/internal/repl/recoverable.js needs to be changed to match.
231233 code = `(${ code . trim ( ) } )\n` ;
232234 wrappedCmd = true ;
233235 }
@@ -1505,76 +1507,6 @@ function regexpEscape(s) {
15051507 return s . replace ( / [ - [ \] { } ( ) * + ? . , \\ ^ $ | # \s ] / g, '\\$&' ) ;
15061508}
15071509
1508- // If the error is that we've unexpectedly ended the input,
1509- // then let the user try to recover by adding more input.
1510- function isRecoverableError ( e , code ) {
1511- if ( e && e . name === 'SyntaxError' ) {
1512- var message = e . message ;
1513- if ( message === 'Unterminated template literal' ||
1514- message === 'Unexpected end of input' ) {
1515- return true ;
1516- }
1517-
1518- if ( message === 'missing ) after argument list' ) {
1519- const frames = e . stack . split ( / \r ? \n / ) ;
1520- const pos = frames . findIndex ( ( f ) => f . match ( / ^ \s * \^ + $ / ) ) ;
1521- return pos > 0 && frames [ pos - 1 ] . length === frames [ pos ] . length ;
1522- }
1523-
1524- if ( message === 'Invalid or unexpected token' )
1525- return isCodeRecoverable ( code ) ;
1526- }
1527- return false ;
1528- }
1529-
1530- // Check whether a code snippet should be forced to fail in the REPL.
1531- function isCodeRecoverable ( code ) {
1532- var current , previous , stringLiteral ;
1533- var isBlockComment = false ;
1534- var isSingleComment = false ;
1535- var isRegExpLiteral = false ;
1536- var lastChar = code . charAt ( code . length - 2 ) ;
1537- var prevTokenChar = null ;
1538-
1539- for ( var i = 0 ; i < code . length ; i ++ ) {
1540- previous = current ;
1541- current = code [ i ] ;
1542-
1543- if ( previous === '\\' && ( stringLiteral || isRegExpLiteral ) ) {
1544- current = null ;
1545- } else if ( stringLiteral ) {
1546- if ( stringLiteral === current ) {
1547- stringLiteral = null ;
1548- }
1549- } else if ( isRegExpLiteral && current === '/' ) {
1550- isRegExpLiteral = false ;
1551- } else if ( isBlockComment && previous === '*' && current === '/' ) {
1552- isBlockComment = false ;
1553- } else if ( isSingleComment && current === '\n' ) {
1554- isSingleComment = false ;
1555- } else if ( ! isBlockComment && ! isRegExpLiteral && ! isSingleComment ) {
1556- if ( current === '/' && previous === '/' ) {
1557- isSingleComment = true ;
1558- } else if ( previous === '/' ) {
1559- if ( current === '*' ) {
1560- isBlockComment = true ;
1561- // Distinguish between a division operator and the start of a regex
1562- // by examining the non-whitespace character that precedes the /
1563- } else if ( [ null , '(' , '[' , '{' , '}' , ';' ] . includes ( prevTokenChar ) ) {
1564- isRegExpLiteral = true ;
1565- }
1566- } else {
1567- if ( current . trim ( ) ) prevTokenChar = current ;
1568- if ( current === '\'' || current === '"' ) {
1569- stringLiteral = current ;
1570- }
1571- }
1572- }
1573- }
1574-
1575- return stringLiteral ? lastChar === '\\' : isBlockComment ;
1576- }
1577-
15781510function Recoverable ( err ) {
15791511 this . err = err ;
15801512}
0 commit comments