| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -245,7 +245,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { | |||
| 245 | 245 | } | |
| 246 | 246 | ||
| 247 | 247 | // Result and the text that was completed. | |
| 248 | - const [rawCompletions, completeOn] = data; | ||
| 248 | + const { 0: rawCompletions, 1: completeOn } = data; | ||
| 249 | 249 | ||
| 250 | 250 | if (!rawCompletions || rawCompletions.length === 0) { | |
| 251 | 251 | return; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -309,7 +309,8 @@ function inspect(value, opts) { | |||
| 309 | 309 | ctx.showHidden = opts; | |
| 310 | 310 | } else if (opts) { | |
| 311 | 311 | const optKeys = ObjectKeys(opts); | |
| 312 | - for (const key of optKeys) { | ||
| 312 | + for (let i = 0; i < optKeys.length; ++i) { | ||
| 313 | + const key = optKeys[i]; | ||
| 313 | 314 | // TODO(BridgeAR): Find a solution what to do about stylize. Either make | |
| 314 | 315 | // this function public or add a new API with a similar or better | |
| 315 | 316 | // functionality. | |
@@ -1869,18 +1870,18 @@ function tryStringify(arg) { | |||
| 1869 | 1870 | } | |
| 1870 | 1871 | ||
| 1871 | 1872 | function format(...args) { | |
| 1872 | - return formatWithOptionsInternal(undefined, ...args); | ||
| 1873 | + return formatWithOptionsInternal(undefined, args); | ||
| 1873 | 1874 | } | |
| 1874 | 1875 | ||
| 1875 | 1876 | function formatWithOptions(inspectOptions, ...args) { | |
| 1876 | 1877 | if (typeof inspectOptions !== 'object' || inspectOptions === null) { | |
| 1877 | 1878 | throw new ERR_INVALID_ARG_TYPE( | |
| 1878 | 1879 | 'inspectOptions', 'object', inspectOptions); | |
| 1879 | 1880 | } | |
| 1880 | - return formatWithOptionsInternal(inspectOptions, ...args); | ||
| 1881 | + return formatWithOptionsInternal(inspectOptions, args); | ||
| 1881 | 1882 | } | |
| 1882 | 1883 | ||
| 1883 | - function formatWithOptionsInternal(inspectOptions, ...args) { | ||
| 1884 | + function formatWithOptionsInternal(inspectOptions, args) { | ||
| 1884 | 1885 | const first = args[0]; | |
| 1885 | 1886 | let a = 0; | |
| 1886 | 1887 | let str = ''; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -46,6 +46,7 @@ const { | |||
| 46 | 46 | ArrayPrototypeConcat, | |
| 47 | 47 | ArrayPrototypeFilter, | |
| 48 | 48 | ArrayPrototypeFindIndex, | |
| 49 | + ArrayPrototypeForEach, | ||
| 49 | 50 | ArrayPrototypeIncludes, | |
| 50 | 51 | ArrayPrototypeJoin, | |
| 51 | 52 | ArrayPrototypeMap, | |
@@ -663,7 +664,7 @@ function REPLServer(prompt, | |||
| 663 | 664 | let matched = false; | |
| 664 | 665 | ||
| 665 | 666 | errStack = ''; | |
| 666 | - for (const line of lines) { | ||
| 667 | + ArrayPrototypeForEach(lines, (line) => { | ||
| 667 | 668 | if (!matched && | |
| 668 | 669 | RegExpPrototypeTest(/^\[?([A-Z][a-z0-9_]*)*Error/, line)) { | |
| 669 | 670 | errStack += writer.options.breakLength >= line.length ? | |
@@ -673,7 +674,7 @@ function REPLServer(prompt, | |||
| 673 | 674 | } else { | |
| 674 | 675 | errStack += line; | |
| 675 | 676 | } | |
| 676 | - } | ||
| 677 | + }); | ||
| 677 | 678 | if (!matched) { | |
| 678 | 679 | const ln = lines.length === 1 ? ' ' : ':\n'; | |
| 679 | 680 | errStack = `Uncaught${ln}${errStack}`; | |
@@ -754,9 +755,7 @@ function REPLServer(prompt, | |||
| 754 | 755 | const prioritizedSigintQueue = new SafeSet(); | |
| 755 | 756 | self.on('SIGINT', function onSigInt() { | |
| 756 | 757 | if (prioritizedSigintQueue.size > 0) { | |
| 757 | - for (const task of prioritizedSigintQueue) { | ||
| 758 | - task(); | ||
| 759 | - } | ||
| 758 | + ArrayPrototypeForEach(prioritizedSigintQueue, (task) => task()); | ||
| 760 | 759 | return; | |
| 761 | 760 | } | |
| 762 | 761 | ||
@@ -1010,13 +1009,13 @@ REPLServer.prototype.createContext = function() { | |||
| 1010 | 1009 | }, () => { | |
| 1011 | 1010 | context = vm.createContext(); | |
| 1012 | 1011 | }); | |
| 1013 | - for (const name of ObjectGetOwnPropertyNames(global)) { | ||
| 1012 | + ArrayPrototypeForEach(ObjectGetOwnPropertyNames(global), (name) => { | ||
| 1014 | 1013 | // Only set properties that do not already exist as a global builtin. | |
| 1015 | 1014 | if (!globalBuiltins.has(name)) { | |
| 1016 | 1015 | ObjectDefineProperty(context, name, | |
| 1017 | 1016 | ObjectGetOwnPropertyDescriptor(global, name)); | |
| 1018 | 1017 | } | |
| 1019 | - } | ||
| 1018 | + }); | ||
| 1020 | 1019 | context.global = context; | |
| 1021 | 1020 | const _console = new Console(this.output); | |
| 1022 | 1021 | ObjectDefineProperty(context, 'console', { | |
@@ -1231,7 +1230,7 @@ function complete(line, callback) { | |||
| 1231 | 1230 | paths = ArrayPrototypeConcat(module.paths, CJSModule.globalPaths); | |
| 1232 | 1231 | } | |
| 1233 | 1232 | ||
| 1234 | - for (let dir of paths) { | ||
| 1233 | + ArrayPrototypeForEach(paths, (dir) => { | ||
| 1235 | 1234 | dir = path.resolve(dir, subdir); | |
| 1236 | 1235 | const dirents = gracefulReaddir(dir, { withFileTypes: true }) || []; | |
| 1237 | 1236 | for (const dirent of dirents) { | |
@@ -1259,7 +1258,7 @@ function complete(line, callback) { | |||
| 1259 | 1258 | } | |
| 1260 | 1259 | } | |
| 1261 | 1260 | } | |
| 1262 | - } | ||
| 1261 | + }); | ||
| 1263 | 1262 | if (group.length) { | |
| 1264 | 1263 | ArrayPrototypePush(completionGroups, group); | |
| 1265 | 1264 | } | |
@@ -1269,7 +1268,7 @@ function complete(line, callback) { | |||
| 1269 | 1268 | } | |
| 1270 | 1269 | } else if (RegExpPrototypeTest(fsAutoCompleteRE, line) && | |
| 1271 | 1270 | this.allowBlockingCompletions) { | |
| 1272 | - [completionGroups, completeOn] = completeFSFunctions(line); | ||
| 1271 | + ({ 0: completionGroups, 1: completeOn } = completeFSFunctions(line)); | ||
| 1273 | 1272 | // Handle variable member lookup. | |
| 1274 | 1273 | // We support simple chained expressions like the following (no function | |
| 1275 | 1274 | // calls, etc.). That is for simplicity and also because we *eval* that | |
@@ -1282,7 +1281,7 @@ function complete(line, callback) { | |||
| 1282 | 1281 | // foo.<|> # completions for 'foo' with filter '' | |
| 1283 | 1282 | } else if (line.length === 0 || | |
| 1284 | 1283 | RegExpPrototypeTest(/\w|\.|\$/, line[line.length - 1])) { | |
| 1285 | - const [match] = RegExpPrototypeExec(simpleExpressionRE, line) || ['']; | ||
| 1284 | + const { 0: match } = RegExpPrototypeExec(simpleExpressionRE, line) || ['']; | ||
| 1286 | 1285 | if (line.length !== 0 && !match) { | |
| 1287 | 1286 | completionGroupsLoaded(); | |
| 1288 | 1287 | return; | |
@@ -1352,11 +1351,11 @@ function complete(line, callback) { | |||
| 1352 | 1351 | ||
| 1353 | 1352 | if (memberGroups.length) { | |
| 1354 | 1353 | expr += chaining; | |
| 1355 | - for (const group of memberGroups) { | ||
| 1354 | + ArrayPrototypeForEach(memberGroups, (group) => { | ||
| 1356 | 1355 | ArrayPrototypePush(completionGroups, | |
| 1357 | 1356 | ArrayPrototypeMap(group, | |
| 1358 | 1357 | (member) => `${expr}${member}`)); | |
| 1359 | - } | ||
| 1358 | + }); | ||
| 1360 | 1359 | if (filter) { | |
| 1361 | 1360 | filter = `${expr}${filter}`; | |
| 1362 | 1361 | } | |
@@ -1375,37 +1374,38 @@ function complete(line, callback) { | |||
| 1375 | 1374 | // Filter, sort (within each group), uniq and merge the completion groups. | |
| 1376 | 1375 | if (completionGroups.length && filter) { | |
| 1377 | 1376 | const newCompletionGroups = []; | |
| 1378 | - for (const group of completionGroups) { | ||
| 1377 | + ArrayPrototypeForEach(completionGroups, (group) => { | ||
| 1379 | 1378 | const filteredGroup = ArrayPrototypeFilter( | |
| 1380 | 1379 | group, | |
| 1381 | 1380 | (str) => StringPrototypeStartsWith(str, filter) | |
| 1382 | 1381 | ); | |
| 1383 | 1382 | if (filteredGroup.length) { | |
| 1384 | 1383 | ArrayPrototypePush(newCompletionGroups, filteredGroup); | |
| 1385 | 1384 | } | |
| 1386 | - } | ||
| 1385 | + }); | ||
| 1387 | 1386 | completionGroups = newCompletionGroups; | |
| 1388 | 1387 | } | |
| 1389 | 1388 | ||
| 1390 | 1389 | const completions = []; | |
| 1391 | 1390 | // Unique completions across all groups. | |
| 1392 | - const uniqueSet = new SafeSet(['']); | ||
| 1391 | + const uniqueSet = new SafeSet(); | ||
| 1392 | + uniqueSet.add(''); | ||
| 1393 | 1393 | // Completion group 0 is the "closest" (least far up the inheritance | |
| 1394 | 1394 | // chain) so we put its completions last: to be closest in the REPL. | |
| 1395 | - for (const group of completionGroups) { | ||
| 1395 | + ArrayPrototypeForEach(completionGroups, (group) => { | ||
| 1396 | 1396 | ArrayPrototypeSort(group, (a, b) => (b > a ? 1 : -1)); | |
| 1397 | 1397 | const setSize = uniqueSet.size; | |
| 1398 | - for (const entry of group) { | ||
| 1398 | + ArrayPrototypeForEach(group, (entry) => { | ||
| 1399 | 1399 | if (!uniqueSet.has(entry)) { | |
| 1400 | 1400 | ArrayPrototypeUnshift(completions, entry); | |
| 1401 | 1401 | uniqueSet.add(entry); | |
| 1402 | 1402 | } | |
| 1403 | - } | ||
| 1403 | + }); | ||
| 1404 | 1404 | // Add a separator between groups. | |
| 1405 | 1405 | if (uniqueSet.size !== setSize) { | |
| 1406 | 1406 | ArrayPrototypeUnshift(completions, ''); | |
| 1407 | 1407 | } | |
| 1408 | - } | ||
| 1408 | + }); | ||
| 1409 | 1409 | ||
| 1410 | 1410 | // Remove obsolete group entry, if present. | |
| 1411 | 1411 | if (completions[0] === '') { | |
@@ -1569,14 +1569,13 @@ function defineDefaultCommands(repl) { | |||
| 1569 | 1569 | const longestNameLength = MathMax( | |
| 1570 | 1570 | ...ArrayPrototypeMap(names, (name) => name.length) | |
| 1571 | 1571 | ); | |
| 1572 | - for (let n = 0; n < names.length; n++) { | ||
| 1573 | - const name = names[n]; | ||
| 1572 | + ArrayPrototypeForEach(names, (name) => { | ||
| 1574 | 1573 | const cmd = this.commands[name]; | |
| 1575 | 1574 | const spaces = | |
| 1576 | 1575 | StringPrototypeRepeat(' ', longestNameLength - name.length + 3); | |
| 1577 | 1576 | const line = `.${name}${cmd.help ? spaces + cmd.help : ''}\n`; | |
| 1578 | 1577 | this.output.write(line); | |
| 1579 | - } | ||
| 1578 | + }); | ||
| 1580 | 1579 | this.output.write('\nPress Ctrl+C to abort current expression, ' + | |
| 1581 | 1580 | 'Ctrl+D to exit the REPL\n'); | |
| 1582 | 1581 | this.displayPrompt(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -504,7 +504,56 @@ const tests = [ | |||
| 504 | 504 | prompt, | |
| 505 | 505 | ], | |
| 506 | 506 | clean: true | |
| 507 | - } | ||
| 507 | + }, | ||
| 508 | + { | ||
| 509 | + env: { NODE_REPL_HISTORY: defaultHistoryPath }, | ||
| 510 | + test: (function*() { | ||
| 511 | + // Deleting Array iterator should not break history feature. | ||
| 512 | + // | ||
| 513 | + // Using a generator function instead of an object to allow the test to | ||
| 514 | + // keep iterating even when Array.prototype[Symbol.iterator] has been | ||
| 515 | + // deleted. | ||
| 516 | + yield 'const ArrayIteratorPrototype ='; | ||
| 517 | + yield ' Object.getPrototypeOf(Array.prototype[Symbol.iterator]());'; | ||
| 518 | + yield ENTER; | ||
| 519 | + yield 'const {next} = ArrayIteratorPrototype;'; | ||
| 520 | + yield ENTER; | ||
| 521 | + yield 'const realArrayIterator = Array.prototype[Symbol.iterator];'; | ||
| 522 | + yield ENTER; | ||
| 523 | + yield 'delete Array.prototype[Symbol.iterator];'; | ||
| 524 | + yield ENTER; | ||
| 525 | + yield 'delete ArrayIteratorPrototype.next;'; | ||
| 526 | + yield ENTER; | ||
| 527 | + yield UP; | ||
| 528 | + yield UP; | ||
| 529 | + yield DOWN; | ||
| 530 | + yield DOWN; | ||
| 531 | + yield 'fu'; | ||
| 532 | + yield 'n'; | ||
| 533 | + yield RIGHT; | ||
| 534 | + yield BACKSPACE; | ||
| 535 | + yield LEFT; | ||
| 536 | + yield LEFT; | ||
| 537 | + yield 'A'; | ||
| 538 | + yield BACKSPACE; | ||
| 539 | + yield GO_TO_END; | ||
| 540 | + yield BACKSPACE; | ||
| 541 | + yield WORD_LEFT; | ||
| 542 | + yield WORD_RIGHT; | ||
| 543 | + yield ESCAPE; | ||
| 544 | + yield ENTER; | ||
| 545 | + yield 'Array.proto'; | ||
| 546 | + yield RIGHT; | ||
| 547 | + yield '.pu'; | ||
| 548 | + yield ENTER; | ||
| 549 | + yield 'ArrayIteratorPrototype.next = next;'; | ||
| 550 | + yield ENTER; | ||
| 551 | + yield 'Array.prototype[Symbol.iterator] = realArrayIterator;'; | ||
| 552 | + yield ENTER; | ||
| 553 | + })(), | ||
| 554 | + expected: [], | ||
| 555 | + clean: false | ||
| 556 | + }, | ||
| 508 | 557 | ]; | |
| 509 | 558 | const numtests = tests.length; | |
| 510 | 559 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,68 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + const { spawn } = require('child_process'); | ||
| 5 | + | ||
| 6 | + const replProcess = spawn(process.argv0, ['--interactive'], { | ||
| 7 | + stdio: ['pipe', 'pipe', 'inherit'], | ||
| 8 | + windowsHide: true, | ||
| 9 | + }); | ||
| 10 | + | ||
| 11 | + replProcess.on('error', common.mustNotCall()); | ||
| 12 | + | ||
| 13 | + const replReadyState = (async function* () { | ||
| 14 | + let ready; | ||
| 15 | + const SPACE = ' '.charCodeAt(); | ||
| 16 | + const BRACKET = '>'.charCodeAt(); | ||
| 17 | + const DOT = '.'.charCodeAt(); | ||
| 18 | + replProcess.stdout.on('data', (data) => { | ||
| 19 | + ready = data[data.length - 1] === SPACE && ( | ||
| 20 | + data[data.length - 2] === BRACKET || ( | ||
| 21 | + data[data.length - 2] === DOT && | ||
| 22 | + data[data.length - 3] === DOT && | ||
| 23 | + data[data.length - 4] === DOT | ||
| 24 | + )); | ||
| 25 | + }); | ||
| 26 | + | ||
| 27 | + const processCrashed = new Promise((resolve, reject) => | ||
| 28 | + replProcess.on('exit', reject) | ||
| 29 | + ); | ||
| 30 | + while (true) { | ||
| 31 | + await Promise.race([new Promise(setImmediate), processCrashed]); | ||
| 32 | + if (ready) { | ||
| 33 | + ready = false; | ||
| 34 | + yield; | ||
| 35 | + } | ||
| 36 | + } | ||
| 37 | + })(); | ||
| 38 | + async function writeLn(data, expectedOutput) { | ||
| 39 | + await replReadyState.next(); | ||
| 40 | + if (expectedOutput) { | ||
| 41 | + replProcess.stdout.once('data', common.mustCall((data) => | ||
| 42 | + assert.match(data.toString('utf8'), expectedOutput) | ||
| 43 | + )); | ||
| 44 | + } | ||
| 45 | + await new Promise((resolve, reject) => replProcess.stdin.write( | ||
| 46 | + `${data}\n`, | ||
| 47 | + (err) => (err ? reject(err) : resolve()) | ||
| 48 | + )); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + async function main() { | ||
| 52 | + await writeLn( | ||
| 53 | + 'const ArrayIteratorPrototype =' + | ||
| 54 | + ' Object.getPrototypeOf(Array.prototype[Symbol.iterator]());' | ||
| 55 | + ); | ||
| 56 | + await writeLn('delete Array.prototype[Symbol.iterator];'); | ||
| 57 | + await writeLn('delete ArrayIteratorPrototype.next;'); | ||
| 58 | + | ||
| 59 | + await writeLn( | ||
| 60 | + 'for(const x of [3, 2, 1]);', | ||
| 61 | + /Uncaught TypeError: \[3,2,1\] is not iterable/ | ||
| 62 | + ); | ||
| 63 | + await writeLn('.exit'); | ||
| 64 | + | ||
| 65 | + assert(!replProcess.connected); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + main().then(common.mustCall()); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments