Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
210 lines
5.8 KiB
Plaintext
210 lines
5.8 KiB
Plaintext
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
|
const core = require('@sentry/core');
|
|
const debugBuild = require('../debug-build.js');
|
|
const eventbuilder = require('../eventbuilder.js');
|
|
const helpers = require('../helpers.js');
|
|
|
|
const INTEGRATION_NAME = 'GlobalHandlers';
|
|
|
|
const _globalHandlersIntegration = ((options = {}) => {
|
|
const _options = {
|
|
onerror: true,
|
|
onunhandledrejection: true,
|
|
...options,
|
|
};
|
|
|
|
return {
|
|
name: INTEGRATION_NAME,
|
|
setupOnce() {
|
|
Error.stackTraceLimit = 50;
|
|
},
|
|
setup(client) {
|
|
if (_options.onerror) {
|
|
_installGlobalOnErrorHandler(client);
|
|
globalHandlerLog('onerror');
|
|
}
|
|
if (_options.onunhandledrejection) {
|
|
_installGlobalOnUnhandledRejectionHandler(client);
|
|
globalHandlerLog('onunhandledrejection');
|
|
}
|
|
},
|
|
};
|
|
}) ;
|
|
|
|
const globalHandlersIntegration = core.defineIntegration(_globalHandlersIntegration);
|
|
|
|
function _installGlobalOnErrorHandler(client) {
|
|
core.addGlobalErrorInstrumentationHandler(data => {
|
|
const { stackParser, attachStacktrace } = getOptions();
|
|
|
|
if (core.getClient() !== client || helpers.shouldIgnoreOnError()) {
|
|
return;
|
|
}
|
|
|
|
const { msg, url, line, column, error } = data;
|
|
|
|
const event = _enhanceEventWithInitialFrame(
|
|
eventbuilder.eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),
|
|
url,
|
|
line,
|
|
column,
|
|
);
|
|
|
|
event.level = 'error';
|
|
|
|
core.captureEvent(event, {
|
|
originalException: error,
|
|
mechanism: {
|
|
handled: false,
|
|
type: 'auto.browser.global_handlers.onerror',
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
function _installGlobalOnUnhandledRejectionHandler(client) {
|
|
core.addGlobalUnhandledRejectionInstrumentationHandler(e => {
|
|
const { stackParser, attachStacktrace } = getOptions();
|
|
|
|
if (core.getClient() !== client || helpers.shouldIgnoreOnError()) {
|
|
return;
|
|
}
|
|
|
|
const error = _getUnhandledRejectionError(e);
|
|
|
|
const event = core.isPrimitive(error)
|
|
? _eventFromRejectionWithPrimitive(error)
|
|
: eventbuilder.eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);
|
|
|
|
event.level = 'error';
|
|
|
|
core.captureEvent(event, {
|
|
originalException: error,
|
|
mechanism: {
|
|
handled: false,
|
|
type: 'auto.browser.global_handlers.onunhandledrejection',
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
function _getUnhandledRejectionError(error) {
|
|
if (core.isPrimitive(error)) {
|
|
return error;
|
|
}
|
|
|
|
// dig the object of the rejection out of known event types
|
|
try {
|
|
|
|
// PromiseRejectionEvents store the object of the rejection under 'reason'
|
|
// see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
|
|
if ('reason' in (error )) {
|
|
return (error ).reason;
|
|
}
|
|
|
|
// something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents
|
|
// to CustomEvents, moving the `promise` and `reason` attributes of the PRE into
|
|
// the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec
|
|
// see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and
|
|
// https://github.com/getsentry/sentry-javascript/issues/2380
|
|
if ('detail' in (error ) && 'reason' in (error ).detail) {
|
|
return (error ).detail.reason;
|
|
}
|
|
} catch {} // eslint-disable-line no-empty
|
|
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* Create an event from a promise rejection where the `reason` is a primitive.
|
|
*
|
|
* @param reason: The `reason` property of the promise rejection
|
|
* @returns An Event object with an appropriate `exception` value
|
|
*/
|
|
function _eventFromRejectionWithPrimitive(reason) {
|
|
return {
|
|
exception: {
|
|
values: [
|
|
{
|
|
type: 'UnhandledRejection',
|
|
// String() is needed because the Primitive type includes symbols (which can't be automatically stringified)
|
|
value: `Non-Error promise rejection captured with value: ${String(reason)}`,
|
|
},
|
|
],
|
|
},
|
|
};
|
|
}
|
|
|
|
function _enhanceEventWithInitialFrame(
|
|
event,
|
|
url,
|
|
line,
|
|
column,
|
|
) {
|
|
// event.exception
|
|
const e = (event.exception = event.exception || {});
|
|
// event.exception.values
|
|
const ev = (e.values = e.values || []);
|
|
// event.exception.values[0]
|
|
const ev0 = (ev[0] = ev[0] || {});
|
|
// event.exception.values[0].stacktrace
|
|
const ev0s = (ev0.stacktrace = ev0.stacktrace || {});
|
|
// event.exception.values[0].stacktrace.frames
|
|
const ev0sf = (ev0s.frames = ev0s.frames || []);
|
|
|
|
const colno = column;
|
|
const lineno = line;
|
|
const filename = getFilenameFromUrl(url) ?? core.getLocationHref();
|
|
|
|
// event.exception.values[0].stacktrace.frames
|
|
if (ev0sf.length === 0) {
|
|
ev0sf.push({
|
|
colno,
|
|
filename,
|
|
function: core.UNKNOWN_FUNCTION,
|
|
in_app: true,
|
|
lineno,
|
|
});
|
|
}
|
|
|
|
return event;
|
|
}
|
|
|
|
function globalHandlerLog(type) {
|
|
debugBuild.DEBUG_BUILD && core.debug.log(`Global Handler attached: ${type}`);
|
|
}
|
|
|
|
function getOptions() {
|
|
const client = core.getClient();
|
|
const options = client?.getOptions() || {
|
|
stackParser: () => [],
|
|
attachStacktrace: false,
|
|
};
|
|
return options;
|
|
}
|
|
|
|
function getFilenameFromUrl(url) {
|
|
if (!core.isString(url) || url.length === 0) {
|
|
return undefined;
|
|
}
|
|
|
|
// Strip data URL content to avoid long base64 strings in stack frames
|
|
// (e.g. when initializing a Worker with a base64 encoded script)
|
|
// Don't include data prefix for filenames as it's not useful for stack traces
|
|
// Wrap with < > to indicate it's a placeholder
|
|
if (url.startsWith('data:')) {
|
|
return `<${core.stripDataUrlContent(url, false)}>`;
|
|
}
|
|
|
|
return url;
|
|
}
|
|
|
|
exports._eventFromRejectionWithPrimitive = _eventFromRejectionWithPrimitive;
|
|
exports._getUnhandledRejectionError = _getUnhandledRejectionError;
|
|
exports.globalHandlersIntegration = globalHandlersIntegration;
|
|
//# sourceMappingURL=globalhandlers.js.map
|