Add coexistence checks to all enqueue methods to prevent loading both React and Grid.js assets simultaneously. Changes: - ReactAdmin.php: Only enqueue React assets when ?react=1 - Init.php: Skip Grid.js when React active on admin pages - Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0 - Customer.php, Product.php, License.php: Add coexistence checks Now the toggle between Classic and React versions works correctly. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
210 lines
8.7 KiB
JavaScript
210 lines
8.7 KiB
JavaScript
import { __assign } from "tslib";
|
|
import { getGlobalObject } from './global';
|
|
import { addNonEnumerableProperty } from './object';
|
|
import { snipLine } from './string';
|
|
/**
|
|
* UUID4 generator
|
|
*
|
|
* @returns string Generated UUID4.
|
|
*/
|
|
export function uuid4() {
|
|
var global = getGlobalObject();
|
|
var crypto = global.crypto || global.msCrypto;
|
|
if (!(crypto === void 0) && crypto.getRandomValues) {
|
|
// Use window.crypto API if available
|
|
var arr = new Uint16Array(8);
|
|
crypto.getRandomValues(arr);
|
|
// set 4 in byte 7
|
|
// eslint-disable-next-line no-bitwise
|
|
arr[3] = (arr[3] & 0xfff) | 0x4000;
|
|
// set 2 most significant bits of byte 9 to '10'
|
|
// eslint-disable-next-line no-bitwise
|
|
arr[4] = (arr[4] & 0x3fff) | 0x8000;
|
|
var pad = function (num) {
|
|
var v = num.toString(16);
|
|
while (v.length < 4) {
|
|
v = "0" + v;
|
|
}
|
|
return v;
|
|
};
|
|
return (pad(arr[0]) + pad(arr[1]) + pad(arr[2]) + pad(arr[3]) + pad(arr[4]) + pad(arr[5]) + pad(arr[6]) + pad(arr[7]));
|
|
}
|
|
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
|
|
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
// eslint-disable-next-line no-bitwise
|
|
var r = (Math.random() * 16) | 0;
|
|
// eslint-disable-next-line no-bitwise
|
|
var v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
return v.toString(16);
|
|
});
|
|
}
|
|
/**
|
|
* Parses string form of URL into an object
|
|
* // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B
|
|
* // intentionally using regex and not <a/> href parsing trick because React Native and other
|
|
* // environments where DOM might not be available
|
|
* @returns parsed URL object
|
|
*/
|
|
export function parseUrl(url) {
|
|
if (!url) {
|
|
return {};
|
|
}
|
|
var match = url.match(/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/);
|
|
if (!match) {
|
|
return {};
|
|
}
|
|
// coerce to undefined values to empty string so we don't get 'undefined'
|
|
var query = match[6] || '';
|
|
var fragment = match[8] || '';
|
|
return {
|
|
host: match[4],
|
|
path: match[5],
|
|
protocol: match[2],
|
|
relative: match[5] + query + fragment,
|
|
};
|
|
}
|
|
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
|
|
*/
|
|
export function getEventDescription(event) {
|
|
var message = event.message, eventId = event.event_id;
|
|
if (message) {
|
|
return message;
|
|
}
|
|
var firstException = getFirstException(event);
|
|
if (firstException) {
|
|
if (firstException.type && firstException.value) {
|
|
return firstException.type + ": " + firstException.value;
|
|
}
|
|
return firstException.type || firstException.value || eventId || '<unknown>';
|
|
}
|
|
return eventId || '<unknown>';
|
|
}
|
|
/**
|
|
* 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
|
|
*/
|
|
export function addExceptionTypeValue(event, value, type) {
|
|
var exception = (event.exception = event.exception || {});
|
|
var values = (exception.values = exception.values || []);
|
|
var 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
|
|
*/
|
|
export function addExceptionMechanism(event, newMechanism) {
|
|
var firstException = getFirstException(event);
|
|
if (!firstException) {
|
|
return;
|
|
}
|
|
var defaultMechanism = { type: 'generic', handled: true };
|
|
var currentMechanism = firstException.mechanism;
|
|
firstException.mechanism = __assign(__assign(__assign({}, defaultMechanism), currentMechanism), newMechanism);
|
|
if (newMechanism && 'data' in newMechanism) {
|
|
var mergedData = __assign(__assign({}, (currentMechanism && currentMechanism.data)), newMechanism.data);
|
|
firstException.mechanism.data = mergedData;
|
|
}
|
|
}
|
|
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
|
var 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-]+)*))?$/;
|
|
/**
|
|
* Parses input into a SemVer interface
|
|
* @param input string representation of a semver version
|
|
*/
|
|
export function parseSemver(input) {
|
|
var match = input.match(SEMVER_REGEXP) || [];
|
|
var major = parseInt(match[1], 10);
|
|
var minor = parseInt(match[2], 10);
|
|
var patch = parseInt(match[3], 10);
|
|
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
|
|
*/
|
|
export function addContextToFrame(lines, frame, linesOfContext) {
|
|
if (linesOfContext === void 0) { linesOfContext = 5; }
|
|
var lineno = frame.lineno || 0;
|
|
var maxLines = lines.length;
|
|
var sourceLine = Math.max(Math.min(maxLines, lineno - 1), 0);
|
|
frame.pre_context = lines
|
|
.slice(Math.max(0, sourceLine - linesOfContext), sourceLine)
|
|
.map(function (line) { return snipLine(line, 0); });
|
|
frame.context_line = snipLine(lines[Math.min(maxLines - 1, sourceLine)], frame.colno || 0);
|
|
frame.post_context = lines
|
|
.slice(Math.min(sourceLine + 1, maxLines), sourceLine + 1 + linesOfContext)
|
|
.map(function (line) { return snipLine(line, 0); });
|
|
}
|
|
/**
|
|
* Strip the query string and fragment off of a given URL or path (if present)
|
|
*
|
|
* @param urlPath Full URL or path, including possible query string and/or fragment
|
|
* @returns URL or path without query string or fragment
|
|
*/
|
|
export function stripUrlQueryAndFragment(urlPath) {
|
|
// eslint-disable-next-line no-useless-escape
|
|
return urlPath.split(/[\?#]/, 1)[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)
|
|
*/
|
|
export 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;
|
|
}
|
|
//# sourceMappingURL=misc.js.map
|