This commit is contained in:
Lukas Stabe 2022-10-19 03:55:32 +02:00
parent 3d8e2f79f5
commit c38a05a0de
6 changed files with 89 additions and 69 deletions

View File

@ -55,7 +55,7 @@ struct ContentView: View {
}
case .d(_, let ints, let other):
VStack {
Text("\(other)")
Text("d \(other)")
Text("count \(ints.count)")
}
}

View File

@ -34,13 +34,13 @@ extension FiberReconciler.Fiber: CustomDebugStringConvertible {
proposal: .unspecified
)
return """
\(spaces)\(debugDescription)\(element != nil ? "(\(element!))" : "")
\(child?.flush(level: level + 2) ?? "")\
\(spaces)\(String(describing: typeInfo?.type ?? Any.self)
.split(separator: "<")[0])\(element != nil ? "(\(element!))" : "") {\(element != nil ?
"\n\(spaces)geometry: \(geometry)" :
"")
\(child?.flush(level: level + 2) ?? "")
\(spaces)}
\(sibling?.flush(level: level) ?? "")
"""
}
public var recursiveDescription: String {
flush()
}
}

View File

@ -130,16 +130,13 @@ extension FiberReconciler {
// Create the node and its element.
var nextValue = nextValue
print("TreeReducer visiting view \(nextValue)")
let resultChild: Result
if let existing = partialResult.nextExisting {
print("updating existing \(existing)")
// If a fiber already exists, simply update it with the new view.
let elementParent = partialResult.fiber?.element != nil
? partialResult.fiber
: partialResult.fiber?.elementParent
existing.elementParent = elementParent
// If a fiber already exists, simply update it with the new view.
let key: ObjectIdentifier?
if let elementParent = existing.elementParent {
key = ObjectIdentifier(elementParent)
@ -152,9 +149,6 @@ extension FiberReconciler {
key.map { partialResult.elementIndices[$0, default: 0] },
partialResult.nextTraits
)
// existing.element = newContent.map { .init(from: $0) }
resultChild = Result(
fiber: existing,
visitChildren: visitChildren(partialResult.fiber?.reconciler, nextValue),
@ -167,10 +161,8 @@ extension FiberReconciler {
)
partialResult.nextExisting = existing.sibling
partialResult.nextExistingAlternate = partialResult.nextExistingAlternate?.sibling
existing.sibling = nil
} else {
print("creating new")
let elementParent = partialResult.fiber?.element != nil
? partialResult.fiber
: partialResult.fiber?.elementParent

View File

@ -243,8 +243,6 @@ public final class FiberReconciler<Renderer: FiberRenderer> {
///
/// A `reconcile()` call is queued from `fiberChanged` once per run loop.
func reconcile() {
print("reconcile(), changedFibers: \(changedFibers)")
isReconciling = true
let changedFibers = changedFibers
self.changedFibers.removeAll()
@ -268,13 +266,10 @@ public final class FiberReconciler<Renderer: FiberRenderer> {
// Essentially, making the work in progress tree the current,
// and leaving the current available to be the work in progress
// on our next update.
let alternate = alternate
self.alternate = current
current = alternate
print("============== reconcile done, current is now:\n\(current.recursiveDescription)")
isReconciling = false
for action in afterReconcileActions {

View File

@ -84,11 +84,9 @@ struct ReconcilePass: FiberReconcilerPass {
}
}
print("run(...) iteration, shouldReconcile: \(shouldReconcile), node:", node.fiber ?? "<nil>")
// If this fiber has an element, set its `elementIndex`
// and increment the `elementIndices` value for its `elementParent`.
if node.fiber?.element != nil,
if node.newContent != nil || node.fiber?.element != nil,
let elementParent = node.fiber?.elementParent
{
node.fiber?.elementIndex = caches.elementIndex(for: elementParent, increment: true)
@ -101,12 +99,6 @@ struct ReconcilePass: FiberReconcilerPass {
caches.mutations.append(mutation)
}
///////------------_!!!!!!!!!!!!!!!!!!!!
//////// wheeeere are new fiber elements creted?????
////.how is element formed?
////-------------------
// Ensure the `TreeReducer` can access any necessary state.
node.elementIndices = caches.elementIndices
// Pass view traits down to the nearest element fiber.
@ -119,7 +111,6 @@ struct ReconcilePass: FiberReconcilerPass {
// Update `DynamicProperty`s before accessing the `View`'s body.
node.fiber?.updateDynamicProperties()
// Compute the children of the node.
print("run(...): reducing tree")
let reducer = FiberReconciler<R>.TreeReducer.SceneVisitor(initialResult: node)
node.visitChildren(reducer)
@ -157,7 +148,9 @@ struct ReconcilePass: FiberReconcilerPass {
if let parent = node.fiber?.element != nil ? node.fiber : node.fiber?.elementParent {
invalidateCache(for: parent, in: reconciler, caches: caches)
}
walk(alternateChild) { node in
var nextChildOrSibling: FiberReconciler.Fiber? = alternateChild
while let child = nextChildOrSibling {
walk(child) { node in
if let element = node.element,
let parent = node.elementParent?.element
{
@ -167,6 +160,8 @@ struct ReconcilePass: FiberReconcilerPass {
}
return true
}
nextChildOrSibling = child.sibling
}
}
if reducer.result.child == nil {
// Make sure we clear the child if there was none
@ -198,18 +193,21 @@ struct ReconcilePass: FiberReconcilerPass {
var alternateSibling = node.fiber?.alternate?.sibling
// The alternate had siblings that no longer exist.
while alternateSibling != nil {
if let fiber = alternateSibling?.elementParent {
while let currentAltSibling = alternateSibling {
if let fiber = currentAltSibling.elementParent {
invalidateCache(for: fiber, in: reconciler, caches: caches)
}
if let element = alternateSibling?.element,
let parent = alternateSibling?.elementParent?.element
walk(currentAltSibling) { node in
if let element = node.element,
let parent = node.elementParent?.element
{
// Removals happen in reverse order, so a child element is removed before
// its parent.
caches.mutations.insert(.remove(element: element, parent: parent), at: 0)
}
alternateSibling = alternateSibling?.sibling
return true
}
alternateSibling = currentAltSibling.sibling
}
guard let parent = node.parent else { return }
// When we walk back to the root, exit
@ -232,17 +230,63 @@ struct ReconcilePass: FiberReconcilerPass {
in reconciler: FiberReconciler<R>,
caches: FiberReconciler<R>.Caches
) -> Mutation<R>? {
print("reconcile(...), node:", node.fiber ?? "<nil>", "alternate:", node.fiber?.alternate ?? "<nil>")
if let element = node.fiber?.element ?? node.newContent.map({ .init(from: $0) }),
if node.fiber?.element == nil,
node.fiber?.alternate?.element == nil,
let content = node.newContent,
let index = node.fiber?.elementIndex,
let parent = node.fiber?.elementParent?.element
{
if node.fiber?.alternate?.element == nil { // This didn't exist before (no alternate)
if let fiber = node.fiber {
invalidateCache(for: fiber, in: reconciler, caches: caches)
}
print(" -> .insert")
node.fiber?.element = element
let el = R.ElementType(from: content)
node.fiber?.element = el
return .insert(element: el, parent: parent, index: index)
}
if node.fiber?.element == nil,
let altElement = node.fiber?.alternate?.element,
let content = node.newContent,
let parent = node.fiber?.elementParent?.element
{
if let fiber = node.fiber {
invalidateCache(for: fiber, in: reconciler, caches: caches)
}
if node.fiber?.typeInfo?.type != node.fiber?.alternate?.typeInfo?.type {
let el = R.ElementType(from: content)
node.fiber?.element = el
return .replace(parent: parent, previous: altElement, replacement: el)
} else if content != altElement.content {
node.fiber?.element = altElement
return .update(
previous: altElement,
newContent: content,
geometry: node.fiber?.geometry ?? .init(
origin: .init(origin: .zero),
dimensions: .init(size: .zero, alignmentGuides: [:]),
proposal: .unspecified
)
)
}
}
if let alt = node.fiber?.alternate?.element,
let parent = node.fiber?.elementParent?.element,
node.newContent == nil
{
node.fiber?.element = nil
return .remove(element: alt, parent: parent)
}
if let element = node.fiber?.element,
let index = node.fiber?.elementIndex,
let parent = node.fiber?.elementParent?.element
{
if node.fiber?.alternate == nil { // This didn't exist before (no alternate)
if let fiber = node.fiber {
invalidateCache(for: fiber, in: reconciler, caches: caches)
}
return .insert(element: element, parent: parent, index: index)
} else if node.fiber?.typeInfo?.type != node.fiber?.alternate?.typeInfo?.type,
let previous = node.fiber?.alternate?.element
@ -250,16 +294,14 @@ struct ReconcilePass: FiberReconcilerPass {
if let fiber = node.fiber {
invalidateCache(for: fiber, in: reconciler, caches: caches)
}
print(" -> .replace")
// This is a completely different type of view.
return .replace(parent: parent, previous: previous, replacement: element)
} else if let newContent = node.newContent,
node.fiber?.element?.content != node.fiber?.alternate?.element?.content
newContent != element.content
{
if let fiber = node.fiber {
invalidateCache(for: fiber, in: reconciler, caches: caches)
}
print(" -> .update")
// This is the same type of view, but its backing data has changed.
return .update(
previous: element,
@ -271,9 +313,7 @@ struct ReconcilePass: FiberReconcilerPass {
)
)
}
print(" ! didn't update, content \(element.content), new content \(node.newContent as Any)")
}
print(" -> nil, element", node.fiber?.element != nil, "elementIndex", node.fiber?.elementIndex != nil, "elementParent", node.fiber?.elementParent?.element != nil)
return nil
}

View File

@ -57,12 +57,6 @@ public final class DOMElement: FiberElement {
}
}
extension DOMElement: CustomStringConvertible {
public var description: String {
"DOMElement(tag: \(content.tag), attributes: \(content.attributes.filter { $0.key != "style" }), innerHTML: \(content.innerHTML ?? "nil"))"
}
}
public extension DOMElement.Content {
init<V>(from primitiveView: V, useDynamicLayout: Bool) where V: View {
guard let primitiveView = primitiveView as? HTMLConvertible else { fatalError() }
@ -297,7 +291,6 @@ public struct DOMFiberRenderer: FiberRenderer {
public func commit(_ mutations: [Mutation<Self>]) {
for mutation in mutations {
print(mutation)
switch mutation {
case let .insert(newElement, parent, index):
let element = createElement(newElement)