readline: replace quadratic regex with linear one · nodejs/node@78fad32 (original) (raw)

2 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -569,8 +569,11 @@ function commonPrefix(strings) {
569 569
570 570 Interface.prototype._wordLeft = function() {
571 571 if (this.cursor > 0) {
572 +// Reverse the string and match a word near beginning
573 +// to avoid quadratic time complexity
572 574 var leading = this.line.slice(0, this.cursor);
573 -var match = leading.match(/(?:[^\w\s]+|\w+
575 +var reversed = leading.split('').reverse().join('');
576 +var match = reversed.match(/^\s*(?:[^\w\s]+|\w+)?/);
574 577 this._moveCursor(-match[0].length);
575 578 }
576 579 };
@@ -626,8 +629,11 @@ Interface.prototype._deleteRight = function() {
626 629
627 630 Interface.prototype._deleteWordLeft = function() {
628 631 if (this.cursor > 0) {
632 +// Reverse the string and match a word near beginning
633 +// to avoid quadratic time complexity
629 634 var leading = this.line.slice(0, this.cursor);
630 -var match = leading.match(/(?:[^\w\s]+|\w+
635 +var reversed = leading.split('').reverse().join('');
636 +var match = reversed.match(/^\s*(?:[^\w\s]+|\w+)?/);
631 637 leading = leading.slice(0, leading.length - match[0].length);
632 638 this.line = leading + this.line.slice(this.cursor, this.line.length);
633 639 this.cursor = leading.length;
Original file line number Diff line number Diff line change
@@ -1272,3 +1272,26 @@ const crlfDelay = Infinity;
1272 1272 }), delay);
1273 1273 }
1274 1274 });
1275 +
1276 +// Ensure that the _wordLeft method works even for large input
1277 +{
1278 +const input = new Readable({
1279 +read() {
1280 +this.push('\x1B[1;5D'); // CTRL + Left
1281 +this.push(null);
1282 +},
1283 +});
1284 +const output = new Writable({
1285 +write: common.mustCall((data, encoding, cb) => {
1286 +assert.strictEqual(rl.cursor, rl.line.length - 1);
1287 +cb();
1288 +}),
1289 +});
1290 +const rl = new readline.createInterface({
1291 +input: input,
1292 +output: output,
1293 +terminal: true,
1294 +});
1295 +rl.line = `a${' '.repeat(1e6)}a`;
1296 +rl.cursor = rl.line.length;
1297 +}