Changeset 131004 in webkit


Ignore:
Timestamp:
Oct 10, 2012 8:17:42 PM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Move :before and :after into the DOM
https://bugs.webkit.org/show_bug.cgi?id=95117

Patch by Elliott Sprehn <esprehn@chromium.org> on 2012-10-10
Reviewed by Eric Seidel.

Source/WebCore:

Reimplement generated content :before and :after as DOM Elements. Now ElementRareData has
two RefPtrs to PseudoElements for the generated content and Node has methods for traversing
the tree including generated content.

This allows the generated content to be treated as real nodes instead of anonymous and take
part in the usual recalcStyle and attach flow which fixes many bugs and vastly simplifies the
lifecycle of generated content.

No new tests needed for now.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • Target.pri:
  • WebCore.gypi:
  • WebCore.vcproj/WebCore.vcproj:
  • WebCore.xcodeproj/project.pbxproj:
  • dom/DOMAllInOne.cpp:
  • dom/Element.cpp:

(WebCore::Element::attach): Add generated content if needed.
(WebCore::Element::detach): Remove all child generated content.
(WebCore::Element::recalcStyle): Add or remove generated content based on the new style.
(WebCore::Element::updatePseudoElement): Updates pseudo content based on a pseudoId.
(WebCore):
(WebCore::Element::createPseudoElementIfNeeded):
(WebCore::Element::beforePseudoElement):
(WebCore::Element::afterPseudoElement):

  • dom/Element.h:

(WebCore):
(Element):

  • dom/ElementRareData.h:

(ElementRareData):
(WebCore::ElementRareData::setPseudoElement):
(WebCore):
(WebCore::ElementRareData::pseudoElement):

  • dom/Node.cpp:

(WebCore::Node::pseudoAwarePreviousSibling):
(WebCore):
(WebCore::Node::pseudoAwareNextSibling):
(WebCore::checkAcceptChild): Forbid moving PseudoElements for sanity. The code never does this.

  • dom/Node.h:

(Node):
(WebCore::Node::isPseudoElement):
(WebCore::Node::pseudoId): Fast path that only calls virtualPseudoId if the node has custom callbacks so isPseudoElement is fast.
(WebCore::Node::virtualPseudoId):
(WebCore::Node::isBeforePseudoElement):
(WebCore::Node::isAfterPseudoElement):

  • dom/NodeRenderingContext.cpp:

(WebCore::NodeRenderingContext::nextRenderer): Changed to find the next sibling of pseudos for insertion.

  • dom/PseudoElement.cpp: Added.

(WebCore):
(WebCore::pseudoElementName):
(WebCore::PseudoElement::PseudoElement):
(WebCore::PseudoElement::pseudoRendererIsNeeded):
(WebCore::PseudoElement::customStyleForRenderer):
(WebCore::PseudoElement::attach):
(WebCore::PseudoElement::rendererIsNeeded):
(WebCore::PseudoElement::updateChildStyle): Propagates the style downward into the anonymous renderers for the content.
(WebCore::PseudoElement::didRecalcStyle):
(WebCore::PseudoElement::createRendererForContent): Refactored from RenderObjectChildList.

  • dom/PseudoElement.h: Added.

(WebCore):
(PseudoElement):
(WebCore::PseudoElement::create):
(WebCore::toPseudoElement):

  • rendering/HitTestResult.cpp:

(WebCore::HitTestResult::setInnerNode): Hit testing a PseudoElement should really hit the parent.
(WebCore::HitTestResult::setInnerNonSharedNode): Same as above.

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::styleDidChange): Remove old generated content code, same for below.
(WebCore::RenderBlock::splitBlocks):
(WebCore::RenderBlock::addChildIgnoringAnonymousColumnBlocks):
(WebCore::RenderBlock::createReplacementRunIn):
(WebCore::RenderBlock::renderName):

  • rendering/RenderBlock.h:

(RenderBlock):

  • rendering/RenderButton.cpp:
  • rendering/RenderButton.h:

(RenderButton):

  • rendering/RenderCounter.cpp:

(WebCore::RenderCounter::originalText):

  • rendering/RenderDeprecatedFlexibleBox.cpp:

(WebCore::RenderDeprecatedFlexibleBox::renderName):

  • rendering/RenderGrid.cpp:

(WebCore::RenderGrid::renderName):

  • rendering/RenderInline.cpp:

(WebCore::RenderInline::styleDidChange):
(WebCore::RenderInline::addChildIgnoringContinuation):
(WebCore::RenderInline::splitInlines):
(WebCore::RenderInline::renderName):

  • rendering/RenderListItem.cpp:

(WebCore::RenderListItem::updateMarkerLocation):

  • rendering/RenderMultiColumnBlock.cpp:

(WebCore::RenderMultiColumnBlock::renderName):

  • rendering/RenderObject.cpp:

(WebCore::RenderObject::createObject):

  • rendering/RenderObject.h:

(WebCore::RenderObject::isPseudoElement):
(RenderObject):
(WebCore::RenderObject::generatingNode):

  • rendering/RenderObjectChildList.cpp:
  • rendering/RenderObjectChildList.h:

(RenderObjectChildList):

  • rendering/RenderRubyText.cpp:
  • rendering/RenderRubyText.h:

(RenderRubyText):

  • rendering/RenderTableCell.h:

(WebCore::RenderTableCell::renderName):

  • rendering/RenderTableRow.cpp:

(WebCore::RenderTableRow::styleDidChange):

  • rendering/RenderTableRow.h:

(WebCore::RenderTableRow::renderName):

  • rendering/RenderTableSection.cpp:

(WebCore::RenderTableSection::addChild):

  • rendering/RenderTableSection.h:

(WebCore::RenderTableSection::renderName):

  • rendering/RenderTreeAsText.cpp:

(WebCore::RenderTreeAsText::writeRenderObject):

LayoutTests:

Regenerated some baselines for tests given the new generated content architecture and disabled
tests that are testing generated content on inputs which were wrong.

  • fast/css-generated-content/before-content-continuation-chain-expected.txt:
  • platform/chromium-mac/fast/css-generated-content/table-row-group-to-inline-expected.png:
  • platform/chromium/TestExpectations: Disable the tests for generated content on inputs. A follow up CL with remove these tests.
  • platform/mac/fast/css-generated-content/table-row-group-to-inline-expected.png:
  • platform/mac/fast/css-generated-content/table-row-group-to-inline-expected.txt:

This test always produced wrong output because we leave an anonymous RenderTable in the tree,
and now that generated content is handled like DOM nodes this test renders differently since the
content ends up after the left over RenderTable. Both outputs are wrong until Bug 86261 is fixed.

Location:
trunk
Files:
2 added
43 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r131000 r131004  
     12012-10-10  Elliott Sprehn  <esprehn@chromium.org>
     2
     3        Move :before and :after into the DOM       
     4        https://bugs.webkit.org/show_bug.cgi?id=95117
     5
     6        Reviewed by Eric Seidel.
     7
     8        Regenerated some baselines for tests given the new generated content architecture and disabled
     9        tests that are testing generated content on inputs which were wrong.
     10
     11        * fast/css-generated-content/before-content-continuation-chain-expected.txt:
     12        * platform/chromium-mac/fast/css-generated-content/table-row-group-to-inline-expected.png:
     13        * platform/chromium/TestExpectations: Disable the tests for generated content on inputs. A follow up CL with remove these tests.
     14        * platform/mac/fast/css-generated-content/table-row-group-to-inline-expected.png:
     15        * platform/mac/fast/css-generated-content/table-row-group-to-inline-expected.txt:
     16           This test always produced wrong output because we leave an anonymous RenderTable in the tree,
     17           and now that generated content is handled like DOM nodes this test renders differently since the
     18           content ends up after the left over RenderTable. Both outputs are wrong until Bug 86261 is fixed.
     19
    1202012-10-10  Levi Weintraub  <leviw@chromium.org>
    221
  • trunk/LayoutTests/fast/css-generated-content/before-content-continuation-chain-expected.txt

    r108109 r131004  
    44  RenderBlock {HTML} at (0,0) size 800x416
    55    RenderBody {BODY} at (8,8) size 784x400
     6      RenderBlock (anonymous) at (0,0) size 784x0
     7        RenderInline {SPAN} at (0,0) size 0x0 [color=#008000]
    68      RenderBlock (anonymous) at (0,0) size 784x200
    7         RenderInline {SPAN} at (0,0) size 200x200 [color=#008000]
    8           RenderInline (generated) at (0,0) size 200x200 [color=#0000FF]
    9             RenderText at (0,0) size 200x200
    10               text run at (0,0) width 200: "A"
    11       RenderBlock (anonymous) at (0,200) size 784x0
    12         RenderBlock {DIV} at (0,0) size 784x0 [color=#008000]
     9        RenderBlock (generated) at (0,0) size 784x200 [color=#0000FF]
     10          RenderText at (0,0) size 200x200
     11            text run at (0,0) width 200: "A"
     12        RenderBlock {DIV} at (0,200) size 784x0 [color=#008000]
    1313      RenderBlock (anonymous) at (0,200) size 784x200
    1414        RenderInline {SPAN} at (0,0) size 200x200 [color=#008000]
  • trunk/LayoutTests/platform/chromium/TestExpectations

    r131000 r131004  
    36153615webkit.org/b/97325 css3/masking/clip-path-circle-relative-overflow.html [ ImageOnlyFailure Pass ]
    36163616
     3617# Needs rebaseline after bug 95117 is fixed
     3618webkit.org/b/98687 fast/css-generated-content/table-row-group-to-inline.html [ Failure Pass ]
     3619
     3620# Should not be testing for generated content in inputs yet.
     3621webkit.org/b/98836 fast/forms/time-multiple-fields/time-multiple-fields-appearance-pseudo-elements.html [ Skip ]
     3622webkit.org/b/98836 fast/forms/month-multiple-fields/month-multiple-fields-appearance-pseudo-elements.html [ Skip ]
     3623webkit.org/b/98836 fast/forms/week-multiple-fields/week-multiple-fields-appearance-pseudo-elements.html [ Skip ]
     3624webkit.org/b/98836 fast/forms/date-multiple-fields/date-multiple-fields-appearance-pseudo-elements.html [ Skip ]
     3625
    36173626webkit.org/b/91544 media/media-continues-playing-after-replace-source.html [ Pass Timeout ]
    36183627
  • trunk/LayoutTests/platform/mac/fast/css-generated-content/table-row-group-to-inline-expected.txt

    r35318 r131004  
    1515          RenderBlock (anonymous) at (0,0) size 744x18
    1616            RenderListMarker at (-17,0) size 7x18: bullet
     17          RenderTable at (0,18) size 0x0
     18          RenderBlock (anonymous) at (0,18) size 744x18
    1719            RenderInline (generated) at (0,0) size 31x18
    1820              RenderText at (0,0) size 31x18
    1921                text run at (0,0) width 31: "hello"
    20           RenderTable at (0,18) size 0x0
    21           RenderBlock (anonymous) at (0,18) size 744x18
    22             RenderText {#text} at (0,0) size 21x18
    23               text run at (0,0) width 21: "test"
     22            RenderText {#text} at (31,0) size 21x18
     23              text run at (31,0) width 21: "test"
  • trunk/Source/WebCore/CMakeLists.txt

    r130962 r131004  
    11971197    dom/ProgressEvent.cpp
    11981198    dom/PropertyNodeList.cpp
     1199    dom/PseudoElement.cpp
    11991200    dom/QualifiedName.cpp
    12001201    dom/Range.cpp
  • trunk/Source/WebCore/ChangeLog

    r131003 r131004  
     12012-10-10  Elliott Sprehn  <esprehn@chromium.org>
     2
     3        Move :before and :after into the DOM       
     4        https://bugs.webkit.org/show_bug.cgi?id=95117
     5
     6        Reviewed by Eric Seidel.
     7
     8        Reimplement generated content :before and :after as DOM Elements. Now ElementRareData has
     9        two RefPtrs to PseudoElements for the generated content and Node has methods for traversing
     10        the tree including generated content.
     11
     12        This allows the generated content to be treated as real nodes instead of anonymous and take
     13        part in the usual recalcStyle and attach flow which fixes many bugs and vastly simplifies the
     14        lifecycle of generated content.
     15
     16        No new tests needed for now.
     17
     18        * CMakeLists.txt:
     19        * GNUmakefile.list.am:
     20        * Target.pri:
     21        * WebCore.gypi:
     22        * WebCore.vcproj/WebCore.vcproj:
     23        * WebCore.xcodeproj/project.pbxproj:
     24        * dom/DOMAllInOne.cpp:
     25        * dom/Element.cpp:
     26        (WebCore::Element::attach): Add generated content if needed.
     27        (WebCore::Element::detach): Remove all child generated content.
     28        (WebCore::Element::recalcStyle): Add or remove generated content based on the new style.
     29        (WebCore::Element::updatePseudoElement): Updates pseudo content based on a pseudoId.
     30        (WebCore):
     31        (WebCore::Element::createPseudoElementIfNeeded):
     32        (WebCore::Element::beforePseudoElement):
     33        (WebCore::Element::afterPseudoElement):
     34        * dom/Element.h:
     35        (WebCore):
     36        (Element):
     37        * dom/ElementRareData.h:
     38        (ElementRareData):
     39        (WebCore::ElementRareData::setPseudoElement):
     40        (WebCore):
     41        (WebCore::ElementRareData::pseudoElement):
     42        * dom/Node.cpp:
     43        (WebCore::Node::pseudoAwarePreviousSibling):
     44        (WebCore):
     45        (WebCore::Node::pseudoAwareNextSibling):
     46        (WebCore::checkAcceptChild): Forbid moving PseudoElements for sanity. The code never does this.
     47        * dom/Node.h:
     48        (Node):
     49        (WebCore::Node::isPseudoElement):
     50        (WebCore::Node::pseudoId): Fast path that only calls virtualPseudoId if the node has custom callbacks so isPseudoElement is fast.
     51        (WebCore::Node::virtualPseudoId):
     52        (WebCore::Node::isBeforePseudoElement):
     53        (WebCore::Node::isAfterPseudoElement):
     54        * dom/NodeRenderingContext.cpp:
     55        (WebCore::NodeRenderingContext::nextRenderer): Changed to find the next sibling of pseudos for insertion.
     56        * dom/PseudoElement.cpp: Added.
     57        (WebCore):
     58        (WebCore::pseudoElementName):
     59        (WebCore::PseudoElement::PseudoElement):
     60        (WebCore::PseudoElement::pseudoRendererIsNeeded):
     61        (WebCore::PseudoElement::customStyleForRenderer):
     62        (WebCore::PseudoElement::attach):
     63        (WebCore::PseudoElement::rendererIsNeeded):
     64        (WebCore::PseudoElement::updateChildStyle): Propagates the style downward into the anonymous renderers for the content.
     65        (WebCore::PseudoElement::didRecalcStyle):
     66        (WebCore::PseudoElement::createRendererForContent): Refactored from RenderObjectChildList.
     67        * dom/PseudoElement.h: Added.
     68        (WebCore):
     69        (PseudoElement):
     70        (WebCore::PseudoElement::create):
     71        (WebCore::toPseudoElement):
     72        * rendering/HitTestResult.cpp:
     73        (WebCore::HitTestResult::setInnerNode): Hit testing a PseudoElement should really hit the parent.
     74        (WebCore::HitTestResult::setInnerNonSharedNode): Same as above.
     75        * rendering/RenderBlock.cpp:
     76        (WebCore::RenderBlock::styleDidChange): Remove old generated content code, same for below.
     77        (WebCore::RenderBlock::splitBlocks):
     78        (WebCore::RenderBlock::addChildIgnoringAnonymousColumnBlocks):
     79        (WebCore::RenderBlock::createReplacementRunIn):
     80        (WebCore::RenderBlock::renderName):
     81        * rendering/RenderBlock.h:
     82        (RenderBlock):
     83        * rendering/RenderButton.cpp:
     84        * rendering/RenderButton.h:
     85        (RenderButton):
     86        * rendering/RenderCounter.cpp:
     87        (WebCore::RenderCounter::originalText):
     88        * rendering/RenderDeprecatedFlexibleBox.cpp:
     89        (WebCore::RenderDeprecatedFlexibleBox::renderName):
     90        * rendering/RenderGrid.cpp:
     91        (WebCore::RenderGrid::renderName):
     92        * rendering/RenderInline.cpp:
     93        (WebCore::RenderInline::styleDidChange):
     94        (WebCore::RenderInline::addChildIgnoringContinuation):
     95        (WebCore::RenderInline::splitInlines):
     96        (WebCore::RenderInline::renderName):
     97        * rendering/RenderListItem.cpp:
     98        (WebCore::RenderListItem::updateMarkerLocation):
     99        * rendering/RenderMultiColumnBlock.cpp:
     100        (WebCore::RenderMultiColumnBlock::renderName):
     101        * rendering/RenderObject.cpp:
     102        (WebCore::RenderObject::createObject):
     103        * rendering/RenderObject.h:
     104        (WebCore::RenderObject::isPseudoElement):
     105        (RenderObject):
     106        (WebCore::RenderObject::generatingNode):
     107        * rendering/RenderObjectChildList.cpp:
     108        * rendering/RenderObjectChildList.h:
     109        (RenderObjectChildList):
     110        * rendering/RenderRubyText.cpp:
     111        * rendering/RenderRubyText.h:
     112        (RenderRubyText):
     113        * rendering/RenderTableCell.h:
     114        (WebCore::RenderTableCell::renderName):
     115        * rendering/RenderTableRow.cpp:
     116        (WebCore::RenderTableRow::styleDidChange):
     117        * rendering/RenderTableRow.h:
     118        (WebCore::RenderTableRow::renderName):
     119        * rendering/RenderTableSection.cpp:
     120        (WebCore::RenderTableSection::addChild):
     121        * rendering/RenderTableSection.h:
     122        (WebCore::RenderTableSection::renderName):
     123        * rendering/RenderTreeAsText.cpp:
     124        (WebCore::RenderTreeAsText::writeRenderObject):
     125
    11262012-10-10  Sam Weinig  <sam@webkit.org>
    2127
  • trunk/Source/WebCore/GNUmakefile.list.am

    r130947 r131004  
    28912891        Source/WebCore/dom/PropertyNodeList.cpp \
    28922892        Source/WebCore/dom/PropertyNodeList.h \
     2893        Source/WebCore/dom/PseudoElement.cpp \
     2894        Source/WebCore/dom/PseudoElement.h \
    28932895        Source/WebCore/dom/QualifiedName.cpp \
    28942896        Source/WebCore/dom/QualifiedName.h \
  • trunk/Source/WebCore/Target.pri

    r130947 r131004  
    439439    dom/ProgressEvent.cpp \
    440440    dom/PropertyNodeList.cpp \
     441    dom/PseudoElement.cpp \
    441442    dom/QualifiedName.cpp \
    442443    dom/Range.cpp \
     
    15991600    dom/ProgressEvent.h \
    16001601    dom/PropertyNodeList.h \
     1602    dom/PseudoElement.h \
    16011603    dom/QualifiedName.h \
    16021604    dom/Range.h \
  • trunk/Source/WebCore/WebCore.gypi

    r130947 r131004  
    682682            'dom/PendingScript.h',
    683683            'dom/Position.h',
     684            'dom/PseudoElement.h',
    684685            'dom/QualifiedName.h',
    685686            'dom/Range.h',
     
    39243925            'dom/PropertyNodeList.cpp',
    39253926            'dom/PropertyNodeList.h',
     3927            'dom/PseudoElement.cpp',
    39263928            'dom/QualifiedName.cpp',
    39273929            'dom/Range.cpp',
  • trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj

    r130962 r131004  
    5356053560                        </File>
    5356153561                        <File
     53562                                RelativePath="..\dom\PseudoElement.h"
     53563                                >
     53564                        </File>
     53565                        <File
     53566                                RelativePath="..\dom\PseudoElement.cpp"
     53567                                >
     53568                                <FileConfiguration
     53569                                        Name="Debug|Win32"
     53570                                        ExcludedFromBuild="true"
     53571                                        >
     53572                                        <Tool
     53573                                                Name="VCCLCompilerTool"
     53574                                        />
     53575                                </FileConfiguration>
     53576                                <FileConfiguration
     53577                                        Name="Release|Win32"
     53578                                        ExcludedFromBuild="true"
     53579                                        >
     53580                                        <Tool
     53581                                                Name="VCCLCompilerTool"
     53582                                        />
     53583                                </FileConfiguration>
     53584                                <FileConfiguration
     53585                                        Name="Debug_Cairo_CFLite|Win32"
     53586                                        ExcludedFromBuild="true"
     53587                                        >
     53588                                        <Tool
     53589                                                Name="VCCLCompilerTool"
     53590                                        />
     53591                                </FileConfiguration>
     53592                                <FileConfiguration
     53593                                        Name="Release_Cairo_CFLite|Win32"
     53594                                        ExcludedFromBuild="true"
     53595                                        >
     53596                                        <Tool
     53597                                                Name="VCCLCompilerTool"
     53598                                        />
     53599                                </FileConfiguration>
     53600                                <FileConfiguration
     53601                                        Name="Debug_All|Win32"
     53602                                        ExcludedFromBuild="true"
     53603                                        >
     53604                                        <Tool
     53605                                                Name="VCCLCompilerTool"
     53606                                        />
     53607                                </FileConfiguration>
     53608                                <FileConfiguration
     53609                                        Name="Production|Win32"
     53610                                        ExcludedFromBuild="true"
     53611                                        >
     53612                                        <Tool
     53613                                                Name="VCCLCompilerTool"
     53614                                        />
     53615                                </FileConfiguration>
     53616                        </File>
     53617                        <File
    5356253618                                RelativePath="..\dom\PropertyNodeList.h"
    5356353619                                >
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r130962 r131004  
    65676567                FE80DA710E9C472F000D6F75 /* JSPositionError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE80DA6D0E9C472F000D6F75 /* JSPositionError.cpp */; };
    65686568                FE80DA720E9C472F000D6F75 /* JSPositionError.h in Headers */ = {isa = PBXBuildFile; fileRef = FE80DA6E0E9C472F000D6F75 /* JSPositionError.h */; };
     6569                FF945ECB161F7F3600971BC8 /* PseudoElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FF945EC9161F7F3600971BC8 /* PseudoElement.cpp */; };
     6570                FF945ECC161F7F3600971BC8 /* PseudoElement.h in Headers */ = {isa = PBXBuildFile; fileRef = FF945ECA161F7F3600971BC8 /* PseudoElement.h */; };
    65696571                FFD5B97A135CC97800D5E92A /* PageVisibilityState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FFD5B977135CC97800D5E92A /* PageVisibilityState.cpp */; };
    65706572                FFD5B97B135CC97800D5E92A /* PageVisibilityState.h in Headers */ = {isa = PBXBuildFile; fileRef = FFD5B978135CC97800D5E92A /* PageVisibilityState.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    1401914021                FE80DA6D0E9C472F000D6F75 /* JSPositionError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPositionError.cpp; sourceTree = "<group>"; };
    1402014022                FE80DA6E0E9C472F000D6F75 /* JSPositionError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPositionError.h; sourceTree = "<group>"; };
     14023                FF945EC9161F7F3600971BC8 /* PseudoElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PseudoElement.cpp; sourceTree = "<group>"; };
     14024                FF945ECA161F7F3600971BC8 /* PseudoElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PseudoElement.h; sourceTree = "<group>"; };
    1402114025                FFD5B977135CC97800D5E92A /* PageVisibilityState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageVisibilityState.cpp; sourceTree = "<group>"; };
    1402214026                FFD5B978135CC97800D5E92A /* PageVisibilityState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageVisibilityState.h; sourceTree = "<group>"; };
     
    2185321857                                1059459815B42AA0004D37FD /* PropertyNodeList.h */,
    2185421858                                1059459A15B42AC0004D37FD /* PropertyNodeList.idl */,
     21859                                FF945EC9161F7F3600971BC8 /* PseudoElement.cpp */,
     21860                                FF945ECA161F7F3600971BC8 /* PseudoElement.h */,
    2185521861                                550A0BC7085F6039007353D6 /* QualifiedName.cpp */,
    2185621862                                550A0BC8085F6039007353D6 /* QualifiedName.h */,
     
    2464624652                                51A052561058874000CC9E95 /* ProtectionSpaceHash.h in Headers */,
    2464724653                                1AF8E11A1256592600230FF7 /* ProxyServer.h in Headers */,
     24654                                FF945ECC161F7F3600971BC8 /* PseudoElement.h in Headers */,
    2464824655                                10FB084B14E15C7E00A3DB98 /* PublicURLManager.h in Headers */,
    2464924656                                E4D687790ED7AE4F006EA978 /* PurgeableBuffer.h in Headers */,
     
    2791227919                                1AF8E13312565A4400230FF7 /* ProxyServer.cpp in Sources */,
    2791327920                                1AF8E1C3125673E000230FF7 /* ProxyServerCFNet.cpp in Sources */,
     27921                                FF945ECB161F7F3600971BC8 /* PseudoElement.cpp in Sources */,
    2791427922                                E4D687770ED7AE3D006EA978 /* PurgeableBufferMac.cpp in Sources */,
    2791527923                                550A0BC9085F6039007353D6 /* QualifiedName.cpp in Sources */,
  • trunk/Source/WebCore/dom/DOMAllInOne.cpp

    r126627 r131004  
    115115#include "ProcessingInstruction.cpp"
    116116#include "ProgressEvent.cpp"
     117#include "PseudoElement.cpp"
    117118#include "Range.cpp"
    118119#include "RangeException.cpp"
  • trunk/Source/WebCore/dom/Element.cpp

    r130354 r131004  
    6262#include "Page.h"
    6363#include "PointerLockController.h"
     64#include "PseudoElement.h"
    6465#include "RenderRegion.h"
    6566#include "RenderView.h"
     
    10171018        if (firstChild())
    10181019            parentPusher.push();
     1020        updatePseudoElement(BEFORE);
    10191021        ContainerNode::attach();
     1022        updatePseudoElement(AFTER);
    10201023    }
    10211024
     
    10471050    if (hasRareData()) {
    10481051        ElementRareData* data = elementRareData();
     1052        data->setPseudoElement(BEFORE, 0);
     1053        data->setPseudoElement(AFTER, 0);
    10491054        data->setIsInCanvasSubtree(false);
    10501055        data->resetComputedStyle();
     
    11981203    }
    11991204
     1205    updatePseudoElement(BEFORE, change);
     1206
    12001207    // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
    12011208    // For now we will just worry about the common case, since it's a lot trickier to get the second case right
     
    12221229    }
    12231230
     1231    updatePseudoElement(AFTER, change);
     1232
    12241233    clearNeedsStyleRecalc();
    12251234    clearChildNeedsStyleRecalc();
     
    18041813}
    18051814
     1815void Element::updatePseudoElement(PseudoId pseudoId, StyleChange change)
     1816{
     1817    PseudoElement* existing = hasRareData() ? elementRareData()->pseudoElement(pseudoId) : 0;
     1818    if (existing) {
     1819        // PseudoElement styles hang off the parent element's style so we need to manually tell
     1820        // the pseudo element it's style has changed (or we could pass Force).
     1821        existing->setNeedsStyleRecalc();
     1822        existing->recalcStyle(change);
     1823        if (!existing->renderer())
     1824            elementRareData()->setPseudoElement(pseudoId, 0);
     1825    } else if (RefPtr<PseudoElement> element = createPseudoElementIfNeeded(pseudoId)) {
     1826        element->attach();
     1827        ensureElementRareData()->setPseudoElement(pseudoId, element);
     1828    }
     1829}
     1830
     1831PassRefPtr<PseudoElement> Element::createPseudoElementIfNeeded(PseudoId pseudoId)
     1832{
     1833    if (!document()->styleSheetCollection()->usesBeforeAfterRules())
     1834        return 0;
     1835
     1836    if (isPseudoElement() || !renderer() || !renderer()->canHaveGeneratedChildren())
     1837        return 0;
     1838
     1839    RenderStyle* style = renderer()->getCachedPseudoStyle(pseudoId);
     1840    if (!style || !PseudoElement::pseudoRendererIsNeeded(style))
     1841        return 0;
     1842
     1843    return PseudoElement::create(this, pseudoId);
     1844}
     1845
     1846PseudoElement* Element::beforePseudoElement() const
     1847{
     1848    return hasRareData() ? elementRareData()->pseudoElement(BEFORE) : 0;
     1849}
     1850
     1851PseudoElement* Element::afterPseudoElement() const
     1852{
     1853    return hasRareData() ? elementRareData()->pseudoElement(AFTER) : 0;
     1854}
     1855
    18061856// ElementTraversal API
    18071857Element* Element::firstElementChild() const
  • trunk/Source/WebCore/dom/Element.h

    r129903 r131004  
    4444class IntSize;
    4545class Localizer;
     46class PseudoElement;
    4647class RenderRegion;
    4748class ShadowRoot;
     
    346347    virtual void beginParsingChildren();
    347348
     349    PseudoElement* beforePseudoElement() const;
     350    PseudoElement* afterPseudoElement() const;
     351
    348352    // ElementTraversal API
    349353    Element* firstElementChild() const;
     
    476480
    477481private:
     482    void updatePseudoElement(PseudoId, StyleChange = NoChange);
     483    PassRefPtr<PseudoElement> createPseudoElementIfNeeded(PseudoId);
     484
    478485    void updateInvalidAttributes() const;
    479486
  • trunk/Source/WebCore/dom/ElementRareData.h

    r130278 r131004  
    3030#include "NamedNodeMap.h"
    3131#include "NodeRareData.h"
     32#include "PseudoElement.h"
    3233#include "StyleInheritedData.h"
    3334#include <wtf/OwnPtr.h>
     
    4142    ElementRareData();
    4243    virtual ~ElementRareData();
     44
     45    void setPseudoElement(PseudoId, PassRefPtr<PseudoElement>);
     46    PseudoElement* pseudoElement(PseudoId) const;
    4347
    4448    void resetComputedStyle();
     
    120124    OwnPtr<NamedNodeMap> m_attributeMap;
    121125
     126    RefPtr<PseudoElement> m_generatedBefore;
     127    RefPtr<PseudoElement> m_generatedAfter;
     128
    122129    IntSize m_savedLayerScrollOffset;
    123130};
     
    138145}
    139146
     147inline void ElementRareData::setPseudoElement(PseudoId pseudoId, PassRefPtr<PseudoElement> element)
     148{
     149    switch (pseudoId) {
     150    case BEFORE:
     151        m_generatedBefore = element;
     152        break;
     153    case AFTER:
     154        m_generatedAfter = element;
     155        break;
     156    default:
     157        ASSERT_NOT_REACHED();
     158    }
     159}
     160
     161inline PseudoElement* ElementRareData::pseudoElement(PseudoId pseudoId) const
     162{
     163    switch (pseudoId) {
     164    case BEFORE:
     165        return m_generatedBefore.get();
     166    case AFTER:
     167        return m_generatedAfter.get();
     168    default:
     169        ASSERT_NOT_REACHED();
     170        return 0;
     171    }
     172}
     173
    140174inline void ElementRareData::resetComputedStyle()
    141175{
  • trunk/Source/WebCore/dom/Node.cpp

    r130824 r131004  
    467467}
    468468
     469Node* Node::pseudoAwarePreviousSibling() const
     470{
     471    if (isElementNode() && !previousSibling()) {
     472        Element* parent = parentOrHostElement();
     473        if (!parent)
     474            return 0;
     475        if (isAfterPseudoElement() && parent->lastChild())
     476            return parent->lastChild();
     477        if (!isBeforePseudoElement())
     478            return parent->beforePseudoElement();
     479    }
     480    return previousSibling();
     481}
     482
     483Node* Node::pseudoAwareNextSibling() const
     484{
     485    if (isElementNode() && !nextSibling()) {
     486        Element* parent = parentOrHostElement();
     487        if (!parent)
     488            return 0;
     489        if (isBeforePseudoElement() && parent->firstChild())
     490            return parent->firstChild();
     491        if (!isAfterPseudoElement())
     492            return parent->afterPseudoElement();
     493    }
     494    return nextSibling();
     495}
     496
    469497NodeRareData* Node::rareData() const
    470498{
     
    11841212        return;
    11851213    }
    1186    
     1214
     1215    // Assert because this should never happen, but also protect non-debug builds
     1216    // from tree corruption.
     1217    ASSERT(!newChild->isPseudoElement());
     1218    if (newChild->isPseudoElement()) {
     1219        ec = HIERARCHY_REQUEST_ERR;
     1220        return;
     1221    }
     1222
    11871223    if (newParent->isReadOnlyNode()) {
    11881224        ec = NO_MODIFICATION_ALLOWED_ERR;
  • trunk/Source/WebCore/dom/Node.h

    r130266 r131004  
    173173    NamedNodeMap* attributes() const;
    174174
     175    Node* pseudoAwarePreviousSibling() const;
     176    Node* pseudoAwareNextSibling() const;
     177
    175178    virtual KURL baseURI() const;
    176179   
     
    217220    bool isSVGElement() const { return getFlag(IsSVGFlag); }
    218221
     222    bool isPseudoElement() const
     223    {
     224        return pseudoId() != NOPSEUDO;
     225    }
     226
     227    PseudoId pseudoId() const
     228    {
     229        return (isElementNode() && hasCustomCallbacks()) ? virtualPseudoId() : NOPSEUDO;
     230    }
     231
     232    virtual PseudoId virtualPseudoId() const { return NOPSEUDO; }
     233    bool isBeforePseudoElement() const { return pseudoId() == BEFORE; }
     234    bool isAfterPseudoElement() const { return pseudoId() == AFTER; }
    219235    virtual bool isMediaControlElement() const { return false; }
    220236    virtual bool isMediaControls() const { return false; }
  • trunk/Source/WebCore/dom/NodeRenderingContext.cpp

    r126359 r131004  
    3636#include "HTMLShadowElement.h"
    3737#include "Node.h"
     38#include "PseudoElement.h"
    3839#include "RenderFullScreen.h"
    3940#include "RenderNamedFlowThread.h"
     
    9394    if (m_parentDetails.node() && !m_parentDetails.node()->attached())
    9495        return 0;
     96
     97    // FIXME: This is wrong when the next sibling was actually moved around by shadow insertion points.
     98    if (m_node->isPseudoElement()) {
     99        Node* sibling = m_node->pseudoAwareNextSibling();
     100        while (sibling && !sibling->renderer())
     101            sibling = sibling->pseudoAwareNextSibling();
     102        return sibling ? sibling->renderer() : 0;
     103    }
    95104
    96105    ComposedShadowTreeWalker walker(m_node);
  • trunk/Source/WebCore/rendering/HitTestResult.cpp

    r128677 r131004  
    262262void HitTestResult::setInnerNode(Node* n)
    263263{
     264    if (n && n->isPseudoElement())
     265        n = n->parentOrHostNode();
    264266    m_innerNode = n;
    265267}
     
    267269void HitTestResult::setInnerNonSharedNode(Node* n)
    268270{
     271    if (n && n->isPseudoElement())
     272        n = n->parentOrHostNode();
    269273    m_innerNonSharedNode = n;
    270274}
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r130824 r131004  
    347347    m_lineHeight = -1;
    348348
    349     // Update pseudos for :before and :after now.
    350     if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules() && canHaveGeneratedChildren()) {
    351         updateBeforeAfterContent(BEFORE);
    352         updateBeforeAfterContent(AFTER);
    353     }
    354 
    355349    // After our style changed, if we lose our ability to propagate floats into next sibling
    356350    // blocks, then we need to find the top most parent containing that overhanging float and
     
    382376        parentBlock->markSiblingsWithFloatsForLayout();
    383377    }
    384 }
    385 
    386 void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId)
    387 {
    388     // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
    389     if (parent() && parent()->createsAnonymousWrapper())
    390         return;
    391     children()->updateBeforeAfterContent(this, pseudoId);
    392378}
    393379
     
    603589    RenderBoxModelObject* currChild = this;
    604590    RenderObject* currChildNextSibling = currChild->nextSibling();
    605     bool documentUsesBeforeAfterRules = document()->styleSheetCollection()->usesBeforeAfterRules();
    606 
    607     // Note: |this| can be destroyed inside this loop if it is an empty anonymous
    608     // block and we try to call updateBeforeAfterContent inside which removes the
    609     // generated content and additionally cleans up |this| empty anonymous block.
    610     // See RenderBlock::removeChild(). DO NOT reference any local variables to |this|
    611     // after this point.
     591
    612592    while (curr && curr != fromBlock) {
    613593        ASSERT(curr->isRenderBlock());
     
    631611            cloneBlock->setContinuation(oldCont);
    632612        }
    633 
    634         // Someone may have indirectly caused a <q> to split.  When this happens, the :after content
    635         // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that the inline's :after
    636         // content gets properly destroyed.
    637         bool isLastChild = (currChildNextSibling == blockCurr->lastChild());
    638         if (documentUsesBeforeAfterRules)
    639             blockCurr->children()->updateBeforeAfterContent(blockCurr, AFTER);
    640         if (isLastChild && currChildNextSibling != blockCurr->lastChild())
    641             currChildNextSibling = 0; // We destroyed the last child, so now we need to update
    642                                       // the value of currChildNextSibling.
    643613
    644614        // Now we need to take all of the children starting from the first child
     
    872842            if (!isAnonymousBlock())
    873843                setContinuation(newBox);
    874 
    875             // Someone may have put a <p> inside a <q>, causing a split.  When this happens, the :after content
    876             // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that our :after
    877             // content gets properly destroyed.
    878             bool isFirstChild = (beforeChild == firstChild());
    879             bool isLastChild = (beforeChild == lastChild());
    880             if (document()->styleSheetCollection()->usesBeforeAfterRules())
    881                 children()->updateBeforeAfterContent(this, AFTER);
    882             if (isLastChild && beforeChild != lastChild()) {
    883                 // We destroyed the last child, so now we need to update our insertion
    884                 // point to be 0. It's just a straight append now.
    885                 beforeChild = 0;
    886             } else if (isFirstChild && beforeChild != firstChild()) {
    887                 // If beforeChild was the last anonymous block that collapsed,
    888                 // then we need to update its value.
    889                 beforeChild = firstChild();
    890             }
    891844
    892845            splitFlow(beforeChild, newBox, newChild, oldContinuation);
     
    18661819    ASSERT(runIn->isRunIn());
    18671820
    1868     // First we destroy any :before/:after content. It will be regenerated by the new run-in.
    1869     // Exception is if the run-in itself is generated.
    1870     if (runIn->style()->styleType() != BEFORE && runIn->style()->styleType() != AFTER) {
    1871         RenderObject* generatedContent;
    1872         if (runIn->getCachedPseudoStyle(BEFORE) && (generatedContent = runIn->beforePseudoElementRenderer()))
    1873             generatedContent->destroy();
    1874         if (runIn->getCachedPseudoStyle(AFTER) && (generatedContent = runIn->afterPseudoElementRenderer()))
    1875             generatedContent->destroy();
    1876     }
    1877 
    18781821    bool newRunInShouldBeBlock = !runIn->isRenderBlock();
    18791822    Node* runInNode = runIn->node();
     
    74307373    if (isAnonymousBlock())
    74317374        return "RenderBlock (anonymous)";
    7432     else if (isAnonymous())
     7375    if (isAnonymous())
     7376        return "RenderBlock (generated)";
     7377    // FIXME: Temporary hack while the new generated content system is being implemented.
     7378    if (isPseudoElement())
    74337379        return "RenderBlock (generated)";
    74347380    if (isRelPositioned())
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r130851 r131004  
    543543
    544544    virtual void borderFitAdjust(LayoutRect&) const; // Shrink the box in which the border paints if border-fit is set.
    545 
    546     virtual void updateBeforeAfterContent(PseudoId);
    547545   
    548546    virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby.
  • trunk/Source/WebCore/rendering/RenderButton.cpp

    r129204 r131004  
    150150}
    151151
    152 void RenderButton::updateBeforeAfterContent(PseudoId type)
    153 {
    154     if (m_inner)
    155         m_inner->children()->updateBeforeAfterContent(m_inner, type, this);
    156     else
    157         children()->updateBeforeAfterContent(this, type);
    158 }
    159 
    160152LayoutRect RenderButton::controlClipRect(const LayoutPoint& additionalOffset) const
    161153{
  • trunk/Source/WebCore/rendering/RenderButton.h

    r129204 r131004  
    5151    virtual void updateFromElement();
    5252
    53     virtual void updateBeforeAfterContent(PseudoId);
    54 
    5553    virtual bool canHaveGeneratedChildren() const OVERRIDE;
    5654    virtual bool hasControlClip() const { return true; }
  • trunk/Source/WebCore/rendering/RenderCounter.cpp

    r130612 r131004  
    502502            if (!beforeAfterContainer)
    503503                return 0;
    504             if (!beforeAfterContainer->isAnonymous())
     504            if (!beforeAfterContainer->isAnonymous() && !beforeAfterContainer->isPseudoElement())
    505505                return 0; // RenderCounters are restricted to before and after pseudo elements
    506506            PseudoId containerStyle = beforeAfterContainer->style()->styleType();
  • trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp

    r130549 r131004  
    10861086const char *RenderDeprecatedFlexibleBox::renderName() const
    10871087{
     1088    // FIXME: Temporary hack while the new generated content system is being implemented.
     1089    if (isPseudoElement())
     1090        return "RenderDeprecatedFlexibleBox (generated)";
     1091
    10881092    if (isFloating())
    10891093        return "RenderDeprecatedFlexibleBox (floating)";
  • trunk/Source/WebCore/rendering/RenderGrid.cpp

    r128786 r131004  
    204204const char* RenderGrid::renderName() const
    205205{
     206    // FIXME: Temporary hack while the new generated content system is being implemented.
     207    if (isPseudoElement())
     208        return "RenderGrid (generated)";
     209
    206210    if (isFloating())
    207211        return "RenderGrid (floating)";
  • trunk/Source/WebCore/rendering/RenderInline.cpp

    r130829 r131004  
    4141#include "VisiblePosition.h"
    4242
    43 #include <wtf/TemporaryChange.h>
    44 
    4543#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION)
    4644#include "Frame.h"
     
    170168    RenderStyle* newStyle = style();
    171169    RenderInline* continuation = inlineElementContinuation();
    172     {
    173         TemporaryChange<bool> enableAfter(RenderObjectChildList::s_enableUpdateBeforeAfterContent, false);
    174         RenderInline* nextInlineElementCont = 0;
    175         for (RenderInline* currCont = continuation; currCont; currCont = nextInlineElementCont) {
    176             nextInlineElementCont = currCont->inlineElementContinuation();
    177             // We need to update :after content for the last continuation in the chain.
    178             RenderObjectChildList::s_enableUpdateBeforeAfterContent = !nextInlineElementCont;
    179             RenderBoxModelObject* nextCont = currCont->continuation();
    180             currCont->setContinuation(0);
    181             currCont->setStyle(newStyle);
    182             currCont->setContinuation(nextCont);
    183         }
     170    for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) {
     171        RenderBoxModelObject* nextCont = currCont->continuation();
     172        currCont->setContinuation(0);
     173        currCont->setStyle(newStyle);
     174        currCont->setContinuation(nextCont);
    184175    }
    185176
     
    201192        }
    202193        m_alwaysCreateLineBoxes = alwaysCreateLineBoxes;
    203     }
    204 
    205     // Update pseudos for :before and :after now.
    206     if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules()) {
    207         children()->updateBeforeAfterContent(this, BEFORE);
    208         children()->updateBeforeAfterContent(this, AFTER);
    209194    }
    210195}
     
    329314        RenderBoxModelObject* oldContinuation = continuation();
    330315        setContinuation(newBox);
    331 
    332         // Someone may have put a <p> inside a <q>, causing a split.  When this happens, the :after content
    333         // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that our :after
    334         // content gets properly destroyed.
    335         bool isLastChild = (beforeChild == lastChild());
    336         if (document()->styleSheetCollection()->usesBeforeAfterRules())
    337             children()->updateBeforeAfterContent(this, AFTER);
    338         if (isLastChild && beforeChild != lastChild())
    339             beforeChild = 0; // We destroyed the last child, so now we need to update our insertion
    340                              // point to be 0.  It's just a straight append now.
    341316
    342317        splitFlow(beforeChild, newBox, newChild, oldContinuation);
     
    405380            inlineCurr->setContinuation(cloneInline);
    406381            cloneInline->setContinuation(oldCont);
    407 
    408             // Someone may have indirectly caused a <q> to split.  When this happens, the :after content
    409             // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that the inline's :after
    410             // content gets properly destroyed.
    411             if (document()->styleSheetCollection()->usesBeforeAfterRules())
    412                 inlineCurr->children()->updateBeforeAfterContent(inlineCurr, AFTER);
    413382
    414383            // Now we need to take all of the children starting from the first child
     
    764733    if (isAnonymous())
    765734        return "RenderInline (generated)";
     735    // FIXME: Temporary hack while the new generated content system is being implemented.
     736    if (isPseudoElement())
     737        return "RenderInline (generated)";
    766738    if (isRunIn())
    767739        return "RenderInline (run-in)";
  • trunk/Source/WebCore/rendering/RenderListItem.cpp

    r126359 r131004  
    269269                m_marker->computePreferredLogicalWidths();
    270270            // If markerPar is an anonymous block that has lost all its children, destroy it.
    271             // Extraneous anonymous blocks can cause problems for RenderBlock::updateBeforeAfterContent.
    272271            if (markerPar && markerPar->isAnonymousBlock() && !markerPar->firstChild() && !toRenderBlock(markerPar)->continuation())
    273272                markerPar->destroy();
  • trunk/Source/WebCore/rendering/RenderMultiColumnBlock.cpp

    r128201 r131004  
    147147const char* RenderMultiColumnBlock::renderName() const
    148148{   
     149    // FIXME: Temporary hack while the new generated content system is being implemented.
     150    if (isPseudoElement())
     151        return "RenderMultiColumnBlock (generated)";
     152
    149153    if (isFloating())
    150154        return "RenderMultiColumnBlock (floating)";
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r130829 r131004  
    131131    // Otherwise acts as if we didn't support this feature.
    132132    const ContentData* contentData = style->contentData();
    133     if (contentData && !contentData->next() && contentData->isImage() && doc != node) {
     133    if (contentData && !contentData->next() && contentData->isImage() && doc != node && !node->isPseudoElement()) {
    134134        RenderImage* image = new (arena) RenderImage(node);
    135135        // RenderImageResourceStyleImage requires a style being present on the image but we don't want to
  • trunk/Source/WebCore/rendering/RenderObject.h

    r130829 r131004  
    318318    RenderArena* renderArena() const { return document()->renderArena(); }
    319319
     320    bool isPseudoElement() const { return node() && node()->isPseudoElement(); }
     321
    320322    virtual bool isBR() const { return false; }
    321323    virtual bool isBlockFlow() const { return false; }
     
    610612    // This is the same as node() except for renderers of :before and :after
    611613    // pseudo elements for which their parent node is returned.
    612     Node* generatingNode() const { return m_node == document() ? 0 : m_node; }
     614    Node* generatingNode() const
     615    {
     616        // FIXME: Fix the DOM traversals in RenderCounter and remove the use of generatingNode().
     617        Node* node = m_node == document() ? 0 : m_node;
     618        if (node && node->isPseudoElement())
     619            return node->parentOrHostNode();
     620        return node;
     621    }
    613622    void setNode(Node* node) { m_node = node; }
    614623
  • trunk/Source/WebCore/rendering/RenderObjectChildList.cpp

    r130555 r131004  
    4646namespace WebCore {
    4747
    48 bool RenderObjectChildList::s_enableUpdateBeforeAfterContent = true;
    49 
    5048void RenderObjectChildList::destroyLeftoverChildren()
    5149{
     
    198196}
    199197
    200 static RenderObject* findBeforeAfterParent(RenderObject* object)
    201 {
    202     // Only table parts and flex-boxes need to search for the :before or :after parent
    203     // FIXME: We could likely get away without this check and always look for the right parent.
    204     if (!(object->isTable() || object->isTableSection() || object->isTableRow() || object->isFlexibleBoxIncludingDeprecated()))
    205         return object;
    206 
    207     // If there is a :first-letter style applied on the :before or :after content,
    208     // then we want the parent of the first-letter block
    209     RenderObject* beforeAfterParent = object;
    210     while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage())
    211         && (beforeAfterParent->style()->styleType() != FIRST_LETTER))
    212         beforeAfterParent = beforeAfterParent->firstChild();
    213 
    214     return beforeAfterParent ? beforeAfterParent->parent() : 0;
    215 }
    216 
    217198RenderObject* RenderObjectChildList::beforePseudoElementRenderer(const RenderObject* owner) const
    218199{
     
    261242}
    262243
    263 void RenderObjectChildList::updateBeforeAfterStyle(RenderObject* child, PseudoId type, RenderStyle* pseudoElementStyle)
    264 {
    265     if (!child || child->style()->styleType() != type)
    266         return;
    267 
    268     // We have generated content present still. We want to walk this content and update our
    269     // style information with the new pseudo-element style.
    270     child->setStyle(pseudoElementStyle);
    271 
    272     RenderObject* beforeAfterParent = findBeforeAfterParent(child);
    273     if (!beforeAfterParent)
    274         return;
    275 
    276     // When beforeAfterParent is not equal to child (e.g. in tables),
    277     // we need to create new styles inheriting from pseudoElementStyle
    278     // on all the intermediate parents (leaving their display same).
    279     if (beforeAfterParent != child) {
    280         RenderObject* curr = beforeAfterParent;
    281         while (curr && curr != child) {
    282             ASSERT(curr->isAnonymous());
    283             RefPtr<RenderStyle> newStyle = RenderStyle::create();
    284             newStyle->inheritFrom(pseudoElementStyle);
    285             newStyle->setDisplay(curr->style()->display());
    286             newStyle->setStyleType(curr->style()->styleType());
    287             curr->setStyle(newStyle);
    288             curr = curr->parent();
    289         }
    290     }
    291 
    292     // Note that if we ever support additional types of generated content (which should be way off
    293     // in the future), this code will need to be patched.
    294     for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
    295         if (genChild->isText())
    296             // Generated text content is a child whose style also needs to be set to the pseudo-element style.
    297             genChild->setStyle(pseudoElementStyle);
    298         else if (genChild->isImage()) {
    299             // Images get an empty style that inherits from the pseudo.
    300             RefPtr<RenderStyle> style = RenderStyle::create();
    301             style->inheritFrom(pseudoElementStyle);
    302             genChild->setStyle(style.release());
    303         } else {
    304             // RenderListItem may insert a list marker here. We do not need to care about this case.
    305             // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it.
    306             ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER);
    307         }
    308     }
    309 }
    310 
    311 static RenderObject* createRendererForBeforeAfterContent(RenderObject* owner, const ContentData* content, RenderStyle* pseudoElementStyle)
    312 {
    313     RenderObject* renderer = 0;
    314     switch (content->type()) {
    315     case CONTENT_NONE:
    316         break;
    317     case CONTENT_TEXT:
    318         renderer = new (owner->renderArena()) RenderTextFragment(owner->document() /* anonymous object */, static_cast<const TextContentData*>(content)->text().impl());
    319         renderer->setStyle(pseudoElementStyle);
    320         break;
    321     case CONTENT_OBJECT: {
    322         RenderImage* image = new (owner->renderArena()) RenderImage(owner->document()); // anonymous object
    323         RefPtr<RenderStyle> style = RenderStyle::create();
    324         style->inheritFrom(pseudoElementStyle);
    325         image->setStyle(style.release());
    326         if (const StyleImage* styleImage = static_cast<const ImageContentData*>(content)->image())
    327             image->setImageResource(RenderImageResourceStyleImage::create(const_cast<StyleImage*>(styleImage)));
    328         else
    329             image->setImageResource(RenderImageResource::create());
    330         renderer = image;
    331         break;
    332     }
    333     case CONTENT_COUNTER:
    334         renderer = new (owner->renderArena()) RenderCounter(owner->document(), *static_cast<const CounterContentData*>(content)->counter());
    335         renderer->setStyle(pseudoElementStyle);
    336         break;
    337     case CONTENT_QUOTE:
    338         renderer = new (owner->renderArena()) RenderQuote(owner->document(), static_cast<const QuoteContentData*>(content)->quote());
    339         renderer->setStyle(pseudoElementStyle);
    340         break;
    341     }
    342     return renderer;
    343 }
    344 
    345 static RenderObject* ensureBeforeAfterContainer(RenderObject* owner, PseudoId type, RenderStyle* pseudoElementStyle, Node* generatingNode, RenderObject* insertBefore)
    346 {
    347     // Make a generated box that might be any display type now that we are able to drill down into children
    348     // to find the original content properly.
    349     RenderObject* generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
    350     ASSERT(generatingNode); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.
    351     generatedContentContainer->setNode(generatingNode); // This allows access to the generatingNode.
    352     generatedContentContainer->setStyle(pseudoElementStyle);
    353     if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) {
    354         // The generated content container is not allowed here -> abort.
    355         generatedContentContainer->destroy();
    356         return 0;
    357     }
    358 
    359     // When we don't have a first child and are part of a continuation chain,
    360     // insertBefore is incorrectly set to zero above, which causes the :before
    361     // child to end up at the end of continuation chain.
    362     // See https://bugs.webkit.org/show_bug.cgi?id=78380.
    363     if (!insertBefore && type == BEFORE && owner->virtualContinuation())
    364         owner->addChildIgnoringContinuation(generatedContentContainer, 0);
    365     else
    366         owner->addChild(generatedContentContainer, insertBefore);
    367 
    368     return generatedContentContainer;
    369 }
    370 
    371 void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject)
    372 {
    373     // Double check that the document did in fact use generated content rules.  Otherwise we should not have been called.
    374     ASSERT(owner->document()->styleSheetCollection()->usesBeforeAfterRules());
    375 
    376     // In CSS2, before/after pseudo-content cannot nest.  Check this first.
    377     if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER)
    378         return;
    379     if (!s_enableUpdateBeforeAfterContent)
    380         return;
    381    
    382     if (!styledObject)
    383         styledObject = owner;
    384 
    385     RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
    386     RenderObject* child;
    387     switch (type) {
    388     case BEFORE:
    389         child = beforePseudoElementRenderer(owner);
    390         break;
    391     case AFTER:
    392         child = afterPseudoElementRenderer(owner);
    393         break;
    394     default:
    395         ASSERT_NOT_REACHED();
    396         return;
    397     }
    398 
    399     // Whether or not we currently have generated content attached.
    400     bool oldContentPresent = child;
    401 
    402     // Whether or not we now want generated content.
    403     bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
    404 
    405     // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
    406     // :after content and not :before content.
    407     if (newContentWanted && type == BEFORE && owner->isElementContinuation())
    408         newContentWanted = false;
    409 
    410     // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
    411     // then we don't generate the :after content.
    412     if (newContentWanted && type == AFTER && owner->virtualContinuation())
    413         newContentWanted = false;
    414    
    415     // If we don't want generated content any longer, or if we have generated content, but it's no longer
    416     // identical to the new content data we want to build render objects for, then we nuke all
    417     // of the old generated content.
    418     if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle, owner->document()) == Node::Detach)) {
    419         // Nuke the child.
    420         if (child->style()->styleType() == type) {
    421             oldContentPresent = false;
    422             child->destroy();
    423             child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild();
    424         }
    425     }
    426 
    427     // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
    428     // have no generated content and can now return.
    429     if (!newContentWanted)
    430         return;
    431 
    432     if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && !pseudoElementStyle->isFloating() &&
    433         !pseudoElementStyle->hasOutOfFlowPosition())
    434         // According to the CSS2 spec (the end of section 12.1), the only allowed
    435         // display values for the pseudo style are NONE and INLINE for inline flows.
    436         // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
    437         // For now we at least relax the restriction to allow all inline types like inline-block
    438         // and inline-table.
    439         pseudoElementStyle->setDisplay(INLINE);
    440 
    441     if (oldContentPresent) {
    442         updateBeforeAfterStyle(child, type, pseudoElementStyle);
    443         return; // We've updated the generated content. That's all we needed to do.
    444     }
    445    
    446     RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0;
    447     if (insertBefore && insertBefore->isAnonymousBlock() && insertBefore->childrenInline() && !insertBefore->isEmpty()) {
    448         // We are going to add the "before" element. We have to check whether the "insertBefore" element
    449         // is an anonymous block with inline children. If it is, then we should insert the "before" element
    450         // before the first inline child of the anonymous block, otherwise we will end up with the "before"
    451         // element in a different block. We do this only when the anonymous block has children, otherwise
    452         // we end up with the before element in a wrong block.
    453         insertBefore = insertBefore->firstChild();
    454     }
    455 
    456     // Nothing goes before the intruded run-in, not even generated content.
    457     if (insertBefore && insertBefore->isRunIn() && owner->isRenderBlock()
    458         && toRenderBlock(owner)->runInIsPlacedIntoSiblingBlock(insertBefore))
    459         insertBefore = insertBefore->nextSibling();
    460 
    461     // Generated content consists of a single container that houses multiple children (specified
    462     // by the content property). This generated content container gets the pseudo-element style set on it.
    463     // For pseudo-elements that are regions, the container is the RenderRegion.
    464     RenderObject* generatedContentContainer = 0;
    465 
    466     if (!pseudoElementStyle->regionThread().isEmpty())
    467         generatedContentContainer = ensureBeforeAfterContainer(owner, type, pseudoElementStyle, styledObject->node(), insertBefore);
    468     else {
    469         // Walk our list of generated content and create render objects for each.
    470         for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
    471             RenderObject* renderer = createRendererForBeforeAfterContent(owner, content, pseudoElementStyle);
    472 
    473             if (renderer) {
    474                 if (!generatedContentContainer) {
    475                     generatedContentContainer = ensureBeforeAfterContainer(owner, type, pseudoElementStyle, styledObject->node(), insertBefore);
    476                     if (!generatedContentContainer) {
    477                         renderer->destroy();
    478                         return;
    479                     }
    480                 }
    481                 if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))
    482                     generatedContentContainer->addChild(renderer);
    483                 else
    484                     renderer->destroy();
    485             }
    486         }
    487     }
    488 
    489     if (!generatedContentContainer)
    490         return;
    491 
    492     // Handle placement of run-ins. We do the run-in placement at the end since generatedContentContainer can get destroyed.
    493     RenderObject* generatedContentContainerImmediateParent = generatedContentContainer->parent();
    494     if (generatedContentContainerImmediateParent->isRenderBlock())
    495         toRenderBlock(generatedContentContainerImmediateParent)->placeRunInIfNeeded(generatedContentContainer, PlaceGeneratedRunIn);
    496 }
    497 
    498244} // namespace WebCore
  • trunk/Source/WebCore/rendering/RenderObjectChildList.h

    r130555 r131004  
    5757    void insertChildNode(RenderObject* owner, RenderObject* child, RenderObject* before, bool notifyRenderer = true);
    5858
    59     void updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject = 0);
    6059    RenderObject* beforePseudoElementRenderer(const RenderObject* owner) const;
    6160    RenderObject* afterPseudoElementRenderer(const RenderObject* owner) const;
    6261
    63 public:
    64     static bool s_enableUpdateBeforeAfterContent;
    65 
    6662private:
    67     void updateBeforeAfterStyle(RenderObject* child, PseudoId type, RenderStyle* pseudoElementStyle);
    68 
    6963    RenderObject* m_firstChild;
    7064    RenderObject* m_lastChild;
  • trunk/Source/WebCore/rendering/RenderRubyText.cpp

    r120495 r131004  
    8989}
    9090
    91 void RenderRubyText::updateBeforeAfterContent(PseudoId pseudoId)
    92 {
    93     // RenderRubyText manages its own :before and :after content
    94     // and is not handled by its anonymous wrappers RenderRubyRun
    95     // and RenderRuby. This contrasts with other ruby children, which
    96     // are enclosed in RenderRubyBase and hence they are able to
    97     // update their :before, :after content (since RenderRubyBase
    98     // is not a anonymous wrapper).
    99     return children()->updateBeforeAfterContent(this, pseudoId);
    100 }
    101 
    10291} // namespace WebCore
  • trunk/Source/WebCore/rendering/RenderRubyText.h

    r95901 r131004  
    4747    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
    4848
    49     virtual void updateBeforeAfterContent(PseudoId);
    50 
    5149private:
    5250    virtual bool avoidsFloats() const;
  • trunk/Source/WebCore/rendering/RenderTableCell.h

    r130710 r131004  
    210210
    211211private:
    212     virtual const char* renderName() const { return isAnonymous() ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
     212    virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
    213213
    214214    virtual bool isTableCell() const { return true; }
  • trunk/Source/WebCore/rendering/RenderTableRow.cpp

    r130081 r131004  
    5454}
    5555
    56 void RenderTableRow::updateBeforeAndAfterContent()
    57 {
    58     if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules()) {
    59         children()->updateBeforeAfterContent(this, BEFORE);
    60         children()->updateBeforeAfterContent(this, AFTER);
    61     }
    62 }
    63 
    6456void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
    6557{
     
    6860    RenderBox::styleDidChange(diff, oldStyle);
    6961    propagateStyleToAnonymousChildren();
    70 
    71     if (parent())
    72         updateBeforeAndAfterContent();
    7362
    7463    if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight())
  • trunk/Source/WebCore/rendering/RenderTableRow.h

    r130081 r131004  
    4343    RenderTable* table() const { return toRenderTable(parent()->parent()); }
    4444
    45     void updateBeforeAndAfterContent();
    4645    void paintOutlineForRowIfNeeded(PaintInfo&, const LayoutPoint&);
    4746
     
    9089    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
    9190
    92     virtual const char* renderName() const { return isAnonymous() ? "RenderTableRow (anonymous)" : "RenderTableRow"; }
     91    virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableRow (anonymous)" : "RenderTableRow"; }
    9392
    9493    virtual bool isTableRow() const { return true; }
  • trunk/Source/WebCore/rendering/RenderTableSection.cpp

    r130612 r131004  
    187187    ASSERT(!beforeChild || beforeChild->isTableRow());
    188188    RenderBox::addChild(child, beforeChild);
    189     toRenderTableRow(child)->updateBeforeAndAfterContent();
    190189}
    191190
  • trunk/Source/WebCore/rendering/RenderTableSection.h

    r130454 r131004  
    201201    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
    202202
    203     virtual const char* renderName() const { return isAnonymous() ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
     203    virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
    204204
    205205    virtual bool isTableSection() const { return true; }
  • trunk/Source/WebCore/rendering/RenderTreeAsText.cpp

    r130918 r131004  
    222222    if (o.node()) {
    223223        String tagName = getTagName(o.node());
     224        // FIXME: Temporary hack to make tests pass by simulating the old generated content output.
     225        if (o.isPseudoElement() || (o.parent() && o.parent()->isPseudoElement()))
     226            tagName = emptyAtom;
    224227        if (!tagName.isEmpty()) {
    225228            ts << " {" << tagName << "}";
Note: See TracChangeset for help on using the changeset viewer.