1"use strict";
2/**
3 * Copyright (c) 650 Industries.
4 * Copyright (c) Meta Platforms, Inc. and affiliates.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE file in the root directory of this source tree.
8 */
9Object.defineProperty(exports, "__esModule", { value: true });
10exports.createStringifySafeWithLimits = void 0;
11/**
12 * Tries to stringify with JSON.stringify and toString, but catches exceptions
13 * (e.g. from circular objects) and always returns a string and never throws.
14 */
15function createStringifySafeWithLimits(limits) {
16    const { maxDepth = Number.POSITIVE_INFINITY, maxStringLimit = Number.POSITIVE_INFINITY, maxArrayLimit = Number.POSITIVE_INFINITY, maxObjectKeysLimit = Number.POSITIVE_INFINITY, } = limits;
17    const stack = [];
18    function replacer(_key, value) {
19        while (stack.length && this !== stack[0]) {
20            stack.shift();
21        }
22        if (typeof value === 'string') {
23            const truncatedString = '...(truncated)...';
24            if (value.length > maxStringLimit + truncatedString.length) {
25                return value.substring(0, maxStringLimit) + truncatedString;
26            }
27            return value;
28        }
29        if (typeof value !== 'object' || value === null) {
30            return value;
31        }
32        let retval = value;
33        if (Array.isArray(value)) {
34            if (stack.length >= maxDepth) {
35                retval = `[ ... array with ${value.length} values ... ]`;
36            }
37            else if (value.length > maxArrayLimit) {
38                retval = value
39                    .slice(0, maxArrayLimit)
40                    .concat([`... extra ${value.length - maxArrayLimit} values truncated ...`]);
41            }
42        }
43        else {
44            // Add refinement after Array.isArray call.
45            if (typeof value !== 'object') {
46                throw new Error('This was already found earlier');
47            }
48            const keys = Object.keys(value);
49            if (stack.length >= maxDepth) {
50                retval = `{ ... object with ${keys.length} keys ... }`;
51            }
52            else if (keys.length > maxObjectKeysLimit) {
53                // Return a sample of the keys.
54                retval = {};
55                for (const k of keys.slice(0, maxObjectKeysLimit)) {
56                    retval[k] = value[k];
57                }
58                const truncatedKey = '...(truncated keys)...';
59                retval[truncatedKey] = keys.length - maxObjectKeysLimit;
60            }
61        }
62        stack.unshift(retval);
63        return retval;
64    }
65    return function stringifySafe(arg) {
66        if (arg === undefined) {
67            return 'undefined';
68        }
69        else if (arg === null) {
70            return 'null';
71        }
72        else if (typeof arg === 'function') {
73            try {
74                return arg.toString();
75            }
76            catch {
77                return '[function unknown]';
78            }
79        }
80        else if (arg instanceof Error) {
81            return arg.name + ': ' + arg.message;
82        }
83        else {
84            // Perform a try catch, just in case the object has a circular
85            // reference or stringify throws for some other reason.
86            try {
87                const ret = JSON.stringify(arg, replacer);
88                if (ret === undefined) {
89                    return '["' + typeof arg + '" failed to stringify]';
90                }
91                return ret;
92            }
93            catch {
94                if (typeof arg.toString === 'function') {
95                    try {
96                        // $FlowFixMe[incompatible-use] : toString shouldn't take any arguments in general.
97                        return arg.toString();
98                    }
99                    catch { }
100                }
101            }
102        }
103        return '["' + typeof arg + '" failed to stringify]';
104    };
105}
106exports.createStringifySafeWithLimits = createStringifySafeWithLimits;
107const stringifySafe = createStringifySafeWithLimits({
108    maxDepth: 10,
109    maxStringLimit: 100,
110    maxArrayLimit: 50,
111    maxObjectKeysLimit: 50,
112});
113exports.default = stringifySafe;
114//# sourceMappingURL=index.js.map