package.build.esm.misc.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils Show documentation
Show all versions of utils Show documentation
Utilities for all Sentry JavaScript SDKs
The newest version!
import { addNonEnumerableProperty } from './object.js';
import { snipLine } from './string.js';
import { GLOBAL_OBJ } from './worldwide.js';
/**
* UUID4 generator
*
* @returns string Generated UUID4.
*/
function uuid4() {
const gbl = GLOBAL_OBJ ;
const crypto = gbl.crypto || gbl.msCrypto;
let getRandomByte = () => Math.random() * 16;
try {
if (crypto && crypto.randomUUID) {
return crypto.randomUUID().replace(/-/g, '');
}
if (crypto && crypto.getRandomValues) {
getRandomByte = () => {
// crypto.getRandomValues might return undefined instead of the typed array
// in old Chromium versions (e.g. 23.0.1235.0 (151422))
// However, `typedArray` is still filled in-place.
// @see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#typedarray
const typedArray = new Uint8Array(1);
crypto.getRandomValues(typedArray);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return typedArray[0];
};
}
} catch (_) {
// some runtimes can crash invoking crypto
// https://github.com/getsentry/sentry-javascript/issues/8935
}
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
// Concatenating the following numbers as strings results in '10000000100040008000100000000000'
return (([1e7] ) + 1e3 + 4e3 + 8e3 + 1e11).replace(/[018]/g, c =>
// eslint-disable-next-line no-bitwise
((c ) ^ ((getRandomByte() & 15) >> ((c ) / 4))).toString(16),
);
}
function getFirstException(event) {
return event.exception && event.exception.values ? event.exception.values[0] : undefined;
}
/**
* Extracts either message or type+value from an event that can be used for user-facing logs
* @returns event's description
*/
function getEventDescription(event) {
const { message, event_id: eventId } = event;
if (message) {
return message;
}
const firstException = getFirstException(event);
if (firstException) {
if (firstException.type && firstException.value) {
return `${firstException.type}: ${firstException.value}`;
}
return firstException.type || firstException.value || eventId || '';
}
return eventId || '';
}
/**
* Adds exception values, type and value to an synthetic Exception.
* @param event The event to modify.
* @param value Value of the exception.
* @param type Type of the exception.
* @hidden
*/
function addExceptionTypeValue(event, value, type) {
const exception = (event.exception = event.exception || {});
const values = (exception.values = exception.values || []);
const firstException = (values[0] = values[0] || {});
if (!firstException.value) {
firstException.value = value || '';
}
if (!firstException.type) {
firstException.type = type || 'Error';
}
}
/**
* Adds exception mechanism data to a given event. Uses defaults if the second parameter is not passed.
*
* @param event The event to modify.
* @param newMechanism Mechanism data to add to the event.
* @hidden
*/
function addExceptionMechanism(event, newMechanism) {
const firstException = getFirstException(event);
if (!firstException) {
return;
}
const defaultMechanism = { type: 'generic', handled: true };
const currentMechanism = firstException.mechanism;
firstException.mechanism = { ...defaultMechanism, ...currentMechanism, ...newMechanism };
if (newMechanism && 'data' in newMechanism) {
const mergedData = { ...(currentMechanism && currentMechanism.data), ...newMechanism.data };
firstException.mechanism.data = mergedData;
}
}
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
const SEMVER_REGEXP =
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
/**
* Represents Semantic Versioning object
*/
function _parseInt(input) {
return parseInt(input || '', 10);
}
/**
* Parses input into a SemVer interface
* @param input string representation of a semver version
*/
function parseSemver(input) {
const match = input.match(SEMVER_REGEXP) || [];
const major = _parseInt(match[1]);
const minor = _parseInt(match[2]);
const patch = _parseInt(match[3]);
return {
buildmetadata: match[5],
major: isNaN(major) ? undefined : major,
minor: isNaN(minor) ? undefined : minor,
patch: isNaN(patch) ? undefined : patch,
prerelease: match[4],
};
}
/**
* This function adds context (pre/post/line) lines to the provided frame
*
* @param lines string[] containing all lines
* @param frame StackFrame that will be mutated
* @param linesOfContext number of context lines we want to add pre/post
*/
function addContextToFrame(lines, frame, linesOfContext = 5) {
// When there is no line number in the frame, attaching context is nonsensical and will even break grouping
if (frame.lineno === undefined) {
return;
}
const maxLines = lines.length;
const sourceLine = Math.max(Math.min(maxLines - 1, frame.lineno - 1), 0);
frame.pre_context = lines
.slice(Math.max(0, sourceLine - linesOfContext), sourceLine)
.map((line) => snipLine(line, 0));
// We guard here to ensure this is not larger than the existing number of lines
const lineIndex = Math.min(maxLines - 1, sourceLine);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
frame.context_line = snipLine(lines[lineIndex], frame.colno || 0);
frame.post_context = lines
.slice(Math.min(sourceLine + 1, maxLines), sourceLine + 1 + linesOfContext)
.map((line) => snipLine(line, 0));
}
/**
* Checks whether or not we've already captured the given exception (note: not an identical exception - the very object
* in question), and marks it captured if not.
*
* This is useful because it's possible for an error to get captured by more than one mechanism. After we intercept and
* record an error, we rethrow it (assuming we've intercepted it before it's reached the top-level global handlers), so
* that we don't interfere with whatever effects the error might have had were the SDK not there. At that point, because
* the error has been rethrown, it's possible for it to bubble up to some other code we've instrumented. If it's not
* caught after that, it will bubble all the way up to the global handlers (which of course we also instrument). This
* function helps us ensure that even if we encounter the same error more than once, we only record it the first time we
* see it.
*
* Note: It will ignore primitives (always return `false` and not mark them as seen), as properties can't be set on
* them. {@link: Object.objectify} can be used on exceptions to convert any that are primitives into their equivalent
* object wrapper forms so that this check will always work. However, because we need to flag the exact object which
* will get rethrown, and because that rethrowing happens outside of the event processing pipeline, the objectification
* must be done before the exception captured.
*
* @param A thrown exception to check or flag as having been seen
* @returns `true` if the exception has already been captured, `false` if not (with the side effect of marking it seen)
*/
function checkOrSetAlreadyCaught(exception) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (exception && (exception ).__sentry_captured__) {
return true;
}
try {
// set it this way rather than by assignment so that it's not ennumerable and therefore isn't recorded by the
// `ExtraErrorData` integration
addNonEnumerableProperty(exception , '__sentry_captured__', true);
} catch (err) {
// `exception` is a primitive, so we can't mark it seen
}
return false;
}
/**
* Checks whether the given input is already an array, and if it isn't, wraps it in one.
*
* @param maybeArray Input to turn into an array, if necessary
* @returns The input, if already an array, or an array with the input as the only element, if not
*/
function arrayify(maybeArray) {
return Array.isArray(maybeArray) ? maybeArray : [maybeArray];
}
export { addContextToFrame, addExceptionMechanism, addExceptionTypeValue, arrayify, checkOrSetAlreadyCaught, getEventDescription, parseSemver, uuid4 };
//# sourceMappingURL=misc.js.map