doesn't need to be reopened. It can just close.
+ HTMLStackElem* currElem = maxElem->next;
+ HTMLStackElem* prevElem = maxElem;
+ while (currElem != elem) {
+ HTMLStackElem* nextElem = currElem->next;
+ if (!isResidualStyleTag(currElem->tagName)) {
+ prevElem->next = nextElem;
+ prevElem->derefNode();
+ prevElem->node = currElem->node;
+ prevElem->didRefNode = currElem->didRefNode;
+ delete currElem;
+ m_treeDepth--;
+ } else
+ prevElem = currElem;
+ currElem = nextElem;
+ }
+
+ // We have to reopen residual tags in between maxElem and elem. An example of this case is:
+ // MooFoo
.
+ // In this case, we need to transform the part before the into:
+ // Moo
+ // so that the will remain open. This involves the modification of elements
+ // in the block stack.
+ // This will also affect how we ultimately reparent the block, since we want it to end up
+ // under the reopened residual tags (e.g., the in the above example.)
+ RefPtr prevNode = 0;
+ currElem = maxElem;
+ while (currElem->node != residualElem) {
+ if (isResidualStyleTag(currElem->node->localName())) {
+ // Create a clone of this element.
+ // We call releaseRef to get a raw pointer since we plan to hand over ownership to currElem.
+ Node* currNode = currElem->node->cloneNode(false).releaseRef();
+ reportError(ResidualStyleError, &currNode->localName());
+
+ // Change the stack element's node to point to the clone.
+ // The stack element adopts the reference we obtained above by calling release().
+ currElem->derefNode();
+ currElem->node = currNode;
+ currElem->didRefNode = true;
+
+ // Attach the previous node as a child of this new node.
+ if (prevNode)
+ currNode->appendChild(prevNode, ec);
+ else // The new parent for the block element is going to be the innermost clone.
+ parentElem = currNode; // FIXME: We shifted parentElem to be a residual inline. We never checked to see if blockElem could be legally placed inside the inline though.
+
+ prevNode = currNode;
+ }
+
+ currElem = currElem->next;
+ }
+
+ // Now append the chain of new residual style elements if one exists.
+ if (prevNode)
+ elem->node->appendChild(prevNode, ec); // FIXME: This append can result in weird stuff happening, like an inline chain being put into a table section.
+ }
+
+ // Check if the block is still in the tree. If it isn't, then we don't
+ // want to remove it from its parent (that would crash) or insert it into
+ // a new parent later. See http://bugs.webkit.org/show_bug.cgi?id=6778
+ bool isBlockStillInTree = blockElem->parentNode();
+
+ // We need to make a clone of |residualElem| and place it just inside |blockElem|.
+ // All content of |blockElem| is reparented to be under this clone. We then
+ // reparent |blockElem| using real DOM calls so that attachment/detachment will
+ // be performed to fix up the rendering tree.
+ // So for this example: ...FooGoo
+ // The end result will be: ...FooGoo
+ //
+ // Step 1: Remove |blockElem| from its parent, doing a batch detach of all the kids.
+ if (isBlockStillInTree)
+ blockElem->parentNode()->removeChild(blockElem, ec);
+
+ Node* newNodePtr = 0;
+ if (blockElem->firstChild()) {
+ // Step 2: Clone |residualElem|.
+ RefPtr newNode = residualElem->cloneNode(false); // Shallow clone. We don't pick up the same kids.
+ newNodePtr = newNode.get();
+ reportError(ResidualStyleError, &newNode->localName());
+
+ // Step 3: Place |blockElem|'s children under |newNode|. Remove all of the children of |blockElem|
+ // before we've put |newElem| into the document. That way we'll only do one attachment of all
+ // the new content (instead of a bunch of individual attachments).
+ Node* currNode = blockElem->firstChild();
+ while (currNode) {
+ Node* nextNode = currNode->nextSibling();
+ newNode->appendChild(currNode, ec);
+ currNode = nextNode;
+ }
+
+ // Step 4: Place |newNode| under |blockElem|. |blockElem| is still out of the document, so no
+ // attachment can occur yet.
+ blockElem->appendChild(newNode.release(), ec);
+ } else
+ finished = true;
+
+ // Step 5: Reparent |blockElem|. Now the full attachment of the fixed up tree takes place.
+ if (isBlockStillInTree)
+ parentElem->appendChild(blockElem, ec);
+
+ // Step 6: Pull |elem| out of the stack, since it is no longer enclosing us. Also update
+ // the node associated with the previous stack element so that when it gets popped,
+ // it doesn't make the residual element the next current node.
+ HTMLStackElem* currElem = maxElem;
+ HTMLStackElem* prevElem = 0;
+ while (currElem != elem) {
+ prevElem = currElem;
+ currElem = currElem->next;
+ }
+ prevElem->next = elem->next;
+ prevElem->derefNode();
+ prevElem->node = elem->node;
+ prevElem->didRefNode = elem->didRefNode;
+ m_treeDepth--;
+ if (!finished) {
+ // Repurpose |elem| to represent |newNode| and insert it at the appropriate position
+ // in the stack. We do not do this for the innermost block, because in that case the new
+ // node is effectively no longer open.
+ elem->next = maxElem;
+ elem->node = prevMaxElem->node;
+ elem->didRefNode = prevMaxElem->didRefNode;
+ elem->strayTableContent = false;
+ prevMaxElem->next = elem;
+ ASSERT(newNodePtr);
+ prevMaxElem->node = newNodePtr;
+ newNodePtr->ref();
+ prevMaxElem->didRefNode = true;
+ m_treeDepth++;
+ } else
+ delete elem;
+ }
+
+ // FIXME: If we ever make a case like this work:
+ //
+ // Then this check will be too simplistic. Right now the