diff --git a/src/jsc/bindings/bindings.cpp b/src/jsc/bindings/bindings.cpp index 97fbbf7b30fd..98400d1f419b 100644 --- a/src/jsc/bindings/bindings.cpp +++ b/src/jsc/bindings/bindings.cpp @@ -1297,6 +1297,17 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark return false; } + const PropertyName errors(vm.propertyNames->errors); + auto leftErrors = left->get(globalObject, errors); + RETURN_IF_EXCEPTION(scope, {}); + auto rightErrors = right->get(globalObject, errors); + RETURN_IF_EXCEPTION(scope, {}); + bool errorsEqual = Bun__deepEquals(globalObject, leftErrors, rightErrors, gcBuffer, stack, scope, true); + RETURN_IF_EXCEPTION(scope, {}); + if (!errorsEqual) { + return false; + } + // check arbitrary enumerable properties. `.stack` is not checked. left->materializeErrorInfoIfNeeded(vm); RETURN_IF_EXCEPTION(scope, {}); diff --git a/test/js/node/assert/deep-equal.test.ts b/test/js/node/assert/deep-equal.test.ts index 2948f9bc7655..7ebe601d12d5 100644 --- a/test/js/node/assert/deep-equal.test.ts +++ b/test/js/node/assert/deep-equal.test.ts @@ -395,6 +395,41 @@ const cases: Case[] = [ strict: false, loose: false, }, + { + name: "AggregateError with deep-equal errors", + a: () => new AggregateError([new TypeError("x")], "agg"), + b: () => new AggregateError([new TypeError("x")], "agg"), + strict: true, + loose: true, + }, + { + name: "AggregateError with different inner errors", + a: () => new AggregateError([new Error("x")], "agg"), + b: () => new AggregateError([new Error("y")], "agg"), + strict: false, + loose: false, + }, + { + name: "AggregateError with different error counts", + a: () => new AggregateError([new Error("x")], "agg"), + b: () => new AggregateError([new Error("x"), new Error("x")], "agg"), + strict: false, + loose: false, + }, + { + name: "AggregateError vs plain Error with same message", + a: () => new AggregateError([], "x"), + b: () => new Error("x"), + strict: false, + loose: false, + }, + { + name: "Error with non-enumerable own errors vs Error without", + a: () => Object.defineProperty(new Error("x"), "errors", { value: [1], enumerable: false, configurable: true }), + b: () => new Error("x"), + strict: false, + loose: false, + }, // Map and Set. {