Crash in render tree after dynamically mutating the slot value
https://bugs.webkit.org/show_bug.cgi?id=167502
Patch by Ryosuke Niwa <rniwa@webkit.org> on 2017-02-09
Reviewed by Antti Koivisto.
Source/WebCore:
The crash was caused by attributeChanged not destructing the render tree after an assigned element had been
removed from its slot. Since the style resolver can no longer find this element in the flat tree, we need to
delete its render object as if the element had been removed from the DOM tree.
Tests: fast/html/details-summary-slot.html
fast/shadow-dom/shadow-slot-attribute-change-crash.html
* dom/Element.cpp:
(WebCore::Element::attributeChanged):
* html/HTMLSummaryElement.cpp:
(WebCore::SummarySlotElement): Added. Always use the default slot regardless of the slot attribute's value.
(WebCore::HTMLSummaryElement::create): Use SummarySlotElement
LayoutTests:
Added regression tests for the crash, and one for assigning non-empty slot value to a child
of a summary element. The slot attribute should always be ignored since the fact summary
element has its own shadow tree is an implementation detail that should never be exposed.
* fast/html/details-summary-slot-expected.html: Added.
* fast/html/details-summary-slot.html: Added.
* fast/shadow-dom/shadow-slot-attribute-change-crash-expected.txt: Added.
* fast/shadow-dom/shadow-slot-attribute-change-crash.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@212028 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/html/HTMLSummaryElement.cpp b/Source/WebCore/html/HTMLSummaryElement.cpp
index f35f962..9910bd1 100644
--- a/Source/WebCore/html/HTMLSummaryElement.cpp
+++ b/Source/WebCore/html/HTMLSummaryElement.cpp
@@ -31,15 +31,26 @@
#include "PlatformMouseEvent.h"
#include "RenderBlockFlow.h"
#include "ShadowRoot.h"
+#include "SlotAssignment.h"
namespace WebCore {
using namespace HTMLNames;
+class SummarySlotElement final : public SlotAssignment {
+private:
+ void hostChildElementDidChange(const Element&, ShadowRoot& shadowRoot) override
+ {
+ didChangeSlot(SlotAssignment::defaultSlotName(), shadowRoot);
+ }
+
+ const AtomicString& slotNameForHostChild(const Node&) const override { return SlotAssignment::defaultSlotName(); }
+};
+
Ref<HTMLSummaryElement> HTMLSummaryElement::create(const QualifiedName& tagName, Document& document)
{
Ref<HTMLSummaryElement> summary = adoptRef(*new HTMLSummaryElement(tagName, document));
- summary->addShadowRoot(ShadowRoot::create(document, ShadowRootMode::UserAgent));
+ summary->addShadowRoot(ShadowRoot::create(document, std::make_unique<SummarySlotElement>()));
return summary;
}