rojo/plugin/src/Reconciler/hydrate.lua
Joe 354d4c8b21 Add yield intervals for diffing and hydrating processes
- Introduced `DIFF_YIELD_INTERVAL` and `HYDRATE_YIELD_INTERVAL` constants to manage execution pacing during the diffing and hydrating processes, respectively.
- Implemented logic to pause execution every specified interval to improve performance and prevent potential blocking in long-running operations.
- Enhanced the `diff` and `hydrate` functions to track and yield based on their respective counts, ensuring smoother operation during intensive tasks.

These changes aim to enhance the responsiveness of the system during heavy processing tasks by introducing controlled yielding mechanisms.
2026-02-19 01:49:13 -06:00

80 lines
2.2 KiB
Lua

--[[
Defines the process of "hydration" -- matching up a virtual DOM with
concrete instances and assigning them IDs.
Uses the change-count matching algorithm to handle duplicate-named
instances: groups by (Name, ClassName), then greedy-assigns pairs
by fewest total reconciler changes (recursive into subtrees).
]]
local Packages = script.Parent.Parent.Parent.Packages
local Log = require(Packages.Log)
local invariant = require(script.Parent.Parent.invariant)
local Matching = require(script.Parent.matching)
local HYDRATE_YIELD_INTERVAL = 1000
local function hydrate(instanceMap, virtualInstances, rootId, rootInstance, session)
if not session then
session = Matching.newSession()
end
if not session.hydrateCount then
session.hydrateCount = 0
end
session.hydrateCount += 1
if session.hydrateCount % HYDRATE_YIELD_INTERVAL == 0 then
task.wait()
end
local virtualInstance = virtualInstances[rootId]
if virtualInstance == nil then
invariant("Cannot hydrate an instance not present in virtualInstances\nID: {}", rootId)
end
instanceMap:insert(rootId, rootInstance)
local existingChildren = rootInstance:GetChildren()
local virtualChildIds = virtualInstance.Children
-- Filter out virtual children missing from virtualInstances
local validVirtualIds: { string } = {}
for _, childId in ipairs(virtualChildIds) do
if virtualInstances[childId] then
table.insert(validVirtualIds, childId)
else
Log.warn(
"Hydration: virtualInstances missing child ID {} (parent: {} '{}')",
childId,
rootId,
virtualInstance.Name
)
end
end
local result =
Matching.matchChildren(session, validVirtualIds, existingChildren, virtualInstances, rootId, rootInstance)
-- Recursively hydrate matched pairs
for _, pair in result.matched do
hydrate(instanceMap, virtualInstances, pair.virtualId, pair.studioInstance, session)
end
-- Log unmatched virtual children (no Studio counterpart found)
for _, virtualId in result.unmatchedVirtual do
local virtualChild = virtualInstances[virtualId]
if virtualChild then
Log.debug(
"Hydration: No match for virtual child '{}' ({}) under '{}' ({})",
virtualChild.Name,
virtualChild.ClassName,
virtualInstance.Name,
rootInstance:GetFullName()
)
end
end
end
return hydrate