Skip to content

Commit 59455bd

Browse files
committed
Custom error cloning to fix node v21 issue
1 parent f98bfdf commit 59455bd

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

lib/clone.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ module.exports = internals.clone = function (obj, options = {}, _seen = null) {
8888
continue;
8989
}
9090

91+
if (baseProto === Types.error &&
92+
(key === 'message' || key === 'stack')) {
93+
94+
continue; // Already a part of the base object
95+
}
96+
9197
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
9298
if (descriptor) {
9399
if (descriptor.get ||
@@ -162,6 +168,14 @@ internals.base = function (obj, baseProto, options) {
162168

163169
return newObj;
164170
}
171+
else if (baseProto === Types.error) {
172+
const err = structuredClone(obj); // Needed to copy internal stack state
173+
if (proto !== baseProto) {
174+
Object.setPrototypeOf(err, proto); // Fix prototype
175+
}
176+
177+
return err;
178+
}
165179

166180
if (internals.needsProtoHack.has(baseProto)) {
167181
const newObj = new proto.constructor();

test/clone.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,34 @@ describe('clone()', () => {
680680
expect(b.get(nestedObj)).to.equal(a.get(nestedObj));
681681
});
682682

683+
it('clones Error', () => {
684+
685+
class CustomError extends Error {
686+
name = 'CustomError';
687+
}
688+
689+
const a = new CustomError('bad');
690+
a.test = Symbol('test');
691+
692+
const b = Hoek.clone(a);
693+
694+
expect(b).to.equal(a);
695+
expect(b).to.not.shallow.equal(a);
696+
expect(b).to.be.instanceOf(CustomError);
697+
expect(b.stack).to.equal(a.stack); // Explicitly validate the .stack getters
698+
});
699+
700+
it('cloned Error handles late stack update', () => {
701+
702+
const a = new Error('bad');
703+
const b = Hoek.clone(a);
704+
705+
a.stack = 'late update';
706+
707+
expect(b).to.equal(a);
708+
expect(b.stack).to.not.equal(a.stack);
709+
});
710+
683711
it('ignores symbols', () => {
684712

685713
const sym = Symbol();

0 commit comments

Comments
 (0)