Changeset 120062 in webkit


Ignore:
Timestamp:
Jun 12, 2012 5:28:29 AM (12 years ago)
Author:
commit-queue@webkit.org
Message:

[Shadow DOM] <style> inside Shadow subtree should be scoped inside the subtree.
https://bugs.webkit.org/show_bug.cgi?id=87805

Source/WebCore:

Modified HTMLStyleElement to be treated as a scoped style independent
of its "scoped" attribute's value if HTMLStyleElement is in shadow
subtree. HTMLStyleElement has the following four cases talking about
"scoped" attribute and whether is in shadow subtree or not:
1, HTMLStyleElement is "scoped" and is in document tree,
2, HTMLStyleElement is "scoped" and is in shadow subtree,
3, HTMLStyleElement is not "scoped" and is in document tree, and
4, HTMLStyleElement is not "scoped" and is in shadow subtree.
The case 1 and 2 are not changed. This patch affected the case 4.
At the case 4, the HTMLStyleElement's scoping node is the shadow root.
This change is the first step for fixing style scope bug,
i.e. HTMLStyleElements in shadow subtree are applied to any element
in document tree.

Patch by Takashi Sakamoto <tasak@google.com> on 2012-06-12
Reviewed by Dimitri Glazkov.

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

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::determineScope):
Modified to return a shadow root if a targeted stylesheet owner node is
not scoped but in some shadow DOM subtree.

  • html/HTMLStyleElement.cpp:

(WebCore::HTMLStyleElement::HTMLStyleElement):
(WebCore::HTMLStyleElement::parseAttribute):
Modified to use the below scopedAttributeChanged when a changed
attribute's name is "scoped".
(WebCore::HTMLStyleElement::scopedAttributeChanged):
Newly added. According to new scoped value and isInShadowTree,
add or remove style rules to/from scopedAuthorRules via
registerWithScopingNode or unregisterWithScopingNode.
(WebCore::HTMLStyleElement::registerWithScopingNode):
Added one boolean argument to determine whether HTMLStyleElement is
scoped or not. The reason why not using scoped() is the comment:
"We cannot rely on the scoped element already being present when this
method is invoked. Therefore we cannot rely on scoped()"
(WebCore::HTMLStyleElement::unregisterWithScopingNode):
Changed the code for updating m_isRegisteredWithScopingNode. Now
set m_scopedStyleRegistrationState to be NotRegistered.
(WebCore::HTMLStyleElement::insertedInto):
Modified to invoke registerWithScopingNode when an element is not
scoped but in some shadow subtree.
(WebCore::HTMLStyleElement::removedFrom):
Modified to invoke unregisterWithScopingNode when an element is not
scoped but in some shadow subtree.

  • html/HTMLStyleElement.h:

(HTMLStyleElement):
Modified the type of m_isRegisteredWithScopingNode from bool to
enum and renamed to m_scopedStyleRegistrationState. Now the member
variable keeps what HTMLStyleElement's scoping node is, i.e.
none (this means, not in shadow subtree and not scoped), shadow root or
parent node.
Added one new method scopedAttributeChanged's declaration and
modified the declaration of registerWithScopingNode.

LayoutTests:

Patch by Takashi Sakamoto <tasak@google.com> on 2012-06-12
Reviewed by Dimitri Glazkov.

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

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r120059 r120062  
     12012-06-12  Takashi Sakamoto  <tasak@google.com>
     2
     3        [Shadow DOM] <style> inside Shadow subtree should be scoped inside the subtree.
     4        https://bugs.webkit.org/show_bug.cgi?id=87805
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        * fast/css/style-scoped/registering-shadowroot-expected.txt:
     9        * fast/css/style-scoped/registering-shadowroot.html:
     10        * fast/css/style-scoped/style-scoped-change-scoped-in-shadow-expected.txt: Added.
     11        * fast/css/style-scoped/style-scoped-change-scoped-in-shadow.html: Added.
     12
    1132012-06-12  Mario Sanchez Prada  <msanchez@igalia.com>
    214
  • trunk/LayoutTests/fast/css/style-scoped/registering-shadowroot-expected.txt

    r107793 r120062  
    1515--- Unsetting @scoped ---
    1616PASS internals.numberOfScopedHTMLStyleChildren(host) is 0
    17 PASS internals.numberOfScopedHTMLStyleChildren(sr) is 0
     17PASS internals.numberOfScopedHTMLStyleChildren(sr) is 1
    1818--- Setting @scoped ---
    1919PASS internals.numberOfScopedHTMLStyleChildren(host) is 0
  • trunk/LayoutTests/fast/css/style-scoped/registering-shadowroot.html

    r107793 r120062  
    4949            style.scoped = false;
    5050            shouldBe("internals.numberOfScopedHTMLStyleChildren(host)", "0");
    51             shouldBe("internals.numberOfScopedHTMLStyleChildren(sr)", "0"); /* <style> in shadow, not scoped */
     51            shouldBe("internals.numberOfScopedHTMLStyleChildren(sr)", "1"); /* <style> in shadow, not scoped */
    5252
    5353            debug("--- Setting @scoped ---");
  • trunk/Source/WebCore/ChangeLog

    r120061 r120062  
     12012-06-12  Takashi Sakamoto  <tasak@google.com>
     2
     3        [Shadow DOM] <style> inside Shadow subtree should be scoped inside the subtree.
     4        https://bugs.webkit.org/show_bug.cgi?id=87805
     5
     6        Modified HTMLStyleElement to be treated as a scoped style independent
     7        of its "scoped" attribute's value if HTMLStyleElement is in shadow
     8        subtree. HTMLStyleElement has the following four cases talking about
     9        "scoped" attribute and whether is in shadow subtree or not:
     10        1, HTMLStyleElement is "scoped" and is in document tree,
     11        2, HTMLStyleElement is "scoped" and is in shadow subtree,
     12        3, HTMLStyleElement is not "scoped" and is in document tree, and
     13        4, HTMLStyleElement is not "scoped" and is in shadow subtree.
     14        The case 1 and 2 are not changed. This patch affected the case 4.
     15        At the case 4, the HTMLStyleElement's scoping node is the shadow root.
     16        This change is the first step for fixing style scope bug,
     17        i.e. HTMLStyleElements in shadow subtree are applied to any element
     18        in document tree.
     19
     20        Reviewed by Dimitri Glazkov.
     21
     22        Test: fast/css/style-scoped/style-scoped-change-scoped-in-shadow.html
     23
     24        * css/StyleResolver.cpp:
     25        (WebCore::StyleResolver::determineScope):
     26        Modified to return a shadow root if a targeted stylesheet owner node is
     27        not scoped but in some shadow DOM subtree.
     28        * html/HTMLStyleElement.cpp:
     29        (WebCore::HTMLStyleElement::HTMLStyleElement):
     30        (WebCore::HTMLStyleElement::parseAttribute):
     31        Modified to use the below scopedAttributeChanged when a changed
     32        attribute's name is "scoped".
     33        (WebCore::HTMLStyleElement::scopedAttributeChanged):
     34        Newly added. According to new scoped value and isInShadowTree,
     35        add or remove style rules to/from scopedAuthorRules via
     36        registerWithScopingNode or unregisterWithScopingNode.
     37        (WebCore::HTMLStyleElement::registerWithScopingNode):
     38        Added one boolean argument to determine whether HTMLStyleElement is
     39        scoped or not. The reason why not using scoped() is the comment:
     40        "We cannot rely on the scoped element already being present when this
     41        method is invoked. Therefore we cannot rely on scoped()"
     42        (WebCore::HTMLStyleElement::unregisterWithScopingNode):
     43        Changed the code for updating m_isRegisteredWithScopingNode. Now
     44        set m_scopedStyleRegistrationState to be NotRegistered.
     45        (WebCore::HTMLStyleElement::insertedInto):
     46        Modified to invoke registerWithScopingNode when an element is not
     47        scoped but in some shadow subtree.
     48        (WebCore::HTMLStyleElement::removedFrom):
     49        Modified to invoke unregisterWithScopingNode when an element is not
     50        scoped but in some shadow subtree.
     51        * html/HTMLStyleElement.h:
     52        (HTMLStyleElement):
     53        Modified the type of m_isRegisteredWithScopingNode from bool to
     54        enum and renamed to m_scopedStyleRegistrationState. Now the member
     55        variable keeps what HTMLStyleElement's scoping node is, i.e.
     56        none (this means, not in shadow subtree and not scoped), shadow root or
     57        parent node.
     58        Added one new method scopedAttributeChanged's declaration and
     59        modified the declaration of registerWithScopingNode.
     60
    1612012-06-12  Amy Ousterhout  <aousterh@chromium.org>
    262
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r120057 r120062  
    501501    HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(ownerNode);
    502502    if (!styleElement->scoped())
    503         return 0;
     503        return styleElement->isInShadowTree()? styleElement->shadowRoot() : 0;
    504504
    505505    ContainerNode* parent = styleElement->parentNode();
  • trunk/Source/WebCore/html/HTMLStyleElement.cpp

    r120057 r120062  
    3333#include "ScriptEventListener.h"
    3434#include "ScriptableDocumentParser.h"
     35#include "ShadowRoot.h"
    3536#include "StyleSheetContents.h"
    3637
     
    5152    , m_loadedSheet(false)
    5253#if ENABLE(STYLE_SCOPED)
    53     , m_isRegisteredWithScopingNode(false)
     54    , m_scopedStyleRegistrationState(NotRegistered)
    5455#endif
    5556{
     
    5960HTMLStyleElement::~HTMLStyleElement()
    6061{
    61     // During tear-down, willRemove isn't called, so m_isRegisteredWithScopingNode may still be set here.
    62     // Therefore we can't ASSERT(!m_isRegisteredWithScopingNode).
     62    // During tear-down, willRemove isn't called, so m_scopedStyleRegistrationState may still be RegisteredAsScoped or RegisteredInShadowRoot here.
     63    // Therefore we can't ASSERT(m_scopedStyleRegistrationState == NotRegistered).
    6364    StyleElement::clearDocumentData(document(), this);
    6465
     
    8081        setAttributeEventListener(eventNames().errorEvent, createAttributeEventListener(this, attribute));
    8182#if ENABLE(STYLE_SCOPED)
    82     else if (attribute.name() == scopedAttr) {
    83         if (!attribute.isNull() && !m_isRegisteredWithScopingNode && inDocument())
    84             registerWithScopingNode();
    85         else if (attribute.isNull() && m_isRegisteredWithScopingNode)
    86             unregisterWithScopingNode();
    87     }
     83    else if (attribute.name() == scopedAttr)
     84        scopedAttributeChanged(!attribute.isNull());
    8885#endif
    8986    else
     
    9188}
    9289
     90#if ENABLE(STYLE_SCOPED)
     91void HTMLStyleElement::scopedAttributeChanged(bool scoped)
     92{
     93    if (!inDocument())
     94        return;
     95
     96    if (scoped) {
     97        // As any <style> in a shadow tree is treated as "scoped",
     98        // need to remove the <style> from its shadow root.
     99        if (m_scopedStyleRegistrationState == RegisteredInShadowRoot)
     100            unregisterWithScopingNode(shadowRoot());
     101
     102        if (m_scopedStyleRegistrationState != RegisteredAsScoped)
     103            registerWithScopingNode(true);
     104        return;
     105    }
     106
     107    // If the <style> was scoped, need to remove the <style> from the scoping
     108    // element, i.e. the parent node.
     109    if (m_scopedStyleRegistrationState == RegisteredAsScoped)
     110        unregisterWithScopingNode(parentNode());
     111
     112    // As any <style> in a shadow tree is treated as "scoped",
     113    // need to add the <style> to its shadow root.
     114    if (isInShadowTree() && m_scopedStyleRegistrationState != RegisteredInShadowRoot)
     115        registerWithScopingNode(false);
     116}
     117#endif
     118
    93119void HTMLStyleElement::finishParsingChildren()
    94120{
     
    98124
    99125#if ENABLE(STYLE_SCOPED)
    100 void HTMLStyleElement::registerWithScopingNode()
     126void HTMLStyleElement::registerWithScopingNode(bool scoped)
    101127{
    102128    // Note: We cannot rely on the 'scoped' element already being present when this method is invoked.
    103129    // Therefore we cannot rely on scoped()!
    104     ASSERT(!m_isRegisteredWithScopingNode);
     130    ASSERT(m_scopedStyleRegistrationState == NotRegistered);
    105131    ASSERT(inDocument());
    106     if (m_isRegisteredWithScopingNode)
     132    if (m_scopedStyleRegistrationState != NotRegistered)
    107133        return;
    108134    if (!ContextEnabledFeatures::styleScopedEnabled(document()))
    109135        return;
    110136
    111     ContainerNode* scope = parentNode();
     137    ContainerNode* scope = scoped ? parentNode() : shadowRoot();
    112138    if (!scope)
    113139        return;
     
    124150        document()->styleResolverChanged(DeferRecalcStyle);
    125151
    126     m_isRegisteredWithScopingNode = true;
     152    m_scopedStyleRegistrationState = scoped ? RegisteredAsScoped : RegisteredInShadowRoot;
    127153}
    128154
     
    131157    // Note: We cannot rely on the 'scoped' element still being present when this method is invoked.
    132158    // Therefore we cannot rely on scoped()!
    133     ASSERT(m_isRegisteredWithScopingNode || !ContextEnabledFeatures::styleScopedEnabled(document()));
    134     if (!m_isRegisteredWithScopingNode)
     159    ASSERT(m_scopedStyleRegistrationState != NotRegistered || !ContextEnabledFeatures::styleScopedEnabled(document()));
     160    if (m_scopedStyleRegistrationState == NotRegistered)
    135161        return;
    136162    if (!ContextEnabledFeatures::styleScopedEnabled(document()))
     
    146172        document()->styleResolverChanged(DeferRecalcStyle);
    147173
    148     m_isRegisteredWithScopingNode = false;
     174    m_scopedStyleRegistrationState = NotRegistered;
    149175}
    150176#endif
     
    156182        StyleElement::insertedIntoDocument(document(), this);
    157183#if ENABLE(STYLE_SCOPED)
    158         if (scoped() && !m_isRegisteredWithScopingNode)
    159             registerWithScopingNode();
     184        if (m_scopedStyleRegistrationState == NotRegistered && (scoped() || isInShadowTree()))
     185            registerWithScopingNode(scoped());
    160186#endif
    161187    }
     
    173199    // Now, if we want to register <style scoped> even if it's not inDocument,
    174200    // we'd need to find a way to discern whether that is the case, or whether <style scoped> itself is about to be removed.
    175     if (m_isRegisteredWithScopingNode)
    176         unregisterWithScopingNode(parentNode() ? parentNode() : insertionPoint);
     201    if (m_scopedStyleRegistrationState != NotRegistered) {
     202        ContainerNode* scope = parentNode()? parentNode() : insertionPoint;
     203        if (m_scopedStyleRegistrationState == RegisteredInShadowRoot)
     204            scope = scope->shadowRoot();
     205        unregisterWithScopingNode(scope);
     206    }
    177207#endif
    178208
  • trunk/Source/WebCore/html/HTMLStyleElement.h

    r118963 r120062  
    7777    virtual const AtomicString& type() const;
    7878
    79     void registerWithScopingNode();
    80     void unregisterWithScopingNode() { unregisterWithScopingNode(parentNode()); }
    81     void unregisterWithScopingNode(ContainerNode* scope);
     79#if ENABLE(STYLE_SCOPED)
     80    void scopedAttributeChanged(bool);
     81    void registerWithScopingNode(bool);
     82    void unregisterWithScopingNode(ContainerNode*);
     83#endif
    8284
    8385    bool m_firedLoad;
     
    8587
    8688#if ENABLE(STYLE_SCOPED)
    87     bool m_isRegisteredWithScopingNode;
     89    enum ScopedStyleRegistrationState {
     90        NotRegistered,
     91        RegisteredAsScoped,
     92        RegisteredInShadowRoot
     93    };
     94    ScopedStyleRegistrationState m_scopedStyleRegistrationState;
    8895#endif
    8996};
Note: See TracChangeset for help on using the changeset viewer.