diff --git a/plugin/src/Reconciler/trueEquals.lua b/plugin/src/Reconciler/trueEquals.lua index a2fd5dc1..8588112e 100644 --- a/plugin/src/Reconciler/trueEquals.lua +++ b/plugin/src/Reconciler/trueEquals.lua @@ -13,6 +13,12 @@ local NULL_REF: string = "00000000000000000000000000000000" local EPSILON: number = 0.0001 local function fuzzyEq(a: number, b: number): boolean + if a == b then + return true + end + if a ~= a then + return b ~= b + end local diff = math.abs(a - b) local maxVal = math.max(math.abs(a), math.abs(b), 1) return diff < EPSILON or diff < maxVal * EPSILON @@ -90,9 +96,6 @@ local function trueEquals(a: any, b: any): boolean end if t == "number" then - if a ~= a then - return b ~= b - end return fuzzyEq(a, b) end if t == "Color3" then diff --git a/plugin/src/Reconciler/trueEquals.spec.lua b/plugin/src/Reconciler/trueEquals.spec.lua index 108c8fdb..7b1fc526 100644 --- a/plugin/src/Reconciler/trueEquals.spec.lua +++ b/plugin/src/Reconciler/trueEquals.spec.lua @@ -224,6 +224,14 @@ return function() it("large values within relative epsilon", function() expect(trueEquals(Vector3.new(1e6, 1e6, 1e6), Vector3.new(1e6 + 50, 1e6, 1e6))).to.equal(true) end) + + it("NaN component equal", function() + expect(trueEquals(Vector3.new(0 / 0, 1, 2), Vector3.new(0 / 0, 1, 2))).to.equal(true) + end) + + it("NaN vs finite component", function() + expect(trueEquals(Vector3.new(0 / 0, 1, 2), Vector3.new(0, 1, 2))).to.equal(false) + end) end) describe("Vector2", function() @@ -238,6 +246,22 @@ return function() it("Y differs by 1", function() expect(trueEquals(Vector2.new(1, 2), Vector2.new(1, 3))).to.equal(false) end) + + it("infinity components", function() + expect(trueEquals(Vector2.new(math.huge, math.huge), Vector2.new(math.huge, math.huge))).to.equal(true) + end) + + it("mixed infinity and finite", function() + expect(trueEquals(Vector2.new(math.huge, 0), Vector2.new(math.huge, 1))).to.equal(false) + end) + + it("NaN components", function() + expect(trueEquals(Vector2.new(0 / 0, 0 / 0), Vector2.new(0 / 0, 0 / 0))).to.equal(true) + end) + + it("NaN vs finite component", function() + expect(trueEquals(Vector2.new(0 / 0, 1), Vector2.new(1, 1))).to.equal(false) + end) end) describe("CFrame", function()