2017-09-26 01:42:16 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const Buffer = require('buffer').Buffer;
|
2019-01-30 15:21:07 +01:00
|
|
|
const {
|
2019-04-05 11:11:26 +02:00
|
|
|
ArrayPrototype,
|
|
|
|
FunctionPrototype,
|
2019-01-30 15:21:07 +01:00
|
|
|
Object,
|
|
|
|
ObjectPrototype,
|
2019-04-05 11:11:26 +02:00
|
|
|
SafeSet,
|
2019-01-30 15:21:07 +01:00
|
|
|
} = primordials;
|
2017-09-26 01:42:16 +02:00
|
|
|
|
|
|
|
const kSerializedError = 0;
|
|
|
|
const kSerializedObject = 1;
|
|
|
|
const kInspectedError = 2;
|
|
|
|
|
|
|
|
const errors = {
|
|
|
|
Error, TypeError, RangeError, URIError, SyntaxError, ReferenceError, EvalError
|
|
|
|
};
|
|
|
|
const errorConstructorNames = new SafeSet(Object.keys(errors));
|
|
|
|
|
|
|
|
function TryGetAllProperties(object, target = object) {
|
|
|
|
const all = Object.create(null);
|
|
|
|
if (object === null)
|
|
|
|
return all;
|
2019-04-05 11:11:26 +02:00
|
|
|
Object.assign(all,
|
|
|
|
TryGetAllProperties(Object.getPrototypeOf(object), target));
|
|
|
|
const keys = Object.getOwnPropertyNames(object);
|
|
|
|
ArrayPrototype.forEach(keys, (key) => {
|
2019-02-16 07:43:58 +01:00
|
|
|
let descriptor;
|
|
|
|
try {
|
2019-04-05 11:11:26 +02:00
|
|
|
descriptor = Object.getOwnPropertyDescriptor(object, key);
|
2019-02-16 07:43:58 +01:00
|
|
|
} catch { return; }
|
2017-09-26 01:42:16 +02:00
|
|
|
const getter = descriptor.get;
|
|
|
|
if (getter && key !== '__proto__') {
|
|
|
|
try {
|
2019-04-05 11:11:26 +02:00
|
|
|
descriptor.value = FunctionPrototype.call(getter, target);
|
2017-09-26 01:42:16 +02:00
|
|
|
} catch {}
|
|
|
|
}
|
|
|
|
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 (var current = object;
|
|
|
|
current !== null;
|
2019-04-05 11:11:26 +02:00
|
|
|
current = Object.getPrototypeOf(current)) {
|
|
|
|
const desc = Object.getOwnPropertyDescriptor(current, 'constructor');
|
2017-09-26 01:42:16 +02:00
|
|
|
if (desc && desc.value) {
|
2019-04-05 11:11:26 +02:00
|
|
|
Object.defineProperty(constructors, constructors.length, {
|
2017-09-26 01:42:16 +02:00
|
|
|
value: desc.value, enumerable: true
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return constructors;
|
|
|
|
}
|
|
|
|
|
|
|
|
function GetName(object) {
|
2019-04-05 11:11:26 +02:00
|
|
|
const desc = Object.getOwnPropertyDescriptor(object, 'name');
|
2017-09-26 01:42:16 +02:00
|
|
|
return desc && desc.value;
|
|
|
|
}
|
|
|
|
|
2019-03-22 18:02:07 +01:00
|
|
|
let internalUtilInspect;
|
|
|
|
function inspect(...args) {
|
|
|
|
if (!internalUtilInspect) {
|
|
|
|
internalUtilInspect = require('internal/util/inspect');
|
|
|
|
}
|
|
|
|
return internalUtilInspect.inspect(...args);
|
2017-09-26 01:42:16 +02:00
|
|
|
}
|
|
|
|
|
2019-03-15 19:18:29 +01:00
|
|
|
let serialize;
|
2017-09-26 01:42:16 +02:00
|
|
|
function serializeError(error) {
|
2019-03-15 19:18:29 +01:00
|
|
|
if (!serialize) serialize = require('v8').serialize;
|
2017-09-26 01:42:16 +02:00
|
|
|
try {
|
|
|
|
if (typeof error === 'object' &&
|
2019-04-05 11:11:26 +02:00
|
|
|
ObjectPrototype.toString(error) === '[object Error]') {
|
2017-09-26 01:42:16 +02:00
|
|
|
const constructors = GetConstructors(error);
|
2019-02-05 21:47:08 +01:00
|
|
|
for (var i = 0; i < constructors.length; i++) {
|
2017-09-26 01:42:16 +02:00
|
|
|
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 {}
|
|
|
|
try {
|
|
|
|
const serialized = serialize(error);
|
|
|
|
return Buffer.concat([Buffer.from([kSerializedObject]), serialized]);
|
|
|
|
} catch {}
|
|
|
|
return Buffer.concat([Buffer.from([kInspectedError]),
|
2019-03-22 18:02:07 +01:00
|
|
|
Buffer.from(inspect(error), 'utf8')]);
|
2017-09-26 01:42:16 +02:00
|
|
|
}
|
|
|
|
|
2019-03-15 19:18:29 +01:00
|
|
|
let deserialize;
|
2017-09-26 01:42:16 +02:00
|
|
|
function deserializeError(error) {
|
2019-03-15 19:18:29 +01:00
|
|
|
if (!deserialize) deserialize = require('v8').deserialize;
|
2017-09-26 01:42:16 +02:00
|
|
|
switch (error[0]) {
|
|
|
|
case kSerializedError:
|
|
|
|
const { constructor, properties } = deserialize(error.subarray(1));
|
|
|
|
const ctor = errors[constructor];
|
|
|
|
return Object.create(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 };
|