From da0c901031d657e4cbd9d1b056bc28e1e0c0cd4a Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Thu, 20 Jun 2024 04:17:34 +0100 Subject: [PATCH] Core: Fix stacktrace cleaner to support URLs with host ports Fixes https://github.com/qunitjs/qunit/issues/1769. --- src/core/stacktrace.js | 45 ++++++++++++++++++++++++++++++++++++----- test/main/stacktrace.js | 8 +++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/core/stacktrace.js b/src/core/stacktrace.js index 1ab07cc48..3798234ec 100644 --- a/src/core/stacktrace.js +++ b/src/core/stacktrace.js @@ -1,10 +1,45 @@ -// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack +// Stacktrace cleaner to focus on the path from error source to test suite. +// +// This should reduce a raw stack trace like this: +// +// > foo.broken()@/src/foo.js +// > Bar@/src/bar.js +// > @/test/bar.test.js +// > @/lib/qunit.js:500:12 +// > @/lib/qunit.js:100:28 +// > @/lib/qunit.js:200:56 +// > setTimeout@ +// > @/dist/vendor.js +// +// and shorten it to show up until the end of the user's bar.test.js code. +// +// > foo.broken()@/src/foo.js +// > Bar@/src/bar.js +// > @/test/bar.test.js +// +// QUnit will obtain one example trace (once per process/pageload suffices), +// strip off any : and ::, and use that as match needle, +// to the first QUnit-internal frames, and then stop at that point. +// Any later frames, including those that are outside QUnit again, will be ommitted +// as being uninteresting to the test, since QUnit will have either started or +// resumed the test. This we also clean away browser built-ins, or other +// vendor/bundler that may be higher up the stack. +// +// Stripping :: is not for prettyness, it is essential for the +// match needle to work, since this sample trace will by definitin not be the +// same line as e.g. the QUnit.test() call we're trying to identify. +// +// See also: +// - https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack +// const fileName = (sourceFromStacktrace(0) || '') - .replace(/(:\d+)+\)?/, '') - // Remove anything prior to the last slash (Unix/Windows) - // from the last frame + // Global replace, because a frame like localhost:4000/lib/qunit.js:1234:50, + // would otherwise (harmlessly, but uselessly) remove only the port (first match). + // https://github.com/qunitjs/qunit/issues/1769 + .replace(/(:\d+)+\)?/g, '') + // Remove anything prior to the last slash (Unix/Windows) from the last frame, + // leaving only "qunit.js". .replace(/.+[/\\]/, ''); - export function extractStacktrace (e, offset) { offset = offset === undefined ? 4 : offset; diff --git a/test/main/stacktrace.js b/test/main/stacktrace.js index 311405de9..5b1ebebe6 100644 --- a/test/main/stacktrace.js +++ b/test/main/stacktrace.js @@ -27,7 +27,13 @@ assert.pushResult({ result: simple.indexOf('/main/stacktrace.js') !== -1, actual: simple, - message: 'current file' + message: 'include current file' + }); + assert.pushResult({ + result: simple.indexOf('qunit.js') === -1, + actual: simple, + expected: 'NOT qunit.js', + message: 'stacktrace cleaning stops before qunit.js' }); var nested = norm(fooParent());