rojo/.cursor/plans/fix_infinity_comparison_71fd9057.plan.md
Joe 1ffed1212d Add prefetch cache for VFS to optimize file reads
- Introduced a `PrefetchCache` structure to store pre-read file contents and canonical paths, enhancing the speed of initial reads during snapshot building.
- Implemented parallel file reading using `rayon` and `walkdir` to populate the cache efficiently.
- Updated the `VfsInner` struct to include the prefetch cache and modified read methods to utilize it, reducing I/O operations.
- Added functions to set and clear the prefetch cache in the `Vfs` API, improving memory management during live operations.
- Enhanced tests to validate the functionality of the prefetch cache, ensuring correct behavior during file reads and canonicalization.

These changes aim to significantly improve the performance of the VFS by minimizing file access times during initial operations.
2026-02-19 02:04:15 -06:00

2.6 KiB

name overview todos isProject
Fix infinity comparison Make `fuzzyEq` self-contained for all IEEE 754 special values (infinity and NaN), eliminating phantom diffs on properties like `UISizeConstraint.MaxSize` and fixing NaN component comparison in compound types.
id content status
fix-lua-fuzzyeq Add exact-equality and NaN checks to `fuzzyEq` in trueEquals.lua completed
id content status
add-tests Add infinity and NaN test cases to trueEquals.spec.lua completed
false

Fix Infinity and NaN Comparison in fuzzyEq

Root Cause

Two bugs in fuzzyEq:

1. Infinity: fuzzyEq(inf, inf) returns false because inf - inf = NaN, and NaN < x is always false. Affects UISizeConstraint.MaxSize which defaults to Vector2(inf, inf).

2. NaN in compound types: NaN equality is handled in the trueEquals number branch (line 93), but fuzzyEq is called directly from vector2Eq, vector3Eq, cframeEq, etc. A Vector2/Vector3/CFrame with a NaN component silently returns false instead of true because fuzzyEq doesn't check for NaN.

Fix

Make fuzzyEq self-contained by adding exact-equality and NaN checks at the top:

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
end

Behavior:

  • inf == inf -> true (caught by a == b)
  • -inf == -inf -> true (caught by a == b)
  • inf == -inf -> false (falls through, inf - (-inf) = inf, fails comparison)
  • NaN == NaN -> true (a == b is false for NaN, then a ~= a catches it)
  • NaN == 5 -> false (a ~= a is true but b ~= b is false)

Remove the now-redundant NaN check in trueEquals line 93 (the number branch if a ~= a then return b ~= b end) since fuzzyEq handles it directly.

Files

1. plugin/src/Reconciler/trueEquals.lua (line 15)

Replace fuzzyEq with the version above.

2. plugin/src/Reconciler/trueEquals.spec.lua

Add test cases for:

  • trueEquals(math.huge, math.huge) -> true
  • trueEquals(-math.huge, -math.huge) -> true
  • trueEquals(math.huge, -math.huge) -> false
  • trueEquals(Vector2.new(math.huge, math.huge), Vector2.new(math.huge, math.huge)) -> true
  • trueEquals(Vector3.new(0/0, 1, 2), Vector3.new(0/0, 1, 2)) -> true (NaN component)
  • trueEquals(Vector2.new(0/0, 0/0), Vector2.new(0/0, 0/0)) -> true (NaN components)