@@ -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,25 @@ 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 ( codeLine , { sourceType : 'module' } ) ;
234
+
235
+ acornWalk . ancestor ( ast , {
236
+ ImportDeclaration ( node , ancestors ) {
237
+ const importedModules = node . source . value ;
238
+ let importedSpecifiers = node . specifiers . map ( ( specifier ) => specifier . local . name ) ;
239
+ if ( importedSpecifiers . length > 1 ) {
240
+ importedSpecifiers = `{${ importedSpecifiers . join ( ',' ) } }` ;
241
+ }
242
+ dynamicImportStatement += `const ${ importedSpecifiers . length || importedModules } = await import('${ importedModules } ');` ;
243
+ } ,
244
+ } ) ;
245
+ return dynamicImportStatement ;
246
+ } ;
247
+
248
+
226
249
function REPLServer ( prompt ,
227
250
stream ,
228
251
eval_ ,
@@ -283,13 +306,13 @@ function REPLServer(prompt,
283
306
get : pendingDeprecation ?
284
307
deprecate ( ( ) => this . input ,
285
308
'repl.inputStream and repl.outputStream are deprecated. ' +
286
- 'Use repl.input and repl.output instead' ,
309
+ 'Use repl.input and repl.output instead' ,
287
310
'DEP0141' ) :
288
311
( ) => this . input ,
289
312
set : pendingDeprecation ?
290
313
deprecate ( ( val ) => this . input = val ,
291
314
'repl.inputStream and repl.outputStream are deprecated. ' +
292
- 'Use repl.input and repl.output instead' ,
315
+ 'Use repl.input and repl.output instead' ,
293
316
'DEP0141' ) :
294
317
( val ) => this . input = val ,
295
318
enumerable : false ,
@@ -300,13 +323,13 @@ function REPLServer(prompt,
300
323
get : pendingDeprecation ?
301
324
deprecate ( ( ) => this . output ,
302
325
'repl.inputStream and repl.outputStream are deprecated. ' +
303
- 'Use repl.input and repl.output instead' ,
326
+ 'Use repl.input and repl.output instead' ,
304
327
'DEP0141' ) :
305
328
( ) => this . output ,
306
329
set : pendingDeprecation ?
307
330
deprecate ( ( val ) => this . output = val ,
308
331
'repl.inputStream and repl.outputStream are deprecated. ' +
309
- 'Use repl.input and repl.output instead' ,
332
+ 'Use repl.input and repl.output instead' ,
310
333
'DEP0141' ) :
311
334
( val ) => this . output = val ,
312
335
enumerable : false ,
@@ -344,9 +367,9 @@ function REPLServer(prompt,
344
367
// instance and that could trigger the `MaxListenersExceededWarning`.
345
368
process . prependListener ( 'newListener' , ( event , listener ) => {
346
369
if ( event === 'uncaughtException' &&
347
- process . domain &&
348
- listener . name !== 'domainUncaughtExceptionClear' &&
349
- domainSet . has ( process . domain ) ) {
370
+ process . domain &&
371
+ listener . name !== 'domainUncaughtExceptionClear' &&
372
+ domainSet . has ( process . domain ) ) {
350
373
// Throw an error so that the event will not be added and the current
351
374
// domain takes over. That way the user is notified about the error
352
375
// and the current code evaluation is stopped, just as any other code
@@ -363,8 +386,8 @@ function REPLServer(prompt,
363
386
const savedRegExMatches = [ '' , '' , '' , '' , '' , '' , '' , '' , '' , '' ] ;
364
387
const sep = '\u0000\u0000\u0000' ;
365
388
const regExMatcher = new RegExp ( `^${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
366
- `${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
367
- `${ sep } (.*)$` ) ;
389
+ `${ sep } (.*)${ sep } (.*)${ sep } (.*)${ sep } (.*)` +
390
+ `${ sep } (.*)$` ) ;
368
391
369
392
eval_ = eval_ || defaultEval ;
370
393
@@ -417,7 +440,7 @@ function REPLServer(prompt,
417
440
// an expression. Note that if the above condition changes,
418
441
// lib/internal/repl/utils.js needs to be changed to match.
419
442
if ( RegExpPrototypeExec ( / ^ \s * { / , code ) !== null &&
420
- RegExpPrototypeExec ( / ; \s * $ / , code ) === null ) {
443
+ RegExpPrototypeExec ( / ; \s * $ / , code ) === null ) {
421
444
code = `(${ StringPrototypeTrim ( code ) } )\n` ;
422
445
wrappedCmd = true ;
423
446
}
@@ -492,7 +515,7 @@ function REPLServer(prompt,
492
515
while ( true ) {
493
516
try {
494
517
if ( self . replMode === module . exports . REPL_MODE_STRICT &&
495
- RegExpPrototypeExec ( / ^ \s * $ / , code ) === null ) {
518
+ RegExpPrototypeExec ( / ^ \s * $ / , code ) === null ) {
496
519
// "void 0" keeps the repl from returning "use strict" as the result
497
520
// value for statements and declarations that don't return a value.
498
521
code = `'use strict'; void 0;\n${ code } ` ;
@@ -684,7 +707,7 @@ function REPLServer(prompt,
684
707
'module' ;
685
708
if ( StringPrototypeIncludes ( e . message , importErrorStr ) ) {
686
709
e . message = 'Cannot use import statement inside the Node.js ' +
687
- 'REPL, alternatively use dynamic import' ;
710
+ 'REPL, alternatively use dynamic import: ' + toDynamicImport ( self . lines . at ( - 1 ) ) ;
688
711
e . stack = SideEffectFreeRegExpPrototypeSymbolReplace (
689
712
/ S y n t a x E r r o r : .* \n / ,
690
713
e . stack ,
@@ -712,7 +735,7 @@ function REPLServer(prompt,
712
735
}
713
736
714
737
if ( options [ kStandaloneREPL ] &&
715
- process . listenerCount ( 'uncaughtException' ) !== 0 ) {
738
+ process . listenerCount ( 'uncaughtException' ) !== 0 ) {
716
739
process . nextTick ( ( ) => {
717
740
process . emit ( 'uncaughtException' , e ) ;
718
741
self . clearBufferedCommand ( ) ;
@@ -729,7 +752,7 @@ function REPLServer(prompt,
729
752
errStack = '' ;
730
753
ArrayPrototypeForEach ( lines , ( line ) => {
731
754
if ( ! matched &&
732
- RegExpPrototypeExec ( / ^ \[ ? ( [ A - Z ] [ a - z 0 - 9 _ ] * ) * E r r o r / , line ) !== null ) {
755
+ RegExpPrototypeExec ( / ^ \[ ? ( [ A - Z ] [ a - z 0 - 9 _ ] * ) * E r r o r / , line ) !== null ) {
733
756
errStack += writer . options . breakLength >= line . length ?
734
757
`Uncaught ${ line } ` :
735
758
`Uncaught:\n${ line } ` ;
@@ -875,8 +898,8 @@ function REPLServer(prompt,
875
898
// display next prompt and return.
876
899
if ( trimmedCmd ) {
877
900
if ( StringPrototypeCharAt ( trimmedCmd , 0 ) === '.' &&
878
- StringPrototypeCharAt ( trimmedCmd , 1 ) !== '.' &&
879
- NumberIsNaN ( NumberParseFloat ( trimmedCmd ) ) ) {
901
+ StringPrototypeCharAt ( trimmedCmd , 1 ) !== '.' &&
902
+ NumberIsNaN ( NumberParseFloat ( trimmedCmd ) ) ) {
880
903
const matches = RegExpPrototypeExec ( / ^ \. ( [ ^ \s ] + ) \s * ( .* ) $ / , trimmedCmd ) ;
881
904
const keyword = matches && matches [ 1 ] ;
882
905
const rest = matches && matches [ 2 ] ;
@@ -901,10 +924,10 @@ function REPLServer(prompt,
901
924
ReflectApply ( _memory , self , [ cmd ] ) ;
902
925
903
926
if ( e && ! self [ kBufferedCommandSymbol ] &&
904
- StringPrototypeStartsWith ( StringPrototypeTrim ( cmd ) , 'npm ' ) ) {
927
+ StringPrototypeStartsWith ( StringPrototypeTrim ( cmd ) , 'npm ' ) ) {
905
928
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' ) ;
929
+ 'Node.js REPL, in your normal shell.\n' +
930
+ '(Press Ctrl+D to exit.)\n' ) ;
908
931
self . displayPrompt ( ) ;
909
932
return ;
910
933
}
@@ -929,11 +952,11 @@ function REPLServer(prompt,
929
952
930
953
// If we got any output - print it (if no error)
931
954
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 ) ) {
955
+ // When an invalid REPL command is used, error message is printed
956
+ // immediately. We don't have to print anything else. So, only when
957
+ // the second argument to this function is there, print it.
958
+ arguments . length === 2 &&
959
+ ( ! self . ignoreUndefined || ret !== undefined ) ) {
937
960
if ( ! self . underscoreAssigned ) {
938
961
self . last = ret ;
939
962
}
@@ -984,7 +1007,7 @@ function REPLServer(prompt,
984
1007
if ( ! self . editorMode || ! self . terminal ) {
985
1008
// Before exiting, make sure to clear the line.
986
1009
if ( key . ctrl && key . name === 'd' &&
987
- self . cursor === 0 && self . line . length === 0 ) {
1010
+ self . cursor === 0 && self . line . length === 0 ) {
988
1011
self . clearLine ( ) ;
989
1012
}
990
1013
clearPreview ( key ) ;
@@ -1181,7 +1204,7 @@ const importRE = /\bimport\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])
1181
1204
const requireRE = / \b r e q u i r e \s * \( \s * [ ' " ` ] ( ( [ \w @ . / : - ] + \/ ) ? (?: [ \w @ . / : - ] * ) ) (? ! [ ^ ' " ` ] ) $ / ;
1182
1205
const fsAutoCompleteRE = / f s (?: \. p r o m i s e s ) ? \. \s * [ a - z ] [ a - z A - Z ] + \( \s * [ " ' ] ( .* ) / ;
1183
1206
const simpleExpressionRE =
1184
- / (?: [ \w $ ' " ` [ { ( ] (?: \w | \$ | [ ' " ` \] } ) ] ) * \? ? \. ) * [ a - z A - Z _ $ ] (?: \w | \$ ) * \? ? \. ? $ / ;
1207
+ / (?: [ \w $ ' " ` [ { ( ] (?: \w | \$ | [ ' " ` \] } ) ] ) * \? ? \. ) * [ a - z A - Z _ $ ] (?: \w | \$ ) * \? ? \. ? $ / ;
1185
1208
const versionedFileNamesRe = / - \d + \. \d + / ;
1186
1209
1187
1210
function isIdentifier ( str ) {
@@ -1337,15 +1360,15 @@ function complete(line, callback) {
1337
1360
const dirents = gracefulReaddir ( dir , { withFileTypes : true } ) || [ ] ;
1338
1361
ArrayPrototypeForEach ( dirents , ( dirent ) => {
1339
1362
if ( RegExpPrototypeExec ( versionedFileNamesRe , dirent . name ) !== null ||
1340
- dirent . name === '.npm' ) {
1363
+ dirent . name === '.npm' ) {
1341
1364
// Exclude versioned names that 'npm' installs.
1342
1365
return ;
1343
1366
}
1344
1367
const extension = path . extname ( dirent . name ) ;
1345
1368
const base = StringPrototypeSlice ( dirent . name , 0 , - extension . length ) ;
1346
1369
if ( ! dirent . isDirectory ( ) ) {
1347
1370
if ( StringPrototypeIncludes ( extensions , extension ) &&
1348
- ( ! subdir || base !== 'index' ) ) {
1371
+ ( ! subdir || base !== 'index' ) ) {
1349
1372
ArrayPrototypePush ( group , `${ subdir } ${ base } ` ) ;
1350
1373
}
1351
1374
return ;
@@ -1398,7 +1421,7 @@ function complete(line, callback) {
1398
1421
ArrayPrototypeForEach ( dirents , ( dirent ) => {
1399
1422
const { name } = dirent ;
1400
1423
if ( RegExpPrototypeExec ( versionedFileNamesRe , name ) !== null ||
1401
- name === '.npm' ) {
1424
+ name === '.npm' ) {
1402
1425
// Exclude versioned names that 'npm' installs.
1403
1426
return ;
1404
1427
}
@@ -1431,20 +1454,20 @@ function complete(line, callback) {
1431
1454
1432
1455
ArrayPrototypePush ( completionGroups , _builtinLibs , nodeSchemeBuiltinLibs ) ;
1433
1456
} else if ( ( match = RegExpPrototypeExec ( fsAutoCompleteRE , line ) ) !== null &&
1434
- this . allowBlockingCompletions ) {
1457
+ this . allowBlockingCompletions ) {
1435
1458
( { 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 ''
1459
+ // Handle variable member lookup.
1460
+ // We support simple chained expressions like the following (no function
1461
+ // calls, etc.). That is for simplicity and also because we *eval* that
1462
+ // leading expression so for safety (see WARNING above) don't want to
1463
+ // eval function calls.
1464
+ //
1465
+ // foo.bar<|> # completions for 'foo' with filter 'bar'
1466
+ // spam.eggs.<|> # completions for 'spam.eggs' with filter ''
1467
+ // foo<|> # all scope vars with filter 'foo'
1468
+ // foo.<|> # completions for 'foo' with filter ''
1446
1469
} else if ( line . length === 0 ||
1447
- RegExpPrototypeExec ( / \w | \. | \$ / , line [ line . length - 1 ] ) !== null ) {
1470
+ RegExpPrototypeExec ( / \w | \. | \$ / , line [ line . length - 1 ] ) !== null ) {
1448
1471
const { 0 : match } = RegExpPrototypeExec ( simpleExpressionRE , line ) || [ '' ] ;
1449
1472
if ( line . length !== 0 && ! match ) {
1450
1473
completionGroupsLoaded ( ) ;
@@ -1495,7 +1518,7 @@ function complete(line, callback) {
1495
1518
try {
1496
1519
let p ;
1497
1520
if ( ( typeof obj === 'object' && obj !== null ) ||
1498
- typeof obj === 'function' ) {
1521
+ typeof obj === 'function' ) {
1499
1522
memberGroups . push ( filteredOwnPropertyNames ( obj ) ) ;
1500
1523
p = ObjectGetPrototypeOf ( obj ) ;
1501
1524
} else {
0 commit comments