-
Notifications
You must be signed in to change notification settings - Fork 0
Incremental flow tree construction
There are three cases to consider:
-
Adding a DOM node—A
RenderObject
is created for the DOM node in question and then theaddChild
method is called on theRenderObject
belonging to the DOM node's parent.addChild
is a virtual method and will perform different fixups depending on its type. For example,RenderBlock
s create anonymous boxes if necessary to accommodate the newRenderObject
child. -
Removing a DOM node—As above, the
RenderObject
belonging to the former DOM node's parent is retrieved andremoveChild
is called on it to remove the child's render object.removeChild
is a virtual method and does different things depending on the class's type. For instance,RenderBlock
removes anonymous boxes as necessary. -
Modifying the style of a DOM node—The
RenderObject
corresponding to the DOM node is retrieved and the old and new styles are compared to determine aStyleDifference
. ThenstyleDidChange
is called on the DOM node. This floodsm_needsLayout
bits (and possibly other bits) around the tree.m_needsLayout
seems to be roughly equivalent to "needs the assign-heights pass to run". Constraint solving passes are skipped as necessary if the appropriate bits are set.
Observe that what WebKit does works out to a bottom-up traversal: it creates render objects and then stitches them in recursively by calling appendChild
. This suggests that an analogous parallel bottom-up computation is possible. Suppose that we have a data type FlowManipulation
which looks as follows:
enum FlowManipulation {
AddFlows([Flow]),
AddBoxes([Box]),
RemoveFlows([Flow]),
RemoveBoxes([Box]),
}
Then for each node we have a kernel function with this type:
-
Input: A DOM node, associated computed style, and possibly
FlowManipulation
s for kids. -
Output: A
FlowManipulation
instance.
The algorithm for this kernel function is as follows:
-
Use the
display
,position
, andcontent
properties of the computed style, as well as DOM node properties, to create the appropriate flows or render boxes (if any). -
If any flows are to be generated, create a
FlowManipulation
describing them. -
Perform flow manipulations for kids as necessary: for example, if this is a
div
node that created aBlockFlow
, thenAddFlows
operations will create children of thisBlockFlow
. Each type of flow will have a different implementation for the various methods: for example, forBlockFlow
instances,AddFlows
orAddBoxes
methods can create anonymous blocks. It is important thatFlowManipulation
s be executed in the correct order, and in the right place in the tree: for this, the DOM node that each member of theAddFlows
orAddBoxes
instruction corresponds to needs to be consulted.
We run this kernel function on each node that was added or removed until no more flow manipulations occur. The root node must always produce an AddFlows
manipulation with a single root element.
This can just be done sequentially with markDirty
style operations, since it's not likely to be high in the profile. (It isn't in Gecko.) We should be able to fairly easily parallelize if we have to. Constraint solving passes will ignore nodes that are not dirty.