UNPKG

nstdlib-nightly

Version:

Node.js standard library converted to runtime-agnostic ES modules.

205 lines (189 loc) 5.67 kB
// Source: https://github.com/nodejs/node/blob/65eff1eb/lib/internal/error_serdes.js import * as __hoisted_v8__ from "nstdlib/lib/v8"; import * as __hoisted_assert__ from "nstdlib/lib/assert"; import { Buffer } from "nstdlib/lib/buffer"; import { inspect as __inspect__ } from "nstdlib/lib/util"; import * as __hoisted_internal_util_inspect__ from "nstdlib/lib/internal/util/inspect"; const { custom: customInspectSymbol } = __inspect__; const kSerializedError = 0; const kSerializedObject = 1; const kInspectedError = 2; const kInspectedSymbol = 3; const kCustomInspectedObject = 4; const kSymbolStringLength = "Symbol(".length; const errors = { Error, TypeError, RangeError, URIError, SyntaxError, ReferenceError, EvalError, }; const errorConstructorNames = new Set(Object.keys(errors)); function TryGetAllProperties(object, target = object) { const all = { __proto__: null }; if (object === null) return all; Object.assign( all, TryGetAllProperties(Object.getPrototypeOf(object), target), ); const keys = Object.getOwnPropertyNames(object); Array.prototype.forEach.call(keys, (key) => { let descriptor; try { // TODO: create a null-prototype descriptor with needed properties only descriptor = Object.getOwnPropertyDescriptor(object, key); } catch { return; } const getter = descriptor.get; if (getter && key !== "__proto__") { try { descriptor.value = Function.prototype.call.call(getter, target); delete descriptor.get; delete descriptor.set; } catch { // Continue regardless of error. } } if (key === "cause") { descriptor.value = serializeError(descriptor.value); all[key] = descriptor; } else if ( "value" in descriptor && typeof descriptor.value !== "function" && typeof descriptor.value !== "symbol" ) { all[key] = descriptor; } }); return all; } function GetConstructors(object) { const constructors = []; for ( let current = object; current !== null; current = Object.getPrototypeOf(current) ) { const desc = Object.getOwnPropertyDescriptor(current, "constructor"); if (desc && desc.value) { Object.defineProperty(constructors, constructors.length, { __proto__: null, value: desc.value, enumerable: true, }); } } return constructors; } function GetName(object) { const desc = Object.getOwnPropertyDescriptor(object, "name"); return desc && desc.value; } let internalUtilInspect; function inspect(...args) { if (!internalUtilInspect) { internalUtilInspect = __hoisted_internal_util_inspect__; } return internalUtilInspect.inspect(...args); } let serialize; function serializeError(error) { if (!serialize) serialize = __hoisted_v8__.serialize; if (typeof error === "symbol") { return Buffer.from( String.fromCharCode(kInspectedSymbol) + inspect(error), "utf8", ); } try { if ( typeof error === "object" && Object.prototype.toString.call(error) === "[object Error]" ) { const constructors = GetConstructors(error); for (let i = 0; i < constructors.length; i++) { const name = GetName(constructors[i]); if (errorConstructorNames.has(name)) { const serialized = serialize({ constructor: name, properties: TryGetAllProperties(error), }); return Buffer.concat([Buffer.from([kSerializedError]), serialized]); } } } } catch { // Continue regardless of error. } try { if (error != null && customInspectSymbol in error) { return Buffer.from( String.fromCharCode(kCustomInspectedObject) + inspect(error), "utf8", ); } } catch { // Continue regardless of error. } try { const serialized = serialize(error); return Buffer.concat([Buffer.from([kSerializedObject]), serialized]); } catch { // Continue regardless of error. } return Buffer.from( String.fromCharCode(kInspectedError) + inspect(error), "utf8", ); } function fromBuffer(error) { return Buffer.from( TypedArrayPrototypeGetBuffer(error), TypedArrayPrototypeGetByteOffset(error) + 1, TypedArrayPrototypeGetByteLength(error) - 1, ); } let deserialize; function deserializeError(error) { if (!deserialize) deserialize = __hoisted_v8__.deserialize; switch (error[0]) { case kSerializedError: { const { constructor, properties } = deserialize(error.subarray(1)); const ctor = errors[constructor]; Object.defineProperty(properties, Symbol.toStringTag, { __proto__: null, value: { __proto__: null, value: "Error", configurable: true }, enumerable: true, }); if ("cause" in properties && "value" in properties.cause) { properties.cause.value = deserializeError(properties.cause.value); } return Object.create(ctor.prototype, properties); } case kSerializedObject: return deserialize(error.subarray(1)); case kInspectedError: return fromBuffer(error).toString("utf8"); case kInspectedSymbol: { const buf = fromBuffer(error); return Symbol.for( String.prototype.substring.call( buf.toString("utf8"), kSymbolStringLength, buf.length - 1, ), ); } case kCustomInspectedObject: return { __proto__: null, [customInspectSymbol]: () => fromBuffer(error).toString("utf8"), }; } __hoisted_assert__.fail("This should not happen"); } export { serializeError }; export { deserializeError };