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