From 25d42634f924d167cabd11d3a7726bc6c8f27fad Mon Sep 17 00:00:00 2001 From: Bharat Middha <5100938+bmiddha@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:23:49 -0700 Subject: [PATCH] refactor(rushell): expose parse error cause Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14 --- .../parse-error-cause_2026-08-17-20-14.json | 10 ++++++ libraries/rushell/src/ParseError.ts | 7 ++-- libraries/rushell/src/test/ParseError.test.ts | 35 +++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 common/changes/@microsoft/rushell/parse-error-cause_2026-08-17-20-14.json create mode 100644 libraries/rushell/src/test/ParseError.test.ts diff --git a/common/changes/@microsoft/rushell/parse-error-cause_2026-08-17-20-14.json b/common/changes/@microsoft/rushell/parse-error-cause_2026-08-17-20-14.json new file mode 100644 index 00000000000..ccdbc634d20 --- /dev/null +++ b/common/changes/@microsoft/rushell/parse-error-cause_2026-08-17-20-14.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rushell", + "comment": "Expose a ParseError's underlying error through the standard Error.cause property while retaining innerError as an alias.", + "type": "patch" + } + ], + "packageName": "@microsoft/rushell" +} diff --git a/libraries/rushell/src/ParseError.ts b/libraries/rushell/src/ParseError.ts index 6819956a9ea..5062ee1bd13 100644 --- a/libraries/rushell/src/ParseError.ts +++ b/libraries/rushell/src/ParseError.ts @@ -19,12 +19,15 @@ export class ParseError extends Error { public readonly unformattedMessage: string; /** - * The underlying error, if this error is resulted from an earlier error. + * The underlying error, if this error resulted from an earlier error. + * + * @remarks + * This property is a backwards-compatible alias for {@link Error.cause}. */ public readonly innerError: Error | undefined; public constructor(message: string, range: TextRange, innerError?: Error) { - super(_formatMessage(message, range)); + super(_formatMessage(message, range), innerError === undefined ? undefined : { cause: innerError }); // Boilerplate for extending a system class // diff --git a/libraries/rushell/src/test/ParseError.test.ts b/libraries/rushell/src/test/ParseError.test.ts new file mode 100644 index 00000000000..e9d8329d478 --- /dev/null +++ b/libraries/rushell/src/test/ParseError.test.ts @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import { ParseError } from '../ParseError'; +import { TextRange } from '../TextRange'; + +test('omits cause when no inner error is supplied', () => { + const error: ParseError = new ParseError('Parse failed', TextRange.empty); + + expect(error.message).toBe('Parse failed'); + expect(error.name).toBe('Error'); + expect(error.stack).toContain('Error: Parse failed'); + expect(Object.hasOwn(error, 'cause')).toBe(false); + expect(error.cause).toBeUndefined(); + expect(Object.getOwnPropertyDescriptor(error, 'innerError')).toEqual({ + configurable: true, + enumerable: true, + value: undefined, + writable: true + }); +}); + +test('exposes the inner error as the standard cause and legacy alias', () => { + const innerError: Error = new Error('Inner failure'); + const error: ParseError = new ParseError('Parse failed', TextRange.empty, innerError); + + expect(error.cause).toBe(innerError); + expect(error.innerError).toBe(innerError); + expect(Object.getOwnPropertyDescriptor(error, 'cause')).toEqual({ + configurable: true, + enumerable: false, + value: innerError, + writable: true + }); +});