diff --git a/src/jsc/bindings/BunObject.cpp b/src/jsc/bindings/BunObject.cpp index 04c1c4ca808b..675a490cc248 100644 --- a/src/jsc/bindings/BunObject.cpp +++ b/src/jsc/bindings/BunObject.cpp @@ -699,18 +699,11 @@ JSC_DEFINE_HOST_FUNCTION(functionBunDeepEquals, (JSGlobalObject * globalObject, JSC::JSValue arg1 = callFrame->uncheckedArgument(0); JSC::JSValue arg2 = callFrame->uncheckedArgument(1); JSC::JSValue strict = callFrame->argument(2); - JSC::JSValue skipPrototype = callFrame->argument(3); Vector, 16> stack; MarkedArgumentBuffer gcBuffer; if (strict.isBoolean() && strict.asBoolean()) { - if (skipPrototype.isBoolean() && skipPrototype.asBoolean()) { - bool isEqual = Bun__deepEquals(globalObject, arg1, arg2, gcBuffer, stack, scope, true); - RETURN_IF_EXCEPTION(scope, {}); - return JSValue::encode(jsBoolean(isEqual)); - } - bool isEqual = Bun__deepEquals(globalObject, arg1, arg2, gcBuffer, stack, scope, true); RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(jsBoolean(isEqual)); diff --git a/src/jsc/bindings/bindings.cpp b/src/jsc/bindings/bindings.cpp index 697570290da2..02448315d8a3 100644 --- a/src/jsc/bindings/bindings.cpp +++ b/src/jsc/bindings/bindings.cpp @@ -1925,10 +1925,6 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark return std::nullopt; } -// The other combinations are instantiated by their uses in this file. This one is -// only reached from `Bun.deepEquals(a, b, true, true)` in BunObject.cpp. -template bool Bun__deepEquals(JSC::JSGlobalObject*, JSValue, JSValue, MarkedArgumentBuffer&, Vector, 16>&, ThrowScope&, bool); - /** * @brief `Bun.deepMatch(a, b)` * diff --git a/test/js/bun/bun-object/deep-equals.test.ts b/test/js/bun/bun-object/deep-equals.test.ts index 5f57134f5b80..a423560e80c5 100644 --- a/test/js/bun/bun-object/deep-equals.test.ts +++ b/test/js/bun/bun-object/deep-equals.test.ts @@ -112,6 +112,28 @@ describe("Bun.deepEquals strict mode", () => { expect(Bun.deepEquals(new Foo(), { a: 1 }, true)).toBe(false); }); + // The switch that drops the constructor check (node's skipPrototype) is only + // reachable through util.isDeepStrictEqual and the node:assert Assert class; + // Bun.deepEquals has no fourth argument, so anything after `strict` is ignored. + it("ignores arguments after strict", () => { + const deepEquals = Bun.deepEquals as (a: unknown, b: unknown, ...rest: unknown[]) => boolean; + class Foo { + a = 1; + } + class Str extends String {} + for (const extra of [true, 1, "skipPrototype", {}]) { + expect(deepEquals(new Foo(), { a: 1 }, true, extra)).toBe(false); + expect(deepEquals({ a: 1 }, new Foo(), true, extra)).toBe(false); + expect(deepEquals({ x: new Foo() }, { x: { a: 1 } }, true, extra)).toBe(false); + expect(deepEquals(new String("a"), new Str("a"), true, extra)).toBe(false); + expect(deepEquals(new Str("a"), new String("a"), true, extra)).toBe(false); + + expect(deepEquals(new Foo(), new Foo(), true, extra)).toBe(true); + expect(deepEquals({ a: 1 }, { a: 1, b: undefined }, true, extra)).toBe(false); + expect(deepEquals(new Foo(), { a: 1 }, false, extra)).toBe(true); + } + }); + it("is symmetric", () => { const a = { entries: [1, 2] }; const b = { entries: [1, 2], extra: undefined };