@tapjs/error-serdes
Version:
Port of node's error_serdes.js to userland, plus test message streaming
95 lines • 3.29 kB
JavaScript
// This module is more or less a direct port of the serialization logic
// from node's lib/internal/error_serdes module, with primordials removed.
import { errorCtorNames, kCustomInspect, kCustomInspectedObject, kInspectedError, kInspectedSymbol, kSerializedError, kSerializedObject, } from './constants.js';
import { inspect } from 'node:util';
import { serialize } from 'v8';
const getAllProps = (obj, target = obj) => {
const all = Object.create(null);
if (obj === null)
return all;
Object.assign(all, getAllProps(Object.getPrototypeOf(obj), target));
const keys = Object.getOwnPropertyNames(obj);
for (const key of keys) {
const desc = Object.getOwnPropertyDescriptor(obj, key);
/* c8 ignore start */
if (!desc)
continue;
/* c8 ignore stop */
const getter = desc.get;
if (getter) {
try {
delete desc.get;
delete desc.set;
desc.value = getter.call(target);
}
catch { }
}
if (key === 'cause') {
desc.value = serializeError(desc.value);
all.cause = desc;
}
else if ('value' in desc &&
typeof desc.value !== 'function' &&
typeof desc.value !== 'symbol') {
all[key] = desc;
}
}
return all;
};
const isError = (obj) => typeof obj === 'object' &&
Object.prototype.toString.call(obj) === '[object Error]';
const getCtors = (obj) => {
const ctors = [];
for (let cur = obj; cur !== null; cur = Object.getPrototypeOf(cur)) {
const desc = Object.getOwnPropertyDescriptor(cur, 'constructor');
const value = desc?.value;
if (typeof value === 'function') {
ctors.push(value);
}
}
return ctors;
};
const getName = (f) => {
const n = Object.getOwnPropertyDescriptor(f, 'name')?.value;
if (typeof n === 'string')
return n;
};
export const serializeError = (er) => {
if (typeof er === 'symbol') {
return Buffer.from(String.fromCharCode(kInspectedSymbol) + String(er), 'utf8');
}
try {
if (isError(er)) {
const ctors = getCtors(er);
for (const c of ctors) {
const name = getName(c);
if (name && errorCtorNames.has(name)) {
const serialized = serialize({
constructor: name,
properties: getAllProps(er),
});
return Buffer.concat([
Buffer.from([kSerializedError]),
serialized,
]);
}
}
/* c8 ignore start */
}
}
catch { }
/* c8 ignore stop */
try {
if (er !== null && er !== undefined && kCustomInspect in er) {
return Buffer.from(String.fromCharCode(kCustomInspectedObject) + inspect(er), 'utf8');
}
}
catch { }
try {
const serialized = serialize(er);
return Buffer.concat([Buffer.from([kSerializedObject]), serialized]);
}
catch { }
return Buffer.from(String.fromCharCode(kInspectedError) + inspect(er), 'utf8');
};
//# sourceMappingURL=serialize.js.map