| 'use strict'; |
| |
| const Buffer = require('buffer').Buffer; |
| const { |
| ArrayPrototypeForEach, |
| Error, |
| EvalError, |
| FunctionPrototypeCall, |
| ObjectAssign, |
| ObjectCreate, |
| ObjectDefineProperty, |
| ObjectGetOwnPropertyDescriptor, |
| ObjectGetOwnPropertyNames, |
| ObjectGetPrototypeOf, |
| ObjectKeys, |
| ObjectPrototypeToString, |
| RangeError, |
| ReferenceError, |
| SafeSet, |
| SymbolToStringTag, |
| SyntaxError, |
| TypeError, |
| URIError, |
| } = primordials; |
| |
| const kSerializedError = 0; |
| const kSerializedObject = 1; |
| const kInspectedError = 2; |
| |
| const errors = { |
| Error, TypeError, RangeError, URIError, SyntaxError, ReferenceError, EvalError |
| }; |
| const errorConstructorNames = new SafeSet(ObjectKeys(errors)); |
| |
| function TryGetAllProperties(object, target = object) { |
| const all = ObjectCreate(null); |
| if (object === null) |
| return all; |
| ObjectAssign(all, |
| TryGetAllProperties(ObjectGetPrototypeOf(object), target)); |
| const keys = ObjectGetOwnPropertyNames(object); |
| ArrayPrototypeForEach(keys, (key) => { |
| let descriptor; |
| try { |
| descriptor = ObjectGetOwnPropertyDescriptor(object, key); |
| } catch { return; } |
| const getter = descriptor.get; |
| if (getter && key !== '__proto__') { |
| try { |
| descriptor.value = FunctionPrototypeCall(getter, target); |
| } catch { |
| // Continue regardless of error. |
| } |
| } |
| if ('value' in descriptor && typeof descriptor.value !== 'function') { |
| delete descriptor.get; |
| delete descriptor.set; |
| all[key] = descriptor; |
| } |
| }); |
| return all; |
| } |
| |
| function GetConstructors(object) { |
| const constructors = []; |
| |
| for (let current = object; |
| current !== null; |
| current = ObjectGetPrototypeOf(current)) { |
| const desc = ObjectGetOwnPropertyDescriptor(current, 'constructor'); |
| if (desc && desc.value) { |
| ObjectDefineProperty(constructors, constructors.length, { |
| __proto__: null, |
| value: desc.value, enumerable: true |
| }); |
| } |
| } |
| |
| return constructors; |
| } |
| |
| function GetName(object) { |
| const desc = ObjectGetOwnPropertyDescriptor(object, 'name'); |
| return desc && desc.value; |
| } |
| |
| let internalUtilInspect; |
| function inspect(...args) { |
| if (!internalUtilInspect) { |
| internalUtilInspect = require('internal/util/inspect'); |
| } |
| return internalUtilInspect.inspect(...args); |
| } |
| |
| let serialize; |
| function serializeError(error) { |
| if (!serialize) serialize = require('v8').serialize; |
| try { |
| if (typeof error === 'object' && |
| ObjectPrototypeToString(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 { |
| const serialized = serialize(error); |
| return Buffer.concat([Buffer.from([kSerializedObject]), serialized]); |
| } catch { |
| // Continue regardless of error. |
| } |
| return Buffer.concat([Buffer.from([kInspectedError]), |
| Buffer.from(inspect(error), 'utf8')]); |
| } |
| |
| let deserialize; |
| function deserializeError(error) { |
| if (!deserialize) deserialize = require('v8').deserialize; |
| switch (error[0]) { |
| case kSerializedError: { |
| const { constructor, properties } = deserialize(error.subarray(1)); |
| const ctor = errors[constructor]; |
| ObjectDefineProperty(properties, SymbolToStringTag, { |
| __proto__: null, |
| value: { value: 'Error', configurable: true }, |
| enumerable: true |
| }); |
| return ObjectCreate(ctor.prototype, properties); |
| } |
| case kSerializedObject: |
| return deserialize(error.subarray(1)); |
| case kInspectedError: { |
| const buf = Buffer.from(error.buffer, |
| error.byteOffset + 1, |
| error.byteLength - 1); |
| return buf.toString('utf8'); |
| } |
| } |
| require('assert').fail('This should not happen'); |
| } |
| |
| module.exports = { serializeError, deserializeError }; |