@@ -104,7 +104,11 @@ const {
104
104
const {
105
105
isIdentifierStart,
106
106
isIdentifierChar,
107
+ Parser : acornParser ,
107
108
} = require ( 'internal/deps/acorn/acorn/dist/acorn' ) ;
109
+
110
+ const acornWalk = require ( 'internal/deps/acorn/acorn-walk/dist/walk' ) ;
111
+
108
112
const {
109
113
decorateErrorStack,
110
114
isError,
@@ -223,6 +227,24 @@ module.paths = CJSModule._nodeModulePaths(module.filename);
223
227
const writer = ( obj ) => inspect ( obj , writer . options ) ;
224
228
writer . options = { ...inspect . defaultOptions , showProxy : true } ;
225
229
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
+
226
248
function REPLServer ( prompt ,
227
249
stream ,
228
250
eval_ ,
@@ -283,13 +305,13 @@ function REPLServer(prompt,
283
305
get : pendingDeprecation ?
284
306
deprecate ( ( ) => this . input ,
285
307
'repl.inputStream and repl.outputStream are deprecated. ' +
286
- 'Use repl.input and repl.output instead' ,
308
+ 'Use repl.input and repl.output instead' ,
287
309
'DEP0141' ) :
288
310
( ) => this . input ,
289
311
set : pendingDeprecation ?
290
312
deprecate ( ( val ) => this . input = val ,
291
313
'repl.inputStream and repl.outputStream are deprecated. ' +
292
- 'Use repl.input and repl.output instead' ,
314
+ 'Use repl.input and repl.output instead' ,
293
315
'DEP0141' ) :
294
316
( val ) => this . input = val ,
295
317
enumerable : false ,
@@ -300,13 +322,13 @@ function REPLServer(prompt,
300
322
get : pendingDeprecation ?
301
323
deprecate ( ( ) => this . output ,
302
324
'repl.inputStream and repl.outputStream are deprecated. ' +
303
- 'Use repl.input and repl.output instead' ,
325
+ 'Use repl.input and repl.output instead' ,
304
326
'DEP0141' ) :
305
327
( ) => this . output ,
306
328
set : pendingDeprecation ?
307
329
deprecate ( ( val ) => this . output = val ,
308
330
'repl.inputStream and repl.outputStream are deprecated. ' +
309
- 'Use repl.input and repl.output instead' ,
331
+ 'Use repl.input and repl.output instead' ,
310
332
'DEP0141' ) :
311
333
( val ) => this . output = val ,
312
334
enumerable : false ,
@@ -344,9 +366,9 @@ function REPLServer(prompt,
344
366
// instance and that could trigger the `MaxListenersExceededWarning`.
345
367
process . prependListener ( 'newListener' , ( event , listener ) => {
346
368
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 ) ) {
350
372
// Throw an error so that the event will not be added and the current
351
373
// domain takes over. That way the user is notified about the error
352
374
// and the current code evaluation is stopped, just as any other code
@@ -363,8 +385,8 @@ function REPLServer(prompt,
363
385
const savedRegExMatches = [ '' , '' , '' , '' , '' , '' , '' , '' , '' , '' ] ;
364
386
const sep = '\u0000\u0000\u0000' ;
365
387
const regExMatcher = new RegExp ( `^${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
366
- `${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
367
- `${ sep } (.*)$` ) ;
388
+ `${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
389
+ `${ sep } (.*)$` ) ;
368
390
369
391
eval_ = eval_ || defaultEval ;
370
392
@@ -417,7 +439,7 @@ function REPLServer(prompt,
417
439
// an expression. Note that if the above condition changes,
418
440
// lib/internal/repl/utils.js needs to be changed to match.
419
441
if ( RegExpPrototypeExec ( / ^ \s * { / , code ) !== null &&
420
- RegExpPrototypeExec ( / ; \s * $ / , code ) === null ) {
442
+ RegExpPrototypeExec ( / ; \s * $ / , code ) === null ) {
421
443
code = `(${ StringPrototypeTrim ( code ) } )\n` ;
422
444
wrappedCmd = true ;
423
445
}
@@ -492,7 +514,7 @@ function REPLServer(prompt,
492
514
while ( true ) {
493
515
try {
494
516
if ( self . replMode === module . exports . REPL_MODE_STRICT &&
495
- RegExpPrototypeExec ( / ^ \s * $ / , code ) === null ) {
517
+ RegExpPrototypeExec ( / ^ \s * $ / , code ) === null ) {
496
518
// "void 0" keeps the repl from returning "use strict" as the result
497
519
// value for statements and declarations that don't return a value.
498
520
code = `'use strict'; void 0;\n${ code } ` ;
@@ -684,7 +706,7 @@ function REPLServer(prompt,
684
706
'module' ;
685
707
if ( StringPrototypeIncludes ( e . message , importErrorStr ) ) {
686
708
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 ) ) ;
688
710
e . stack = SideEffectFreeRegExpPrototypeSymbolReplace (
689
711
/ S y n t a x E r r o r : .* \n / ,
690
712
e . stack ,
@@ -712,7 +734,7 @@ function REPLServer(prompt,
712
734
}
713
735
714
736
if ( options [ kStandaloneREPL ] &&
715
- process . listenerCount ( 'uncaughtException' ) !== 0 ) {
737
+ process . listenerCount ( 'uncaughtException' ) !== 0 ) {
716
738
process . nextTick ( ( ) => {
717
739
process . emit ( 'uncaughtException' , e ) ;
718
740
self . clearBufferedCommand ( ) ;
@@ -729,7 +751,7 @@ function REPLServer(prompt,
729
751
errStack = '' ;
730
752
ArrayPrototypeForEach ( lines , ( line ) => {
731
753
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 ) {
733
755
errStack += writer . options . breakLength >= line . length ?
734
756
`Uncaught ${ line } ` :
735
757
`Uncaught:\n${ line } ` ;
@@ -875,8 +897,8 @@ function REPLServer(prompt,
875
897
// display next prompt and return.
876
898
if ( trimmedCmd ) {
877
899
if ( StringPrototypeCharAt ( trimmedCmd , 0 ) === '.' &&
878
- StringPrototypeCharAt ( trimmedCmd , 1 ) !== '.' &&
879
- NumberIsNaN ( NumberParseFloat ( trimmedCmd ) ) ) {
900
+ StringPrototypeCharAt ( trimmedCmd , 1 ) !== '.' &&
901
+ NumberIsNaN ( NumberParseFloat ( trimmedCmd ) ) ) {
880
902
const matches = RegExpPrototypeExec ( / ^ \. ( [ ^ \s ] + ) \s * ( .* ) $ / , trimmedCmd ) ;
881
903
const keyword = matches && matches [ 1 ] ;
882
904
const rest = matches && matches [ 2 ] ;
@@ -901,10 +923,10 @@ function REPLServer(prompt,
901
923
ReflectApply ( _memory , self , [ cmd ] ) ;
902
924
903
925
if ( e && ! self [ kBufferedCommandSymbol ] &&
904
- StringPrototypeStartsWith ( StringPrototypeTrim ( cmd ) , 'npm ' ) ) {
926
+ StringPrototypeStartsWith ( StringPrototypeTrim ( cmd ) , 'npm ' ) ) {
905
927
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' ) ;
908
930
self . displayPrompt ( ) ;
909
931
return ;
910
932
}
@@ -929,11 +951,11 @@ function REPLServer(prompt,
929
951
930
952
// If we got any output - print it (if no error)
931
953
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 ) ) {
937
959
if ( ! self . underscoreAssigned ) {
938
960
self . last = ret ;
939
961
}
@@ -984,7 +1006,7 @@ function REPLServer(prompt,
984
1006
if ( ! self . editorMode || ! self . terminal ) {
985
1007
// Before exiting, make sure to clear the line.
986
1008
if ( key . ctrl && key . name === 'd' &&
987
- self . cursor === 0 && self . line . length === 0 ) {
1009
+ self . cursor === 0 && self . line . length === 0 ) {
988
1010
self . clearLine ( ) ;
989
1011
}
990
1012
clearPreview ( key ) ;
@@ -1181,7 +1203,7 @@ const importRE = /\bimport\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])
1181
1203
const requireRE = / \b r e q u i r e \s * \( \s * [ ' " ` ] ( ( [ \w @ . / : - ] + \/ ) ? (?: [ \w @ . / : - ] * ) ) (? ! [ ^ ' " ` ] ) $ / ;
1182
1204
const fsAutoCompleteRE = / f s (?: \. p r o m i s e s ) ? \. \s * [ a - z ] [ a - z A - Z ] + \( \s * [ " ' ] ( .* ) / ;
1183
1205
const simpleExpressionRE =
1184
- / (?: [ \w $ ' " ` [ { ( ] (?: \w | \$ | [ ' " ` \] } ) ] ) * \? ? \. ) * [ a - z A - Z _ $ ] (?: \w | \$ ) * \? ? \. ? $ / ;
1206
+ / (?: [ \w $ ' " ` [ { ( ] (?: \w | \$ | [ ' " ` \] } ) ] ) * \? ? \. ) * [ a - z A - Z _ $ ] (?: \w | \$ ) * \? ? \. ? $ / ;
1185
1207
const versionedFileNamesRe = / - \d + \. \d + / ;
1186
1208
1187
1209
function isIdentifier ( str ) {
@@ -1337,15 +1359,15 @@ function complete(line, callback) {
1337
1359
const dirents = gracefulReaddir ( dir , { withFileTypes : true } ) || [ ] ;
1338
1360
ArrayPrototypeForEach ( dirents , ( dirent ) => {
1339
1361
if ( RegExpPrototypeExec ( versionedFileNamesRe , dirent . name ) !== null ||
1340
- dirent . name === '.npm' ) {
1362
+ dirent . name === '.npm' ) {
1341
1363
// Exclude versioned names that 'npm' installs.
1342
1364
return ;
1343
1365
}
1344
1366
const extension = path . extname ( dirent . name ) ;
1345
1367
const base = StringPrototypeSlice ( dirent . name , 0 , - extension . length ) ;
1346
1368
if ( ! dirent . isDirectory ( ) ) {
1347
1369
if ( StringPrototypeIncludes ( extensions , extension ) &&
1348
- ( ! subdir || base !== 'index' ) ) {
1370
+ ( ! subdir || base !== 'index' ) ) {
1349
1371
ArrayPrototypePush ( group , `${ subdir } ${ base } ` ) ;
1350
1372
}
1351
1373
return ;
@@ -1398,7 +1420,7 @@ function complete(line, callback) {
1398
1420
ArrayPrototypeForEach ( dirents , ( dirent ) => {
1399
1421
const { name } = dirent ;
1400
1422
if ( RegExpPrototypeExec ( versionedFileNamesRe , name ) !== null ||
1401
- name === '.npm' ) {
1423
+ name === '.npm' ) {
1402
1424
// Exclude versioned names that 'npm' installs.
1403
1425
return ;
1404
1426
}
@@ -1431,20 +1453,20 @@ function complete(line, callback) {
1431
1453
1432
1454
ArrayPrototypePush ( completionGroups , _builtinLibs , nodeSchemeBuiltinLibs ) ;
1433
1455
} else if ( ( match = RegExpPrototypeExec ( fsAutoCompleteRE , line ) ) !== null &&
1434
- this . allowBlockingCompletions ) {
1456
+ this . allowBlockingCompletions ) {
1435
1457
( { 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 ''
1446
1468
} else if ( line . length === 0 ||
1447
- RegExpPrototypeExec ( / \w | \. | \$ / , line [ line . length - 1 ] ) !== null ) {
1469
+ RegExpPrototypeExec ( / \w | \. | \$ / , line [ line . length - 1 ] ) !== null ) {
1448
1470
const { 0 : match } = RegExpPrototypeExec ( simpleExpressionRE , line ) || [ '' ] ;
1449
1471
if ( line . length !== 0 && ! match ) {
1450
1472
completionGroupsLoaded ( ) ;
@@ -1495,7 +1517,7 @@ function complete(line, callback) {
1495
1517
try {
1496
1518
let p ;
1497
1519
if ( ( typeof obj === 'object' && obj !== null ) ||
1498
- typeof obj === 'function' ) {
1520
+ typeof obj === 'function' ) {
1499
1521
memberGroups . push ( filteredOwnPropertyNames ( obj ) ) ;
1500
1522
p = ObjectGetPrototypeOf ( obj ) ;
1501
1523
} else {
0 commit comments