Break apart plugin reconciler (#332)

* Start splitting apart reconciler, with tests

* Reify children in reify

* Baseline hydrate implementation

* Remove debug print

* Scaffold out diff implementation, just supporting name changes

* invariant -> error in decodeValue

* Flesh out diff and add getProperty

* Clear out top-level reconciler interface, start updating code that touches it

* Address review feedback

* Add (experimental) Selene configuration

* Add emptiness checks to PatchSet, remove unimplement invert method

* Improve descendant destruction behavior in InstanceMap

* Track instanceId on all reify errors

* Base implementation of applyPatch, returning partial patches on failure

* Change reify to accept InstanceMap and insert instances into it

* Start testing applyPatch for removals

* Add test for applyPatch adding instances successfully and not

* Add , which is just error with formatting

* Correctly use new diff and applyPatch APIs

* Improve applyPatch logging and fix field name typo

* Better debug output when reify fails

* Print out unapplied patch in debug mode

* Don't write properties if their values are not different.

This was exposed trying to sync the Rojo plugin, which
has a gigantic ModuleScript in it with the reflection
database. This workaround was present in some form in
many versions of Rojo, and I guess we still need it.

This time, I actually documented why it's here so that
I don't forget for the umpteenth time...

* Add placeholder test that needs to happen still

* Introduce easier plugin testing, write applyPatch properties test

* Delete legacy get/setCanonicalProperty files

* Fix trying to remove numbers instead of instances

* Change applyPatch to return partial patches instead of binary success

* Work towards being able to decode and apply refs

* Add helpers for PatchSet assertions

* Apply refs in reify, test all cases

* Improve diagnostics when patches fail to apply

* Stop logging when destroying untracked instances, it's ok

* Remove read before setting property in applyPatch

* Fix diff thinking all properties are changed
This commit is contained in:
Lucien Greathouse
2020-11-11 16:30:23 -08:00
committed by GitHub
parent 50f0a2bd2e
commit f66860bdfe
26 changed files with 1818 additions and 466 deletions

View File

@@ -0,0 +1,52 @@
--[[
Attempts to read a property from the given instance.
]]
local RbxDom = require(script.Parent.Parent.Parent.RbxDom)
local Error = require(script.Parent.Error)
local function getProperty(instance, propertyName)
local descriptor = RbxDom.findCanonicalPropertyDescriptor(instance.ClassName, propertyName)
-- We can skip unknown properties; they're not likely reflected to Lua.
--
-- A good example of a property like this is `Model.ModelInPrimary`, which
-- is serialized but not reflected to Lua.
if descriptor == nil then
return false, Error.new(Error.UnknownProperty, {
className = instance.ClassName,
propertyName = propertyName,
})
end
if descriptor.scriptability == "None" or descriptor.scriptability == "Write" then
return false, Error.new(Error.UnreadableProperty, {
className = instance.ClassName,
propertyName = propertyName,
})
end
local success, valueOrErr = descriptor:read(instance)
if not success then
local err = valueOrErr
-- If we don't have permission to read a property, we can chalk that up
-- to our database being out of date and the engine being right.
if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then
return false, Error.new(Error.LackingPropertyPermissions, {
className = instance.ClassName,
propertyName = propertyName,
})
end
return false, Error.new(Error.OtherPropertyError, {
className = instance.ClassName,
propertyName = propertyName,
})
end
return true, valueOrErr
end
return getProperty