summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom/ShadowRoot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom/ShadowRoot.cpp')
-rw-r--r--Source/WebCore/dom/ShadowRoot.cpp160
1 files changed, 102 insertions, 58 deletions
diff --git a/Source/WebCore/dom/ShadowRoot.cpp b/Source/WebCore/dom/ShadowRoot.cpp
index 8115139aa..f54fd74b2 100644
--- a/Source/WebCore/dom/ShadowRoot.cpp
+++ b/Source/WebCore/dom/ShadowRoot.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -27,68 +28,94 @@
#include "config.h"
#include "ShadowRoot.h"
+#include "CSSStyleSheet.h"
#include "ElementTraversal.h"
-#include "HistogramSupport.h"
-#include "InsertionPoint.h"
+#include "ExceptionCode.h"
+#include "HTMLSlotElement.h"
#include "RenderElement.h"
#include "RuntimeEnabledFeatures.h"
+#include "SlotAssignment.h"
#include "StyleResolver.h"
+#include "StyleScope.h"
#include "markup.h"
namespace WebCore {
struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope {
unsigned countersAndFlags[1];
- ContentDistributor distributor;
+ void* styleScope;
void* host;
+ void* slotAssignment;
};
COMPILE_ASSERT(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small);
-enum ShadowRootUsageOriginType {
- ShadowRootUsageOriginWeb = 0,
- ShadowRootUsageOriginNotWeb,
- ShadowRootUsageOriginMax
-};
-
-ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
- : DocumentFragment(0, CreateShadowRoot)
- , TreeScope(this, &document)
- , m_applyAuthorStyles(false)
- , m_resetStyleInheritance(false)
+ShadowRoot::ShadowRoot(Document& document, ShadowRootMode type)
+ : DocumentFragment(document, CreateShadowRoot)
+ , TreeScope(*this, document)
, m_type(type)
- , m_hostElement(0)
+ , m_styleScope(std::make_unique<Style::Scope>(*this))
+{
+}
+
+
+ShadowRoot::ShadowRoot(Document& document, std::unique_ptr<SlotAssignment>&& slotAssignment)
+ : DocumentFragment(document, CreateShadowRoot)
+ , TreeScope(*this, document)
+ , m_type(ShadowRootMode::UserAgent)
+ , m_styleScope(std::make_unique<Style::Scope>(*this))
+ , m_slotAssignment(WTFMove(slotAssignment))
{
}
+
ShadowRoot::~ShadowRoot()
{
+ if (isConnected())
+ document().didRemoveInDocumentShadowRoot(*this);
+
// We cannot let ContainerNode destructor call willBeDeletedFrom()
// for this ShadowRoot instance because TreeScope destructor
// clears Node::m_treeScope thus ContainerNode is no longer able
// to access it Document reference after that.
- willBeDeletedFrom(documentInternal());
+ willBeDeletedFrom(document());
// We must remove all of our children first before the TreeScope destructor
// runs so we don't go through TreeScopeAdopter for each child with a
// destructed tree scope in each descendant.
removeDetachedChildren();
+}
- // We must call clearRareData() here since a ShadowRoot class inherits TreeScope
- // as well as Node. See a comment on TreeScope.h for the reason.
- if (hasRareData())
- clearRareData();
+Node::InsertionNotificationRequest ShadowRoot::insertedInto(ContainerNode& insertionPoint)
+{
+ bool wasInDocument = isConnected();
+ DocumentFragment::insertedInto(insertionPoint);
+ if (insertionPoint.isConnected() && !wasInDocument)
+ document().didInsertInDocumentShadowRoot(*this);
+ return InsertionDone;
}
-void ShadowRoot::dropChildren()
+void ShadowRoot::removedFrom(ContainerNode& insertionPoint)
{
- removeDetachedChildren();
+ DocumentFragment::removedFrom(insertionPoint);
+ if (insertionPoint.isConnected() && !isConnected())
+ document().didRemoveInDocumentShadowRoot(*this);
}
-PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec)
+void ShadowRoot::didMoveToNewDocument(Document& oldDocument)
{
- ec = DATA_CLONE_ERR;
- return 0;
+ ASSERT(&document() != &oldDocument);
+ ASSERT(&m_styleScope->document() == &oldDocument);
+
+ // Style scopes are document specific.
+ m_styleScope = std::make_unique<Style::Scope>(*this);
+
+ DocumentFragment::didMoveToNewDocument(oldDocument);
+}
+
+Style::Scope& ShadowRoot::styleScope()
+{
+ return *m_styleScope;
}
String ShadowRoot::innerHTML() const
@@ -96,15 +123,14 @@ String ShadowRoot::innerHTML() const
return createMarkup(*this, ChildrenOnly);
}
-void ShadowRoot::setInnerHTML(const String& markup, ExceptionCode& ec)
+ExceptionOr<void> ShadowRoot::setInnerHTML(const String& markup)
{
- if (isOrphan()) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, hostElement(), AllowScriptingContent, ec))
- replaceChildrenWithFragment(*this, fragment.release(), ec);
+ if (isOrphan())
+ return Exception { INVALID_ACCESS_ERR };
+ auto fragment = createFragmentForInnerOuterHTML(*host(), markup, AllowScriptingContent);
+ if (fragment.hasException())
+ return fragment.releaseException();
+ return replaceChildrenWithFragment(*this, fragment.releaseReturnValue());
}
bool ShadowRoot::childTypeAllowed(NodeType type) const
@@ -115,50 +141,68 @@ bool ShadowRoot::childTypeAllowed(NodeType type) const
case COMMENT_NODE:
case TEXT_NODE:
case CDATA_SECTION_NODE:
- case ENTITY_REFERENCE_NODE:
return true;
default:
return false;
}
}
-void ShadowRoot::setApplyAuthorStyles(bool value)
+void ShadowRoot::setResetStyleInheritance(bool value)
{
- if (isOrphan())
- return;
+ // If this was ever changed after initialization, child styles would need to be invalidated here.
+ m_resetStyleInheritance = value;
+}
- if (m_applyAuthorStyles != value) {
- m_applyAuthorStyles = value;
- hostElement()->setNeedsStyleRecalc();
- }
+Ref<Node> ShadowRoot::cloneNodeInternal(Document&, CloningOperation)
+{
+ RELEASE_ASSERT_NOT_REACHED();
+ return *static_cast<Node*>(nullptr); // ShadowRoots should never be cloned.
}
-void ShadowRoot::setResetStyleInheritance(bool value)
+void ShadowRoot::removeAllEventListeners()
{
- if (isOrphan())
- return;
+ DocumentFragment::removeAllEventListeners();
+ for (Node* node = firstChild(); node; node = NodeTraversal::next(*node))
+ node->removeAllEventListeners();
+}
- if (value != m_resetStyleInheritance) {
- m_resetStyleInheritance = value;
- if (hostElement())
- setNeedsStyleRecalc();
- }
+
+HTMLSlotElement* ShadowRoot::findAssignedSlot(const Node& node)
+{
+ ASSERT(node.parentNode() == host());
+ if (!m_slotAssignment)
+ return nullptr;
+ return m_slotAssignment->findAssignedSlot(node, *this);
}
-void ShadowRoot::childrenChanged(const ChildChange& change)
+void ShadowRoot::addSlotElementByName(const AtomicString& name, HTMLSlotElement& slot)
{
- if (isOrphan())
- return;
+ if (!m_slotAssignment)
+ m_slotAssignment = std::make_unique<SlotAssignment>();
- ContainerNode::childrenChanged(change);
- invalidateDistribution();
+ return m_slotAssignment->addSlotElementByName(name, slot, *this);
}
-void ShadowRoot::removeAllEventListeners()
+void ShadowRoot::removeSlotElementByName(const AtomicString& name, HTMLSlotElement& slot)
{
- DocumentFragment::removeAllEventListeners();
- for (Node* node = firstChild(); node; node = NodeTraversal::next(node))
- node->removeAllEventListeners();
+ return m_slotAssignment->removeSlotElementByName(name, slot, *this);
+}
+
+const Vector<Node*>* ShadowRoot::assignedNodesForSlot(const HTMLSlotElement& slot)
+{
+ if (!m_slotAssignment)
+ return nullptr;
+ return m_slotAssignment->assignedNodesForSlot(slot, *this);
+}
+
+Vector<ShadowRoot*> assignedShadowRootsIfSlotted(const Node& node)
+{
+ Vector<ShadowRoot*> result;
+ for (auto* slot = node.assignedSlot(); slot; slot = slot->assignedSlot()) {
+ ASSERT(slot->containingShadowRoot());
+ result.append(slot->containingShadowRoot());
+ }
+ return result;
}
}