@@ -104,7 +104,11 @@ const {
104104const {
105105 isIdentifierStart,
106106 isIdentifierChar,
107+ Parser : acornParser ,
107108} = require ( 'internal/deps/acorn/acorn/dist/acorn' ) ;
109+
110+ const acornWalk = require ( 'internal/deps/acorn/acorn-walk/dist/walk' ) ;
111+
108112const {
109113 decorateErrorStack,
110114 isError,
@@ -223,6 +227,24 @@ module.paths = CJSModule._nodeModulePaths(module.filename);
223227const writer = ( obj ) => inspect ( obj , writer . options ) ;
224228writer . options = { ...inspect . defaultOptions , showProxy : true } ;
225229
230+ // Converts static import statement to dynamic import statement
231+ const toDynamicImport = ( codeLine ) => {
232+ let dynamicImportStatement = '' ;
233+ const ast = acornParser . parse ( codeLine , { sourceType : 'module' , ecmaVersion : 'latest' } ) ;
234+ acornWalk . ancestor ( ast , {
235+ ImportDeclaration ( node ) {
236+ const importedModules = node . source . value ;
237+ let importedSpecifiers = ArrayPrototypeMap ( node . specifiers , ( specifier ) => specifier . local . name ) ;
238+ if ( importedSpecifiers . length > 1 ) {
239+ importedSpecifiers = `{${ ArrayPrototypeJoin ( importedSpecifiers , ',' ) } }` ;
240+ }
241+ dynamicImportStatement = `const ${ importedSpecifiers } = await import('${ importedModules } ');` ;
242+ } ,
243+ } ) ;
244+ return dynamicImportStatement ;
245+ } ;
246+
247+
226248function REPLServer ( prompt ,
227249 stream ,
228250 eval_ ,
@@ -283,13 +305,13 @@ function REPLServer(prompt,
283305 get : pendingDeprecation ?
284306 deprecate ( ( ) => this . input ,
285307 'repl.inputStream and repl.outputStream are deprecated. ' +
286- 'Use repl.input and repl.output instead' ,
308+ 'Use repl.input and repl.output instead' ,
287309 'DEP0141' ) :
288310 ( ) => this . input ,
289311 set : pendingDeprecation ?
290312 deprecate ( ( val ) => this . input = val ,
291313 'repl.inputStream and repl.outputStream are deprecated. ' +
292- 'Use repl.input and repl.output instead' ,
314+ 'Use repl.input and repl.output instead' ,
293315 'DEP0141' ) :
294316 ( val ) => this . input = val ,
295317 enumerable : false ,
@@ -300,13 +322,13 @@ function REPLServer(prompt,
300322 get : pendingDeprecation ?
301323 deprecate ( ( ) => this . output ,
302324 'repl.inputStream and repl.outputStream are deprecated. ' +
303- 'Use repl.input and repl.output instead' ,
325+ 'Use repl.input and repl.output instead' ,
304326 'DEP0141' ) :
305327 ( ) => this . output ,
306328 set : pendingDeprecation ?
307329 deprecate ( ( val ) => this . output = val ,
308330 'repl.inputStream and repl.outputStream are deprecated. ' +
309- 'Use repl.input and repl.output instead' ,
331+ 'Use repl.input and repl.output instead' ,
310332 'DEP0141' ) :
311333 ( val ) => this . output = val ,
312334 enumerable : false ,
@@ -344,9 +366,9 @@ function REPLServer(prompt,
344366 // instance and that could trigger the `MaxListenersExceededWarning`.
345367 process . prependListener ( 'newListener' , ( event , listener ) => {
346368 if ( event === 'uncaughtException' &&
347- process . domain &&
348- listener . name !== 'domainUncaughtExceptionClear' &&
349- domainSet . has ( process . domain ) ) {
369+ process . domain &&
370+ listener . name !== 'domainUncaughtExceptionClear' &&
371+ domainSet . has ( process . domain ) ) {
350372 // Throw an error so that the event will not be added and the current
351373 // domain takes over. That way the user is notified about the error
352374 // and the current code evaluation is stopped, just as any other code
@@ -363,8 +385,8 @@ function REPLServer(prompt,
363385 const savedRegExMatches = [ '' , '' , '' , '' , '' , '' , '' , '' , '' , '' ] ;
364386 const sep = '\u0000\u0000\u0000' ;
365387 const regExMatcher = new RegExp ( `^${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
366- `${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
367- `${ sep } (.*)$` ) ;
388+ `${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
389+ `${ sep } (.*)$` ) ;
368390
369391 eval_ = eval_ || defaultEval ;
370392
@@ -417,7 +439,7 @@ function REPLServer(prompt,
417439 // an expression. Note that if the above condition changes,
418440 // lib/internal/repl/utils.js needs to be changed to match.
419441 if ( RegExpPrototypeExec ( / ^ \s * { / , code ) !== null &&
420- RegExpPrototypeExec ( / ; \s * $ / , code ) === null ) {
442+ RegExpPrototypeExec ( / ; \s * $ / , code ) === null ) {
421443 code = `(${ StringPrototypeTrim ( code ) } )\n` ;
422444 wrappedCmd = true ;
423445 }
@@ -492,7 +514,7 @@ function REPLServer(prompt,
492514 while ( true ) {
493515 try {
494516 if ( self . replMode === module . exports . REPL_MODE_STRICT &&
495- RegExpPrototypeExec ( / ^ \s * $ / , code ) === null ) {
517+ RegExpPrototypeExec ( / ^ \s * $ / , code ) === null ) {
496518 // "void 0" keeps the repl from returning "use strict" as the result
497519 // value for statements and declarations that don't return a value.
498520 code = `'use strict'; void 0;\n${ code } ` ;
@@ -684,7 +706,7 @@ function REPLServer(prompt,
684706 'module' ;
685707 if ( StringPrototypeIncludes ( e . message , importErrorStr ) ) {
686708 e . message = 'Cannot use import statement inside the Node.js ' +
687- 'REPL, alternatively use dynamic import' ;
709+ 'REPL, alternatively use dynamic import: ' + toDynamicImport ( self . lines . at ( - 1 ) ) ;
688710 e . stack = SideEffectFreeRegExpPrototypeSymbolReplace (
689711 / S y n t a x E r r o r : .* \n / ,
690712 e . stack ,
@@ -712,7 +734,7 @@ function REPLServer(prompt,
712734 }
713735
714736 if ( options [ kStandaloneREPL ] &&
715- process . listenerCount ( 'uncaughtException' ) !== 0 ) {
737+ process . listenerCount ( 'uncaughtException' ) !== 0 ) {
716738 process . nextTick ( ( ) => {
717739 process . emit ( 'uncaughtException' , e ) ;
718740 self . clearBufferedCommand ( ) ;
@@ -729,7 +751,7 @@ function REPLServer(prompt,
729751 errStack = '' ;
730752 ArrayPrototypeForEach ( lines , ( line ) => {
731753 if ( ! matched &&
732- RegExpPrototypeExec ( / ^ \[ ? ( [ A - Z ] [ a - z 0 - 9 _ ] * ) * E r r o r / , line ) !== null ) {
754+ RegExpPrototypeExec ( / ^ \[ ? ( [ A - Z ] [ a - z 0 - 9 _ ] * ) * E r r o r / , line ) !== null ) {
733755 errStack += writer . options . breakLength >= line . length ?
734756 `Uncaught ${ line } ` :
735757 `Uncaught:\n${ line } ` ;
@@ -875,8 +897,8 @@ function REPLServer(prompt,
875897 // display next prompt and return.
876898 if ( trimmedCmd ) {
877899 if ( StringPrototypeCharAt ( trimmedCmd , 0 ) === '.' &&
878- StringPrototypeCharAt ( trimmedCmd , 1 ) !== '.' &&
879- NumberIsNaN ( NumberParseFloat ( trimmedCmd ) ) ) {
900+ StringPrototypeCharAt ( trimmedCmd , 1 ) !== '.' &&
901+ NumberIsNaN ( NumberParseFloat ( trimmedCmd ) ) ) {
880902 const matches = RegExpPrototypeExec ( / ^ \. ( [ ^ \s ] + ) \s * ( .* ) $ / , trimmedCmd ) ;
881903 const keyword = matches && matches [ 1 ] ;
882904 const rest = matches && matches [ 2 ] ;
@@ -901,10 +923,10 @@ function REPLServer(prompt,
901923 ReflectApply ( _memory , self , [ cmd ] ) ;
902924
903925 if ( e && ! self [ kBufferedCommandSymbol ] &&
904- StringPrototypeStartsWith ( StringPrototypeTrim ( cmd ) , 'npm ' ) ) {
926+ StringPrototypeStartsWith ( StringPrototypeTrim ( cmd ) , 'npm ' ) ) {
905927 self . output . write ( 'npm should be run outside of the ' +
906- 'Node.js REPL, in your normal shell.\n' +
907- '(Press Ctrl+D to exit.)\n' ) ;
928+ 'Node.js REPL, in your normal shell.\n' +
929+ '(Press Ctrl+D to exit.)\n' ) ;
908930 self . displayPrompt ( ) ;
909931 return ;
910932 }
@@ -929,11 +951,11 @@ function REPLServer(prompt,
929951
930952 // If we got any output - print it (if no error)
931953 if ( ! e &&
932- // When an invalid REPL command is used, error message is printed
933- // immediately. We don't have to print anything else. So, only when
934- // the second argument to this function is there, print it.
935- arguments . length === 2 &&
936- ( ! self . ignoreUndefined || ret !== undefined ) ) {
954+ // When an invalid REPL command is used, error message is printed
955+ // immediately. We don't have to print anything else. So, only when
956+ // the second argument to this function is there, print it.
957+ arguments . length === 2 &&
958+ ( ! self . ignoreUndefined || ret !== undefined ) ) {
937959 if ( ! self . underscoreAssigned ) {
938960 self . last = ret ;
939961 }
@@ -984,7 +1006,7 @@ function REPLServer(prompt,
9841006 if ( ! self . editorMode || ! self . terminal ) {
9851007 // Before exiting, make sure to clear the line.
9861008 if ( key . ctrl && key . name === 'd' &&
987- self . cursor === 0 && self . line . length === 0 ) {
1009+ self . cursor === 0 && self . line . length === 0 ) {
9881010 self . clearLine ( ) ;
9891011 }
9901012 clearPreview ( key ) ;
@@ -1181,7 +1203,7 @@ const importRE = /\bimport\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])
11811203const requireRE = / \b r e q u i r e \s * \( \s * [ ' " ` ] ( ( [ \w @ . / : - ] + \/ ) ? (?: [ \w @ . / : - ] * ) ) (? ! [ ^ ' " ` ] ) $ / ;
11821204const fsAutoCompleteRE = / f s (?: \. p r o m i s e s ) ? \. \s * [ a - z ] [ a - z A - Z ] + \( \s * [ " ' ] ( .* ) / ;
11831205const simpleExpressionRE =
1184- / (?: [ \w $ ' " ` [ { ( ] (?: \w | \$ | [ ' " ` \] } ) ] ) * \? ? \. ) * [ a - z A - Z _ $ ] (?: \w | \$ ) * \? ? \. ? $ / ;
1206+ / (?: [ \w $ ' " ` [ { ( ] (?: \w | \$ | [ ' " ` \] } ) ] ) * \? ? \. ) * [ a - z A - Z _ $ ] (?: \w | \$ ) * \? ? \. ? $ / ;
11851207const versionedFileNamesRe = / - \d + \. \d + / ;
11861208
11871209function isIdentifier ( str ) {
@@ -1337,15 +1359,15 @@ function complete(line, callback) {
13371359 const dirents = gracefulReaddir ( dir , { withFileTypes : true } ) || [ ] ;
13381360 ArrayPrototypeForEach ( dirents , ( dirent ) => {
13391361 if ( RegExpPrototypeExec ( versionedFileNamesRe , dirent . name ) !== null ||
1340- dirent . name === '.npm' ) {
1362+ dirent . name === '.npm' ) {
13411363 // Exclude versioned names that 'npm' installs.
13421364 return ;
13431365 }
13441366 const extension = path . extname ( dirent . name ) ;
13451367 const base = StringPrototypeSlice ( dirent . name , 0 , - extension . length ) ;
13461368 if ( ! dirent . isDirectory ( ) ) {
13471369 if ( StringPrototypeIncludes ( extensions , extension ) &&
1348- ( ! subdir || base !== 'index' ) ) {
1370+ ( ! subdir || base !== 'index' ) ) {
13491371 ArrayPrototypePush ( group , `${ subdir } ${ base } ` ) ;
13501372 }
13511373 return ;
@@ -1398,7 +1420,7 @@ function complete(line, callback) {
13981420 ArrayPrototypeForEach ( dirents , ( dirent ) => {
13991421 const { name } = dirent ;
14001422 if ( RegExpPrototypeExec ( versionedFileNamesRe , name ) !== null ||
1401- name === '.npm' ) {
1423+ name === '.npm' ) {
14021424 // Exclude versioned names that 'npm' installs.
14031425 return ;
14041426 }
@@ -1431,20 +1453,20 @@ function complete(line, callback) {
14311453
14321454 ArrayPrototypePush ( completionGroups , _builtinLibs , nodeSchemeBuiltinLibs ) ;
14331455 } else if ( ( match = RegExpPrototypeExec ( fsAutoCompleteRE , line ) ) !== null &&
1434- this . allowBlockingCompletions ) {
1456+ this . allowBlockingCompletions ) {
14351457 ( { 0 : completionGroups , 1 : completeOn } = completeFSFunctions ( match ) ) ;
1436- // Handle variable member lookup.
1437- // We support simple chained expressions like the following (no function
1438- // calls, etc.). That is for simplicity and also because we *eval* that
1439- // leading expression so for safety (see WARNING above) don't want to
1440- // eval function calls.
1441- //
1442- // foo.bar<|> # completions for 'foo' with filter 'bar'
1443- // spam.eggs.<|> # completions for 'spam.eggs' with filter ''
1444- // foo<|> # all scope vars with filter 'foo'
1445- // foo.<|> # completions for 'foo' with filter ''
1458+ // Handle variable member lookup.
1459+ // We support simple chained expressions like the following (no function
1460+ // calls, etc.). That is for simplicity and also because we *eval* that
1461+ // leading expression so for safety (see WARNING above) don't want to
1462+ // eval function calls.
1463+ //
1464+ // foo.bar<|> # completions for 'foo' with filter 'bar'
1465+ // spam.eggs.<|> # completions for 'spam.eggs' with filter ''
1466+ // foo<|> # all scope vars with filter 'foo'
1467+ // foo.<|> # completions for 'foo' with filter ''
14461468 } else if ( line . length === 0 ||
1447- RegExpPrototypeExec ( / \w | \. | \$ / , line [ line . length - 1 ] ) !== null ) {
1469+ RegExpPrototypeExec ( / \w | \. | \$ / , line [ line . length - 1 ] ) !== null ) {
14481470 const { 0 : match } = RegExpPrototypeExec ( simpleExpressionRE , line ) || [ '' ] ;
14491471 if ( line . length !== 0 && ! match ) {
14501472 completionGroupsLoaded ( ) ;
@@ -1495,7 +1517,7 @@ function complete(line, callback) {
14951517 try {
14961518 let p ;
14971519 if ( ( typeof obj === 'object' && obj !== null ) ||
1498- typeof obj === 'function' ) {
1520+ typeof obj === 'function' ) {
14991521 memberGroups . push ( filteredOwnPropertyNames ( obj ) ) ;
15001522 p = ObjectGetPrototypeOf ( obj ) ;
15011523 } else {
0 commit comments