From 1a0264f8c572d2fac33595598995f7274a648381 Mon Sep 17 00:00:00 2001 From: Niels Roesen Abildgaard Date: Wed, 8 Jun 2022 22:20:58 +0200 Subject: [PATCH 1/4] Add (failing) test for serialization of causes of errors --- test/err.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/err.test.js b/test/err.test.js index 956cb5b..87e795e 100644 --- a/test/err.test.js +++ b/test/err.test.js @@ -194,3 +194,21 @@ test('serializes aggregate errors', { skip: !global.AggregateError }, function ( t.match(serialized.aggregateErrors[1].stack, /^Error: bar/) t.match(serialized.stack, /err\.test\.js:/) }) + +test('serializes causes', function (t) { + t.plan(7) + + const foo = new Error('foo') + const bar = new Error('bar', { cause: foo }) + + const serialized = serializer(bar) + + t.equal(serialized.type, 'Error') + t.equal(serialized.message, 'bar: foo') // message serialization already walks cause-chain + t.match(serialized.stack, /err\.test\.js:/) + + t.ok(serialized.cause) + t.equal(serialized.cause.type, 'Error') + t.equal(serialized.cause.message, 'foo') + t.match(serialized.cause.stack, /err\.test\.js:/) +}) From 5a05c336e8e4c63609daa54de8246801ace114be Mon Sep 17 00:00:00 2001 From: Niels Roesen Abildgaard Date: Wed, 8 Jun 2022 22:24:15 +0200 Subject: [PATCH 2/4] Add cause serialization to error serializer The error serializer already handles the case where an error is not of type Error (or AggregateError) well, so there is no reason to add special handling for that. We can simply pass whatever is in `cause` into the serializer, and we should get a serialized result out. --- lib/err.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/err.js b/lib/err.js index ccd81c9..d92fce4 100644 --- a/lib/err.js +++ b/lib/err.js @@ -28,6 +28,11 @@ const pinoErrProto = Object.create({}, { writable: true, value: undefined }, + cause: { + enumerable: true, + writable: true, + value: undefined + }, raw: { enumerable: false, get: function () { @@ -60,6 +65,10 @@ function errSerializer (err) { _err.aggregateErrors = err.errors.map(err => errSerializer(err)) } + if (err.cause) { + _err.cause = errSerializer(err.cause) + } + for (const key in err) { if (_err[key] === undefined) { const val = err[key] From c9d6598d90e7871422ec69fc411528b44037d82c Mon Sep 17 00:00:00 2001 From: Niels Roesen Abildgaard Date: Fri, 10 Jun 2022 15:55:19 +0200 Subject: [PATCH 3/4] Add `cause` to errors in similar way to what is done in other errors --- test/err.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/err.test.js b/test/err.test.js index 87e795e..f57abd8 100644 --- a/test/err.test.js +++ b/test/err.test.js @@ -198,8 +198,8 @@ test('serializes aggregate errors', { skip: !global.AggregateError }, function ( test('serializes causes', function (t) { t.plan(7) - const foo = new Error('foo') - const bar = new Error('bar', { cause: foo }) + const bar = new Error('bar') + bar.cause = new Error('foo') const serialized = serializer(bar) From 78256b80451a0352e9f249e511ca499fa60113ce Mon Sep 17 00:00:00 2001 From: Niels Roesen Abildgaard Date: Fri, 10 Jun 2022 18:38:01 +0200 Subject: [PATCH 4/4] Expand cause serialization test to show recursion --- test/err.test.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/err.test.js b/test/err.test.js index f57abd8..f3f0d77 100644 --- a/test/err.test.js +++ b/test/err.test.js @@ -196,19 +196,25 @@ test('serializes aggregate errors', { skip: !global.AggregateError }, function ( }) test('serializes causes', function (t) { - t.plan(7) + t.plan(11) const bar = new Error('bar') bar.cause = new Error('foo') + bar.cause.cause = new Error('baz') const serialized = serializer(bar) t.equal(serialized.type, 'Error') - t.equal(serialized.message, 'bar: foo') // message serialization already walks cause-chain + t.equal(serialized.message, 'bar: foo: baz') // message serialization already walks cause-chain t.match(serialized.stack, /err\.test\.js:/) t.ok(serialized.cause) t.equal(serialized.cause.type, 'Error') - t.equal(serialized.cause.message, 'foo') + t.equal(serialized.cause.message, 'foo: baz') t.match(serialized.cause.stack, /err\.test\.js:/) + + t.ok(serialized.cause.cause) + t.equal(serialized.cause.cause.type, 'Error') + t.equal(serialized.cause.cause.message, 'baz') + t.match(serialized.cause.cause.stack, /err\.test\.js:/) })