Skip to content

Updates#9

Merged
gilbarbara merged 3 commits into
mainfrom
updates
Feb 4, 2026
Merged

Updates#9
gilbarbara merged 3 commits into
mainfrom
updates

Conversation

@gilbarbara
Copy link
Copy Markdown
Owner

This pull request improves the deep equality comparison logic in the codebase by refactoring the main comparison function, adding special handling for Error, WeakMap, and WeakSet objects, and introducing new tests to verify these behaviors. The changes enhance correctness and maintainability, especially for edge cases involving error objects and weak collections.

Equality comparison improvements

  • Refactored the internal deep equality logic by splitting object comparison into a dedicated compareObjects function and moving plain object key/value checks to a new equalPlainObject helper. This makes the code clearer and easier to maintain. [1] [2] [3]
  • Added special handling for WeakMap and WeakSet instances so that they are only considered equal if they are the same reference; otherwise, they are not comparable and always return false.
  • Added a new equalError helper to compare Error objects by their name, message, and (recursively) their cause property, improving correctness for error comparisons. [1] [2]

Testing enhancements

  • Added comprehensive tests for error object equality, including cases with different messages, types, causes, and deep causes, ensuring robust coverage for error comparison logic.
  • Added new tests for WeakMap and WeakSet comparison behavior, verifying that only identical references are considered equal and that distinct instances are not comparable.

CI workflow update

  • Added a build step to the CI workflow (.github/workflows/ci.yml) before publishing the package, ensuring that the code is properly built prior to release.

Copilot AI review requested due to automatic review settings February 4, 2026 02:08
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Feb 4, 2026

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the deep equality comparison logic to improve maintainability and adds specialized handling for Error objects and WeakMap/WeakSet collections. The refactoring extracts object comparison logic into separate focused functions while adding support for comparing Error objects by their name, message, and cause properties.

Changes:

  • Refactored object comparison by extracting compareObjects and equalPlainObject helper functions, improving code organization and readability
  • Added equalError function to compare Error objects by name, message, and cause (recursively)
  • Added special handling for WeakMap and WeakSet to return false for different instances (only same reference is equal)
  • Updated TypeScript target to ES2022 to support Error.cause property
  • Added build step to CI workflow before publishing

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/index.ts Refactored comparison logic by extracting compareObjects and equalPlainObject functions; added equalError for Error comparison; added WeakMap/WeakSet handling
test/objects.spec.ts Added comprehensive test cases for Error object equality comparison covering same/different messages, types, causes, and deep causes
test/weakmap-weakset.spec.ts Added new test file verifying WeakMap and WeakSet comparison behavior (same reference vs different instances)
tsconfig.json Updated target from ES2020 to ES2022 to support Error.cause property
.github/workflows/ci.yml Added build step before npm publish to ensure code is built before release

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/index.ts
if (left.toString !== Object.prototype.toString) {
return left.toString() === right.toString();
}
if (left instanceof WeakMap || left instanceof WeakSet) {
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WeakMap/WeakSet check is inconsistent with the pattern used for other types in this function. All other instanceof checks (Map, Set, Error, etc.) verify both left and right parameters, but this check only verifies left. While technically correct due to the constructor equality check on line 16, this inconsistency makes the code harder to understand and maintain. Consider changing to if ((left instanceof WeakMap && right instanceof WeakMap) || (left instanceof WeakSet && right instanceof WeakSet)) to match the established pattern.

Suggested change
if (left instanceof WeakMap || left instanceof WeakSet) {
if ((left instanceof WeakMap && right instanceof WeakMap) || (left instanceof WeakSet && right instanceof WeakSet)) {

Copilot uses AI. Check for mistakes.
Comment thread test/objects.spec.ts
Comment on lines +5 to +44
it.each([
{
description: 'errors with same message are equal',
value1: new Error('a'),
value2: new Error('a'),
expected: true,
},
{
description: 'errors with different message are not equal',
value1: new Error('a'),
value2: new Error('b'),
expected: false,
},
{
description: 'TypeError and Error with same message are not equal',
value1: new TypeError('a'),
value2: new Error('a'),
expected: false,
},
{
description: 'errors with same cause are equal',
value1: new Error('a', { cause: 'x' }),
value2: new Error('a', { cause: 'x' }),
expected: true,
},
{
description: 'errors with different cause are not equal',
value1: new Error('a', { cause: 'x' }),
value2: new Error('a', { cause: 'y' }),
expected: false,
},
{
description: 'errors with deep cause are equal',
value1: new Error('a', { cause: { n: 1 } }),
value2: new Error('a', { cause: { n: 1 } }),
expected: true,
},
])('$description', ({ expected, value1, value2 }) => {
expect(equal(value1, value2)).toBe(expected);
});
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error comparison tests are missing a test case for when one error has a cause property and the other doesn't (e.g., new Error('a', { cause: 'x' }) vs new Error('a')). Adding this test case would improve coverage and verify that the comparison correctly handles this edge case.

Copilot uses AI. Check for mistakes.
Comment thread src/index.ts
Comment on lines +119 to +128
/**
* Check if errors are equal.
*/
function equalError(left: Error, right: Error, seen: Seen): boolean {
return (
left.message === right.message &&
left.name === right.name &&
compareValues(left.cause, right.cause, seen)
);
}
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The equalError function only compares the message, name, and cause properties of Error objects, ignoring any custom properties that may have been added to the Error instances. While this appears to be an intentional design choice to treat Errors as value objects, it creates inconsistent behavior compared to how plain objects are handled (where all properties are compared). Consider documenting this behavior in the function's JSDoc comment to make the design decision explicit.

Copilot uses AI. Check for mistakes.
@gilbarbara gilbarbara merged commit a9a2dcd into main Feb 4, 2026
11 checks passed
@gilbarbara gilbarbara deleted the updates branch February 4, 2026 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants