Skip to content
Permalink
Browse files
Prototype declarative shadow DOM
https://bugs.webkit.org/show_bug.cgi?id=245556

Reviewed by Chris Dumez.

Implement the declarative shadow DOM an experimental feature.

See whatwg/html#5465 and whatwg/dom#892

There are a few differences between what's being proposed and what we implement:
1. getInnerHTML method is not added; we've given quite a few feedback on this method, and it's nowhere near ready for implementation.
2. Declarative shadow DOMs inside another template element doesn't automatically get converted to a shadow tree,
and there is no special treatment of declarative shadow DOM when cloning Nodes.

* LayoutTests/imported/w3c/web-platform-tests/html/semantics/popups/popup-light-dismiss.tentative-expected.txt: Rebaselined.
* LayoutTests/imported/w3c/web-platform-tests/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative-expected.txt:
Rebaselined the test now that we pass more test cases.
* LayoutTests/imported/w3c/web-platform-tests/shadow-dom/declarative/declarative-shadow-dom-basic.tentative-expected.txt: Ditto.
* LayoutTests/imported/w3c/web-platform-tests/shadow-dom/declarative/declarative-shadow-dom-opt-in.tentative-expected.txt: Ditto.
* LayoutTests/imported/w3c/web-platform-tests/shadow-dom/declarative/innerhtml-before-closing-tag.tentative-expected.txt: Ditto.
* LayoutTests/imported/w3c/web-platform-tests/shadow-dom/declarative/move-template-before-closing-tag-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/shadow-dom/declarative/move-template-before-closing-tag.tentative-expected.txt: Ditto.
* LayoutTests/imported/w3c/web-platform-tests/shadow-dom/declarative/script-access.tentative-expected.txt: Rebaselined.

* Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml: Added a runtime flag.

* Source/WebCore/CMakeLists.txt:
* Source/WebCore/DerivedSources-input.xcfilelist:
* Source/WebCore/DerivedSources-output.xcfilelist:
* Source/WebCore/DerivedSources.make:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:

* Source/WebCore/dom/DOMImplementation.cpp:
(WebCore::createXMLDocument): Disable declarative shadow DOM in a document created by DOMImplementation.createDocument.
(WebCore::DOMImplementation::createDocument): Ditto.
(WebCore::DOMImplementation::createHTMLDocument): Ditto.

* Source/WebCore/dom/Document.cpp:
(WebCore::Document::Document): Initialize newly introduced m_parserContentPolicy with DefaultParserContentPolicy.
(WebCore::Document::createParser): Specify m_parserContentPolicy as an argument to XMLDocumentParser::create.

* Source/WebCore/dom/Document.h:
(WebCore::Document::parserContentPolicy const): Added.
(WebCore::Document::setParserContentPolicy): Added.

* Source/WebCore/dom/Element.cpp:
(WebCore::Element::attachShadow): Returns the shadow root of declarative shadow DOM if one is available. This happens exactly once
since this function then clears the flag from ShadowRoot.
(WebCore::Element::attachDeclarativeShadow): Added.

* Source/WebCore/dom/Element.h:
* Source/WebCore/dom/FragmentScriptingPermission.h:
(WebCore::ParserContentPolicy): Added AllowDeclarativeShadowDOM.

* Source/WebCore/dom/ScriptableDocumentParser.h:
(WebCore::ScriptableDocumentParser::parserContentPolicy const): Made this const.
(WebCore::ScriptableDocumentParser::setParserContentPolicy): Added.
(WebCore::ScriptableDocumentParser::ScriptableDocumentParser): Added

* Source/WebCore/dom/ShadowRoot.h:
(WebCore::ShadowRoot::isDeclarativeShadowRoot): Added.
(WebCore::ShadowRoot::setIsDeclarativeShadowRoot): Added.

* Source/WebCore/html/HTMLAttributeNames.in:

* Source/WebCore/html/HTMLDocument.cpp:
(WebCore::HTMLDocument::createParser): Pass in the parser content policy.

* Source/WebCore/html/HTMLTemplateElement.cpp:
(WebCore::HTMLTemplateElement::attachAsDeclarativeShadowRootIfNeeded): Added. Implements the main logic of declarative shadow DOM.

* Source/WebCore/html/HTMLTemplateElement.h:
* Source/WebCore/html/parser/HTMLConstructionSite.cpp:
(WebCore::HTMLConstructionSite::attachDeclarativeShadowRootIfNeeded): Added.

* Source/WebCore/html/parser/HTMLConstructionSite.h:

* Source/WebCore/html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::HTMLDocumentParser): Takes OptionSet<ParserContentPolicy> as an argument.
(WebCore::HTMLDocumentParser::create): Ditto.

* Source/WebCore/html/parser/HTMLDocumentParser.h:

* Source/WebCore/html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::processTemplateEndTag): Attach the template content as the declarative shadow DOM if applicable.

* Source/WebCore/xml/DOMParser.cpp:
(WebCore::DOMParser::parseFromString): Added ParseFromStringOptions as an argument.

* Source/WebCore/xml/DOMParser.h:
* Source/WebCore/xml/DOMParser.idl:

* Source/WebCore/xml/ParseFromStringOptions.h: Added.
* Source/WebCore/xml/ParseFromStringOptions.idl: Added.

* Source/WebCore/xml/XMLHttpRequest.cpp:
(XMLHttpRequest::responseXML): Disable declarative shadow DOM in the response document.

* Source/WebCore/xml/parser/XMLDocumentParser.h:
(WebCore::XMLDocumentParser::create): Takes OptionSet<ParserContentPolicy> as an argument.

* Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::XMLDocumentParser::XMLDocumentParser): Ditto.

Canonical link: https://commits.webkit.org/254964@main
  • Loading branch information
rniwa committed Sep 28, 2022
1 parent fdd3720 commit 46837e56d6f57f7e52bf92c9534cc7683909eee5
Show file tree
Hide file tree
Showing 40 changed files with 295 additions and 121 deletions.
@@ -1,4 +1,5 @@
CONSOLE MESSAGE: TypeError: null is not an object (evaluating 'document.querySelector('#myElement').shadowRoot.querySelector')
CONSOLE MESSAGE: TypeError: popup7.showPopUp is not a function. (In 'popup7.showPopUp()', 'popup7.showPopUp' is undefined)
CONSOLE MESSAGE: TypeError: popup7.showPopUp is not a function. (In 'popup7.showPopUp()', 'popup7.showPopUp' is undefined)
Popup 1 Popup 1 Popup1 anchor (no action) Outside all popups
Inside popup 1 Popup 2 Inside popup 1 after button
Inside popup 2
@@ -25,7 +26,7 @@ Popup
Hint
Manual

Harness Error (FAIL), message = TypeError: null is not an object (evaluating 'document.querySelector('#myElement').shadowRoot.querySelector')
Harness Error (FAIL), message = TypeError: popup7.showPopUp is not a function. (In 'popup7.showPopUp()', 'popup7.showPopUp' is undefined)

FAIL Clicking outside a popup will dismiss the popup promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
FAIL Clicking inside a popup does not close that popup promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
@@ -40,6 +41,8 @@ FAIL Dragging from an open popup outside an open popup should leave the popup op
FAIL An invoking element should be part of the ancestor chain promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
FAIL An invoking element that was not used to invoke the popup can still be part of the ancestor chain promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
FAIL Scrolling within a popup should not close the popup promise_test: Unhandled rejection with value: object "TypeError: popup6.showPopUp is not a function. (In 'popup6.showPopUp()', 'popup6.showPopUp' is undefined)"
FAIL Clicking inside a shadow DOM popup does not close that popup promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
FAIL Clicking outside a shadow DOM popup should close that popup promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
FAIL Moving focus back to the anchor element should not dismiss the popup promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
FAIL Moving focus back to the active trigger element should not dismiss the popup promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
FAIL Moving focus back to an inactive trigger element should also *not* dismiss the popup promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."

Large diffs are not rendered by default.

@@ -1,18 +1,12 @@

FAIL Declarative Shadow DOM: Basic test assert_equals: No leftover template node expected null but got Element node <template shadowroot="open">
<slot id="s1" name="slot...
PASS Declarative Shadow DOM: Basic test
FAIL Declarative Shadow DOM: Feature detection assert_true: Unable to feature detect expected true got false
FAIL Declarative Shadow DOM: Fragment parser basic test assert_equals: No leftover template node expected null but got Element node <template shadowroot="open">
<slot id="s1" name="...
PASS Declarative Shadow DOM: Fragment parser basic test
PASS Declarative Shadow DOM: Invalid shadow root attribute
FAIL Declarative Shadow DOM: Closed shadow root attribute assert_equals: No template - converted to shadow root expected null but got Element node <template shadowroot="closed">
</template>
FAIL Declarative Shadow DOM: Missing closing tag assert_equals: No leftover template node expected null but got Element node <template shadowroot="open">
<slot id="s1" name="...
FAIL Declarative Shadow DOM: delegates focus attribute assert_true: No shadow root found expected true got false
FAIL Declarative Shadow DOM: Multiple roots assert_equals: No leftover template nodes from either root expected null but got Element node <template shadowroot="open">
<span>root 1</span>
</...
PASS Declarative Shadow DOM: Closed shadow root attribute
PASS Declarative Shadow DOM: Missing closing tag
PASS Declarative Shadow DOM: delegates focus attribute
PASS Declarative Shadow DOM: Multiple roots
FAIL Declarative Shadow DOM: template containing declarative shadow root assert_true: Inner div should have a shadow root expected true got false
FAIL Declarative Shadow DOM: template containing (deeply nested) declarative shadow root assert_true: Inner div should have a shadow root expected true got false
FAIL Declarative Shadow DOM: template containing a template containing declarative shadow root assert_true: Inner div should have a shadow root expected true got false
@@ -1,7 +1,7 @@



FAIL Non-fragment parsing needs no opt-in assert_true: Shadow root NOT FOUND. expected true got false
PASS Non-fragment parsing needs no opt-in
PASS innerHTML on a <a>
PASS innerHTML on a <abbr>
PASS innerHTML on a <address>
@@ -106,17 +106,17 @@ PASS innerHTML on a <wbr>
PASS innerHTML on template
PASS innerHTML on template, with nested template content
PASS innerHTML on shadowRoot
FAIL DOMParser assert_true: Shadow root NOT FOUND. expected true got false
PASS DOMParser
PASS createHTMLDocument with innerHTML - not supported
PASS createContextualFragment - not supported
PASS XMLHttpRequest - not supported
PASS insertAdjacentHTML on element - not supported
FAIL document.write allowed from synchronous script loaded from main document assert_true: Shadow root NOT FOUND. expected true got false
PASS document.write allowed from synchronous script loaded from main document
PASS document.write disallowed on fresh document
FAIL iframe assert_true: Shadow root NOT FOUND. expected true got false
FAIL iframe, no sandbox assert_true: Shadow root NOT FOUND. expected true got false
FAIL sandboxed iframe allows declarative Shadow DOM assert_true: expected true got false
FAIL iframe with no sandbox allows declarative Shadow DOM assert_true: expected true got false
PASS iframe
PASS iframe, no sandbox
PASS sandboxed iframe allows declarative Shadow DOM
PASS iframe with no sandbox allows declarative Shadow DOM



@@ -1,3 +1,3 @@

FAIL Declarative Shadow DOM: innerHTML should work while parsing declarative shadow root <template> assert_true: Declarative shadow template should not be left over expected true got false
PASS Declarative Shadow DOM: innerHTML should work while parsing declarative shadow root <template>

This file was deleted.

@@ -1,5 +1,5 @@

FAIL Moving the template node during parsing should attach to initial parent (content before observer) assert_true: Declarative shadow template should not be left over expected true got false
FAIL Moving the template node during parsing should attach to initial parent (content after observer) assert_true: Declarative shadow template should not be left over expected true got false
PASS Moving the template node during parsing should attach to initial parent (content before observer)
PASS Moving the template node during parsing should attach to initial parent (content after observer)
PASS Moving the template node from invalid parent to valid parent should still not attach

@@ -1,5 +1,6 @@
CONSOLE MESSAGE: Error: assert_equals: Declarative template content should be null expected null but got DocumentFragment node with 3 children
CONSOLE MESSAGE: Error: assert_unreached: Unrecognized template Reached unreachable code
CONSOLE MESSAGE: Error: assert_unreached: Unrecognized template Reached unreachable code

Harness Error (FAIL), message = Error: assert_equals: Declarative template content should be null expected null but got DocumentFragment node with 3 children

@@ -581,6 +581,18 @@ CrossOriginOpenerPolicyEnabled:
WebCore:
default: false

DeclarativeShadowDOMEnabled:
type: bool
humanReadableName: "Declarative Shadow DOM"
humanReadableDescription: "Enable Declarative Shadow DOM"
defaultValue:
WebKitLegacy:
default: false
WebKit:
default: false
WebCore:
default: false

DefaultARIAForCustomElementsEnabled:
type: bool
humanReadableName: "Default ARIA for Custom Elements"
@@ -1325,6 +1325,7 @@ set(WebCore_NON_SVG_IDL_FILES

xml/CustomXPathNSResolver.idl
xml/DOMParser.idl
xml/ParseFromStringOptions.idl
xml/XMLHttpRequest.idl
xml/XMLHttpRequestEventTarget.idl
xml/XMLHttpRequestProgressEvent.idl
@@ -1720,6 +1720,7 @@ $(PROJECT_DIR)/worklets/WorkletGlobalScope.idl
$(PROJECT_DIR)/worklets/WorkletOptions.idl
$(PROJECT_DIR)/xml/CustomXPathNSResolver.idl
$(PROJECT_DIR)/xml/DOMParser.idl
$(PROJECT_DIR)/xml/ParseFromStringOptions.idl
$(PROJECT_DIR)/xml/XMLHttpRequest.idl
$(PROJECT_DIR)/xml/XMLHttpRequestEventTarget.idl
$(PROJECT_DIR)/xml/XMLHttpRequestProgressEvent.idl
@@ -1862,6 +1862,8 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPanningModelType.cpp
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPanningModelType.h
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSParentNode.cpp
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSParentNode.h
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSParseFromStringOptions.cpp
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSParseFromStringOptions.h
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPath2D.cpp
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPath2D.h
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPayerErrorFields.cpp
@@ -1535,6 +1535,7 @@ JS_BINDING_IDLS := \
$(WebCore)/worklets/WorkletOptions.idl \
$(WebCore)/xml/CustomXPathNSResolver.idl \
$(WebCore)/xml/DOMParser.idl \
$(WebCore)/xml/ParseFromStringOptions.idl \
$(WebCore)/xml/XMLHttpRequest.idl \
$(WebCore)/xml/XMLHttpRequestEventTarget.idl \
$(WebCore)/xml/XMLHttpRequestProgressEvent.idl \
@@ -3643,6 +3643,7 @@ JSPannerNode.cpp
JSPannerOptions.cpp
JSPanningModelType.cpp
JSParentNode.cpp
JSParseFromStringOptions.cpp
JSPath2D.cpp
JSPayerErrorFields.cpp
JSPaymentAddress.cpp
@@ -3380,6 +3380,7 @@
9B2D8A7914997CCF00ECEF3E /* UndoStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B2D8A7814997CCF00ECEF3E /* UndoStep.h */; settings = {ATTRIBUTES = (Private, ); }; };
9B32CDA913DF7FA900F34D13 /* RenderedPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B32CDA713DF7FA900F34D13 /* RenderedPosition.h */; };
9B417064125662B3006B28FC /* ApplyBlockElementCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B417062125662B3006B28FC /* ApplyBlockElementCommand.h */; };
9B43D54F28E132FF0095509C /* ParseFromStringOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BB892FA28E12FFD00E7408F /* ParseFromStringOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
9B4F0636289F3882007831DB /* SlotAssignmentMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B4F0630289F2F08007831DB /* SlotAssignmentMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
9B50B1DE17CD4C0F0087F63C /* FormNamedItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B50B1DC17CD4C0F0087F63C /* FormNamedItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
9B532EA41BA928570038A827 /* SlotAssignment.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B532EA21BA928570038A827 /* SlotAssignment.h */; };
@@ -13857,6 +13858,8 @@
9BAB6C6A12550631001626D4 /* EditingStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingStyle.h; sourceTree = "<group>"; };
9BAB6C6B12550631001626D4 /* EditingStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditingStyle.cpp; sourceTree = "<group>"; };
9BAF3B2312C1A39800014BF1 /* WritingDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WritingDirection.h; sourceTree = "<group>"; };
9BB892FA28E12FFD00E7408F /* ParseFromStringOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseFromStringOptions.h; sourceTree = "<group>"; };
9BB892FB28E12FFE00E7408F /* ParseFromStringOptions.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ParseFromStringOptions.idl; sourceTree = "<group>"; };
9BC5F9DE1D5AAD5D002B749D /* CustomElementRegistry.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CustomElementRegistry.idl; sourceTree = "<group>"; };
9BC5F9DF1D5AAF6A002B749D /* JSCustomElementRegistryCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomElementRegistryCustom.cpp; sourceTree = "<group>"; };
9BC6C21913CCC97B008E0337 /* HTMLTextFormControlElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTextFormControlElement.h; sourceTree = "<group>"; };
@@ -31980,6 +31983,8 @@
1ACE53E30A8D18E70022947D /* DOMParser.idl */,
E10B9B6B0B747599003ED890 /* NativeXPathNSResolver.cpp */,
E10B9B6A0B747599003ED890 /* NativeXPathNSResolver.h */,
9BB892FA28E12FFD00E7408F /* ParseFromStringOptions.h */,
9BB892FB28E12FFE00E7408F /* ParseFromStringOptions.idl */,
538F10A31F900BDC005102CE /* SoftLinkLibxslt.cpp */,
538F10A41F900BDD005102CE /* SoftLinkLibxslt.h */,
A833C7F60A2CF1D800D57664 /* xmlattrs.in */,
@@ -37477,6 +37482,7 @@
CDCD41E81C3DDB0A00965D99 /* ParsedContentRange.h in Headers */,
447958041643B49A001E0A7F /* ParsedContentType.h in Headers */,
5C4A0FDA25C3449A00D9EE97 /* ParsedRequestRange.h in Headers */,
9B43D54F28E132FF0095509C /* ParseFromStringOptions.h in Headers */,
536D5A23193E8E0C00CE4CAB /* ParsingUtilities.h in Headers */,
46893B8427E8D74C002CC13D /* PartitionedSecurityOrigin.h in Headers */,
F55B3DCA1251F12D003EF269 /* PasswordInputType.h in Headers */,
@@ -84,16 +84,21 @@ ExceptionOr<Ref<DocumentType>> DOMImplementation::createDocumentType(const AtomS

static inline Ref<XMLDocument> createXMLDocument(const String& namespaceURI, const Settings& settings)
{
RefPtr<XMLDocument> document;
if (namespaceURI == SVGNames::svgNamespaceURI)
return SVGDocument::create(nullptr, settings, URL());
if (namespaceURI == HTMLNames::xhtmlNamespaceURI)
return XMLDocument::createXHTML(nullptr, settings, URL());
return XMLDocument::create(nullptr, settings, URL());
document = SVGDocument::create(nullptr, settings, URL());
else if (namespaceURI == HTMLNames::xhtmlNamespaceURI)
document = XMLDocument::createXHTML(nullptr, settings, URL());
else
document = XMLDocument::create(nullptr, settings, URL());
document->setParserContentPolicy({ ParserContentPolicy::AllowScriptingContent, ParserContentPolicy::AllowPluginContent });
return document.releaseNonNull();
}

ExceptionOr<Ref<XMLDocument>> DOMImplementation::createDocument(const AtomString& namespaceURI, const AtomString& qualifiedName, DocumentType* documentType)
{
auto document = createXMLDocument(namespaceURI, m_document.settings());
document->setParserContentPolicy({ ParserContentPolicy::AllowScriptingContent, ParserContentPolicy::AllowPluginContent });
document->setContextDocument(m_document.contextDocument());
document->setSecurityOriginPolicy(m_document.securityOriginPolicy());

@@ -126,6 +131,7 @@ Ref<CSSStyleSheet> DOMImplementation::createCSSStyleSheet(const String&, const S
Ref<HTMLDocument> DOMImplementation::createHTMLDocument(String&& title)
{
auto document = HTMLDocument::create(nullptr, m_document.settings(), URL(), { });
document->setParserContentPolicy({ ParserContentPolicy::AllowScriptingContent, ParserContentPolicy::AllowPluginContent });
document->open();
document->write(nullptr, { "<!doctype html><html><head></head><body></body></html>"_s });
if (!title.isNull()) {
@@ -544,6 +544,7 @@ Document::Document(Frame* frame, const Settings& settings, const URL& url, Docum
, FrameDestructionObserver(frame)
, m_settings(settings)
, m_quirks(makeUniqueRef<Quirks>(*this))
, m_parserContentPolicy(DefaultParserContentPolicy)
, m_cachedResourceLoader(createCachedResourceLoader(frame))
, m_creationURL(url)
, m_domTreeVersion(++s_globalTreeVersion)
@@ -2885,7 +2886,7 @@ void Document::setVisuallyOrdered()
Ref<DocumentParser> Document::createParser()
{
// FIXME: this should probably pass the frame instead
return XMLDocumentParser::create(*this, view());
return XMLDocumentParser::create(*this, view(), m_parserContentPolicy);
}

bool Document::hasHighlight() const
@@ -37,6 +37,7 @@
#include "DocumentEventTiming.h"
#include "FocusOptions.h"
#include "FontSelectorClient.h"
#include "FragmentScriptingPermission.h"
#include "FrameDestructionObserver.h"
#include "FrameIdentifier.h"
#include "FrameLoaderTypes.h"
@@ -891,6 +892,9 @@ class Document

Document& contextDocument() const;
void setContextDocument(Document& document) { m_contextDocument = document; }

OptionSet<ParserContentPolicy> parserContentPolicy() const { return m_parserContentPolicy; }
void setParserContentPolicy(OptionSet<ParserContentPolicy> policy) { m_parserContentPolicy = policy; }

// Helper functions for forwarding DOMWindow event related tasks to the DOMWindow if it exists.
void setWindowAttributeEventListener(const AtomString& eventType, const QualifiedName& attributeName, const AtomString& value, DOMWrapperWorld&);
@@ -1842,6 +1846,7 @@ class Document

RefPtr<DOMWindow> m_domWindow;
WeakPtr<Document, WeakPtrImplWithEventTargetData> m_contextDocument;
OptionSet<ParserContentPolicy> m_parserContentPolicy;

Ref<CachedResourceLoader> m_cachedResourceLoader;
RefPtr<DocumentParser> m_parser;
@@ -2690,8 +2690,15 @@ ExceptionOr<ShadowRoot&> Element::attachShadow(const ShadowRootInit& init)
{
if (!canAttachAuthorShadowRoot(*this))
return Exception { NotSupportedError };
if (shadowRoot())
if (RefPtr shadowRoot = this->shadowRoot()) {
if (shadowRoot->isDeclarativeShadowRoot()) {
ChildListMutationScope mutation(*shadowRoot);
shadowRoot->removeChildren();
shadowRoot->setIsDeclarativeShadowRoot(false);
return *shadowRoot;
}
return Exception { NotSupportedError };
}
if (init.mode == ShadowRootMode::UserAgent)
return Exception { TypeError };
auto shadow = ShadowRoot::create(document(), init.mode, init.slotAssignment, init.delegatesFocus ? ShadowRoot::DelegatesFocus::Yes : ShadowRoot::DelegatesFocus::No, isPrecustomizedOrDefinedCustomElement() ? ShadowRoot::AvailableToElementInternals::Yes : ShadowRoot::AvailableToElementInternals::No);
@@ -2700,6 +2707,16 @@ ExceptionOr<ShadowRoot&> Element::attachShadow(const ShadowRootInit& init)
return result;
}

ExceptionOr<ShadowRoot&> Element::attachDeclarativeShadow(ShadowRootMode mode, bool delegatesFocus)
{
auto exceptionOrShadowRoot = attachShadow({ mode, delegatesFocus });
if (exceptionOrShadowRoot.hasException())
return exceptionOrShadowRoot.releaseException();
auto& shadowRoot = exceptionOrShadowRoot.releaseReturnValue();
shadowRoot.setIsDeclarativeShadowRoot(true);
return shadowRoot;
}

ShadowRoot* Element::shadowRootForBindings(JSC::JSGlobalObject& lexicalGlobalObject) const
{
auto* shadow = shadowRoot();

0 comments on commit 46837e5

Please sign in to comment.