# Whitespace LayoutObjects
Text nodes which only contain whitespaces sometimes have a layout object and
sometimes they don't. This document tries to explain why and how these layout
objects are created.
## Why
For layout purposes, whitespace nodes are sometimes significant, but not
always. In Blink, we try to create as few of them as possible to save memory,
and save CPU by having fewer layout objects to traverse.
### Inline flow
Whitespace typically matters in an inline flow context. Example:
<span>A</span> </span>B</span>
If we didn't create a LayoutObject for the whitespace node between the two
spans, we would have rendered the markup above as "AB" as the span layout
objects would have been siblings in the layout tree.
### Block flow
Whitespace typically doesn't matter in a block flow context. Example:
<div>A</div> <div>B</div>
In the example above, the whitespace node between the divs would not contribute
to layout/rendering. Hence, we can skip creating a LayoutText for it.
### Out-of-flow
Out-of-flow elements like absolutely positioned elements do not affect inline
or block in-flow layout. That means we can skip such elements when considering
the need for whitespace layout objects.
Example:
<div><span style="position:absolute">A</span> </span>B</span></div>
In the example above, we don't need to create a whitespace layout object since
it will be the first in-flow child of the block, and will not contribute to the
layout/rendering.
Example:
<span>A</span> <span style="position:absolute">Z</span> <span>B</span>
In the example above, we need to create a whitespace layout object to separate
the A and B in the rendering. However, we only need to create a layout object
for one of the whitespace nodes as whitespace collapse.
### Preformatted text and editing
Some values of the CSS white-space property will cause whitespace to not
collapse and affect layout and rendering also in block layout. In those cases
we always create layout objects for whitespace nodes.
Whitespace nodes are also significant in editing mode.
## How
We decide if we need to attach or re-attach the layout tree for a text node as
part of the layout tree rebuild. A layout tree rebuild starts at the
documentElement by calling Element::RebuildLayoutTree.
### RebuildLayoutTree
The Element::RebuildLayoutTree traversal happens in the flat tree order
traversing children from right to left (see RebuildChildrenLayoutTrees in the
ContainerNode class). We keep track of the last seen text node in an instance
of the WhitespaceAttacher class which is passed to the various traversal
methods.
Important methods:
WhitespaceAttacher::*
Element::RebuildLayoutTree
ContainerNode::RebuildChildrenLayoutTrees
### Attaching a layout tree
Once we encounter a node which needs re-attachment during RebuildLayoutTree, we
do a Node::AttachLayoutTree for that sub-tree. AttachLayoutTree attaches nodes
in the flat tree order, but as opposed to RebuildLayoutTree, siblings are
attached from left to right. In order to decide if a whitespace Text node needs
a LayoutObject or not, we keep track of the previous in-flow layout tree
sibling in the AttachContext passed to AttachLayoutTree.
When a sub-tree has been (re-)attached, we know which is the last in-flow
LayoutObject of that subtree (normally the root, unless the root is
display:contents or display:none). This last in-flow layout object, stored in
the AttachContext, is passed into the WhitespaceAttacher to see if a sub-sequent
whitespace node needs to be re-attached due to a different display type for the
root of the (re-)attached subtree. See following sub-section.
Important methods:
Text::AttachLayoutTree()
Text::TextLayoutObjectIsNeeded()
#### Re-attaching whitespace layout objects
When the computed display value changes, the requirement for whitespace
siblings may change.
Example:
<span style="position:absolute">A</span> <span>B</span>
Initially, we don't need a layout object for the whitespace above. If we change
the position of the first span to static, we need a layout object for the
whitespace. During layout tree rebuild, we keep track of the last text node
sibling in the WhitespaceAttacher. The text node is reset when we encounter a
node with an in-flow layout box. Remember that we traverse from right to left.
That means we have stored the whitespace node above in the WhitespaceAttacher
when we re-attach the left-most span. After re-attachment we re-attach the
stored text node based on passing the first span with its LayoutObject as
previous in-flow into WhitespaceAttacher::DidReattachElement.
DidReattachElement will re-attach whitespace siblings as necessary.
#### Known issues
https://crbug.com/750758