1'use strict'; 2 3const Buffer = require('buffer').Buffer; 4const { 5 ArrayPrototypeForEach, 6 Error, 7 EvalError, 8 FunctionPrototypeCall, 9 ObjectAssign, 10 ObjectCreate, 11 ObjectDefineProperty, 12 ObjectGetOwnPropertyDescriptor, 13 ObjectGetOwnPropertyNames, 14 ObjectGetPrototypeOf, 15 ObjectKeys, 16 ObjectPrototypeToString, 17 RangeError, 18 ReferenceError, 19 SafeSet, 20 SymbolToStringTag, 21 SyntaxError, 22 TypeError, 23 URIError, 24} = primordials; 25 26const kSerializedError = 0; 27const kSerializedObject = 1; 28const kInspectedError = 2; 29 30const errors = { 31 Error, TypeError, RangeError, URIError, SyntaxError, ReferenceError, EvalError 32}; 33const errorConstructorNames = new SafeSet(ObjectKeys(errors)); 34 35function TryGetAllProperties(object, target = object) { 36 const all = ObjectCreate(null); 37 if (object === null) 38 return all; 39 ObjectAssign(all, 40 TryGetAllProperties(ObjectGetPrototypeOf(object), target)); 41 const keys = ObjectGetOwnPropertyNames(object); 42 ArrayPrototypeForEach(keys, (key) => { 43 let descriptor; 44 try { 45 descriptor = ObjectGetOwnPropertyDescriptor(object, key); 46 } catch { return; } 47 const getter = descriptor.get; 48 if (getter && key !== '__proto__') { 49 try { 50 descriptor.value = FunctionPrototypeCall(getter, target); 51 } catch {} 52 } 53 if ('value' in descriptor && typeof descriptor.value !== 'function') { 54 delete descriptor.get; 55 delete descriptor.set; 56 all[key] = descriptor; 57 } 58 }); 59 return all; 60} 61 62function GetConstructors(object) { 63 const constructors = []; 64 65 for (let current = object; 66 current !== null; 67 current = ObjectGetPrototypeOf(current)) { 68 const desc = ObjectGetOwnPropertyDescriptor(current, 'constructor'); 69 if (desc && desc.value) { 70 ObjectDefineProperty(constructors, constructors.length, { 71 value: desc.value, enumerable: true 72 }); 73 } 74 } 75 76 return constructors; 77} 78 79function GetName(object) { 80 const desc = ObjectGetOwnPropertyDescriptor(object, 'name'); 81 return desc && desc.value; 82} 83 84let internalUtilInspect; 85function inspect(...args) { 86 if (!internalUtilInspect) { 87 internalUtilInspect = require('internal/util/inspect'); 88 } 89 return internalUtilInspect.inspect(...args); 90} 91 92let serialize; 93function serializeError(error) { 94 if (!serialize) serialize = require('v8').serialize; 95 try { 96 if (typeof error === 'object' && 97 ObjectPrototypeToString(error) === '[object Error]') { 98 const constructors = GetConstructors(error); 99 for (let i = 0; i < constructors.length; i++) { 100 const name = GetName(constructors[i]); 101 if (errorConstructorNames.has(name)) { 102 const serialized = serialize({ 103 constructor: name, 104 properties: TryGetAllProperties(error) 105 }); 106 return Buffer.concat([Buffer.from([kSerializedError]), serialized]); 107 } 108 } 109 } 110 } catch {} 111 try { 112 const serialized = serialize(error); 113 return Buffer.concat([Buffer.from([kSerializedObject]), serialized]); 114 } catch {} 115 return Buffer.concat([Buffer.from([kInspectedError]), 116 Buffer.from(inspect(error), 'utf8')]); 117} 118 119let deserialize; 120function deserializeError(error) { 121 if (!deserialize) deserialize = require('v8').deserialize; 122 switch (error[0]) { 123 case kSerializedError: 124 const { constructor, properties } = deserialize(error.subarray(1)); 125 const ctor = errors[constructor]; 126 ObjectDefineProperty(properties, SymbolToStringTag, { 127 value: { value: 'Error', configurable: true }, 128 enumerable: true 129 }); 130 return ObjectCreate(ctor.prototype, properties); 131 case kSerializedObject: 132 return deserialize(error.subarray(1)); 133 case kInspectedError: 134 const buf = Buffer.from(error.buffer, 135 error.byteOffset + 1, 136 error.byteLength - 1); 137 return buf.toString('utf8'); 138 } 139 require('assert').fail('This should not happen'); 140} 141 142module.exports = { serializeError, deserializeError }; 143