Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

WIP: Fragments for new reconciler #172

Merged
96 changes: 0 additions & 96 deletions lib/ChildUtils.lua

This file was deleted.

94 changes: 0 additions & 94 deletions lib/ChildUtils.spec.lua

This file was deleted.

6 changes: 3 additions & 3 deletions lib/Component.lua
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,10 @@ function Component:__mount(reconciler, virtualNode)
virtualNode.context = instance._context

internalData.setStateBlockedReason = "render"
local children = instance:render()
local renderResult = instance:render()
internalData.setStateBlockedReason = nil

reconciler.updateVirtualNodeChildren(virtualNode, hostParent, children)
reconciler.updateVirtualNodeWithRenderResult(virtualNode, hostParent, renderResult)

if instance.didMount ~= nil then
instance:didMount()
Expand Down Expand Up @@ -289,7 +289,7 @@ function Component:__update(updatedElement, updatedState)
local renderResult = virtualNode.instance:render()
internalData.setStateBlockedReason = nil

reconciler.updateVirtualNodeChildren(virtualNode, virtualNode.hostParent, renderResult)
reconciler.updateVirtualNodeWithRenderResult(virtualNode, virtualNode.hostParent, renderResult)

if self.didUpdate ~= nil then
self:didUpdate(oldProps, oldState)
Expand Down
107 changes: 107 additions & 0 deletions lib/ElementUtils.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
local Type = require(script.Parent.Type)
local Symbol = require(script.Parent.Symbol)

local function noop()
return nil
end

local ElementUtils = {}

--[[
A signal value indicating that a child should use its parent's key, because
it has no key of its own.

This occurs when you return only one element from a function component or
stateful render function.
]]
ElementUtils.UseParentKey = Symbol.named("UseParentKey")

--[[
Returns an iterator over the children of an element.
`elementOrElements` may be one of:
* a boolean
* nil
* a single element
* a fragment
* a table of elements

If `elementOrElements` is a boolean or nil, this will return an iterator with
zero elements.

If `elementOrElements` is a single element, this will return an iterator with
one element: a tuple where the first value is ElementUtils.UseParentKey, and
the second is the value of `elementOrElements`.

If `elementOrElements` is a fragment or a table, this will return an iterator
over all the elements of the array.

If `elementOrElements` is none of the above, this function will throw.
]]
function ElementUtils.iterateElements(elementOrElements)
local richType = Type.of(elementOrElements)

if richType == Type.Fragment then
return pairs(elementOrElements.elements)
end

-- Single child
if richType == Type.Element then
local called = false

return function()
if called then
return nil
else
called = true
return ElementUtils.UseParentKey, elementOrElements
end
end
end

local regularType = typeof(elementOrElements)

if elementOrElements == nil or regularType == "boolean" then
return noop
end

if regularType == "table" then
return pairs(elementOrElements)
end

error("Invalid elements")
end

--[[
Gets the child corresponding to a given key, respecting Roact's rules for
children. Specifically:
* If `elements` is nil or a boolean, this will return `nil`, regardless of
the key given.
* If `elements` is a single element, this will return `nil`, unless the key
is ElementUtils.UseParentKey.
* If `elements` is a table of elements, this will return `elements[key]`.
]]
function ElementUtils.getElementByKey(elements, hostKey)
if elements == nil or typeof(elements) == "boolean" then
return nil
end

if Type.of(elements) == Type.Element then
if hostKey == ElementUtils.UseParentKey then
return elements
end

return nil
end

if Type.of(elements) == Type.Fragment then
return elements.elements[hostKey]
end

if typeof(elements) == "table" then
return elements[hostKey]
end

error("Invalid elements")
end

return ElementUtils
Loading