@sentry/bundler-plugin-core
Version:
1,483 lines (1,337 loc) • 337 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var core = require('@babel/core');
var componentNameAnnotatePlugin = require('@sentry/babel-plugin-component-annotate');
var SentryCli = require('@sentry/cli');
var fs = require('fs');
var glob = require('glob');
var MagicString = require('magic-string');
var path = require('path');
var unplugin = require('unplugin');
var dotenv = require('dotenv');
var os = require('os');
var findUp = require('find-up');
var crypto = require('crypto');
var childProcess = require('child_process');
var https = require('node:https');
var node_stream = require('node:stream');
var node_zlib = require('node:zlib');
var url = require('url');
var util = require('util');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var componentNameAnnotatePlugin__default = /*#__PURE__*/_interopDefaultLegacy(componentNameAnnotatePlugin);
var SentryCli__default = /*#__PURE__*/_interopDefaultLegacy(SentryCli);
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
var MagicString__default = /*#__PURE__*/_interopDefaultLegacy(MagicString);
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
var path__namespace = /*#__PURE__*/_interopNamespace(path);
var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
var os__namespace = /*#__PURE__*/_interopNamespace(os);
var findUp__default = /*#__PURE__*/_interopDefaultLegacy(findUp);
var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
var childProcess__default = /*#__PURE__*/_interopDefaultLegacy(childProcess);
var https__namespace = /*#__PURE__*/_interopNamespace(https);
var url__namespace = /*#__PURE__*/_interopNamespace(url);
var util__namespace = /*#__PURE__*/_interopNamespace(util);
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
enumerableOnly && (symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
})), keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = null != arguments[i] ? arguments[i] : {};
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
_defineProperty(target, key, source[key]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
return target;
}
function _regeneratorRuntime() {
_regeneratorRuntime = function () {
return exports;
};
var exports = {},
Op = Object.prototype,
hasOwn = Op.hasOwnProperty,
defineProperty = Object.defineProperty || function (obj, key, desc) {
obj[key] = desc.value;
},
$Symbol = "function" == typeof Symbol ? Symbol : {},
iteratorSymbol = $Symbol.iterator || "@@iterator",
asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
function define(obj, key, value) {
return Object.defineProperty(obj, key, {
value: value,
enumerable: !0,
configurable: !0,
writable: !0
}), obj[key];
}
try {
define({}, "");
} catch (err) {
define = function (obj, key, value) {
return obj[key] = value;
};
}
function wrap(innerFn, outerFn, self, tryLocsList) {
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
generator = Object.create(protoGenerator.prototype),
context = new Context(tryLocsList || []);
return defineProperty(generator, "_invoke", {
value: makeInvokeMethod(innerFn, self, context)
}), generator;
}
function tryCatch(fn, obj, arg) {
try {
return {
type: "normal",
arg: fn.call(obj, arg)
};
} catch (err) {
return {
type: "throw",
arg: err
};
}
}
exports.wrap = wrap;
var ContinueSentinel = {};
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var IteratorPrototype = {};
define(IteratorPrototype, iteratorSymbol, function () {
return this;
});
var getProto = Object.getPrototypeOf,
NativeIteratorPrototype = getProto && getProto(getProto(values([])));
NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function (method) {
define(prototype, method, function (arg) {
return this._invoke(method, arg);
});
});
}
function AsyncIterator(generator, PromiseImpl) {
function invoke(method, arg, resolve, reject) {
var record = tryCatch(generator[method], generator, arg);
if ("throw" !== record.type) {
var result = record.arg,
value = result.value;
return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
invoke("next", value, resolve, reject);
}, function (err) {
invoke("throw", err, resolve, reject);
}) : PromiseImpl.resolve(value).then(function (unwrapped) {
result.value = unwrapped, resolve(result);
}, function (error) {
return invoke("throw", error, resolve, reject);
});
}
reject(record.arg);
}
var previousPromise;
defineProperty(this, "_invoke", {
value: function (method, arg) {
function callInvokeWithMethodAndArg() {
return new PromiseImpl(function (resolve, reject) {
invoke(method, arg, resolve, reject);
});
}
return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
}
});
}
function makeInvokeMethod(innerFn, self, context) {
var state = "suspendedStart";
return function (method, arg) {
if ("executing" === state) throw new Error("Generator is already running");
if ("completed" === state) {
if ("throw" === method) throw arg;
return doneResult();
}
for (context.method = method, context.arg = arg;;) {
var delegate = context.delegate;
if (delegate) {
var delegateResult = maybeInvokeDelegate(delegate, context);
if (delegateResult) {
if (delegateResult === ContinueSentinel) continue;
return delegateResult;
}
}
if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
if ("suspendedStart" === state) throw state = "completed", context.arg;
context.dispatchException(context.arg);
} else "return" === context.method && context.abrupt("return", context.arg);
state = "executing";
var record = tryCatch(innerFn, self, context);
if ("normal" === record.type) {
if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
return {
value: record.arg,
done: context.done
};
}
"throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
}
};
}
function maybeInvokeDelegate(delegate, context) {
var methodName = context.method,
method = delegate.iterator[methodName];
if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel;
var record = tryCatch(method, delegate.iterator, context.arg);
if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
var info = record.arg;
return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
}
function pushTryEntry(locs) {
var entry = {
tryLoc: locs[0]
};
1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
}
function resetTryEntry(entry) {
var record = entry.completion || {};
record.type = "normal", delete record.arg, entry.completion = record;
}
function Context(tryLocsList) {
this.tryEntries = [{
tryLoc: "root"
}], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
}
function values(iterable) {
if (iterable) {
var iteratorMethod = iterable[iteratorSymbol];
if (iteratorMethod) return iteratorMethod.call(iterable);
if ("function" == typeof iterable.next) return iterable;
if (!isNaN(iterable.length)) {
var i = -1,
next = function next() {
for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
return next.value = undefined, next.done = !0, next;
};
return next.next = next;
}
}
return {
next: doneResult
};
}
function doneResult() {
return {
value: undefined,
done: !0
};
}
return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
value: GeneratorFunctionPrototype,
configurable: !0
}), defineProperty(GeneratorFunctionPrototype, "constructor", {
value: GeneratorFunction,
configurable: !0
}), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
var ctor = "function" == typeof genFun && genFun.constructor;
return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
}, exports.mark = function (genFun) {
return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
}, exports.awrap = function (arg) {
return {
__await: arg
};
}, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
return this;
}), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
void 0 === PromiseImpl && (PromiseImpl = Promise);
var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
return result.done ? result.value : iter.next();
});
}, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
return this;
}), define(Gp, "toString", function () {
return "[object Generator]";
}), exports.keys = function (val) {
var object = Object(val),
keys = [];
for (var key in object) keys.push(key);
return keys.reverse(), function next() {
for (; keys.length;) {
var key = keys.pop();
if (key in object) return next.value = key, next.done = !1, next;
}
return next.done = !0, next;
};
}, exports.values = values, Context.prototype = {
constructor: Context,
reset: function (skipTempReset) {
if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
},
stop: function () {
this.done = !0;
var rootRecord = this.tryEntries[0].completion;
if ("throw" === rootRecord.type) throw rootRecord.arg;
return this.rval;
},
dispatchException: function (exception) {
if (this.done) throw exception;
var context = this;
function handle(loc, caught) {
return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
}
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i],
record = entry.completion;
if ("root" === entry.tryLoc) return handle("end");
if (entry.tryLoc <= this.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc"),
hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
} else if (hasCatch) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
} else {
if (!hasFinally) throw new Error("try statement without catch or finally");
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
}
}
}
},
abrupt: function (type, arg) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
var finallyEntry = entry;
break;
}
}
finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
var record = finallyEntry ? finallyEntry.completion : {};
return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
},
complete: function (record, afterLoc) {
if ("throw" === record.type) throw record.arg;
return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
},
finish: function (finallyLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
}
},
catch: function (tryLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if ("throw" === record.type) {
var thrown = record.arg;
resetTryEntry(entry);
}
return thrown;
}
}
throw new Error("illegal catch attempt");
},
delegateYield: function (iterable, resultName, nextLoc) {
return this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
}, "next" === this.method && (this.arg = undefined), ContinueSentinel;
}
}, exports;
}
function _typeof(obj) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, _typeof(obj);
}
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _toPrimitive(input, hint) {
if (typeof input !== "object" || input === null) return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint || "default");
if (typeof res !== "object") return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
function _toPropertyKey(arg) {
var key = _toPrimitive(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
// eslint-disable-next-line @typescript-eslint/unbound-method
const objectToString = Object.prototype.toString;
/**
* Checks whether given value's type is one of a few Error or Error-like
* {@link isError}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isError(wat) {
switch (objectToString.call(wat)) {
case '[object Error]':
case '[object Exception]':
case '[object DOMException]':
return true;
default:
return isInstanceOf(wat, Error);
}
}
/**
* Checks whether given value is an instance of the given built-in class.
*
* @param wat The value to be checked
* @param className
* @returns A boolean representing the result.
*/
function isBuiltin(wat, className) {
return objectToString.call(wat) === `[object ${className}]`;
}
/**
* Checks whether given value's type is ErrorEvent
* {@link isErrorEvent}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isErrorEvent$1(wat) {
return isBuiltin(wat, 'ErrorEvent');
}
/**
* Checks whether given value's type is a string
* {@link isString}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isString(wat) {
return isBuiltin(wat, 'String');
}
/**
* Checks whether given string is parameterized
* {@link isParameterizedString}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isParameterizedString(wat) {
return (
typeof wat === 'object' &&
wat !== null &&
'__sentry_template_string__' in wat &&
'__sentry_template_values__' in wat
);
}
/**
* Checks whether given value is a primitive (undefined, null, number, boolean, string, bigint, symbol)
* {@link isPrimitive}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isPrimitive(wat) {
return wat === null || isParameterizedString(wat) || (typeof wat !== 'object' && typeof wat !== 'function');
}
/**
* Checks whether given value's type is an object literal, or a class instance.
* {@link isPlainObject}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isPlainObject(wat) {
return isBuiltin(wat, 'Object');
}
/**
* Checks whether given value's type is an Event instance
* {@link isEvent}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isEvent(wat) {
return typeof Event !== 'undefined' && isInstanceOf(wat, Event);
}
/**
* Checks whether given value's type is an Element instance
* {@link isElement}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isElement(wat) {
return typeof Element !== 'undefined' && isInstanceOf(wat, Element);
}
/**
* Checks whether given value has a then function.
* @param wat A value to be checked.
*/
function isThenable(wat) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
return Boolean(wat && wat.then && typeof wat.then === 'function');
}
/**
* Checks whether given value's type is a SyntheticEvent
* {@link isSyntheticEvent}.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isSyntheticEvent(wat) {
return isPlainObject(wat) && 'nativeEvent' in wat && 'preventDefault' in wat && 'stopPropagation' in wat;
}
/**
* Checks whether given value's type is an instance of provided constructor.
* {@link isInstanceOf}.
*
* @param wat A value to be checked.
* @param base A constructor to be used in a check.
* @returns A boolean representing the result.
*/
function isInstanceOf(wat, base) {
try {
return wat instanceof base;
} catch (_e) {
return false;
}
}
/**
* Checks whether given value's type is a Vue ViewModel.
*
* @param wat A value to be checked.
* @returns A boolean representing the result.
*/
function isVueViewModel(wat) {
// Not using Object.prototype.toString because in Vue 3 it would read the instance's Symbol(Symbol.toStringTag) property.
return !!(typeof wat === 'object' && wat !== null && ((wat ).__isVue || (wat )._isVue));
}
/**
* Truncates given string to the maximum characters count
*
* @param str An object that contains serializable values
* @param max Maximum number of characters in truncated string (0 = unlimited)
* @returns string Encoded
*/
function truncate(str, max = 0) {
if (typeof str !== 'string' || max === 0) {
return str;
}
return str.length <= max ? str : `${str.slice(0, max)}...`;
}
const SDK_VERSION = '8.30.0';
/** Get's the global object for the current JavaScript runtime */
const GLOBAL_OBJ = globalThis ;
/**
* Returns a global singleton contained in the global `__SENTRY__[]` object.
*
* If the singleton doesn't already exist in `__SENTRY__`, it will be created using the given factory
* function and added to the `__SENTRY__` object.
*
* @param name name of the global singleton on __SENTRY__
* @param creator creator Factory function to create the singleton if it doesn't already exist on `__SENTRY__`
* @param obj (Optional) The global object on which to look for `__SENTRY__`, if not `GLOBAL_OBJ`'s return value
* @returns the singleton
*/
function getGlobalSingleton(name, creator, obj) {
const gbl = (obj || GLOBAL_OBJ) ;
const __SENTRY__ = (gbl.__SENTRY__ = gbl.__SENTRY__ || {});
const versionedCarrier = (__SENTRY__[SDK_VERSION] = __SENTRY__[SDK_VERSION] || {});
return versionedCarrier[name] || (versionedCarrier[name] = creator());
}
const WINDOW = GLOBAL_OBJ ;
const DEFAULT_MAX_STRING_LENGTH = 80;
/**
* Given a child DOM element, returns a query-selector statement describing that
* and its ancestors
* e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
* @returns generated DOM path
*/
function htmlTreeAsString(
elem,
options = {},
) {
if (!elem) {
return '<unknown>';
}
// try/catch both:
// - accessing event.target (see getsentry/raven-js#838, #768)
// - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly
// - can throw an exception in some circumstances.
try {
let currentElem = elem ;
const MAX_TRAVERSE_HEIGHT = 5;
const out = [];
let height = 0;
let len = 0;
const separator = ' > ';
const sepLength = separator.length;
let nextStr;
const keyAttrs = Array.isArray(options) ? options : options.keyAttrs;
const maxStringLength = (!Array.isArray(options) && options.maxStringLength) || DEFAULT_MAX_STRING_LENGTH;
while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {
nextStr = _htmlElementAsString(currentElem, keyAttrs);
// bail out if
// - nextStr is the 'html' element
// - the length of the string that would be created exceeds maxStringLength
// (ignore this limit if we are on the first iteration)
if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= maxStringLength)) {
break;
}
out.push(nextStr);
len += nextStr.length;
currentElem = currentElem.parentNode;
}
return out.reverse().join(separator);
} catch (_oO) {
return '<unknown>';
}
}
/**
* Returns a simple, query-selector representation of a DOM element
* e.g. [HTMLElement] => input#foo.btn[name=baz]
* @returns generated DOM path
*/
function _htmlElementAsString(el, keyAttrs) {
const elem = el
;
const out = [];
if (!elem || !elem.tagName) {
return '';
}
// @ts-expect-error WINDOW has HTMLElement
if (WINDOW.HTMLElement) {
// If using the component name annotation plugin, this value may be available on the DOM node
if (elem instanceof HTMLElement && elem.dataset) {
if (elem.dataset['sentryComponent']) {
return elem.dataset['sentryComponent'];
}
if (elem.dataset['sentryElement']) {
return elem.dataset['sentryElement'];
}
}
}
out.push(elem.tagName.toLowerCase());
// Pairs of attribute keys defined in `serializeAttribute` and their values on element.
const keyAttrPairs =
keyAttrs && keyAttrs.length
? keyAttrs.filter(keyAttr => elem.getAttribute(keyAttr)).map(keyAttr => [keyAttr, elem.getAttribute(keyAttr)])
: null;
if (keyAttrPairs && keyAttrPairs.length) {
keyAttrPairs.forEach(keyAttrPair => {
out.push(`[${keyAttrPair[0]}="${keyAttrPair[1]}"]`);
});
} else {
if (elem.id) {
out.push(`#${elem.id}`);
}
const className = elem.className;
if (className && isString(className)) {
const classes = className.split(/\s+/);
for (const c of classes) {
out.push(`.${c}`);
}
}
}
const allowedAttrs = ['aria-label', 'type', 'name', 'title', 'alt'];
for (const k of allowedAttrs) {
const attr = elem.getAttribute(k);
if (attr) {
out.push(`[${k}="${attr}"]`);
}
}
return out.join('');
}
/**
* This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
*
* ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.
*/
const DEBUG_BUILD$1 = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__);
/** Prefix for logging strings */
const PREFIX = 'Sentry Logger ';
const CONSOLE_LEVELS = [
'debug',
'info',
'warn',
'error',
'log',
'assert',
'trace',
] ;
/** This may be mutated by the console instrumentation. */
const originalConsoleMethods
= {};
/** JSDoc */
/**
* Temporarily disable sentry console instrumentations.
*
* @param callback The function to run against the original `console` messages
* @returns The results of the callback
*/
function consoleSandbox(callback) {
if (!('console' in GLOBAL_OBJ)) {
return callback();
}
const console = GLOBAL_OBJ.console ;
const wrappedFuncs = {};
const wrappedLevels = Object.keys(originalConsoleMethods) ;
// Restore all wrapped console methods
wrappedLevels.forEach(level => {
const originalConsoleMethod = originalConsoleMethods[level] ;
wrappedFuncs[level] = console[level] ;
console[level] = originalConsoleMethod;
});
try {
return callback();
} finally {
// Revert restoration to wrapped state
wrappedLevels.forEach(level => {
console[level] = wrappedFuncs[level] ;
});
}
}
function makeLogger() {
let enabled = false;
const logger = {
enable: () => {
enabled = true;
},
disable: () => {
enabled = false;
},
isEnabled: () => enabled,
};
if (DEBUG_BUILD$1) {
CONSOLE_LEVELS.forEach(name => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
logger[name] = (...args) => {
if (enabled) {
consoleSandbox(() => {
GLOBAL_OBJ.console[name](`${PREFIX}[${name}]:`, ...args);
});
}
};
});
} else {
CONSOLE_LEVELS.forEach(name => {
logger[name] = () => undefined;
});
}
return logger ;
}
/**
* This is a logger singleton which either logs things or no-ops if logging is not enabled.
* The logger is a singleton on the carrier, to ensure that a consistent logger is used throughout the SDK.
*/
const logger = getGlobalSingleton('logger', makeLogger);
/** Regular expression used to parse a Dsn. */
const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+)?)?@)([\w.-]+)(?::(\d+))?\/(.+)/;
function isValidProtocol(protocol) {
return protocol === 'http' || protocol === 'https';
}
/**
* Renders the string representation of this Dsn.
*
* By default, this will render the public representation without the password
* component. To get the deprecated private representation, set `withPassword`
* to true.
*
* @param withPassword When set to true, the password will be included.
*/
function dsnToString(dsn, withPassword = false) {
const { host, path, pass, port, projectId, protocol, publicKey } = dsn;
return (
`${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ''}` +
`@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}`
);
}
/**
* Parses a Dsn from a given string.
*
* @param str A Dsn as string
* @returns Dsn as DsnComponents or undefined if @param str is not a valid DSN string
*/
function dsnFromString(str) {
const match = DSN_REGEX.exec(str);
if (!match) {
// This should be logged to the console
consoleSandbox(() => {
// eslint-disable-next-line no-console
console.error(`Invalid Sentry Dsn: ${str}`);
});
return undefined;
}
const [protocol, publicKey, pass = '', host = '', port = '', lastPath = ''] = match.slice(1);
let path = '';
let projectId = lastPath;
const split = projectId.split('/');
if (split.length > 1) {
path = split.slice(0, -1).join('/');
projectId = split.pop() ;
}
if (projectId) {
const projectMatch = projectId.match(/^\d+/);
if (projectMatch) {
projectId = projectMatch[0];
}
}
return dsnFromComponents({ host, pass, path, projectId, port, protocol: protocol , publicKey });
}
function dsnFromComponents(components) {
return {
protocol: components.protocol,
publicKey: components.publicKey || '',
pass: components.pass || '',
host: components.host,
port: components.port || '',
path: components.path || '',
projectId: components.projectId,
};
}
function validateDsn(dsn) {
if (!DEBUG_BUILD$1) {
return true;
}
const { port, projectId, protocol } = dsn;
const requiredComponents = ['protocol', 'publicKey', 'host', 'projectId'];
const hasMissingRequiredComponent = requiredComponents.find(component => {
if (!dsn[component]) {
logger.error(`Invalid Sentry Dsn: ${component} missing`);
return true;
}
return false;
});
if (hasMissingRequiredComponent) {
return false;
}
if (!projectId.match(/^\d+$/)) {
logger.error(`Invalid Sentry Dsn: Invalid projectId ${projectId}`);
return false;
}
if (!isValidProtocol(protocol)) {
logger.error(`Invalid Sentry Dsn: Invalid protocol ${protocol}`);
return false;
}
if (port && isNaN(parseInt(port, 10))) {
logger.error(`Invalid Sentry Dsn: Invalid port ${port}`);
return false;
}
return true;
}
/**
* Creates a valid Sentry Dsn object, identifying a Sentry instance and project.
* @returns a valid DsnComponents object or `undefined` if @param from is an invalid DSN source
*/
function makeDsn(from) {
const components = typeof from === 'string' ? dsnFromString(from) : dsnFromComponents(from);
if (!components || !validateDsn(components)) {
return undefined;
}
return components;
}
/** An error emitted by Sentry SDKs and related utilities. */
class SentryError extends Error {
/** Display name of this error instance. */
constructor( message, logLevel = 'warn') {
super(message);this.message = message;
this.name = new.target.prototype.constructor.name;
// This sets the prototype to be `Error`, not `SentryError`. It's unclear why we do this, but commenting this line
// out causes various (seemingly totally unrelated) playwright tests consistently time out. FYI, this makes
// instances of `SentryError` fail `obj instanceof SentryError` checks.
Object.setPrototypeOf(this, new.target.prototype);
this.logLevel = logLevel;
}
}
/**
* Defines a non-enumerable property on the given object.
*
* @param obj The object on which to set the property
* @param name The name of the property to be set
* @param value The value to which to set the property
*/
function addNonEnumerableProperty(obj, name, value) {
try {
Object.defineProperty(obj, name, {
// enumerable: false, // the default, so we can save on bundle size by not explicitly setting it
value: value,
writable: true,
configurable: true,
});
} catch (o_O) {
DEBUG_BUILD$1 && logger.log(`Failed to add non-enumerable property "${name}" to object`, obj);
}
}
/**
* Encodes given object into url-friendly format
*
* @param object An object that contains serializable values
* @returns string Encoded
*/
function urlEncode(object) {
return Object.keys(object)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(object[key])}`)
.join('&');
}
/**
* Transforms any `Error` or `Event` into a plain object with all of their enumerable properties, and some of their
* non-enumerable properties attached.
*
* @param value Initial source that we have to transform in order for it to be usable by the serializer
* @returns An Event or Error turned into an object - or the value argurment itself, when value is neither an Event nor
* an Error.
*/
function convertToPlainObject(
value,
)
{
if (isError(value)) {
return {
message: value.message,
name: value.name,
stack: value.stack,
...getOwnProperties(value),
};
} else if (isEvent(value)) {
const newObj
= {
type: value.type,
target: serializeEventTarget(value.target),
currentTarget: serializeEventTarget(value.currentTarget),
...getOwnProperties(value),
};
if (typeof CustomEvent !== 'undefined' && isInstanceOf(value, CustomEvent)) {
newObj.detail = value.detail;
}
return newObj;
} else {
return value;
}
}
/** Creates a string representation of the target of an `Event` object */
function serializeEventTarget(target) {
try {
return isElement(target) ? htmlTreeAsString(target) : Object.prototype.toString.call(target);
} catch (_oO) {
return '<unknown>';
}
}
/** Filters out all but an object's own properties */
function getOwnProperties(obj) {
if (typeof obj === 'object' && obj !== null) {
const extractedProps = {};
for (const property in obj) {
if (Object.prototype.hasOwnProperty.call(obj, property)) {
extractedProps[property] = (obj )[property];
}
}
return extractedProps;
} else {
return {};
}
}
/**
* Given any captured exception, extract its keys and create a sorted
* and truncated list that will be used inside the event message.
* eg. `Non-error exception captured with keys: foo, bar, baz`
*/
function extractExceptionKeysForMessage(exception, maxLength = 40) {
const keys = Object.keys(convertToPlainObject(exception));
keys.sort();
const firstKey = keys[0];
if (!firstKey) {
return '[object has no keys]';
}
if (firstKey.length >= maxLength) {
return truncate(firstKey, maxLength);
}
for (let includedKeys = keys.length; includedKeys > 0; includedKeys--) {
const serialized = keys.slice(0, includedKeys).join(', ');
if (serialized.length > maxLength) {
continue;
}
if (includedKeys === keys.length) {
return serialized;
}
return truncate(serialized, maxLength);
}
return '';
}
/**
* Given any object, return a new object having removed all fields whose value was `undefined`.
* Works recursively on objects and arrays.
*
* Attention: This function keeps circular references in the returned object.
*/
function dropUndefinedKeys(inputValue) {
// This map keeps track of what already visited nodes map to.
// Our Set - based memoBuilder doesn't work here because we want to the output object to have the same circular
// references as the input object.
const memoizationMap = new Map();
// This function just proxies `_dropUndefinedKeys` to keep the `memoBuilder` out of this function's API
return _dropUndefinedKeys(inputValue, memoizationMap);
}
function _dropUndefinedKeys(inputValue, memoizationMap) {
if (isPojo(inputValue)) {
// If this node has already been visited due to a circular reference, return the object it was mapped to in the new object
const memoVal = memoizationMap.get(inputValue);
if (memoVal !== undefined) {
return memoVal ;
}
const returnValue = {};
// Store the mapping of this value in case we visit it again, in case of circular data
memoizationMap.set(inputValue, returnValue);
for (const key of Object.keys(inputValue)) {
if (typeof inputValue[key] !== 'undefined') {
returnValue[key] = _dropUndefinedKeys(inputValue[key], memoizationMap);
}
}
return returnValue ;
}
if (Array.isArray(inputValue)) {
// If this node has already been visited due to a circular reference, return the array it was mapped to in the new object
const memoVal = memoizationMap.get(inputValue);
if (memoVal !== undefined) {
return memoVal ;
}
const returnValue = [];
// Store the mapping of this value in case we visit it again, in case of circular data
memoizationMap.set(inputValue, returnValue);
inputValue.forEach((item) => {
returnValue.push(_dropUndefinedKeys(item, memoizationMap));
});
return returnValue ;
}
return inputValue;
}
function isPojo(input) {
if (!isPlainObject(input)) {
return false;
}
try {
const name = (Object.getPrototypeOf(input) ).constructor.name;
return !name || name === 'Object';
} catch (e) {
return true;
}
}
const STACKTRACE_FRAME_LIMIT = 50;
const UNKNOWN_FUNCTION = '?';
// Used to sanitize webpack (error: *) wrapped stack errors
const WEBPACK_ERROR_REGEXP = /\(error: (.*)\)/;
const STRIP_FRAME_REGEXP = /captureMessage|captureException/;
/**
* Creates a stack parser with the supplied line parsers
*
* StackFrames are returned in the correct order for Sentry Exception
* frames and with Sentry SDK internal frames removed from the top and bottom
*
*/
function createStackParser(...parsers) {
const sortedParsers = parsers.sort((a, b) => a[0] - b[0]).map(p => p[1]);
return (stack, skipFirstLines = 0, framesToPop = 0) => {
const frames = [];
const lines = stack.split('\n');
for (let i = skipFirstLines; i < lines.length; i++) {
const line = lines[i] ;
// Ignore lines over 1kb as they are unlikely to be stack frames.
// Many of the regular expressions use backtracking which results in run time that increases exponentially with
// input size. Huge strings can result in hangs/Denial of Service:
// https://github.com/getsentry/sentry-javascript/issues/2286
if (line.length > 1024) {
continue;
}
// https://github.com/getsentry/sentry-javascript/issues/5459
// Remove webpack (error: *) wrappers
const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, '$1') : line;
// https://github.com/getsentry/sentry-javascript/issues/7813
// Skip Error: lines
if (cleanedLine.match(/\S*Error: /)) {
continue;
}
for (const parser of sortedParsers) {
const frame = parser(cleanedLine);
if (frame) {
frames.push(frame);
break;
}
}
if (frames.length >= STACKTRACE_FRAME_LIMIT + framesToPop) {
break;
}
}
return stripSentryFramesAndReverse(frames.slice(framesToPop));
};
}
/**
* Removes Sentry frames from the top and bottom of the stack if present and enforces a limit of max number of frames.
* Assumes stack input is ordered from top to bottom and returns the reverse representation so call site of the
* function that caused the crash is the last frame in the array.
* @hidden
*/
function stripSentryFramesAndReverse(stack) {
if (!stack.length) {
return [];
}
const localStack = Array.from(stack);
// If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
if (/sentryWrapped/.test(getLastStackFrame(localStack).function || '')) {
localStack.pop();
}
// Reversing in the middle of the procedure allows us to just pop the values off the stack
localStack.reverse();
// If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call)
if (STRIP_FRAME_REGEXP.test(getLastStackFrame(localStack).function || '')) {
localStack.pop();
// When using synthetic events, we will have a 2 levels deep stack, as `new Error('Sentry syntheticException')`
// is produced within the hub itself, making it:
//
// Sentry.captureException()
// getCurrentHub().captureException()
//
// instead of just the top `Sentry` call itself.
// This forces us to possibly strip an additional frame in the exact same was as above.
if (STRIP_FRAME_REGEXP.test(getLastStackFrame(localStack).function || '')) {
localStack.pop();
}
}
return localStack.slice(0, STACKTRACE_FRAME_LIMIT).map(frame => ({
...frame,
filename: frame.filename || getLastStackFrame(localStack).filename,
function: frame.function || UNKNOWN_FUNCTION,
}));
}
function getLastStackFrame(arr) {
return arr[arr.length - 1] || {};
}
const defaultFunctionName = '<anonymous>';
/**
* Safely extract function name from itself
*/
function getFunctionName(fn) {
try {
if (!fn || typeof fn !== 'function') {
return defaultFunctionName;
}
return fn.name || defaultFunctionName;
} catch (e) {
// Just accessing custom props in some Selenium environments
// can cause a "Permission denied" exception (see raven-js#495).
return defaultFunctionName;
}
}
// We keep the handlers globally
const handlers = {};
const instrumented = {};
/** Add a handler function. */
function addHandler(type, handler) {
handlers[type] = handlers[type] || [];
(handlers[type] ).push(handler);
}
/** Maybe run an instrumentation function, unless it was already called. */
function maybeInstrument(type, instrumentFn) {
if (!instrumented[type]) {
instrumentFn();
instrumented[type] = true;
}
}
/** Trigger handlers for a given instrumentation type. */
function triggerHandlers(type, data) {
const typeHandlers = type && handlers[type];
if (!typeHandlers) {
return;
}
for (const handler of typeHandlers) {
try {
handler(data);
} catch (e) {
DEBUG_BUILD$1 &&
logger.error(
`Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`,
e,
);
}
}
}
const ONE_SECOND_IN_MS = 1000;
/**
* A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}
* for accessing a high-resolution monotonic clock.
*/
/**
* Returns a timestamp in seconds since the UNIX epoch using the Date API.
*
* TODO(v8): Return type should be rounded.
*/
function dateTimestampInSeconds() {
return Date.now() / ONE_SECOND_IN_MS;
}
/**
* Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not
* support the API.
*
* Wrapping the native API works around differences in behavior from different browsers.
*/
function createUnixTimestampInSecondsFunc() {
const { performance } = GLOBAL_OBJ ;
if (!performance || !performance.now) {
return dateTimestampInSeconds;
}
// Some browser and environments don't have a timeOrigin, so we fallback to
// using Date.now() to compute the starting time.
const approxStartingTimeOrigin = Date.now() - performance.now();
const timeOrigin = performance.timeOrigin == undefined ? approxStartingTimeOrigin : performance.timeOrigin;
// performance.now() is a monotonic clock, which means it starts at 0 when the process begins. To get the current
// wall clock time (actual UNIX timestamp), we need to add the starting time origin and the current time elapsed.
//
// TODO: This does not account for the case where the monotonic clock that powers performance.now() drifts from the
// wall clock time, which causes the returned timestamp to be inaccurate. We should investigate how to detect and
// correct for this.
// See: https://github.com/getsentry/sentry-javascript/issues/2590
// See: https://github.com/mdn/content/issues/4713
// See: https://dev.to/noamr/when-a-millisecond-is-not-a-millisecond-3h6
return () => {
return (timeOrigin + performance.now()) / ONE_SECOND_IN_MS;
};
}
/**
* Returns a timestamp in seconds since the UNIX epoch using either the Performance or Date APIs, depending on the
* availability of the Performance API.
*
* BUG: Note that because of how browsers implement the Performance API, the clock might stop when the computer is
* asleep. This creates a skew between `dateTimestampInSeconds` and `timestampInSeconds`. The
* skew can grow to arbitrary amounts like days, weeks or months.
* See https://github.com/getsentry/sentry-javascript/issues/2590.
*/
const timestampInSeconds = createUnixTimestampInSecondsFunc();
/**
* The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the
* performance API is available.
*/
(() => {
// Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or
// performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin
// data as reliable if they are within a reasonable threshold of the current time.
const { performance } = GLOBAL_OBJ ;
if (!performance || !performance.now) {
return undefined;
}
const threshold = 3600 * 1000;
const performanceNow = performance.now();
const dateNow = Date.now();
// if timeOrigin isn't available set delta to threshold so it isn't used
const timeOriginDelta = performance.timeOrigin
? Math.abs(performance.timeOrigin + performanceNow - dateNow)
: threshold;
const timeOriginIsReliable = timeOriginDelta < threshold;
// While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
// is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
// Also as of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always
// a valid fallback. In the absence of an initial time provided by the browser, fallback to the current time from the
// Date API.
// eslint-disable-next-line deprecation/deprecation
const navigationStart = performance.timing && performance.timing.navigationStart;
const hasNavigationStart = typeof navigationStart === 'number';
// if navigationStart isn't available set delta to threshold so it isn't used
const navigationStartDelta = hasNavigationStart ? Math.abs(navigationStart + performanceNow - dateNow) : threshold;
const navigationStartIsReliable = navigationStartDelta < threshold;
if (timeOriginIsReliable || navigationStartIsReliable) {
// Use the more reliable time origin
if (timeOriginDelta <= navigationStartDelta) {
return performance.timeOrigin;
} else {
return navigationStart;
}
}
return dateNow;
})();
let _oldOnErrorHandler = null;
/**
* Add an instrumentation handler for when an error is captured by the global error handler.
*
* Use at your own risk, this might break without changelog notice, only used internally.
* @hidden
*/
function addGlobalErrorInstrumentationHandler(handler) {
const ty