| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ecba1c5 commit 9ad42b7
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,121 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const Buffer = require('buffer').Buffer; | ||
| 4 | + const { serialize, deserialize } = require('v8'); | ||
| 5 | + const { SafeSet } = require('internal/safe_globals'); | ||
| 6 | + | ||
| 7 | + const kSerializedError = 0; | ||
| 8 | + const kSerializedObject = 1; | ||
| 9 | + const kInspectedError = 2; | ||
| 10 | + | ||
| 11 | + const GetPrototypeOf = Object.getPrototypeOf; | ||
| 12 | + const GetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | ||
| 13 | + const GetOwnPropertyNames = Object.getOwnPropertyNames; | ||
| 14 | + const DefineProperty = Object.defineProperty; | ||
| 15 | + const Assign = Object.assign; | ||
| 16 | + const ObjectPrototypeToString = | ||
| 17 | + Function.prototype.call.bind(Object.prototype.toString); | ||
| 18 | + const ForEach = Function.prototype.call.bind(Array.prototype.forEach); | ||
| 19 | + const Call = Function.prototype.call.bind(Function.prototype.call); | ||
| 20 | + | ||
| 21 | + const errors = { | ||
| 22 | + Error, TypeError, RangeError, URIError, SyntaxError, ReferenceError, EvalError | ||
| 23 | + }; | ||
| 24 | + const errorConstructorNames = new SafeSet(Object.keys(errors)); | ||
| 25 | + | ||
| 26 | + function TryGetAllProperties(object, target = object) { | ||
| 27 | + const all = Object.create(null); | ||
| 28 | + if (object === null) | ||
| 29 | + return all; | ||
| 30 | + Assign(all, TryGetAllProperties(GetPrototypeOf(object), target)); | ||
| 31 | + const keys = GetOwnPropertyNames(object); | ||
| 32 | + ForEach(keys, (key) => { | ||
| 33 | + const descriptor = GetOwnPropertyDescriptor(object, key); | ||
| 34 | + const getter = descriptor.get; | ||
| 35 | + if (getter && key !== '__proto__') { | ||
| 36 | + try { | ||
| 37 | + descriptor.value = Call(getter, target); | ||
| 38 | + } catch {} | ||
| 39 | + } | ||
| 40 | + if ('value' in descriptor && typeof descriptor.value !== 'function') { | ||
| 41 | + delete descriptor.get; | ||
| 42 | + delete descriptor.set; | ||
| 43 | + all[key] = descriptor; | ||
| 44 | + } | ||
| 45 | + }); | ||
| 46 | + return all; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + function GetConstructors(object) { | ||
| 50 | + const constructors = []; | ||
| 51 | + | ||
| 52 | + for (var current = object; | ||
| 53 | + current !== null; | ||
| 54 | + current = GetPrototypeOf(current)) { | ||
| 55 | + const desc = GetOwnPropertyDescriptor(current, 'constructor'); | ||
| 56 | + if (desc && desc.value) { | ||
| 57 | + DefineProperty(constructors, constructors.length, { | ||
| 58 | + value: desc.value, enumerable: true | ||
| 59 | + }); | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + return constructors; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + function GetName(object) { | ||
| 67 | + const desc = GetOwnPropertyDescriptor(object, 'name'); | ||
| 68 | + return desc && desc.value; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + let util; | ||
| 72 | + function lazyUtil() { | ||
| 73 | + if (!util) | ||
| 74 | + util = require('util'); | ||
| 75 | + return util; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + function serializeError(error) { | ||
| 79 | + try { | ||
| 80 | + if (typeof error === 'object' && | ||
| 81 | + ObjectPrototypeToString(error) === '[object Error]') { | ||
| 82 | + const constructors = GetConstructors(error); | ||
| 83 | + for (var i = constructors.length - 1; i >= 0; i--) { | ||
| 84 | + const name = GetName(constructors[i]); | ||
| 85 | + if (errorConstructorNames.has(name)) { | ||
| 86 | + try { error.stack; } catch {} | ||
| 87 | + const serialized = serialize({ | ||
| 88 | + constructor: name, | ||
| 89 | + properties: TryGetAllProperties(error) | ||
| 90 | + }); | ||
| 91 | + return Buffer.concat([Buffer.from([kSerializedError]), serialized]); | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + } catch {} | ||
| 96 | + try { | ||
| 97 | + const serialized = serialize(error); | ||
| 98 | + return Buffer.concat([Buffer.from([kSerializedObject]), serialized]); | ||
| 99 | + } catch {} | ||
| 100 | + return Buffer.concat([Buffer.from([kInspectedError]), | ||
| 101 | + Buffer.from(lazyUtil().inspect(error), 'utf8')]); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + function deserializeError(error) { | ||
| 105 | + switch (error[0]) { | ||
| 106 | + case kSerializedError: | ||
| 107 | + const { constructor, properties } = deserialize(error.subarray(1)); | ||
| 108 | + const ctor = errors[constructor]; | ||
| 109 | + return Object.create(ctor.prototype, properties); | ||
| 110 | + case kSerializedObject: | ||
| 111 | + return deserialize(error.subarray(1)); | ||
| 112 | + case kInspectedError: | ||
| 113 | + const buf = Buffer.from(error.buffer, | ||
| 114 | + error.byteOffset + 1, | ||
| 115 | + error.byteLength - 1); | ||
| 116 | + return buf.toString('utf8'); | ||
| 117 | + } | ||
| 118 | + require('assert').fail('This should not happen'); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + module.exports = { serializeError, deserializeError }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,5 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | - const Buffer = require('buffer').Buffer; | ||
| 4 | 3 | const EventEmitter = require('events'); | |
| 5 | 4 | const assert = require('assert'); | |
| 6 | 5 | const path = require('path'); | |
@@ -17,6 +16,7 @@ const { internalBinding } = require('internal/bootstrap/loaders'); | |||
| 17 | 16 | const { MessagePort, MessageChannel } = internalBinding('messaging'); | |
| 18 | 17 | const { handle_onclose } = internalBinding('symbols'); | |
| 19 | 18 | const { clearAsyncIdStack } = require('internal/async_hooks'); | |
| 19 | + const { serializeError, deserializeError } = require('internal/error-serdes'); | ||
| 20 | 20 | ||
| 21 | 21 | util.inherits(MessagePort, EventEmitter); | |
| 22 | 22 | ||
@@ -453,17 +453,6 @@ function setupChild(evalScript) { | |||
| 453 | 453 | } | |
| 454 | 454 | } | |
| 455 | 455 | ||
| 456 | - // TODO(addaleax): These can be improved a lot. | ||
| 457 | - function serializeError(error) { | ||
| 458 | - return Buffer.from(util.inspect(error), 'utf8'); | ||
| 459 | - } | ||
| 460 | - | ||
| 461 | - function deserializeError(error) { | ||
| 462 | - return Buffer.from(error.buffer, | ||
| 463 | - error.byteOffset, | ||
| 464 | - error.byteLength).toString('utf8'); | ||
| 465 | - } | ||
| 466 | - | ||
| 467 | 456 | function pipeWithoutWarning(source, dest) { | |
| 468 | 457 | const sourceMaxListeners = source._maxListeners; | |
| 469 | 458 | const destMaxListeners = dest._maxListeners; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -102,6 +102,7 @@ | |||
| 102 | 102 | 'lib/internal/constants.js', | |
| 103 | 103 | 'lib/internal/encoding.js', | |
| 104 | 104 | 'lib/internal/errors.js', | |
| 105 | + 'lib/internal/error-serdes.js', | ||
| 105 | 106 | 'lib/internal/fixed_queue.js', | |
| 106 | 107 | 'lib/internal/freelist.js', | |
| 107 | 108 | 'lib/internal/fs/promises.js', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,46 @@ | |||
| 1 | + // Flags: --expose-internals | ||
| 2 | + 'use strict'; | ||
| 3 | + require('../common'); | ||
| 4 | + const assert = require('assert'); | ||
| 5 | + const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes; | ||
| 6 | + const { serializeError, deserializeError } = require('internal/error-serdes'); | ||
| 7 | + | ||
| 8 | + function cycle(err) { | ||
| 9 | + return deserializeError(serializeError(err)); | ||
| 10 | + } | ||
| 11 | + | ||
| 12 | + assert.strictEqual(cycle(0), 0); | ||
| 13 | + assert.strictEqual(cycle(-1), -1); | ||
| 14 | + assert.strictEqual(cycle(1.4), 1.4); | ||
| 15 | + assert.strictEqual(cycle(null), null); | ||
| 16 | + assert.strictEqual(cycle(undefined), undefined); | ||
| 17 | + assert.strictEqual(cycle('foo'), 'foo'); | ||
| 18 | + | ||
| 19 | + { | ||
| 20 | + const err = cycle(new Error('foo')); | ||
| 21 | + assert(err instanceof Error); | ||
| 22 | + assert.strictEqual(err.name, 'Error'); | ||
| 23 | + assert.strictEqual(err.message, 'foo'); | ||
| 24 | + assert(/^Error: foo\n/.test(err.stack)); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + assert.strictEqual(cycle(new RangeError('foo')).name, 'RangeError'); | ||
| 28 | + assert.strictEqual(cycle(new TypeError('foo')).name, 'TypeError'); | ||
| 29 | + assert.strictEqual(cycle(new ReferenceError('foo')).name, 'ReferenceError'); | ||
| 30 | + assert.strictEqual(cycle(new URIError('foo')).name, 'URIError'); | ||
| 31 | + assert.strictEqual(cycle(new EvalError('foo')).name, 'EvalError'); | ||
| 32 | + assert.strictEqual(cycle(new SyntaxError('foo')).name, 'SyntaxError'); | ||
| 33 | + | ||
| 34 | + class SubError extends Error {} | ||
| 35 | + | ||
| 36 | + assert.strictEqual(cycle(new SubError('foo')).name, 'Error'); | ||
| 37 | + | ||
| 38 | + assert.deepStrictEqual(cycle({ message: 'foo' }), { message: 'foo' }); | ||
| 39 | + assert.strictEqual(cycle(Function), '[Function: Function]'); | ||
| 40 | + | ||
| 41 | + { | ||
| 42 | + const err = new ERR_INVALID_ARG_TYPE('object', 'Object', 42); | ||
| 43 | + assert(/^TypeError \[ERR_INVALID_ARG_TYPE\]:/.test(err)); | ||
| 44 | + assert.strictEqual(err.name, 'TypeError [ERR_INVALID_ARG_TYPE]'); | ||
| 45 | + assert.strictEqual(err.code, 'ERR_INVALID_ARG_TYPE'); | ||
| 46 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,8 +10,7 @@ if (!process.env.HAS_STARTED_WORKER) { | |||
| 10 | 10 | const w = new Worker(__filename); | |
| 11 | 11 | w.on('message', common.mustNotCall()); | |
| 12 | 12 | w.on('error', common.mustCall((err) => { | |
| 13 | - // TODO(addaleax): be more specific here | ||
| 14 | - assert(/foo/.test(err)); | ||
| 13 | + assert(/^Error: foo$/.test(err)); | ||
| 15 | 14 | })); | |
| 16 | 15 | } else { | |
| 17 | 16 | setImmediate(() => { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,8 +10,7 @@ if (!process.env.HAS_STARTED_WORKER) { | |||
| 10 | 10 | const w = new Worker(__filename); | |
| 11 | 11 | w.on('message', common.mustNotCall()); | |
| 12 | 12 | w.on('error', common.mustCall((err) => { | |
| 13 | - // TODO(addaleax): be more specific here | ||
| 14 | - assert(/foo/.test(err)); | ||
| 13 | + assert(/^Error: foo$/.test(err)); | ||
| 15 | 14 | })); | |
| 16 | 15 | } else { | |
| 17 | 16 | throw new Error('foo'); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments