Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(512)

Unified Diff: Source/core/html/HTMLStyleElement.cpp

Issue 317143002: Revert of Remove scoped styles. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/html/HTMLStyleElement.h ('k') | Source/core/html/HTMLStyleElement.idl » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/html/HTMLStyleElement.cpp
diff --git a/Source/core/html/HTMLStyleElement.cpp b/Source/core/html/HTMLStyleElement.cpp
index 8f3353943335d8ad296d1d52f1102808c0e3b15a..e4db64902d6d8a7a7a5b4c62477f2a602e2dfc6c 100644
--- a/Source/core/html/HTMLStyleElement.cpp
+++ b/Source/core/html/HTMLStyleElement.cpp
@@ -49,12 +49,15 @@
, StyleElement(&document, createdByParser)
, m_firedLoad(false)
, m_loadedSheet(false)
+ , m_scopedStyleRegistrationState(NotRegistered)
{
ScriptWrappable::init(this);
}
HTMLStyleElement::~HTMLStyleElement()
{
+ // During tear-down, willRemove isn't called, so m_scopedStyleRegistrationState may still be RegisteredAsScoped or RegisteredInShadowRoot here.
+ // Therefore we can't ASSERT(m_scopedStyleRegistrationState == NotRegistered).
#if !ENABLE(OILPAN)
StyleElement::clearDocumentData(document(), this);
#endif
@@ -71,6 +74,8 @@
{
if (name == titleAttr && m_sheet) {
m_sheet->setTitle(value);
+ } else if (name == scopedAttr && ContextFeatures::styleScopedEnabled(&document())) {
+ scopedAttributeChanged(!value.isNull());
} else if (name == mediaAttr && inDocument() && document().isActive() && m_sheet) {
m_sheet->setMediaQueries(MediaQuerySet::create(value));
document().modifiedStyleSheet(m_sheet.get());
@@ -79,18 +84,101 @@
}
}
+void HTMLStyleElement::scopedAttributeChanged(bool scoped)
+{
+ ASSERT(ContextFeatures::styleScopedEnabled(&document()));
+
+ if (!inDocument())
+ return;
+
+ if (scoped) {
+ if (m_scopedStyleRegistrationState == RegisteredAsScoped)
+ return;
+
+ // As any <style> in a shadow tree is treated as "scoped",
+ // need to remove the <style> from its shadow root.
+ ContainerNode* scopingNode = 0;
+ if (m_scopedStyleRegistrationState == RegisteredInShadowRoot) {
+ scopingNode = containingShadowRoot();
+ unregisterWithScopingNode(scopingNode);
+ }
+ document().styleEngine()->removeStyleSheetCandidateNode(this, scopingNode, treeScope());
+ registerWithScopingNode(true);
+
+ document().styleEngine()->addStyleSheetCandidateNode(this, false);
+ document().modifiedStyleSheet(sheet());
+ return;
+ }
+
+ // If the <style> was scoped, need to remove the <style> from the scoping
+ // element, i.e. the parent node.
+ if (m_scopedStyleRegistrationState != RegisteredAsScoped)
+ return;
+
+ unregisterWithScopingNode(parentNode());
+ document().styleEngine()->removeStyleSheetCandidateNode(this, parentNode(), treeScope());
+
+ // As any <style> in a shadow tree is treated as "scoped",
+ // need to add the <style> to its shadow root.
+ if (isInShadowTree())
+ registerWithScopingNode(false);
+
+ document().styleEngine()->addStyleSheetCandidateNode(this, false);
+ // FIXME: currently need to use FullStyleUpdate here.
+ // Because ShadowTreeStyleSheetCollection doesn't know old scoping node.
+ // So setNeedsStyleRecalc for old scoping node is not invoked.
+ document().modifiedStyleSheet(sheet());
+}
+
void HTMLStyleElement::finishParsingChildren()
{
StyleElement::finishParsingChildren(this);
HTMLElement::finishParsingChildren();
}
+void HTMLStyleElement::registerWithScopingNode(bool scoped)
+{
+ // Note: We cannot rely on the 'scoped' element already being present when this method is invoked.
+ // Therefore we cannot rely on scoped()!
+ ASSERT(m_scopedStyleRegistrationState == NotRegistered);
+ ASSERT(inDocument());
+ if (m_scopedStyleRegistrationState != NotRegistered)
+ return;
+
+ ContainerNode* scope = scoped ? parentNode() : containingShadowRoot();
+ if (!scope)
+ return;
+ if (!scope->isElementNode() && !scope->isShadowRoot()) {
+ // DocumentFragment nodes should never be inDocument,
+ // <style> should not be a child of Document, PI or some such.
+ ASSERT_NOT_REACHED();
+ return;
+ }
+ scope->registerScopedHTMLStyleChild();
+ m_scopedStyleRegistrationState = scoped ? RegisteredAsScoped : RegisteredInShadowRoot;
+}
+
+void HTMLStyleElement::unregisterWithScopingNode(ContainerNode* scope)
+{
+ ASSERT(m_scopedStyleRegistrationState != NotRegistered || !ContextFeatures::styleScopedEnabled(&document()));
+ if (!isRegisteredAsScoped())
+ return;
+
+ ASSERT(scope);
+ if (scope) {
+ ASSERT(scope->hasScopedHTMLStyleChild());
+ scope->unregisterScopedHTMLStyleChild();
+ }
+
+ m_scopedStyleRegistrationState = NotRegistered;
+}
+
Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode* insertionPoint)
{
HTMLElement::insertedInto(insertionPoint);
- if (insertionPoint->inDocument() && isInShadowTree()) {
- if (ShadowRoot* scope = containingShadowRoot())
- scope->registerScopedHTMLStyleChild();
+ if (insertionPoint->inDocument()) {
+ if (m_scopedStyleRegistrationState == NotRegistered && (scoped() || isInShadowTree()))
+ registerWithScopingNode(scoped());
}
return InsertionShouldCallDidNotifySubtreeInsertions;
}
@@ -99,18 +187,27 @@
{
HTMLElement::removedFrom(insertionPoint);
- ShadowRoot* scopingNode = containingShadowRoot();
- if (!scopingNode)
- scopingNode = insertionPoint->containingShadowRoot();
-
- if (scopingNode)
- scopingNode->unregisterScopedHTMLStyleChild();
-
- if (!insertionPoint->inDocument())
- return;
-
- TreeScope* containingScope = containingShadowRoot();
- StyleElement::removedFromDocument(document(), this, scopingNode, containingScope ? *containingScope : insertionPoint->treeScope());
+ // In the current implementation, <style scoped> is only registered if the node is in the document.
+ // That is, because willRemove() is also called if an ancestor is removed from the document.
+ // Now, if we want to register <style scoped> even if it's not inDocument,
+ // we'd need to find a way to discern whether that is the case, or whether <style scoped> itself is about to be removed.
+ ContainerNode* scopingNode = 0;
+ if (m_scopedStyleRegistrationState != NotRegistered) {
+ if (m_scopedStyleRegistrationState == RegisteredInShadowRoot) {
+ scopingNode = containingShadowRoot();
+ if (!scopingNode)
+ scopingNode = insertionPoint->containingShadowRoot();
+ } else {
+ scopingNode = parentNode() ? parentNode() : insertionPoint;
+ }
+
+ unregisterWithScopingNode(scopingNode);
+ }
+
+ if (insertionPoint->inDocument()) {
+ TreeScope* containingScope = containingShadowRoot();
+ StyleElement::removedFromDocument(document(), this, scopingNode, containingScope ? *containingScope : insertionPoint->treeScope());
+ }
}
void HTMLStyleElement::didNotifySubtreeInsertionsToDocument()
@@ -134,15 +231,28 @@
return getAttribute(typeAttr);
}
+bool HTMLStyleElement::scoped() const
+{
+ return fastHasAttribute(scopedAttr) && ContextFeatures::styleScopedEnabled(&document());
+}
+
+void HTMLStyleElement::setScoped(bool scopedValue)
+{
+ setBooleanAttribute(scopedAttr, scopedValue);
+}
+
ContainerNode* HTMLStyleElement::scopingNode()
{
if (!inDocument())
return 0;
- if (isInShadowTree())
+ if (!isRegisteredAsScoped())
+ return &document();
+
+ if (isRegisteredInShadowRoot())
return containingShadowRoot();
- return &document();
+ return parentNode();
}
void HTMLStyleElement::dispatchPendingLoadEvents()
« no previous file with comments | « Source/core/html/HTMLStyleElement.h ('k') | Source/core/html/HTMLStyleElement.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698