UNPKG

@bacons/expo-metro-runtime

Version:

Tools for making experimental Metro bundler features work

117 lines 4.28 kB
"use strict"; /** * Copyright (c) Evan Bacon. * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createStringifySafeWithLimits = void 0; /** * Tries to stringify with JSON.stringify and toString, but catches exceptions * (e.g. from circular objects) and always returns a string and never throws. */ function createStringifySafeWithLimits(limits) { const { maxDepth = Number.POSITIVE_INFINITY, maxStringLimit = Number.POSITIVE_INFINITY, maxArrayLimit = Number.POSITIVE_INFINITY, maxObjectKeysLimit = Number.POSITIVE_INFINITY, } = limits; const stack = []; function replacer(key, value) { // @ts-expect-error while (stack.length && this !== stack[0]) { stack.shift(); } if (typeof value === "string") { const truncatedString = "...(truncated)..."; if (value.length > maxStringLimit + truncatedString.length) { return value.substring(0, maxStringLimit) + truncatedString; } return value; } if (typeof value !== "object" || value === null) { return value; } let retval = value; if (Array.isArray(value)) { if (stack.length >= maxDepth) { retval = `[ ... array with ${value.length} values ... ]`; } else if (value.length > maxArrayLimit) { retval = value .slice(0, maxArrayLimit) .concat([ `... extra ${value.length - maxArrayLimit} values truncated ...`, ]); } } else { // Add refinement after Array.isArray call. if (typeof value !== "object") { throw new Error("This was already found earlier"); } let keys = Object.keys(value); if (stack.length >= maxDepth) { retval = `{ ... object with ${keys.length} keys ... }`; } else if (keys.length > maxObjectKeysLimit) { // Return a sample of the keys. retval = {}; for (let k of keys.slice(0, maxObjectKeysLimit)) { retval[k] = value[k]; } const truncatedKey = "...(truncated keys)..."; retval[truncatedKey] = keys.length - maxObjectKeysLimit; } } stack.unshift(retval); return retval; } return function stringifySafe(arg) { if (arg === undefined) { return "undefined"; } else if (arg === null) { return "null"; } else if (typeof arg === "function") { try { return arg.toString(); } catch (e) { return "[function unknown]"; } } else if (arg instanceof Error) { return arg.name + ": " + arg.message; } else { // Perform a try catch, just in case the object has a circular // reference or stringify throws for some other reason. try { const ret = JSON.stringify(arg, replacer); if (ret === undefined) { return '["' + typeof arg + '" failed to stringify]'; } return ret; } catch (e) { if (typeof arg.toString === "function") { try { // $FlowFixMe[incompatible-use] : toString shouldn't take any arguments in general. return arg.toString(); } catch (E) { } } } } return '["' + typeof arg + '" failed to stringify]'; }; } exports.createStringifySafeWithLimits = createStringifySafeWithLimits; const stringifySafe = createStringifySafeWithLimits({ maxDepth: 10, maxStringLimit: 100, maxArrayLimit: 50, maxObjectKeysLimit: 50, }); exports.default = stringifySafe; //# sourceMappingURL=index.js.map