diff --git a/packages/charm-sync/src/__tests__/server.spec.luau b/packages/charm-sync/src/__tests__/server.spec.luau index 800fa88..a74dd33 100644 --- a/packages/charm-sync/src/__tests__/server.spec.luau +++ b/packages/charm-sync/src/__tests__/server.spec.luau @@ -71,7 +71,7 @@ end) test("should replicate partial state patches (reactive)", function() local client = {} - local a: { [string]: number? } = Charm.reactive({ x = 0, y = 0, z = 0 }) + local a = Charm.reactive({ x = { y = 0 }, z = 0 :: number? }) local target, payloads server.addSignalsToClient(client, { a = a }) @@ -82,18 +82,24 @@ test("should replicate partial state patches (reactive)", function() server.flush() assert(target == client, "Expected target to be the client") assert(payloads[1].type == "init", "Expected first payload to be init") - assert(payloads[1].data.a.x == a.x, "Expected init payload to contain value 'a.x'") - assert(payloads[1].data.a.y == a.y, "Expected init payload to contain value 'a.y'") + assert(payloads[1].data.a.x ~= nil, "Expected init payload to contain value 'a.x'") + assert(payloads[1].data.a.x.y == a.x.y, "Expected init payload to contain value 'a.x.y'") assert(payloads[1].data.a.z == a.z, "Expected init payload to contain value 'a.z'") - a.x = 1 + a.x.y = 1 a.z = nil server.flush() assert(target == client, "Expected target to be the client") assert(payloads[1].type == "patch", "Expected first payload to be patch") - assert(payloads[1].data.a.x == 1, "Expected patch payload to contain value 'a.x'") - assert(payloads[1].data.a.y == nil, "Expected patch payload to not contain value 'a.y'") + assert(payloads[1].data.a.x.y == 1, "Expected patch payload to contain value 'a.x'") assert(patch.isNone(payloads[1].data.a.z), "Expected patch payload to contain value 'a.z' as None") + + a.z = 1 + server.flush() + assert(target == client, "Expected target to be the client") + assert(payloads[1].type == "patch", "Expected first payload to be patch") + assert(payloads[1].data.a.z == 1, "Expected patch payload to contain value 'a.z'") + assert(payloads[1].data.a.x == nil, "Expected patch payload to not contain value 'a.x'") end) test("should init new clients", function() diff --git a/packages/charm-sync/src/server.luau b/packages/charm-sync/src/server.luau index 9624d1c..3605521 100644 --- a/packages/charm-sync/src/server.luau +++ b/packages/charm-sync/src/server.luau @@ -88,7 +88,10 @@ local function trackReactive(key: string, proxy: ReactiveProxy) trackedState.dispose = Charm.effect(function() api.track() - if not config.preserveHistory or firstRun then + if not config.preserveHistory then + return + end + if firstRun then firstRun = false else local oldSnapshot = snapshot diff --git a/packages/charm/src/init.luau b/packages/charm/src/init.luau index 7d42368..e31702f 100644 --- a/packages/charm/src/init.luau +++ b/packages/charm/src/init.luau @@ -933,16 +933,14 @@ end ]] local function toRaw(value: T): T if type(value) == "table" and getmetatable(value) ~= nil then - local proxy: ReactiveProxy = value - local api = getmetatable(proxy) - if api.value == proxy.__target then - -- Track the root proxy since nested proxies are already tracked + local value: ReactiveProxy = value + local api = getmetatable(value) + if api then api.track() + return value.__target :: any end - return proxy.__target :: any - else - return value end + return value end local reactiveSystem = system.createReactiveSystem({