Skip to content

Commit 9cb53f6

Browse files
aduh95danielleadams
authored andcommitted
repl: refactor to use more primordials
PR-URL: #36264 Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent faca2b8 commit 9cb53f6

File tree

4 files changed

+242
-149
lines changed

4 files changed

+242
-149
lines changed

lib/internal/repl/await.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
'use strict';
22

33
const {
4+
ArrayFrom,
5+
ArrayPrototypeJoin,
6+
ArrayPrototypePop,
7+
ArrayPrototypePush,
8+
FunctionPrototype,
49
ObjectKeys,
510
} = primordials;
611

@@ -19,7 +24,7 @@ const parser = acorn.Parser.extend(
1924
staticClassFeatures
2025
);
2126

22-
const noop = () => {};
27+
const noop = FunctionPrototype;
2328
const visitorsWithoutAncestors = {
2429
ClassDeclaration(node, state, c) {
2530
if (state.ancestors[state.ancestors.length - 2] === state.body) {
@@ -76,18 +81,18 @@ for (const nodeType of ObjectKeys(walk.base)) {
7681
visitors[nodeType] = (node, state, c) => {
7782
const isNew = node !== state.ancestors[state.ancestors.length - 1];
7883
if (isNew) {
79-
state.ancestors.push(node);
84+
ArrayPrototypePush(state.ancestors, node);
8085
}
8186
callback(node, state, c);
8287
if (isNew) {
83-
state.ancestors.pop();
88+
ArrayPrototypePop(state.ancestors);
8489
}
8590
};
8691
}
8792

8893
function processTopLevelAwait(src) {
8994
const wrapped = `(async () => { ${src} })()`;
90-
const wrappedArray = wrapped.split('');
95+
const wrappedArray = ArrayFrom(wrapped);
9196
let root;
9297
try {
9398
root = parser.parse(wrapped, { ecmaVersion: 'latest' });
@@ -142,7 +147,7 @@ function processTopLevelAwait(src) {
142147
state.append(last.expression, ')');
143148
}
144149

145-
return wrappedArray.join('');
150+
return ArrayPrototypeJoin(wrappedArray, '');
146151
}
147152

148153
module.exports = {

lib/internal/repl/history.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
'use strict';
22

33
const {
4+
ArrayPrototypeJoin,
45
Boolean,
6+
FunctionPrototype,
7+
StringPrototypeSplit,
8+
StringPrototypeTrim,
59
} = primordials;
610

711
const { Interface } = require('readline');
@@ -13,6 +17,8 @@ let debug = require('internal/util/debuglog').debuglog('repl', (fn) => {
1317
});
1418
const { clearTimeout, setTimeout } = require('timers');
1519

20+
const noop = FunctionPrototype;
21+
1622
// XXX(chrisdickinson): The 15ms debounce value is somewhat arbitrary.
1723
// The debounce is to guard against code pasted into the REPL.
1824
const kDebounceHistoryMS = 15;
@@ -27,7 +33,7 @@ function _writeToOutput(repl, message) {
2733
function setupHistory(repl, historyPath, ready) {
2834
// Empty string disables persistent history
2935
if (typeof historyPath === 'string')
30-
historyPath = historyPath.trim();
36+
historyPath = StringPrototypeTrim(historyPath);
3137

3238
if (historyPath === '') {
3339
repl._historyPrev = _replHistoryMessage;
@@ -84,7 +90,7 @@ function setupHistory(repl, historyPath, ready) {
8490
}
8591

8692
if (data) {
87-
repl.history = data.split(/[\n\r]+/, repl.historySize);
93+
repl.history = StringPrototypeSplit(data, /[\n\r]+/, repl.historySize);
8894
} else {
8995
repl.history = [];
9096
}
@@ -128,7 +134,7 @@ function setupHistory(repl, historyPath, ready) {
128134
return;
129135
}
130136
writing = true;
131-
const historyData = repl.history.join(os.EOL);
137+
const historyData = ArrayPrototypeJoin(repl.history, os.EOL);
132138
fs.write(repl._historyHandle, historyData, 0, 'utf8', onwritten);
133139
}
134140

@@ -151,7 +157,7 @@ function setupHistory(repl, historyPath, ready) {
151157
return;
152158
}
153159
repl.off('line', online);
154-
fs.close(repl._historyHandle, () => {});
160+
fs.close(repl._historyHandle, noop);
155161
}
156162
}
157163

lib/internal/repl/utils.js

+48-24
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
'use strict';
22

33
const {
4+
ArrayPrototypeFilter,
5+
ArrayPrototypeIncludes,
6+
ArrayPrototypeMap,
7+
Boolean,
8+
FunctionPrototypeBind,
49
MathMin,
5-
Set,
10+
RegExpPrototypeTest,
11+
SafeSet,
12+
StringPrototypeEndsWith,
13+
StringPrototypeIndexOf,
14+
StringPrototypeLastIndexOf,
15+
StringPrototypeReplace,
16+
StringPrototypeSlice,
17+
StringPrototypeStartsWith,
18+
StringPrototypeToLowerCase,
19+
StringPrototypeTrim,
620
Symbol,
721
} = primordials;
822

@@ -59,7 +73,9 @@ function isRecoverableError(e, code) {
5973
// curly brace with parenthesis. Note: only the open parenthesis is added
6074
// here as the point is to test for potentially valid but incomplete
6175
// expressions.
62-
if (/^\s*\{/.test(code) && isRecoverableError(e, `(${code}`)) return true;
76+
if (RegExpPrototypeTest(/^\s*\{/, code) &&
77+
isRecoverableError(e, `(${code}`))
78+
return true;
6379

6480
let recoverable = false;
6581

@@ -99,9 +115,11 @@ function isRecoverableError(e, code) {
99115
break;
100116

101117
case 'Unterminated string constant':
102-
const token = this.input.slice(this.lastTokStart, this.pos);
118+
const token = StringPrototypeSlice(this.input,
119+
this.lastTokStart, this.pos);
103120
// See https://www.ecma-international.org/ecma-262/#sec-line-terminators
104-
if (/\\(?:\r\n?|\n|\u2028|\u2029)$/.test(token)) {
121+
if (RegExpPrototypeTest(/\\(?:\r\n?|\n|\u2028|\u2029)$/,
122+
token)) {
105123
recoverable = true;
106124
}
107125
}
@@ -235,15 +253,15 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) {
235253
hasCompletions = true;
236254

237255
// If there is a common prefix to all matches, then apply that portion.
238-
const completions = rawCompletions.filter((e) => e);
256+
const completions = ArrayPrototypeFilter(rawCompletions, Boolean);
239257
const prefix = commonPrefix(completions);
240258

241259
// No common prefix found.
242260
if (prefix.length <= completeOn.length) {
243261
return;
244262
}
245263

246-
const suffix = prefix.slice(completeOn.length);
264+
const suffix = StringPrototypeSlice(prefix, completeOn.length);
247265

248266
if (insertPreview) {
249267
repl._insertString(suffix);
@@ -271,16 +289,22 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) {
271289
}
272290

273291
function isInStrictMode(repl) {
274-
return repl.replMode === REPL_MODE_STRICT || process.execArgv
275-
.map((e) => e.toLowerCase().replace(/_/g, '-'))
276-
.includes('--use-strict');
292+
return repl.replMode === REPL_MODE_STRICT || ArrayPrototypeIncludes(
293+
ArrayPrototypeMap(process.execArgv,
294+
(e) => StringPrototypeReplace(
295+
StringPrototypeToLowerCase(e),
296+
/_/g,
297+
'-'
298+
)),
299+
'--use-strict');
277300
}
278301

279302
// This returns a code preview for arbitrary input code.
280303
function getInputPreview(input, callback) {
281304
// For similar reasons as `defaultEval`, wrap expressions starting with a
282305
// curly brace with parenthesis.
283-
if (input.startsWith('{') && !input.endsWith(';') && !wrapped) {
306+
if (StringPrototypeStartsWith(input, '{') &&
307+
!StringPrototypeEndsWith(input, ';') && !wrapped) {
284308
input = `(${input})`;
285309
wrapped = true;
286310
}
@@ -346,7 +370,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) {
346370
return;
347371
}
348372

349-
const line = repl.line.trim();
373+
const line = StringPrototypeTrim(repl.line);
350374

351375
// Do not preview in case the line only contains whitespace.
352376
if (line === '') {
@@ -412,9 +436,9 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) {
412436

413437
// Line breaks are very rare and probably only occur in case of error
414438
// messages with line breaks.
415-
const lineBreakPos = inspected.indexOf('\n');
439+
const lineBreakPos = StringPrototypeIndexOf(inspected, '\n');
416440
if (lineBreakPos !== -1) {
417-
inspected = `${inspected.slice(0, lineBreakPos)}`;
441+
inspected = `${StringPrototypeSlice(inspected, 0, lineBreakPos)}`;
418442
}
419443

420444
const result = repl.useColors ?
@@ -452,7 +476,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) {
452476
// Refresh prints the whole screen again and the preview will be removed
453477
// during that procedure. Print the preview again. This also makes sure
454478
// the preview is always correct after resizing the terminal window.
455-
const originalRefresh = repl._refreshLine.bind(repl);
479+
const originalRefresh = FunctionPrototypeBind(repl._refreshLine, repl);
456480
repl._refreshLine = () => {
457481
inputPreview = null;
458482
originalRefresh();
@@ -462,7 +486,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) {
462486
let insertCompletionPreview = true;
463487
// Insert the longest common suffix of the current input in case the user
464488
// moves to the right while already being at the current input end.
465-
const originalMoveCursor = repl._moveCursor.bind(repl);
489+
const originalMoveCursor = FunctionPrototypeBind(repl._moveCursor, repl);
466490
repl._moveCursor = (dx) => {
467491
const currentCursor = repl.cursor;
468492
originalMoveCursor(dx);
@@ -476,7 +500,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) {
476500

477501
// This is the only function that interferes with the completion insertion.
478502
// Monkey patch it to prevent inserting the completion when it shouldn't be.
479-
const originalClearLine = repl.clearLine.bind(repl);
503+
const originalClearLine = FunctionPrototypeBind(repl.clearLine, repl);
480504
repl.clearLine = () => {
481505
insertCompletionPreview = false;
482506
originalClearLine();
@@ -492,7 +516,7 @@ function setupReverseSearch(repl) {
492516
return { reverseSearch() { return false; } };
493517
}
494518

495-
const alreadyMatched = new Set();
519+
const alreadyMatched = new SafeSet();
496520
const labels = {
497521
r: 'bck-i-search: ',
498522
s: 'fwd-i-search: '
@@ -556,18 +580,18 @@ function setupReverseSearch(repl) {
556580
if (cursor === -1) {
557581
cursor = entry.length;
558582
}
559-
cursor = entry.lastIndexOf(input, cursor - 1);
583+
cursor = StringPrototypeLastIndexOf(entry, input, cursor - 1);
560584
} else {
561-
cursor = entry.indexOf(input, cursor + 1);
585+
cursor = StringPrototypeIndexOf(entry, input, cursor + 1);
562586
}
563587
// Match not found.
564588
if (cursor === -1) {
565589
goToNextHistoryIndex();
566590
// Match found.
567591
} else {
568592
if (repl.useColors) {
569-
const start = entry.slice(0, cursor);
570-
const end = entry.slice(cursor + input.length);
593+
const start = StringPrototypeSlice(entry, 0, cursor);
594+
const end = StringPrototypeSlice(entry, cursor + input.length);
571595
entry = `${start}\x1B[4m${input}\x1B[24m${end}`;
572596
}
573597
print(entry, `${labels[dir]}${input}_`, cursor);
@@ -610,7 +634,7 @@ function setupReverseSearch(repl) {
610634
// tick end instead of after each operation.
611635
let rows = 0;
612636
if (lastMatch !== -1) {
613-
const line = repl.history[lastMatch].slice(0, lastCursor);
637+
const line = StringPrototypeSlice(repl.history[lastMatch], 0, lastCursor);
614638
rows = repl._getDisplayPos(`${repl.getPrompt()}${line}`).rows;
615639
cursorTo(repl.output, promptPos.cols);
616640
} else if (isInReverseSearch && repl.line !== '') {
@@ -632,7 +656,7 @@ function setupReverseSearch(repl) {
632656
// To know exactly how many rows we have to move the cursor back we need the
633657
// cursor rows, the output rows and the input rows.
634658
const prompt = repl.getPrompt();
635-
const cursorLine = `${prompt}${outputLine.slice(0, cursor)}`;
659+
const cursorLine = prompt + StringPrototypeSlice(outputLine, 0, cursor);
636660
const cursorPos = repl._getDisplayPos(cursorLine);
637661
const outputPos = repl._getDisplayPos(`${prompt}${outputLine}`);
638662
const inputPos = repl._getDisplayPos(inputLine);
@@ -690,7 +714,7 @@ function setupReverseSearch(repl) {
690714
search();
691715
} else if (key.name === 'backspace' ||
692716
(key.ctrl && (key.name === 'h' || key.name === 'w'))) {
693-
reset(input.slice(0, input.length - 1));
717+
reset(StringPrototypeSlice(input, 0, input.length - 1));
694718
search();
695719
// Special handle <ctrl> + c and escape. Those should only cancel the
696720
// reverse search. The original line is visible afterwards again.

0 commit comments

Comments
 (0)