summaryrefslogtreecommitdiff
path: root/shared/logger/node_modules/@sentry/utils/esm/object.js
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /shared/logger/node_modules/@sentry/utils/esm/object.js
init commit
Diffstat (limited to 'shared/logger/node_modules/@sentry/utils/esm/object.js')
-rw-r--r--shared/logger/node_modules/@sentry/utils/esm/object.js279
1 files changed, 279 insertions, 0 deletions
diff --git a/shared/logger/node_modules/@sentry/utils/esm/object.js b/shared/logger/node_modules/@sentry/utils/esm/object.js
new file mode 100644
index 0000000..0f5c411
--- /dev/null
+++ b/shared/logger/node_modules/@sentry/utils/esm/object.js
@@ -0,0 +1,279 @@
+import { htmlTreeAsString } from './browser.js';
+import { isError, isEvent, isInstanceOf, isElement, isPlainObject, isPrimitive } from './is.js';
+import { truncate } from './string.js';
+
+/**
+ * Replace a method in an object with a wrapped version of itself.
+ *
+ * @param source An object that contains a method to be wrapped.
+ * @param name The name of the method to be wrapped.
+ * @param replacementFactory A higher-order function that takes the original version of the given method and returns a
+ * wrapped version. Note: The function returned by `replacementFactory` needs to be a non-arrow function, in order to
+ * preserve the correct value of `this`, and the original method must be called using `origMethod.call(this, <other
+ * args>)` or `origMethod.apply(this, [<other args>])` (rather than being called directly), again to preserve `this`.
+ * @returns void
+ */
+function fill(source, name, replacementFactory) {
+ if (!(name in source)) {
+ return;
+ }
+
+ const original = source[name] ;
+ const wrapped = replacementFactory(original) ;
+
+ // Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work
+ // otherwise it'll throw "TypeError: Object.defineProperties called on non-object"
+ if (typeof wrapped === 'function') {
+ try {
+ markFunctionWrapped(wrapped, original);
+ } catch (_Oo) {
+ // This can throw if multiple fill happens on a global object like XMLHttpRequest
+ // Fixes https://github.com/getsentry/sentry-javascript/issues/2043
+ }
+ }
+
+ source[name] = wrapped;
+}
+
+/**
+ * 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) {
+ 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,
+ });
+}
+
+/**
+ * Remembers the original function on the wrapped function and
+ * patches up the prototype.
+ *
+ * @param wrapped the wrapper function
+ * @param original the original function that gets wrapped
+ */
+function markFunctionWrapped(wrapped, original) {
+ const proto = original.prototype || {};
+ wrapped.prototype = original.prototype = proto;
+ addNonEnumerableProperty(wrapped, '__sentry_original__', original);
+}
+
+/**
+ * This extracts the original function if available. See
+ * `markFunctionWrapped` for more information.
+ *
+ * @param func the function to unwrap
+ * @returns the unwrapped version of the function if available.
+ */
+function getOriginalFunction(func) {
+ return func.__sentry_original__;
+}
+
+/**
+ * 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();
+
+ if (!keys.length) {
+ return '[object has no keys]';
+ }
+
+ if (keys[0].length >= maxLength) {
+ return truncate(keys[0], 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 (isPlainObject(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;
+}
+
+/**
+ * Ensure that something is an object.
+ *
+ * Turns `undefined` and `null` into `String`s and all other primitives into instances of their respective wrapper
+ * classes (String, Boolean, Number, etc.). Acts as the identity function on non-primitives.
+ *
+ * @param wat The subject of the objectification
+ * @returns A version of `wat` which can safely be used with `Object` class methods
+ */
+function objectify(wat) {
+ let objectified;
+ switch (true) {
+ case wat === undefined || wat === null:
+ objectified = new String(wat);
+ break;
+
+ // Though symbols and bigints do have wrapper classes (`Symbol` and `BigInt`, respectively), for whatever reason
+ // those classes don't have constructors which can be used with the `new` keyword. We therefore need to cast each as
+ // an object in order to wrap it.
+ case typeof wat === 'symbol' || typeof wat === 'bigint':
+ objectified = Object(wat);
+ break;
+
+ // this will catch the remaining primitives: `String`, `Number`, and `Boolean`
+ case isPrimitive(wat):
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ objectified = new (wat ).constructor(wat);
+ break;
+
+ // by process of elimination, at this point we know that `wat` must already be an object
+ default:
+ objectified = wat;
+ break;
+ }
+ return objectified;
+}
+
+export { addNonEnumerableProperty, convertToPlainObject, dropUndefinedKeys, extractExceptionKeysForMessage, fill, getOriginalFunction, markFunctionWrapped, objectify, urlEncode };
+//# sourceMappingURL=object.js.map