mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
fix(sentry): handle SyntaxError type/value split and Chrome short-function format
Greptile review findings:
P1: Sentry splits SyntaxError into type='SyntaxError' + value='Unexpected
token <'. The value never contains the 'SyntaxError:' prefix, so the
regex never matched. Added excType === 'SyntaxError' check (same pattern
as the existing TypeError dual-check).
P2: The short-function pattern only caught Safari's '(In ...' suffix.
Chrome/V8 emits bare 'xy is not a function'. Simplified to /^\w{1,2}
is not a function/ to cover both engines.
This commit is contained in:
@@ -317,7 +317,7 @@ Sentry.init({
|
||||
/\.(?:toLowerCase|trim|indexOf|findIndex) is not a function/.test(msg)
|
||||
|| /Maximum call stack size exceeded/.test(msg)
|
||||
|| /out of memory/i.test(msg)
|
||||
|| /^\w{1,2} is not a function\. \(In '\w{1,2}\(/.test(msg)
|
||||
|| /^\w{1,2} is not a function/.test(msg)
|
||||
|| /Cannot add property \w+, object is not extensible/.test(msg)
|
||||
|| /^TypeError: Internal error$/.test(msg)
|
||||
|| /NotSupportedError/.test(msg)
|
||||
@@ -327,6 +327,7 @@ Sentry.init({
|
||||
|| /^TypeError: NetworkError/.test(msg)
|
||||
|| /Could not connect to the server/.test(msg)
|
||||
|| /(?:Failed to fetch|Importing a module script failed|error loading) dynamically imported module/i.test(msg)
|
||||
|| (excType === 'SyntaxError' && /^Unexpected (?:token|keyword)/.test(msg))
|
||||
|| /^SyntaxError: Unexpected (?:token|keyword)/.test(msg)
|
||||
|| /Invalid or unexpected token/.test(msg)
|
||||
|| /^Operation timed out/.test(msg)
|
||||
|
||||
@@ -136,11 +136,15 @@ describe('empty-stack network/timeout errors are NOT suppressed', () => {
|
||||
'Importing a module script failed.',
|
||||
'Operation timed out',
|
||||
'signal timed out',
|
||||
'SyntaxError: Unexpected token <',
|
||||
'SyntaxError: Unexpected keyword \'const\'',
|
||||
'Invalid or unexpected token',
|
||||
];
|
||||
|
||||
// SyntaxErrors split by Sentry: type='SyntaxError', value='Unexpected token <'
|
||||
const syntaxErrors = [
|
||||
['Unexpected token <', 'SyntaxError'],
|
||||
['Unexpected keyword \'const\'', 'SyntaxError'],
|
||||
];
|
||||
|
||||
for (const msg of networkErrors) {
|
||||
it(`lets through "${msg.slice(0, 60)}..." with empty stack`, () => {
|
||||
const event = makeEvent(msg, msg.startsWith('SyntaxError') ? 'SyntaxError' : 'TypeError', []);
|
||||
@@ -167,6 +171,25 @@ describe('empty-stack network/timeout errors are NOT suppressed', () => {
|
||||
assert.ok(result !== null, `"${msg}" with first-party stack should NOT be suppressed`);
|
||||
});
|
||||
}
|
||||
|
||||
// Sentry splits SyntaxError into type='SyntaxError' + value='Unexpected token <'
|
||||
// The value field never contains the 'SyntaxError:' prefix.
|
||||
for (const [value, type] of syntaxErrors) {
|
||||
it(`suppresses SyntaxError (split: value="${value}") with third-party stack`, () => {
|
||||
const event = makeEvent(value, type, [extensionFrame()]);
|
||||
assert.equal(beforeSend(event), null);
|
||||
});
|
||||
|
||||
it(`lets through SyntaxError (split: value="${value}") with empty stack`, () => {
|
||||
const event = makeEvent(value, type, []);
|
||||
assert.ok(beforeSend(event) !== null);
|
||||
});
|
||||
|
||||
it(`lets through SyntaxError (split: value="${value}") with first-party stack`, () => {
|
||||
const event = makeEvent(value, type, [firstPartyFrame()]);
|
||||
assert.ok(beforeSend(event) !== null);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ─── All ambiguous errors require confirmed third-party stack ────────────
|
||||
@@ -184,6 +207,17 @@ describe('ambiguous runtime errors', () => {
|
||||
'Element not found',
|
||||
];
|
||||
|
||||
// Chrome V8 emits "xy is not a function" without Safari's "(In 'xy(...')" suffix
|
||||
it('suppresses Chrome-style "t is not a function" with third-party stack', () => {
|
||||
const event = makeEvent('t is not a function', 'TypeError', [extensionFrame()]);
|
||||
assert.equal(beforeSend(event), null);
|
||||
});
|
||||
|
||||
it('suppresses Safari-style "t is not a function. (In \'t(..." with third-party stack', () => {
|
||||
const event = makeEvent("t is not a function. (In 't(1,2)')", 'TypeError', [extensionFrame()]);
|
||||
assert.equal(beforeSend(event), null);
|
||||
});
|
||||
|
||||
for (const msg of ambiguousErrors) {
|
||||
it(`lets through "${msg}" with empty stack (origin unknown)`, () => {
|
||||
const event = makeEvent(msg, 'TypeError', []);
|
||||
|
||||
Reference in New Issue
Block a user