Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/Core/Processor/Read.luau
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,25 @@ function ReadProcessor:onAdd(instance: Instance, __parentId: Types.Ref?): Types.
properties[property] = encodedValue
end
end

for _, property in Dom.getRefProperties(instance.ClassName) do
local readSuccess, instanceValue = Dom.readProperty(instance, property)

if not readSuccess then
local err = Error.new(Error.ReadFailed, property, instance, instanceValue.kind)
Log.warn(err)

continue
end

local encodeSuccess, encodedValue = Dom.EncodedValue.encode(instanceValue, "Ref", self.tree)

if not encodeSuccess or encodedValue.Ref == nil then
continue
end

properties[property] = encodedValue
end
end

for _, child in instance:GetChildren() do
Expand Down Expand Up @@ -226,6 +245,25 @@ function ReadProcessor:onChange(instance: Instance, property: string?): Types.Up
end
end

for _, property in Dom.getRefProperties(instance.ClassName) do
local readSuccess, instanceValue = Dom.readProperty(instance, property)

if not readSuccess then
local err = Error.new(Error.ReadFailed, property, instance, instanceValue.kind)
Log.warn(err)

continue
end

local encodeSuccess, encodedValue = Dom.EncodedValue.encode(instanceValue, "Ref", self.tree)

if not encodeSuccess or encodedValue.Ref == nil then
continue
end

properties[property] = encodedValue
end

return Snapshot.newUpdated(id):withProperties(properties)
end

Expand Down
30 changes: 27 additions & 3 deletions src/Core/Processor/Write.luau
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ function WriteProcessor:applyAddition(
instance.Name = snapshot.name

for property, value in snapshot.properties do
local decodeSuccess, decodedValue = Dom.EncodedValue.decode(value)
local decodeSuccess, decodedValue = Dom.EncodedValue.decode(value, self.tree)

if not decodeSuccess then
local err = Error.new(Error.DecodeFailed, property, value)
Expand Down Expand Up @@ -318,7 +318,7 @@ function WriteProcessor:applyUpdate(snapshot: Types.UpdatedSnapshot, initial: bo
if snapshot.properties then
if initial then
for property, value in snapshot.properties do
local decodeSuccess, decodedValue = Dom.EncodedValue.decode(value)
local decodeSuccess, decodedValue = Dom.EncodedValue.decode(value, self.tree)

if not decodeSuccess then
local err = Error.new(Error.DecodeFailed, property, value)
Expand All @@ -339,7 +339,7 @@ function WriteProcessor:applyUpdate(snapshot: Types.UpdatedSnapshot, initial: bo
local value = snapshot.properties[property]

if value then
local decodeSuccess, snapshotValue = Dom.EncodedValue.decode(value)
local decodeSuccess, snapshotValue = Dom.EncodedValue.decode(value, self.tree)

if not decodeSuccess then
local err = Error.new(Error.DecodeFailed, property, value)
Expand All @@ -364,6 +364,30 @@ function WriteProcessor:applyUpdate(snapshot: Types.UpdatedSnapshot, initial: bo
end
end
end

for _, property in Dom.getRefProperties(instance.ClassName) do
local value = snapshot.properties[property]

if value == nil then
continue
end

local decodeSuccess, snapshotValue = Dom.EncodedValue.decode(value, self.tree)

if not decodeSuccess then
local err = Error.new(Error.DecodeFailed, property, value)
Log.warn(err)

continue
end

local writeSuccess, reason = Dom.writeProperty(instance, property, snapshotValue)

if not writeSuccess then
local err = Error.new(Error.WriteFailed, property, instance, reason.kind)
Log.warn(err)
end
end
end
end

Expand Down
44 changes: 32 additions & 12 deletions src/Lib/Dom/EncodedValue.luau
Original file line number Diff line number Diff line change
Expand Up @@ -437,12 +437,24 @@ types = {
},

Ref = {
fromPod = function(_)
error("Ref cannot be decoded on its own")
fromPod = function(pod, tree)
if tree == nil then
return nil
end

return tree:getInstance(pod)
end,

toPod = function(_)
error("Ref can not be encoded on its own")
toPod = function(roblox, tree)
if roblox == nil then
return buffer.create(16) -- represents Ref::none()
end

if tree == nil then
return nil
end

return tree:getId(roblox)
end,
},

Expand Down Expand Up @@ -470,12 +482,20 @@ types = {
},

SharedString = {
fromPod = function(_pod)
error("SharedString is not supported")
fromPod = function(pod)
if typeof(pod) == "buffer" then
return buffer.tostring(pod)
end

return pod
end,

toPod = function(_roblox)
error("SharedString is not supported")
toPod = function(roblox)
if typeof(roblox) == "string" then
return buffer.fromstring(roblox)
end

return roblox
end,
},

Expand Down Expand Up @@ -568,7 +588,7 @@ types.OptionalCFrame = {
end,
}

function EncodedValue.decode(encodedValue)
function EncodedValue.decode(encodedValue, tree)
local ty, value = next(encodedValue)

if ty == nil then
Expand All @@ -581,10 +601,10 @@ function EncodedValue.decode(encodedValue)
return false, "Couldn't decode value " .. tostring(ty)
end

return true, typeImpl.fromPod(value)
return true, typeImpl.fromPod(value, tree)
end

function EncodedValue.encode(rbxValue, propertyType)
function EncodedValue.encode(rbxValue, propertyType, tree)
assert(propertyType ~= nil, "Property type descriptor is required")

local typeImpl = types[propertyType]
Expand All @@ -593,7 +613,7 @@ function EncodedValue.encode(rbxValue, propertyType)
end

return true, {
[propertyType] = typeImpl.toPod(rbxValue),
[propertyType] = typeImpl.toPod(rbxValue, tree),
}
end

Expand Down
36 changes: 36 additions & 0 deletions src/Lib/Dom/init.luau
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,41 @@ local function getDefaultProperties(className)
return properties
end

local function getRefProperties(className)
local properties = {}
local seen = {}

local currentClassName = className

while currentClassName ~= nil do
local currentClass = database.Classes[currentClassName]

if currentClass == nil then
break
end

for property, propertyData in pairs(currentClass.Properties) do
if seen[property] then
continue
end

seen[property] = true

if
propertyData.Kind.Canonical ~= nil
and propertyData.Scriptability == "ReadWrite"
and propertyData.DataType.Value == "Ref"
then
table.insert(properties, property)
end
end

currentClassName = currentClass.Superclass
end

return properties
end

local function isCreatable(className)
local class = database.Classes[className]

Expand Down Expand Up @@ -100,6 +135,7 @@ return {
writeProperty = writeProperty,
findCanonicalPropertyDescriptor = findCanonicalPropertyDescriptor,
getDefaultProperties = getDefaultProperties,
getRefProperties = getRefProperties,
Error = Error,
EncodedValue = require(script.EncodedValue),
}