Fix the issue that Web Audio test case fails on PR3.
[framework/web/webkit-efl.git] / Source / WebCore / rendering / RenderObjectChildList.cpp
1 /*
2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "RenderObjectChildList.h"
29
30 #include "AXObjectCache.h"
31 #include "ContentData.h"
32 #include "RenderBlock.h"
33 #include "RenderCounter.h"
34 #include "RenderImage.h"
35 #include "RenderImageResourceStyleImage.h"
36 #include "RenderInline.h"
37 #include "RenderLayer.h"
38 #include "RenderListItem.h"
39 #include "RenderNamedFlowThread.h"
40 #include "RenderQuote.h"
41 #include "RenderRegion.h"
42 #include "RenderStyle.h"
43 #include "RenderTextFragment.h"
44 #include "RenderView.h"
45
46 namespace WebCore {
47
48 void RenderObjectChildList::destroyLeftoverChildren()
49 {
50     while (firstChild()) {
51         if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == FIRST_LETTER && !firstChild()->isText()))
52             firstChild()->remove();  // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
53         else if (firstChild()->isRunIn() && firstChild()->node()) {
54             firstChild()->node()->setRenderer(0);
55             firstChild()->node()->setNeedsStyleRecalc();
56             firstChild()->destroy();
57         } else {
58             // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
59             if (firstChild()->node())
60                 firstChild()->node()->setRenderer(0);
61             firstChild()->destroy();
62         }
63     }
64 }
65
66 static RenderNamedFlowThread* renderNamedFlowThreadContainer(RenderObject* object)
67 {
68     while (object && object->isAnonymousBlock() && !object->isRenderNamedFlowThread())
69         object = object->parent();
70
71     return object && object->isRenderNamedFlowThread() ? toRenderNamedFlowThread(object) : 0;
72 }
73
74 RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool fullRemove)
75 {
76     ASSERT(oldChild->parent() == owner);
77
78     if (oldChild->isFloatingOrOutOfFlowPositioned())
79         toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();
80
81     // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
82     // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
83     // disappears gets repainted properly.
84     if (!owner->documentBeingDestroyed() && fullRemove && oldChild->everHadLayout()) {
85         oldChild->setNeedsLayoutAndPrefWidthsRecalc();
86         if (oldChild->isBody())
87             owner->view()->repaint();
88         else
89             oldChild->repaint();
90     }
91
92     // If we have a line box wrapper, delete it.
93     if (oldChild->isBox())
94         toRenderBox(oldChild)->deleteLineBoxWrapper();
95
96     if (!owner->documentBeingDestroyed() && fullRemove) {
97         // if we remove visible child from an invisible parent, we don't know the layer visibility any more
98         RenderLayer* layer = 0;
99         if (owner->style()->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
100             if ((layer = owner->enclosingLayer()))
101                 layer->dirtyVisibleContentStatus();
102         }
103
104          // Keep our layer hierarchy updated.
105         if (oldChild->firstChild() || oldChild->hasLayer()) {
106             if (!layer)
107                 layer = owner->enclosingLayer();
108             oldChild->removeLayers(layer);
109         }
110
111         if (oldChild->isListItem())
112             toRenderListItem(oldChild)->updateListMarkerNumbers();
113
114         if (oldChild->isOutOfFlowPositioned() && owner->childrenInline())
115             owner->dirtyLinesFromChangedChild(oldChild);
116
117         if (oldChild->isRenderRegion())
118             toRenderRegion(oldChild)->detachRegion();
119
120         if (oldChild->inRenderFlowThread()) {
121             if (oldChild->isBox())
122                 oldChild->enclosingRenderFlowThread()->removeRenderBoxRegionInfo(toRenderBox(oldChild));
123             oldChild->enclosingRenderFlowThread()->clearRenderObjectCustomStyle(oldChild);
124         }
125
126         if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner))
127             containerFlowThread->removeFlowChild(oldChild);
128
129 #if ENABLE(SVG)
130         // Update cached boundaries in SVG renderers, if a child is removed.
131         owner->setNeedsBoundariesUpdate();
132 #endif
133     }
134     
135     // If oldChild is the start or end of the selection, then clear the selection to
136     // avoid problems of invalid pointers.
137     // FIXME: The FrameSelection should be responsible for this when it
138     // is notified of DOM mutations.
139     if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
140         owner->view()->clearSelection();
141
142     // remove the child
143     if (oldChild->previousSibling())
144         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
145     if (oldChild->nextSibling())
146         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
147
148     if (firstChild() == oldChild)
149         setFirstChild(oldChild->nextSibling());
150     if (lastChild() == oldChild)
151         setLastChild(oldChild->previousSibling());
152
153     oldChild->setPreviousSibling(0);
154     oldChild->setNextSibling(0);
155     oldChild->setParent(0);
156
157     // rendererRemovedFromTree walks the whole subtree. We can improve performance
158     // by skipping this step when destroying the entire tree.
159     if (!owner->documentBeingDestroyed()) {
160         RenderCounter::rendererRemovedFromTree(oldChild);
161         RenderQuote::rendererRemovedFromTree(oldChild);
162     }
163
164     if (AXObjectCache::accessibilityEnabled())
165         owner->document()->axObjectCache()->childrenChanged(owner);
166
167     return oldChild;
168 }
169
170 void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* newChild, bool fullAppend)
171 {
172     ASSERT(newChild->parent() == 0);
173     ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
174
175     newChild->setParent(owner);
176     RenderObject* lChild = lastChild();
177
178     if (lChild) {
179         newChild->setPreviousSibling(lChild);
180         lChild->setNextSibling(newChild);
181     } else
182         setFirstChild(newChild);
183
184     setLastChild(newChild);
185     
186     if (fullAppend) {
187         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
188         // and don't have a layer attached to ourselves.
189         RenderLayer* layer = 0;
190         if (newChild->firstChild() || newChild->hasLayer()) {
191             layer = owner->enclosingLayer();
192             newChild->addLayers(layer);
193         }
194
195         // if the new child is visible but this object was not, tell the layer it has some visible content
196         // that needs to be drawn and layer visibility optimization can't be used
197         if (owner->style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
198             if (!layer)
199                 layer = owner->enclosingLayer();
200             if (layer)
201                 layer->setHasVisibleContent();
202         }
203
204         if (newChild->isListItem())
205             toRenderListItem(newChild)->updateListMarkerNumbers();
206
207         if (!newChild->isFloating() && owner->childrenInline())
208             owner->dirtyLinesFromChangedChild(newChild);
209
210         if (newChild->isRenderRegion())
211             toRenderRegion(newChild)->attachRegion();
212
213         if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner))
214             containerFlowThread->addFlowChild(newChild);
215     }
216
217     if (!owner->documentBeingDestroyed()) {
218         RenderCounter::rendererSubtreeAttached(newChild);
219         RenderQuote::rendererSubtreeAttached(newChild);
220     }
221     newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
222     if (!owner->normalChildNeedsLayout())
223         owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
224     
225     if (AXObjectCache::accessibilityEnabled())
226         owner->document()->axObjectCache()->childrenChanged(owner);
227 }
228
229 void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* child, RenderObject* beforeChild, bool fullInsert)
230 {
231     if (!beforeChild) {
232         appendChildNode(owner, child, fullInsert);
233         return;
234     }
235
236     ASSERT(!child->parent());
237     while (beforeChild->parent() != owner && beforeChild->parent()->isAnonymousBlock())
238         beforeChild = beforeChild->parent();
239     ASSERT(beforeChild->parent() == owner);
240
241     ASSERT(!owner->isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
242
243     if (beforeChild == firstChild())
244         setFirstChild(child);
245
246     RenderObject* prev = beforeChild->previousSibling();
247     child->setNextSibling(beforeChild);
248     beforeChild->setPreviousSibling(child);
249     if (prev)
250         prev->setNextSibling(child);
251     child->setPreviousSibling(prev);
252
253     child->setParent(owner);
254     
255     if (fullInsert) {
256         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
257         // and don't have a layer attached to ourselves.
258         RenderLayer* layer = 0;
259         if (child->firstChild() || child->hasLayer()) {
260             layer = owner->enclosingLayer();
261             child->addLayers(layer);
262         }
263
264         // if the new child is visible but this object was not, tell the layer it has some visible content
265         // that needs to be drawn and layer visibility optimization can't be used
266         if (owner->style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
267             if (!layer)
268                 layer = owner->enclosingLayer();
269             if (layer)
270                 layer->setHasVisibleContent();
271         }
272
273         if (child->isListItem())
274             toRenderListItem(child)->updateListMarkerNumbers();
275
276         if (!child->isFloating() && owner->childrenInline())
277             owner->dirtyLinesFromChangedChild(child);
278
279         if (child->isRenderRegion())
280             toRenderRegion(child)->attachRegion();
281
282         if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner))
283             containerFlowThread->addFlowChild(child, beforeChild);
284     }
285
286     if (!owner->documentBeingDestroyed()) {
287         RenderCounter::rendererSubtreeAttached(child);
288         RenderQuote::rendererSubtreeAttached(child);
289     }
290     child->setNeedsLayoutAndPrefWidthsRecalc();
291     if (!owner->normalChildNeedsLayout())
292         owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
293     
294     if (AXObjectCache::accessibilityEnabled())
295         owner->document()->axObjectCache()->childrenChanged(owner);
296 }
297
298 static RenderObject* findBeforeAfterParent(RenderObject* object)
299 {
300     // Only table parts and flex-boxes need to search for the :before or :after parent
301     // FIXME: We could likely get away without this check and always look for the right parent.
302     if (!(object->isTable() || object->isTableSection() || object->isTableRow() || object->isFlexibleBoxIncludingDeprecated()))
303         return object;
304
305     // If there is a :first-letter style applied on the :before or :after content,
306     // then we want the parent of the first-letter block
307     RenderObject* beforeAfterParent = object;
308     while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage())
309         && (beforeAfterParent->style()->styleType() != FIRST_LETTER))
310         beforeAfterParent = beforeAfterParent->firstChild();
311
312     return beforeAfterParent ? beforeAfterParent->parent() : 0;
313 }
314
315 RenderObject* RenderObjectChildList::beforePseudoElementRenderer(const RenderObject* owner) const
316 {
317     // An anonymous (generated) inline run-in that has PseudoId BEFORE must come from a grandparent.
318     // Therefore we should skip these generated run-ins when checking our immediate children.
319     // If we don't find our :before child immediately, then we should check if we own a
320     // generated inline run-in in the next level of children.
321     RenderObject* first = const_cast<RenderObject*>(owner);
322     do {
323         first = first->firstChild();
324         // Skip list markers and generated run-ins.
325         while (first && (first->isListMarker() || (first->isRenderInline() && first->isRunIn())))
326             first = first->nextInPreOrderAfterChildren(owner);
327     } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO);
328
329     if (!first)
330         return 0;
331
332     if (first->isBeforeContent())
333         return first;
334
335     // Check for a possible generated run-in, using run-in positioning rules.
336     first = owner->firstChild();
337     if (!first->isRenderBlock())
338         return 0;
339     
340     first = first->firstChild();
341     // We still need to skip any list markers that could exist before the run-in.
342     while (first && first->isListMarker())
343         first = first->nextSibling();
344     if (first && first->isBeforeContent() && first->isRenderInline() && first->isRunIn())
345         return first;
346     
347     return 0;
348 }
349
350 RenderObject* RenderObjectChildList::afterPseudoElementRenderer(const RenderObject* owner) const
351 {
352     RenderObject* last = const_cast<RenderObject*>(owner);
353     do {
354         last = last->lastChild();
355     } while (last && last->isAnonymous() && last->style()->styleType() == NOPSEUDO && !last->isListMarker());
356     if (last && !last->isAfterContent())
357         return 0;
358     return last;
359 }
360
361 void RenderObjectChildList::updateBeforeAfterStyle(RenderObject* child, PseudoId type, RenderStyle* pseudoElementStyle)
362 {
363     if (!child || child->style()->styleType() != type)
364         return;
365
366     // We have generated content present still. We want to walk this content and update our
367     // style information with the new pseudo-element style.
368     child->setStyle(pseudoElementStyle);
369
370     RenderObject* beforeAfterParent = findBeforeAfterParent(child);
371     if (!beforeAfterParent)
372         return;
373
374     // When beforeAfterParent is not equal to child (e.g. in tables),
375     // we need to create new styles inheriting from pseudoElementStyle
376     // on all the intermediate parents (leaving their display same).
377     if (beforeAfterParent != child) {
378         RenderObject* curr = beforeAfterParent;
379         while (curr && curr != child) {
380             ASSERT(curr->isAnonymous());
381             RefPtr<RenderStyle> newStyle = RenderStyle::create();
382             newStyle->inheritFrom(pseudoElementStyle);
383             newStyle->setDisplay(curr->style()->display());
384             newStyle->setStyleType(curr->style()->styleType());
385             curr->setStyle(newStyle);
386             curr = curr->parent();
387         }
388     }
389
390     // Note that if we ever support additional types of generated content (which should be way off
391     // in the future), this code will need to be patched.
392     for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
393         if (genChild->isText())
394             // Generated text content is a child whose style also needs to be set to the pseudo-element style.
395             genChild->setStyle(pseudoElementStyle);
396         else if (genChild->isImage()) {
397             // Images get an empty style that inherits from the pseudo.
398             RefPtr<RenderStyle> style = RenderStyle::create();
399             style->inheritFrom(pseudoElementStyle);
400             genChild->setStyle(style.release());
401         } else {
402             // RenderListItem may insert a list marker here. We do not need to care about this case.
403             // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it.
404             ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER);
405         }
406     }
407 }
408
409 static RenderObject* createRendererForBeforeAfterContent(RenderObject* owner, const ContentData* content, RenderStyle* pseudoElementStyle)
410 {
411     RenderObject* renderer = 0;
412     switch (content->type()) {
413     case CONTENT_NONE:
414         break;
415     case CONTENT_TEXT:
416         renderer = new (owner->renderArena()) RenderTextFragment(owner->document() /* anonymous object */, static_cast<const TextContentData*>(content)->text().impl());
417         renderer->setStyle(pseudoElementStyle);
418         break;
419     case CONTENT_OBJECT: {
420         RenderImage* image = new (owner->renderArena()) RenderImage(owner->document()); // anonymous object
421         RefPtr<RenderStyle> style = RenderStyle::create();
422         style->inheritFrom(pseudoElementStyle);
423         image->setStyle(style.release());
424         if (const StyleImage* styleImage = static_cast<const ImageContentData*>(content)->image())
425             image->setImageResource(RenderImageResourceStyleImage::create(const_cast<StyleImage*>(styleImage)));
426         else
427             image->setImageResource(RenderImageResource::create());
428         renderer = image;
429         break;
430     }
431     case CONTENT_COUNTER:
432         renderer = new (owner->renderArena()) RenderCounter(owner->document(), *static_cast<const CounterContentData*>(content)->counter());
433         renderer->setStyle(pseudoElementStyle);
434         break;
435     case CONTENT_QUOTE:
436         renderer = new (owner->renderArena()) RenderQuote(owner->document(), static_cast<const QuoteContentData*>(content)->quote());
437         renderer->setStyle(pseudoElementStyle);
438         break;
439     }
440     return renderer;
441 }
442
443 void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject)
444 {
445     // Double check that the document did in fact use generated content rules.  Otherwise we should not have been called.
446     ASSERT(owner->document()->usesBeforeAfterRules());
447
448     // In CSS2, before/after pseudo-content cannot nest.  Check this first.
449     if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER)
450         return;
451     
452     if (!styledObject)
453         styledObject = owner;
454
455     RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
456     RenderObject* child;
457     switch (type) {
458     case BEFORE:
459         child = beforePseudoElementRenderer(owner);
460         break;
461     case AFTER:
462         child = afterPseudoElementRenderer(owner);
463         break;
464     default:
465         ASSERT_NOT_REACHED();
466         return;
467     }
468
469     // Whether or not we currently have generated content attached.
470     bool oldContentPresent = child;
471
472     // Whether or not we now want generated content.
473     bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
474
475     // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
476     // :after content and not :before content.
477     if (newContentWanted && type == BEFORE && owner->isElementContinuation())
478         newContentWanted = false;
479
480     // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
481     // then we don't generate the :after content.
482     if (newContentWanted && type == AFTER && owner->virtualContinuation())
483         newContentWanted = false;
484     
485     // If we don't want generated content any longer, or if we have generated content, but it's no longer
486     // identical to the new content data we want to build render objects for, then we nuke all
487     // of the old generated content.
488     if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle, owner->document()) == Node::Detach)) {
489         // Nuke the child. 
490         if (child->style()->styleType() == type) {
491             oldContentPresent = false;
492             child->destroy();
493             child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild();
494         }
495     }
496
497     // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
498     // have no generated content and can now return.
499     if (!newContentWanted)
500         return;
501
502     if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && !pseudoElementStyle->isFloating() &&
503         !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
504         // According to the CSS2 spec (the end of section 12.1), the only allowed
505         // display values for the pseudo style are NONE and INLINE for inline flows.
506         // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
507         // For now we at least relax the restriction to allow all inline types like inline-block
508         // and inline-table.
509         pseudoElementStyle->setDisplay(INLINE);
510
511     if (oldContentPresent) {
512         updateBeforeAfterStyle(child, type, pseudoElementStyle);
513         return; // We've updated the generated content. That's all we needed to do.
514     }
515     
516     RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0;
517     if (insertBefore && insertBefore->isAnonymousBlock() && insertBefore->childrenInline() && !insertBefore->isEmpty()) {
518         // We are going to add the "before" element. We have to check whether the "insertBefore" element
519         // is an anonymous block with inline children. If it is, then we should insert the "before" element
520         // before the first inline child of the anonymous block, otherwise we will end up with the "before"
521         // element in a different block. We do this only when the anonymous block has children, otherwise
522         // we end up with the before element in a wrong block.
523         insertBefore = insertBefore->firstChild();
524     }
525
526     // Nothing goes before the intruded run-in, not even generated content.
527     if (insertBefore && insertBefore->isRunIn() && owner->isRenderBlock()
528         && toRenderBlock(owner)->runInIsPlacedIntoSiblingBlock(insertBefore))
529         insertBefore = insertBefore->nextSibling();
530
531     // Generated content consists of a single container that houses multiple children (specified
532     // by the content property).  This generated content container gets the pseudo-element style set on it.
533     RenderObject* generatedContentContainer = 0;
534
535     // Walk our list of generated content and create render objects for each.
536     for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
537         RenderObject* renderer =  createRendererForBeforeAfterContent(owner, content, pseudoElementStyle);
538
539         if (renderer) {
540             if (!generatedContentContainer) {
541                 // Make a generated box that might be any display type now that we are able to drill down into children
542                 // to find the original content properly.
543                 generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
544                 ASSERT(styledObject->node()); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.
545                 generatedContentContainer->setNode(styledObject->node()); // This allows access to the generatingNode.
546                 generatedContentContainer->setStyle(pseudoElementStyle);
547                 if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) {
548                     // The generated content container is not allowed here -> abort.
549                     generatedContentContainer->destroy();
550                     renderer->destroy();
551                     return;
552                 }
553
554                 // When we don't have a first child and are part of a continuation chain,
555                 // insertBefore is incorrectly set to zero above, which causes the :before
556                 // child to end up at the end of continuation chain.
557                 // See https://bugs.webkit.org/show_bug.cgi?id=78380.
558                 if (!insertBefore && type == BEFORE && owner->virtualContinuation())
559                     owner->addChildIgnoringContinuation(generatedContentContainer, 0);
560                 else
561                     owner->addChild(generatedContentContainer, insertBefore);
562             }
563             if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))
564                 generatedContentContainer->addChild(renderer);
565             else
566                 renderer->destroy();
567         }
568     }
569
570     if (!generatedContentContainer)
571         return;
572
573     // Handle placement of run-ins. We do the run-in placement at the end since generatedContentContainer can get destroyed.
574     RenderObject* generatedContentContainerImmediateParent = generatedContentContainer->parent();
575     if (generatedContentContainerImmediateParent->isRenderBlock())
576         toRenderBlock(generatedContentContainerImmediateParent)->placeRunInIfNeeded(generatedContentContainer, PlaceGeneratedRunIn);
577 }
578
579 } // namespace WebCore