From 60640463c6bc2993b5da4a358725dc4e9cbcca90 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sun, 18 Nov 2018 04:25:05 +0100 Subject: [PATCH 1/2] events: simplify stack compare function This simplifies the `longestSeqContainedIn()` logic by checking for the first identical occurance of at least three frames instead of the longest one. It also removes an unused argument. --- lib/events.js | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/lib/events.js b/lib/events.js index 5dfa34469b09af..5d3a190cf349dd 100644 --- a/lib/events.js +++ b/lib/events.js @@ -103,30 +103,29 @@ EventEmitter.prototype.getMaxListeners = function getMaxListeners() { return $getMaxListeners(this); }; -// Returns the longest sequence of `a` that fully appears in `b`, -// of length at least 3. -// This is a lazy approach but should work well enough, given that stack -// frames are usually unequal or otherwise appear in groups, and that -// we only run this code in case of an unhandled exception. -function longestSeqContainedIn(a, b) { - for (var len = a.length; len >= 3; --len) { - for (var i = 0; i < a.length - len; ++i) { - // Attempt to find a[i:i+len] in b - for (var j = 0; j < b.length - len; ++j) { - let matches = true; - for (var k = 0; k < len; ++k) { - if (a[i + k] !== b[j + k]) { - matches = false; - break; - } +// Returns the length and line number of the first sequence of `a` that fully +// appears in `b` with a length of at least 4. +function identicalSequenceRange(a, b) { + for (var i = 0; i < a.length - 3; i++) { + // Find the first occurrence of the frame that could match up to four + // frames. + const pos = b.indexOf(a[i]); + if (pos !== -1) { + const rest = b.length - pos; + if (rest > 3) { + let len = 1; + const maxLen = Math.min(a.length - i, rest); + while (maxLen > len && a[i + len] === b[pos + len]) { + len++; + } + if (len > 3) { + return [len, i]; } - if (matches) - return [ len, i, j ]; } } } - return [ 0, 0, 0 ]; + return [0, 0]; } function enhanceStackTrace(err, own) { @@ -135,9 +134,9 @@ function enhanceStackTrace(err, own) { const errStack = err.stack.split('\n').slice(1); const ownStack = own.stack.split('\n').slice(1); - const [ len, off ] = longestSeqContainedIn(ownStack, errStack); + const [ len, off ] = identicalSequenceRange(ownStack, errStack); if (len > 0) { - ownStack.splice(off + 1, len - 1, + ownStack.splice(off + 1, len - 2, ' [... lines matching original stack trace ...]'); } // Do this last, because it is the only operation with side effects. From 11a6984df6153a308790919539be4c254a318369 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Fri, 30 Nov 2018 15:46:52 +0100 Subject: [PATCH 2/2] fixup: improve comments --- lib/events.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/events.js b/lib/events.js index 5d3a190cf349dd..476c44c804e412 100644 --- a/lib/events.js +++ b/lib/events.js @@ -107,14 +107,14 @@ EventEmitter.prototype.getMaxListeners = function getMaxListeners() { // appears in `b` with a length of at least 4. function identicalSequenceRange(a, b) { for (var i = 0; i < a.length - 3; i++) { - // Find the first occurrence of the frame that could match up to four - // frames. + // Find the first entry of b that matches the current entry of a. const pos = b.indexOf(a[i]); if (pos !== -1) { const rest = b.length - pos; if (rest > 3) { let len = 1; const maxLen = Math.min(a.length - i, rest); + // Count the number of consecutive entries. while (maxLen > len && a[i + len] === b[pos + len]) { len++; }