Changeset 109563 in webkit


Ignore:
Timestamp:
Mar 2, 2012 5:27:22 AM (12 years ago)
Author:
rolandsteiner@chromium.org
Message:

Scoped stylesheets don't appear to work in Shadow DOM
https://bugs.webkit.org/show_bug.cgi?id=79549

Source/WebCore:

Make the scope stack in CSSStyleSelector use ContainerNode* instead of Element*.
Adapt using sites accordingly.
Push the ShadowRoot to the scope stack in the same way that elements are pushed.
Fix an issue with removedFromDocument() on destruction.

Reviewed by Antti Koivisto.

Test: fast/css/style-scoped/style-scoped-in-shadow.html

  • css/CSSStyleSelector.cpp:

(RuleSet):
(WebCore::CSSStyleSelector::CSSStyleSelector):
(WebCore::CSSStyleSelector::determineScope):
(WebCore::CSSStyleSelector::ruleSetForScope):
(WebCore::CSSStyleSelector::appendAuthorStylesheets):
(WebCore::CSSStyleSelector::setupScopeStack):
(WebCore::CSSStyleSelector::pushScope):
(WebCore):
(WebCore::CSSStyleSelector::popScope):
(WebCore::CSSStyleSelector::pushParentElement):
(WebCore::CSSStyleSelector::popParentElement):
(WebCore::CSSStyleSelector::pushParentShadowRoot):
(WebCore::CSSStyleSelector::popParentShadowRoot):
(WebCore::CSSStyleSelector::matchScopedAuthorRules):
(WebCore::CSSStyleSelector::collectMatchingRulesForList):

  • css/CSSStyleSelector.h:

(CSSStyleSelector):
(WebCore::CSSStyleSelector::pushScope):
(WebCore::CSSStyleSelector::popScope):
(WebCore::CSSStyleSelector::MatchOptions::MatchOptions):
(MatchOptions):
(WebCore::CSSStyleSelector::scopeStackIsConsistent):
(WebCore::CSSStyleSelector::ScopeStackFrame::ScopeStackFrame):
(ScopeStackFrame):

  • css/SelectorChecker.h:

(SelectorCheckingContext):

  • dom/Element.cpp:

(WebCore::StyleSelectorParentPusher::push):
(WebCore::StyleSelectorParentPusher::~StyleSelectorParentPusher):
(WebCore::Element::beginParsingChildren):
(WebCore::Element::finishParsingChildren):

  • dom/ShadowRoot.cpp:

(WebCore::ShadowRoot::attach):
(WebCore):

  • dom/ShadowRoot.h:

(ShadowRoot):

  • dom/ShadowTree.cpp:

(WebCore::ShadowTree::recalcShadowTreeStyle):

  • html/HTMLStyleElement.cpp:

(WebCore::HTMLStyleElement::removedFromDocument):

LayoutTests:

Test that <style scoped> works in shadow DOM as direct child of the ShadowRoot

Reviewed by Antti Koivisto.

  • fast/css/style-scoped/style-scoped-in-shadow-expected.txt: Added.
  • fast/css/style-scoped/style-scoped-in-shadow.html: Added.
