зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1596458 part 2. Fix the innerHTML setter for shadow DOM cases in XML to supply the right context. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D53077 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
39eb418bd8
Коммит
e9cfb6db8e
|
@ -1961,16 +1961,17 @@ void FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML,
|
|||
|
||||
nsAutoScriptLoaderDisabler sld(doc);
|
||||
|
||||
nsAtom* contextLocalName = NodeInfo()->NameAtom();
|
||||
int32_t contextNameSpaceID = GetNameSpaceID();
|
||||
|
||||
FragmentOrElement* parseContext = this;
|
||||
if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(this)) {
|
||||
// Fix up the context to be the host of the ShadowRoot.
|
||||
contextLocalName = shadowRoot->GetHost()->NodeInfo()->NameAtom();
|
||||
contextNameSpaceID = shadowRoot->GetHost()->GetNameSpaceID();
|
||||
// Fix up the context to be the host of the ShadowRoot. See
|
||||
// https://w3c.github.io/DOM-Parsing/#dom-innerhtml-innerhtml setter step 1.
|
||||
parseContext = shadowRoot->GetHost();
|
||||
}
|
||||
|
||||
if (doc->IsHTMLDocument()) {
|
||||
nsAtom* contextLocalName = parseContext->NodeInfo()->NameAtom();
|
||||
int32_t contextNameSpaceID = parseContext->GetNameSpaceID();
|
||||
|
||||
int32_t oldChildCount = target->GetChildCount();
|
||||
aError = nsContentUtils::ParseFragmentHTML(
|
||||
aInnerHTML, target, contextLocalName, contextNameSpaceID,
|
||||
|
@ -1981,14 +1982,14 @@ void FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML,
|
|||
oldChildCount);
|
||||
} else {
|
||||
RefPtr<DocumentFragment> df = nsContentUtils::CreateContextualFragment(
|
||||
target, aInnerHTML, true, aError);
|
||||
parseContext, aInnerHTML, true, aError);
|
||||
if (!aError.Failed()) {
|
||||
// Suppress assertion about node removal mutation events that can't have
|
||||
// listeners anyway, because no one has had the chance to register
|
||||
// mutation listeners on the fragment that comes from the parser.
|
||||
nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
|
||||
|
||||
static_cast<nsINode*>(target)->AppendChild(*df, aError);
|
||||
target->AppendChild(*df, aError);
|
||||
mb.NodesAdded();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ interface ShadowRoot : DocumentFragment
|
|||
|
||||
Element? getElementById(DOMString elementId);
|
||||
|
||||
// https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin
|
||||
[CEReactions, SetterThrows]
|
||||
attribute [TreatNullAs=EmptyString] DOMString innerHTML;
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:bar="bar">
|
||||
<head>
|
||||
<title>Test for Shadow DOM innerHTML setter in XML</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
<![CDATA[
|
||||
// We define our custom elements lazily so we don't mess
|
||||
// with the DOM during parsing.
|
||||
customElements.define("custom-el-1",
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: "open" });
|
||||
try { this.shadowRoot.innerHTML = "<span/>"; } catch (e) {}
|
||||
}
|
||||
});
|
||||
function defineElements() {
|
||||
// We define our custom elements whose behavior involves
|
||||
// ancestors of our parent lazily, because otherwise the
|
||||
// constructor runs before the element is in the DOM and has
|
||||
// the ancestors set up.
|
||||
customElements.define("custom-el-2",
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: "open" });
|
||||
try { this.shadowRoot.innerHTML = "<span/>"; } catch (e) {}
|
||||
}
|
||||
});
|
||||
customElements.define("custom-el-with-prefix",
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: "open" });
|
||||
try {
|
||||
this.shadowRoot.innerHTML = "<bar:span/>";
|
||||
} catch (e) {
|
||||
// Test will fail due to us not having the kid
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<custom-el-1 id="htmlDefault"/>
|
||||
<span xmlns="foo" xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
<html:custom-el-2 id="fooDefault"/>
|
||||
</span>
|
||||
<custom-el-with-prefix id="prefixTest"/>
|
||||
<script>
|
||||
<![CDATA[
|
||||
const htmlNS = "http://www.w3.org/1999/xhtml";
|
||||
test(() => {
|
||||
var el = document.getElementById("htmlDefault");
|
||||
var kid = el.shadowRoot.firstChild;
|
||||
assert_equals(kid.namespaceURI, htmlNS,
|
||||
"Kid's namespace should be our default");
|
||||
}, "InnerHTML behavior on custom element in default XHTML namespace");
|
||||
|
||||
test(defineElements, "Setting up the custom elements");
|
||||
test(() => {
|
||||
var el = document.getElementById("fooDefault");
|
||||
var kid = el.shadowRoot.firstChild;
|
||||
assert_equals(kid.namespaceURI, "foo",
|
||||
"Kid's namespace should be our default");
|
||||
}, "InnerHTML behavior on custom element in default 'foo' namespace");
|
||||
|
||||
test(() => {
|
||||
var el = document.getElementById("prefixTest");
|
||||
var kid = el.shadowRoot.firstChild;
|
||||
assert_equals(kid.namespaceURI, "bar",
|
||||
"Kid's namespace should be based on ancestor prefix");
|
||||
}, "InnerHTML behavior with prefixes on custom element");
|
||||
]]>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче