From ad8931cb4968b2bd25b05dcd3d856ec32e4d7145 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Wed, 21 May 2025 16:49:08 -0700 Subject: [PATCH] fix(zone.js): classes that extend Error should retain cause property (#61599) ZoneAwareError previously did not copy the cause property over to the `this` object when an error extends the native error class. PR Close #61599 --- packages/zone.js/lib/common/error-rewrite.ts | 2 +- packages/zone.js/test/common/Error.spec.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/zone.js/lib/common/error-rewrite.ts b/packages/zone.js/lib/common/error-rewrite.ts index 3e248e95afb..47441e143c6 100644 --- a/packages/zone.js/lib/common/error-rewrite.ts +++ b/packages/zone.js/lib/common/error-rewrite.ts @@ -143,7 +143,7 @@ export function patchError(Zone: ZoneType): void { // We got called with a `new` operator AND we are subclass of ZoneAwareError // in that case we have to copy all of our properties to `this`. Object.keys(error) - .concat('stack', 'message') + .concat('stack', 'message', 'cause') .forEach((key) => { const value = (error as any)[key]; if (value !== undefined) { diff --git a/packages/zone.js/test/common/Error.spec.ts b/packages/zone.js/test/common/Error.spec.ts index 77ee79e0407..64d3982e33a 100644 --- a/packages/zone.js/test/common/Error.spec.ts +++ b/packages/zone.js/test/common/Error.spec.ts @@ -180,6 +180,21 @@ describe('ZoneAwareError', () => { expect(spy).toHaveBeenCalledWith('test'); }); + it('should copy cause on error that extends native', () => { + class WrappedError extends Error { + constructor(error: unknown) { + super( + 'wrapped', + // @ts-ignore + {cause: error}, + ); + } + } + const cause = new Error('original'); + const wrapped = new WrappedError(cause) as any; + expect(wrapped.cause).toBe(cause); + }); + it('should always have stack property even without throw', () => { // in IE, the stack will be undefined without throw // in ZoneAwareError, we will make stack always be