Location:
trunk
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r109554 r109563  
     12012-03-02  Roland Steiner  <rolandsteiner@chromium.org>
     2
     3        Scoped stylesheets don't appear to work in Shadow DOM
     4        https://bugs.webkit.org/show_bug.cgi?id=79549
     5
     6        Test that <style scoped> works in shadow DOM as direct child of the ShadowRoot
     7
     8        Reviewed by Antti Koivisto.
     9
     10        * fast/css/style-scoped/style-scoped-in-shadow-expected.txt: Added.
     11        * fast/css/style-scoped/style-scoped-in-shadow.html: Added.
     12
    1132012-03-02  Philippe Normand  <pnormand@igalia.com>
    214
  • trunk/Source/WebCore/ChangeLog

    r109562 r109563  
     12012-03-02  Roland Steiner  <rolandsteiner@chromium.org>
     2
     3        Scoped stylesheets don't appear to work in Shadow DOM
     4        https://bugs.webkit.org/show_bug.cgi?id=79549
     5
     6        Make the scope stack in CSSStyleSelector use ContainerNode* instead of Element*.
     7        Adapt using sites accordingly.
     8        Push the ShadowRoot to the scope stack in the same way that elements are pushed.
     9        Fix an issue with removedFromDocument() on destruction.
     10
     11        Reviewed by Antti Koivisto.
     12
     13        Test: fast/css/style-scoped/style-scoped-in-shadow.html
     14
     15        * css/CSSStyleSelector.cpp:
     16        (RuleSet):
     17        (WebCore::CSSStyleSelector::CSSStyleSelector):
     18        (WebCore::CSSStyleSelector::determineScope):
     19        (WebCore::CSSStyleSelector::ruleSetForScope):
     20        (WebCore::CSSStyleSelector::appendAuthorStylesheets):
     21        (WebCore::CSSStyleSelector::setupScopeStack):
     22        (WebCore::CSSStyleSelector::pushScope):
     23        (WebCore):
     24        (WebCore::CSSStyleSelector::popScope):
     25        (WebCore::CSSStyleSelector::pushParentElement):
     26        (WebCore::CSSStyleSelector::popParentElement):
     27        (WebCore::CSSStyleSelector::pushParentShadowRoot):
     28        (WebCore::CSSStyleSelector::popParentShadowRoot):
     29        (WebCore::CSSStyleSelector::matchScopedAuthorRules):
     30        (WebCore::CSSStyleSelector::collectMatchingRulesForList):
     31        * css/CSSStyleSelector.h:
     32        (CSSStyleSelector):
     33        (WebCore::CSSStyleSelector::pushScope):
     34        (WebCore::CSSStyleSelector::popScope):
     35        (WebCore::CSSStyleSelector::MatchOptions::MatchOptions):
     36        (MatchOptions):
     37        (WebCore::CSSStyleSelector::scopeStackIsConsistent):
     38        (WebCore::CSSStyleSelector::ScopeStackFrame::ScopeStackFrame):
     39        (ScopeStackFrame):
     40        * css/SelectorChecker.h:
     41        (SelectorCheckingContext):
     42        * dom/Element.cpp:
     43        (WebCore::StyleSelectorParentPusher::push):
     44        (WebCore::StyleSelectorParentPusher::~StyleSelectorParentPusher):
     45        (WebCore::Element::beginParsingChildren):
     46        (WebCore::Element::finishParsingChildren):
     47        * dom/ShadowRoot.cpp:
     48        (WebCore::ShadowRoot::attach):
     49        (WebCore):
     50        * dom/ShadowRoot.h:
     51        (ShadowRoot):
     52        * dom/ShadowTree.cpp:
     53        (WebCore::ShadowTree::recalcShadowTreeStyle):
     54        * html/HTMLStyleElement.cpp:
     55        (WebCore::HTMLStyleElement::removedFromDocument):
     56
    1572012-03-02  Yoshifumi Inoue  <yosin@chromium.org>
    258
  • trunk/Source/WebCore/css/CSSStyleSelector.cpp

    r109541 r109563  
    9393#include "Settings.h"
    9494#include "ShadowData.h"
     95#include "ShadowRoot.h"
    9596#include "ShadowValue.h"
    9697#include "SkewTransformOperation.h"
     
    228229    typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap;
    229230
    230     void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const Element* = 0);
     231    void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const ContainerNode* = 0);
    231232
    232233    void addStyleRule(StyleRule*, bool canUseFastCheckSelector = true, bool isInRegionRule = false);
     
    344345#endif
    345346#if ENABLE(STYLE_SCOPED)
    346     , m_scopingElementStackParent(0)
     347    , m_scopeStackParent(0)
    347348#endif
    348349{
     
    448449
    449450#if ENABLE(STYLE_SCOPED)
    450 const Element* CSSStyleSelector::determineScopingElement(const CSSStyleSheet* sheet)
     451const ContainerNode* CSSStyleSelector::determineScope(const CSSStyleSheet* sheet)
    451452{
    452453    ASSERT(sheet);
     
    463464        return 0;
    464465
    465     return styleElement->parentElement();
    466 }
    467 
    468 inline RuleSet* CSSStyleSelector::scopedRuleSetForElement(const Element* element) const
    469 {
    470     if (!element->hasScopedHTMLStyleChild())
     466    ContainerNode* parent = styleElement->parentNode();
     467    if (!parent)
    471468        return 0;
    472     ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(element);
     469
     470    return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0;
     471}
     472
     473inline RuleSet* CSSStyleSelector::ruleSetForScope(const ContainerNode* scope) const
     474{
     475    if (!scope->hasScopedHTMLStyleChild())
     476        return 0;
     477    ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(scope);
    473478    return it != m_scopedAuthorStyles.end() ? it->second.get() : 0;
    474479}
     
    485490        CSSStyleSheet* cssSheet = static_cast<CSSStyleSheet*>(stylesheets[i].get());
    486491#if ENABLE(STYLE_SCOPED)
    487         const Element* scope = determineScopingElement(cssSheet);
     492        const ContainerNode* scope = determineScope(cssSheet);
    488493        if (scope) {
    489494            pair<ScopedRuleSetMap::iterator, bool> addResult = m_scopedAuthorStyles.add(scope, nullptr);
     
    504509
    505510#if ENABLE(STYLE_SCOPED)
    506 void CSSStyleSelector::setupScopingElementStack(const Element* parent)
     511void CSSStyleSelector::setupScopeStack(const ContainerNode* parent)
    507512{
    508513    // The scoping element stack shouldn't be used if <style scoped> isn't used anywhere.
    509514    ASSERT(!m_scopedAuthorStyles.isEmpty());
    510515
    511     m_scopingElementStack.shrink(0);
    512     for (; parent; parent = parent->parentOrHostElement()) {
    513         RuleSet* ruleSet = scopedRuleSetForElement(parent);
     516    m_scopeStack.shrink(0);
     517    for (; parent; parent = parent->parentOrHostNode()) {
     518        RuleSet* ruleSet = ruleSetForScope(parent);
    514519        if (ruleSet)
    515             m_scopingElementStack.append(ScopeStackFrame(parent, ruleSet));
    516     }
    517     m_scopingElementStack.reverse();
    518     m_scopingElementStackParent = parent;
     520            m_scopeStack.append(ScopeStackFrame(parent, ruleSet));
     521    }
     522    m_scopeStack.reverse();
     523    m_scopeStackParent = parent;
     524}
     525
     526void CSSStyleSelector::pushScope(const ContainerNode* scope, const ContainerNode* scopeParent)
     527{
     528    // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere.
     529    if (m_scopedAuthorStyles.isEmpty()) {
     530        ASSERT(!m_scopeStackParent);
     531        ASSERT(m_scopeStack.isEmpty());
     532        return;
     533    }
     534    // In some wacky cases during style resolve we may get invoked for random elements.
     535    // Recreate the whole scoping element stack in such cases.
     536    if (!scopeStackIsConsistent(scopeParent)) {
     537        setupScopeStack(scope);
     538        return;
     539    }
     540    // Otherwise just push the parent onto the stack.
     541    RuleSet* ruleSet = ruleSetForScope(scope);
     542    if (ruleSet)
     543        m_scopeStack.append(ScopeStackFrame(scope, ruleSet));
     544    m_scopeStackParent = scope;
     545}
     546
     547void CSSStyleSelector::popScope(const ContainerNode* scope)
     548{
     549    // Only bother to update the scoping element stack if it is consistent.
     550    if (scopeStackIsConsistent(scope)) {
     551        m_scopeStack.removeLast();
     552        m_scopeStackParent = scope->parentOrHostNode();
     553    }
    519554}
    520555#endif
    521556
    522 void CSSStyleSelector::pushParent(Element* parent)
    523 {
    524     const Element* parentsParent = parent->parentOrHostElement();
     557void CSSStyleSelector::pushParentElement(Element* parent)
     558{
     559    const ContainerNode* parentsParent = parent->parentOrHostNode();
    525560    // We are not always invoked consistently. For example, script execution can cause us to enter
    526561    // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
     
    531566    else
    532567        m_checker.pushParent(parent);
    533 
    534 #if ENABLE(STYLE_SCOPED)
    535     // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere.
    536     if (m_scopedAuthorStyles.isEmpty()) {
    537         ASSERT(!m_scopingElementStackParent);
    538         ASSERT(m_scopingElementStack.isEmpty());
    539         return;
    540     }
    541     // In some wacky cases during style resolve we may get invoked for random elements.
    542     // Recreate the whole scoping element stack in such cases.
    543     if (!scopingElementStackIsConsistent(parentsParent)) {
    544         setupScopingElementStack(parent);
    545         return;
    546     }
    547     // Otherwise just push the parent onto the stack.
    548     RuleSet* ruleSet = scopedRuleSetForElement(parent);
    549     if (ruleSet)
    550         m_scopingElementStack.append(ScopeStackFrame(parent, ruleSet));
    551     m_scopingElementStackParent = parent;
    552 #endif
    553 }
    554 
    555 void CSSStyleSelector::popParent(Element* parent)
     568    pushScope(parent, parentsParent);
     569}
     570
     571void CSSStyleSelector::popParentElement(Element* parent)
    556572{
    557573    // Note that we may get invoked for some random elements in some wacky cases during style resolve.
     
    559575    if (m_checker.parentStackIsConsistent(parent))
    560576        m_checker.popParent();
    561 #if ENABLE(STYLE_SCOPED)
    562     // Only bother to update the scoping element stack if it is consistent.
    563     if (scopingElementStackIsConsistent(parent)) {
    564         m_scopingElementStack.removeLast();
    565         m_scopingElementStackParent = parent->parentOrHostElement();
    566     }
    567 #endif
     577    popScope(parent);
     578}
     579
     580void CSSStyleSelector::pushParentShadowRoot(const ShadowRoot* shadowRoot)
     581{
     582    ASSERT(shadowRoot->host());
     583    pushScope(shadowRoot, shadowRoot->host());
     584}
     585
     586void CSSStyleSelector::popParentShadowRoot(const ShadowRoot* shadowRoot)
     587{
     588    ASSERT(shadowRoot->host());
     589    popScope(shadowRoot);
    568590}
    569591
     
    859881
    860882    // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
    861     const Element* parent = m_element->parentOrHostElement();
    862     if (!scopingElementStackIsConsistent(parent))
    863         setupScopingElementStack(parent);
    864     for (size_t i = m_scopingElementStack.size(); i; --i) {
    865         const ScopeStackFrame& frame = m_scopingElementStack[i - 1];
    866         options.scope = frame.m_element;
     883    const ContainerNode* parent = m_element->parentOrHostNode();
     884    if (!scopeStackIsConsistent(parent))
     885        setupScopeStack(parent);
     886    for (size_t i = m_scopeStack.size(); i; --i) {
     887        const ScopeStackFrame& frame = m_scopeStack[i - 1];
     888        options.scope = frame.m_scope;
    867889        collectMatchingRules(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
    868890        collectMatchingRulesForRegion(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
    869891    }
    870892    // Also include the current element.
    871     RuleSet* ruleSet = scopedRuleSetForElement(m_element);
     893    RuleSet* ruleSet = ruleSetForScope(m_element);
    872894    if (ruleSet) {
    873895        options.scope = m_element;
     
    21212143}
    21222144
    2123 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData, const Element* scope)
     2145inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData, const ContainerNode* scope)
    21242146{
    21252147    m_dynamicPseudo = NOPSEUDO;
     
    23932415}
    23942416
    2395 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector, const Element* scope)
     2417void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector, const ContainerNode* scope)
    23962418{
    23972419    ASSERT(sheet);
  • trunk/Source/WebCore/css/CSSStyleSelector.h

    r109342 r109563  
    108108
    109109    // Using these during tree walk will allow style selector to optimize child and descendant selector lookups.
    110     void pushParent(Element* parent);
    111     void popParent(Element* parent);
     110    void pushParentElement(Element*);
     111    void popParentElement(Element*);
     112    void pushParentShadowRoot(const ShadowRoot*);
     113    void popParentShadowRoot(const ShadowRoot*);
    112114
    113115    PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, RenderRegion* regionForStyling = 0);
     
    151153    PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeValue&);
    152154
     155#if ENABLE(STYLE_SCOPED)
     156    void pushScope(const ContainerNode* scope, const ContainerNode* scopeParent);
     157    void popScope(const ContainerNode* scope);
     158#else
     159    void pushScope(const ContainerNode*, const ContainerNode*) { }
     160    void popScope(const ContainerNode*) { }
     161#endif
     162
    153163public:
    154164    // These methods will give back the set of rules that matched for a given element (or a pseudo-element).
     
    290300
    291301    struct MatchOptions {
    292         MatchOptions(bool includeEmptyRules, const Element* scope = 0) : scope(scope), includeEmptyRules(includeEmptyRules) { }
    293         const Element* scope;
     302        MatchOptions(bool includeEmptyRules, const ContainerNode* scope = 0) : scope(scope), includeEmptyRules(includeEmptyRules) { }
     303        const ContainerNode* scope;
    294304        bool includeEmptyRules;
    295305    };
     
    311321    void sortAndTransferMatchedRules(MatchResult&);
    312322
    313     bool checkSelector(const RuleData&, const Element* scope = 0);
     323    bool checkSelector(const RuleData&, const ContainerNode* scope = 0);
    314324    bool checkRegionSelector(CSSSelector* regionSelector, Element* regionElement);
    315325    void applyMatchedProperties(const MatchResult&);
     
    454464
    455465#if ENABLE(STYLE_SCOPED)
    456     static const Element* determineScopingElement(const CSSStyleSheet*);
    457 
    458     typedef HashMap<const Element*, OwnPtr<RuleSet> > ScopedRuleSetMap;
    459 
    460     RuleSet* scopedRuleSetForElement(const Element*) const;
    461 
    462     void setupScopingElementStack(const Element*);
    463     bool scopingElementStackIsConsistent(const Element* parent) const { return parent && parent == m_scopingElementStackParent; }
     466    static const ContainerNode* determineScope(const CSSStyleSheet*);
     467
     468    typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > ScopedRuleSetMap;
     469
     470    RuleSet* ruleSetForScope(const ContainerNode*) const;
     471
     472    void setupScopeStack(const ContainerNode*);
     473    bool scopeStackIsConsistent(const ContainerNode* parent) const { return parent && parent == m_scopeStackParent; }
    464474
    465475    ScopedRuleSetMap m_scopedAuthorStyles;
    466476   
    467477    struct ScopeStackFrame {
    468         ScopeStackFrame() : m_element(0), m_ruleSet(0) { }
    469         ScopeStackFrame(const Element* element, RuleSet* ruleSet) : m_element(element), m_ruleSet(ruleSet) { }
    470         const Element* m_element;
     478        ScopeStackFrame() : m_scope(0), m_ruleSet(0) { }
     479        ScopeStackFrame(const ContainerNode* scope, RuleSet* ruleSet) : m_scope(scope), m_ruleSet(ruleSet) { }
     480        const ContainerNode* m_scope;
    471481        RuleSet* m_ruleSet;
    472482    };
    473483    // Vector (used as stack) that keeps track of scoping elements (i.e., elements with a <style scoped> child)
    474484    // encountered during tree iteration for style resolution.
    475     Vector<ScopeStackFrame> m_scopingElementStack;
     485    Vector<ScopeStackFrame> m_scopeStack;
    476486    // Element last seen as parent element when updating m_scopingElementStack.
    477487    // This is used to decide whether m_scopingElementStack is consistent, separately from SelectorChecker::m_parentStack.
    478     const Element* m_scopingElementStackParent;
     488    const ContainerNode* m_scopeStackParent;
    479489#endif
    480490
  • trunk/Source/WebCore/css/SelectorChecker.h

    r107911 r109563  
    6767        CSSSelector* selector;
    6868        Element* element;
    69         const Element* scope;
     69        const ContainerNode* scope;
    7070        VisitedMatchType visitedMatchType;
    7171        RenderStyle* elementStyle;
  • trunk/Source/WebCore/dom/Element.cpp

    r109417 r109563  
    9595            return;
    9696        m_pushedStyleSelector = m_parent->document()->styleSelector();
    97         m_pushedStyleSelector->pushParent(m_parent);
     97        m_pushedStyleSelector->pushParentElement(m_parent);
    9898    }
    9999    ~StyleSelectorParentPusher()
     
    109109            return;
    110110
    111         m_pushedStyleSelector->popParent(m_parent);
     111        m_pushedStyleSelector->popParentElement(m_parent);
    112112    }
    113113
     
    13111311    CSSStyleSelector* styleSelector = document()->styleSelectorIfExists();
    13121312    if (styleSelector && attached())
    1313         styleSelector->pushParent(this);
     1313        styleSelector->pushParentElement(this);
    13141314}
    13151315
     
    13201320    checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
    13211321    if (CSSStyleSelector* styleSelector = document()->styleSelectorIfExists())
    1322         styleSelector->popParent(this);
     1322        styleSelector->popParentElement(this);
    13231323}
    13241324
  • trunk/Source/WebCore/dom/ShadowRoot.cpp

    r109313 r109563  
    2828#include "ShadowRoot.h"
    2929
     30#include "CSSStyleSelector.h"
    3031#include "Document.h"
    3132#include "DocumentFragment.h"
     
    199200}
    200201
    201 }
     202void ShadowRoot::attach()
     203{
     204    CSSStyleSelector* styleSelector = document()->styleSelector();
     205    styleSelector->pushParentShadowRoot(this);
     206    DocumentFragment::attach();
     207    styleSelector->popParentShadowRoot(this);
     208}
     209
     210}
  • trunk/Source/WebCore/dom/ShadowRoot.h

    r109313 r109563  
    8282    bool hasInsertionPoint() const;
    8383
     84    virtual void attach();
     85
    8486private:
    8587    ShadowRoot(Document*);
  • trunk/Source/WebCore/dom/ShadowTree.cpp

    r109313 r109563  
    2828#include "ShadowTree.h"
    2929
     30#include "CSSStyleSelector.h"
    3031#include "Document.h"
    3132#include "Element.h"
     
    246247        reattachHostChildrenAndShadow();
    247248    else {
     249        CSSStyleSelector* styleSelector = youngest->document()->styleSelector();
     250
     251        styleSelector->pushParentShadowRoot(youngest);
    248252        for (Node* n = youngest->firstChild(); n; n = n->nextSibling()) {
    249253            if (n->isElementNode())
     
    252256                toText(n)->recalcTextStyle(change);
    253257        }
     258        styleSelector->popParentShadowRoot(youngest);
    254259    }
    255260
  • trunk/Source/WebCore/html/HTMLStyleElement.cpp

    r108814 r109563  
    165165{
    166166#if ENABLE(STYLE_SCOPED)
    167     ASSERT(!m_isRegisteredWithScopingNode);
     167    // In come cases on teardown willRemove is not called - test here for unregistering again
     168    // FIXME: Do we need to bother?
     169    if (m_isRegisteredWithScopingNode)
     170        unregisterWithScopingNode();
    168171#endif
    169172    HTMLElement::removedFromDocument();
Note: See TracChangeset for help on using the changeset viewer.