Plugin: Port reconciler to use rbx_dom_lua

This commit is contained in:
Lucien Greathouse
2019-05-14 14:22:55 -07:00
parent efc569f6ed
commit 28ea625b01
3 changed files with 39 additions and 58 deletions

View File

@@ -6,6 +6,12 @@ local setCanonicalProperty = require(script.Parent.setCanonicalProperty)
local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue)
local Types = require(script.Parent.Types) local Types = require(script.Parent.Types)
local function setParent(instance, newParent)
pcall(function()
instance.Parent = newParent
end)
end
local Reconciler = {} local Reconciler = {}
Reconciler.__index = Reconciler Reconciler.__index = Reconciler
@@ -117,7 +123,7 @@ function Reconciler:reconcile(virtualInstancesById, id, instance)
-- Some instances, like services, don't like having their Parent -- Some instances, like services, don't like having their Parent
-- property poked, even if we're setting it to the same value. -- property poked, even if we're setting it to the same value.
setCanonicalProperty(instance, "Parent", parent) setParent(instance, parent)
end end
return instance return instance
@@ -154,7 +160,7 @@ function Reconciler:__reify(virtualInstancesById, id, parent)
self:__reify(virtualInstancesById, childId, instance) self:__reify(virtualInstancesById, childId, instance)
end end
setCanonicalProperty(instance, "Parent", parent) setParent(instance, parent)
self.instanceMap:insert(id, instance) self.instanceMap:insert(id, instance)
return instance return instance

View File

@@ -1,38 +1,33 @@
local primitiveTypes = { local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom)
Bool = true,
Enum = true,
Float32 = true,
Float64 = true,
Int32 = true,
Int64 = true,
String = true,
}
local directConstructors = {
CFrame = CFrame.new,
Color3 = Color3.new,
Color3uint8 = Color3.fromRGB,
Rect = Rect.new,
UDim = UDim.new,
UDim2 = UDim2.new,
Vector2 = Vector2.new,
Vector2int16 = Vector2int16.new,
Vector3 = Vector3.new,
Vector3int16 = Vector3int16.new,
}
local function rojoValueToRobloxValue(value) local function rojoValueToRobloxValue(value)
if primitiveTypes[value.Type] then -- TODO: Manually decode this value by looking up its GUID The Rojo server
return value.Value -- doesn't give us valid ref values yet, so this isn't important yet.
if value.Type == "Ref" then
return nil
end end
local constructor = directConstructors[value.Type] -- TODO: Remove this once rbx_dom_weak and rbx_dom_lua agree on encoding
if constructor ~= nil then if value.Type == "BinaryString" then
return constructor(unpack(value.Value)) local actualValue = ""
for i = 1, #value.Value do
actualValue = actualValue .. string.char(i)
end
value = {
Type = "BinaryString",
Value = actualValue,
}
end end
local errorMessage = ("The Rojo plugin doesn't know how to handle values of type %q yet!"):format(tostring(value.Type)) local success, decodedValue = RbxDom.EncodedValue.decode(value)
error(errorMessage)
if not success then
error(decodedValue, 2)
end
return decodedValue
end end
return rojoValueToRobloxValue return rojoValueToRobloxValue

View File

@@ -1,33 +1,17 @@
local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom)
local Logging = require(script.Parent.Logging) local Logging = require(script.Parent.Logging)
--[[ --[[
Attempts to set a property on the given instance. Attempts to set a property on the given instance.
This method deals in terms of what Rojo calls 'canonical properties', which
don't necessarily exist either in serialization or in Lua-reflected APIs,
but may be present in the API dump.
Ideally, canonical properties map 1:1 with properties we can assign, but in
some cases like LocalizationTable contents and CollectionService tags, we
have to read/write properties a little differently.
]] ]]
local function setCanonicalProperty(instance, key, value) local function setCanonicalProperty(instance, key, value)
-- The 'Contents' property of LocalizationTable isn't directly exposed, but if not RbxDom.CanonicalProperty.isScriptable(instance.ClassName, key) then
-- has corresponding (deprecated) getters and setters. return false
if instance.ClassName == "LocalizationTable" and key == "Contents" then
instance:SetContents(value)
return
end
-- Temporary workaround for fixing issue #141 in this specific case.
if instance.ClassName == "Lighting" and key == "Technology" then
return
end end
-- If we don't have permissions to access this value at all, we can skip it. -- If we don't have permissions to access this value at all, we can skip it.
local readSuccess, existingValue = pcall(function() local readSuccess, existingValue = RbxDom.CanonicalProperty.read(instance, key)
return instance[key]
end)
if not readSuccess then if not readSuccess then
-- An error will be thrown if there was a permission issue or if the -- An error will be thrown if there was a permission issue or if the
@@ -35,17 +19,13 @@ local function setCanonicalProperty(instance, key, value)
-- because it's probably their fault. -- because it's probably their fault.
if existingValue:find("lacking permission") then if existingValue:find("lacking permission") then
Logging.trace("Permission error reading property %s on class %s", tostring(key), instance.ClassName) Logging.trace("Permission error reading property %s on class %s", tostring(key), instance.ClassName)
return return false
else else
error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, existingValue), 2) error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, existingValue), 2)
end end
end end
local writeSuccess, err = pcall(function() local writeSuccess, err = RbxDom.CanonicalProperty.write(instance, key, value)
if existingValue ~= value then
instance[key] = value
end
end)
if not writeSuccess then if not writeSuccess then
error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2)