LarpixClient/electron/node_modules/serialize-error/index.js
2026-05-10 14:02:17 +02:00

154 lines
2.9 KiB
JavaScript

'use strict';
class NonError extends Error {
constructor(message) {
super(NonError._prepareSuperMessage(message));
Object.defineProperty(this, 'name', {
value: 'NonError',
configurable: true,
writable: true
});
if (Error.captureStackTrace) {
Error.captureStackTrace(this, NonError);
}
}
static _prepareSuperMessage(message) {
try {
return JSON.stringify(message);
} catch {
return String(message);
}
}
}
const commonProperties = [
{property: 'name', enumerable: false},
{property: 'message', enumerable: false},
{property: 'stack', enumerable: false},
{property: 'code', enumerable: true}
];
const isCalled = Symbol('.toJSON called');
const toJSON = from => {
from[isCalled] = true;
const json = from.toJSON();
delete from[isCalled];
return json;
};
const destroyCircular = ({
from,
seen,
to_,
forceEnumerable,
maxDepth,
depth
}) => {
const to = to_ || (Array.isArray(from) ? [] : {});
seen.push(from);
if (depth >= maxDepth) {
return to;
}
if (typeof from.toJSON === 'function' && from[isCalled] !== true) {
return toJSON(from);
}
for (const [key, value] of Object.entries(from)) {
if (typeof Buffer === 'function' && Buffer.isBuffer(value)) {
to[key] = '[object Buffer]';
continue;
}
if (typeof value === 'function') {
continue;
}
if (!value || typeof value !== 'object') {
to[key] = value;
continue;
}
if (!seen.includes(from[key])) {
depth++;
to[key] = destroyCircular({
from: from[key],
seen: seen.slice(),
forceEnumerable,
maxDepth,
depth
});
continue;
}
to[key] = '[Circular]';
}
for (const {property, enumerable} of commonProperties) {
if (typeof from[property] === 'string') {
Object.defineProperty(to, property, {
value: from[property],
enumerable: forceEnumerable ? true : enumerable,
configurable: true,
writable: true
});
}
}
return to;
};
const serializeError = (value, options = {}) => {
const {maxDepth = Number.POSITIVE_INFINITY} = options;
if (typeof value === 'object' && value !== null) {
return destroyCircular({
from: value,
seen: [],
forceEnumerable: true,
maxDepth,
depth: 0
});
}
// People sometimes throw things besides Error objects…
if (typeof value === 'function') {
// `JSON.stringify()` discards functions. We do too, unless a function is thrown directly.
return `[Function: ${(value.name || 'anonymous')}]`;
}
return value;
};
const deserializeError = (value, options = {}) => {
const {maxDepth = Number.POSITIVE_INFINITY} = options;
if (value instanceof Error) {
return value;
}
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
const newError = new Error(); // eslint-disable-line unicorn/error-message
destroyCircular({
from: value,
seen: [],
to_: newError,
maxDepth,
depth: 0
});
return newError;
}
return new NonError(value);
};
module.exports = {
serializeError,
deserializeError
};