Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var browser_1 = require("./browser"); var is_1 = require("./is"); var string_1 = require("./string"); /** * 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, )` or `origMethod.apply(this, [])` (rather than being called directly), again to preserve `this`. * @returns void */ function fill(source, name, replacementFactory) { if (!(name in source)) { return; } var original = source[name]; var 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; } exports.fill = fill; /** * 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, }); } exports.addNonEnumerableProperty = addNonEnumerableProperty; /** * 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) { var proto = original.prototype || {}; wrapped.prototype = original.prototype = proto; addNonEnumerableProperty(wrapped, '__sentry_original__', original); } exports.markFunctionWrapped = markFunctionWrapped; /** * 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__; } exports.getOriginalFunction = getOriginalFunction; /** * 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(function (key) { return encodeURIComponent(key) + "=" + encodeURIComponent(object[key]); }) .join('&'); } exports.urlEncode = urlEncode; /** * Transforms any object into an object literal with all its attributes * attached to it. * * @param value Initial source that we have to transform in order for it to be usable by the serializer */ function convertToPlainObject(value) { var newObj = value; if (is_1.isError(value)) { newObj = tslib_1.__assign({ message: value.message, name: value.name, stack: value.stack }, getOwnProperties(value)); } else if (is_1.isEvent(value)) { var event_1 = value; newObj = tslib_1.__assign({ type: event_1.type, target: serializeEventTarget(event_1.target), currentTarget: serializeEventTarget(event_1.currentTarget) }, getOwnProperties(event_1)); if (typeof CustomEvent !== 'undefined' && is_1.isInstanceOf(value, CustomEvent)) { newObj.detail = event_1.detail; } } return newObj; } exports.convertToPlainObject = convertToPlainObject; /** Creates a string representation of the target of an `Event` object */ function serializeEventTarget(target) { try { return is_1.isElement(target) ? browser_1.htmlTreeAsString(target) : Object.prototype.toString.call(target); } catch (_oO) { return ''; } } /** Filters out all but an object's own properties */ function getOwnProperties(obj) { var extractedProps = {}; for (var property in obj) { if (Object.prototype.hasOwnProperty.call(obj, property)) { extractedProps[property] = obj[property]; } } return extractedProps; } /** * 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` */ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function extractExceptionKeysForMessage(exception, maxLength) { if (maxLength === void 0) { maxLength = 40; } var keys = Object.keys(convertToPlainObject(exception)); keys.sort(); if (!keys.length) { return '[object has no keys]'; } if (keys[0].length >= maxLength) { return string_1.truncate(keys[0], maxLength); } for (var includedKeys = keys.length; includedKeys > 0; includedKeys--) { var serialized = keys.slice(0, includedKeys).join(', '); if (serialized.length > maxLength) { continue; } if (includedKeys === keys.length) { return serialized; } return string_1.truncate(serialized, maxLength); } return ''; } exports.extractExceptionKeysForMessage = extractExceptionKeysForMessage; /** * Given any object, return the new object with removed keys that value was `undefined`. * Works recursively on objects and arrays. */ function dropUndefinedKeys(val) { var e_1, _a; if (is_1.isPlainObject(val)) { var rv = {}; try { for (var _b = tslib_1.__values(Object.keys(val)), _c = _b.next(); !_c.done; _c = _b.next()) { var key = _c.value; if (typeof val[key] !== 'undefined') { rv[key] = dropUndefinedKeys(val[key]); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } return rv; } if (Array.isArray(val)) { return val.map(dropUndefinedKeys); } return val; } exports.dropUndefinedKeys = dropUndefinedKeys; /** * 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) { var 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 is_1.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; } exports.objectify = objectify; //# sourceMappingURL=object.js.map