Issue #1375 - Fix IsWebComponentsEnabled checks

This commit is contained in:
Matt A. Tobin 2020-04-17 07:43:40 -04:00 committed by Roy Tam
commit ca48752304
13 changed files with 154 additions and 137 deletions

View file

@ -2242,6 +2242,29 @@ WarnIfSandboxIneffective(nsIDocShell* aDocShell,
}
}
bool
nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
{
if (!nsContentUtils::IsWebComponentsEnabled()) {
return false;
}
JS::Rooted<JSObject*> obj(aCx, aObject);
JSAutoCompartment ac(aCx, obj);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj));
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global));
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
if (doc && doc->IsStyledByServo()) {
NS_WARNING("stylo: Web Components not supported yet");
return false;
}
return true;
}
nsresult
nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
nsILoadGroup* aLoadGroup,
@ -5581,65 +5604,12 @@ nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI,
return attribute.forget();
}
bool
nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
{
JS::Rooted<JSObject*> obj(aCx, aObject);
if (nsContentUtils::IsWebComponentsEnabled()) {
return true;
}
// Check for the webcomponents permission. See Bug 1181555.
JSAutoCompartment ac(aCx, obj);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj));
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global));
return IsWebComponentsEnabled(window);
}
bool
nsDocument::IsWebComponentsEnabled(const nsINode* aNode)
{
return aNode->OwnerDoc()->IsWebComponentsEnabled();
}
bool
nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
{
if (nsContentUtils::IsWebComponentsEnabled()) {
return true;
}
nsIDocument* doc = aNodeInfo->GetDocument();
// Use GetScopeObject() here so that data documents work the same way as the
// main document they're associated with.
nsCOMPtr<nsPIDOMWindowInner> window =
do_QueryInterface(doc->GetScopeObject());
return IsWebComponentsEnabled(window);
}
bool
nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow)
{
if (aWindow) {
nsresult rv;
nsCOMPtr<nsIPermissionManager> permMgr =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, false);
uint32_t perm;
rv = permMgr->TestPermissionFromWindow(
aWindow, "moz-extremely-unstable-and-will-change-webcomponents", &perm);
NS_ENSURE_SUCCESS(rv, false);
return perm == nsIPermissionManager::ALLOW_ACTION;
}
return false;
}
NS_IMETHODIMP
nsDocument::GetElementsByTagName(const nsAString& aTagname,
nsIDOMNodeList** aReturn)

View file

@ -755,6 +755,11 @@ public:
virtual void NotifyLayerManagerRecreated() override;
// Check whether web components are enabled for the global of aObject.
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
// Check whether web components are enabled for the document this node belongs
// to.
static bool IsWebComponentsEnabled(const nsINode* aNode);
private:
void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
@ -1341,17 +1346,6 @@ protected:
nsWeakPtr mFullscreenRoot;
public:
// Check whether web components are enabled for the global of aObject.
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
// Check whether web components are enabled for the document this node belongs
// to.
static bool IsWebComponentsEnabled(const nsINode* aNode);
// Check whether web components are enabled for the global of the document
// this nodeinfo comes from.
static bool IsWebComponentsEnabled(mozilla::dom::NodeInfo* aNodeInfo);
// Check whether web components are enabled for the given window.
static bool IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow);
RefPtr<mozilla::EventListenerManager> mListenerManager;
RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
RefPtr<nsScriptLoader> mScriptLoader;

View file

@ -236,17 +236,17 @@ dictionary ShadowRootInit {
// https://dom.spec.whatwg.org/#element
partial interface Element {
// Shadow DOM v1
[Throws, Pref="nsDocument::IsWebComponentsEnabled"]
[Throws, Func="nsDocument::IsWebComponentsEnabled"]
ShadowRoot attachShadow(ShadowRootInit shadowRootInitDict);
[BinaryName="shadowRootByMode", Func="nsDocument::IsWebComponentsEnabled"]
readonly attribute ShadowRoot? shadowRoot;
[BinaryName="assignedSlotByMode", Pref="nsDocument::IsWebComponentsEnabled"]
[BinaryName="assignedSlotByMode", Func="nsDocument::IsWebComponentsEnabled"]
readonly attribute HTMLSlotElement? assignedSlot;
[CEReactions, Unscopable, SetterThrows, Pref="nsDocument::IsWebComponentsEnabled"]
[CEReactions, Unscopable, SetterThrows, Func="nsDocument::IsWebComponentsEnabled"]
attribute DOMString slot;
// [deprecated] Shadow DOM v0
[Throws, Pref="nsDocument::IsWebComponentsEnabled"]
[Throws, Func="nsDocument::IsWebComponentsEnabled"]
ShadowRoot createShadowRoot();
};

View file

@ -7,15 +7,17 @@
<script>
function insertShadowSVG() {
var x = document.getElementById("x");
x.createShadowRoot();
x.shadowRoot.innerHTML =
'<svg width="50px" height="10px"> \
<switch> \
<foreignObject width="50px" height="50px"> \
<div style="width: 100px; height: 10px; background: red;"></div> \
</foreignObject> \
</switch> \
</svg>';
if (x.createShadowRoot) {
x.createShadowRoot();
x.shadowRoot.innerHTML =
'<svg width="50px" height="10px"> \
<switch> \
<foreignObject width="50px" height="50px"> \
<div style="width: 100px; height: 10px; background: red;"></div> \
</foreignObject> \
</switch> \
</svg>';
}
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", insertShadowSVG, false);

View file

@ -1851,7 +1851,7 @@ test-pref(layout.css.grid.enabled,true) == 1053035-1-grid.html 1053035-1-ref.htm
== 1062108-1.html 1062108-1-ref.html
== 1062792-1.html 1062792-1-ref.html
== 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html
test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html
test-pref(dom.webcomponents.enabled,true) fails-if(stylo||styloVsGecko) == 1066554-1.html 1066554-1-ref.html
== 1069716-1.html 1069716-1-ref.html
== 1078262-1.html about:blank
test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html

View file

@ -74,36 +74,40 @@ div.after::after {content: " Y";}
return e;
}
document.body.offsetHeight;
function run() {
document.body.offsetHeight;
shadow("host1").innerHTML = '<content></content> c';
shadow("host2").innerHTML = 'a <content style="display:contents"></content> c';
shadow("host3").innerHTML = 'a <content style="display:contents"></content>';
shadow("host4").innerHTML = '<content style="display:contents"></content>';
shadow("host5").innerHTML = 'a <content style="display:contents"></content>';
shadow("host6").innerHTML = '<z style="color:blue; display:contents"><content></content></z> c';
shadow("host7").innerHTML = 'a <content style="display:contents"></content> c';
shadow("host8").innerHTML = 'a <z style="color:blue; display:contents"><content style="display:contents"></z></content>';
shadow("host9").innerHTML = '<content style="display:contents"></content>';
shadow("hostA").innerHTML = 'a <content style="display:contents"></content>';
shadow("hostB").innerHTML = 'a <content select=".c"></content> <content select=".b"></content> B';
shadow("hostC").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B';
shadow("hostD").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B <content select=".b"></content>';
shadow("hostE").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B';
shadow("hostF").innerHTML = '<content select=".c"></content> <content select=".b"></content> B';
shadow("hostG").innerHTML = '<content select=".b"></content>';
shadow("hostH").innerHTML = '<content select=".b"></content>';
shadow("hostI").innerHTML = 'A<content select=".b"></content>';
shadow("hostJ").innerHTML = 'A<content select=".b"></content>';
shadow("hostK").innerHTML = '<content select=".b"></content>';
shadow("hostL").innerHTML = '<content select=".b"></content>';
shadow("hostM").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostN").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostO").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostP").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostQ").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostR").innerHTML = '<content select="span"></content>';
// TODO(bug 1021572?) shadow("hostY").innerHTML = '<content select="b"><style scoped>:scope{color:green}</style></content>';
shadow("host1").innerHTML = '<content></content> c';
shadow("host2").innerHTML = 'a <content style="display:contents"></content> c';
shadow("host3").innerHTML = 'a <content style="display:contents"></content>';
shadow("host4").innerHTML = '<content style="display:contents"></content>';
shadow("host5").innerHTML = 'a <content style="display:contents"></content>';
shadow("host6").innerHTML = '<z style="color:blue; display:contents"><content></content></z> c';
shadow("host7").innerHTML = 'a <content style="display:contents"></content> c';
shadow("host8").innerHTML = 'a <z style="color:blue; display:contents"><content style="display:contents"></z></content>';
shadow("host9").innerHTML = '<content style="display:contents"></content>';
shadow("hostA").innerHTML = 'a <content style="display:contents"></content>';
shadow("hostB").innerHTML = 'a <content select=".c"></content> <content select=".b"></content> B';
shadow("hostC").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B';
shadow("hostD").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B <content select=".b"></content>';
shadow("hostE").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B';
shadow("hostF").innerHTML = '<content select=".c"></content> <content select=".b"></content> B';
shadow("hostG").innerHTML = '<content select=".b"></content>';
shadow("hostH").innerHTML = '<content select=".b"></content>';
shadow("hostI").innerHTML = 'A<content select=".b"></content>';
shadow("hostJ").innerHTML = 'A<content select=".b"></content>';
shadow("hostK").innerHTML = '<content select=".b"></content>';
shadow("hostL").innerHTML = '<content select=".b"></content>';
shadow("hostM").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostN").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostO").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostP").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostQ").innerHTML = '<content select="b"></content><content select="i"></content>';
shadow("hostR").innerHTML = '<content select="span"></content>';
shadow("hostW").innerHTML = '<z style="color:red"><content select="b"></content></z>';
shadow("hostX").innerHTML = '<z style="color:red"><content select="b"></content></z>';
// TODO(bug 1021572?) shadow("hostY").innerHTML = '<content select="b"><style scoped>:scope{color:green}</style></content>';
}
function tweak() {
document.body.offsetHeight;
@ -224,7 +228,12 @@ div.after::after {content: " Y";}
},0);
}
window.addEventListener("MozReftestInvalidate", tweak, false);
if (document.body.createShadowRoot) {
run();
window.addEventListener("MozReftestInvalidate", tweak, false);
} else {
document.documentElement.removeAttribute("class");
}
</script>
</body>
</html>

View file

@ -48,17 +48,19 @@ div.after::after {content: " Y";}
return e;
}
document.body.offsetHeight;
function run() {
document.body.offsetHeight;
shadow("host1").innerHTML = '<content></content> c';
shadow("host2").innerHTML = 'a <content></content> c';
shadow("host3").innerHTML = 'a <content></content>';
shadow("host4").innerHTML = '<content></content>';
shadow("host5").innerHTML = 'a <content></content>';
shadow("host6").innerHTML = '<z style="color:blue; display:contents"><content></content></z> c';
shadow("host7").innerHTML = 'a <content select=".c"></content> <content select=".b"></content> B';
shadow("host8").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B';
shadow("host9").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B <content select=".b"></content>';
shadow("host1").innerHTML = '<content></content> c';
shadow("host2").innerHTML = 'a <content></content> c';
shadow("host3").innerHTML = 'a <content></content>';
shadow("host4").innerHTML = '<content></content>';
shadow("host5").innerHTML = 'a <content></content>';
shadow("host6").innerHTML = '<z style="color:blue; display:contents"><content></content></z> c';
shadow("host7").innerHTML = 'a <content select=".c"></content> <content select=".b"></content> B';
shadow("host8").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B';
shadow("host9").innerHTML = 'A <content select=".c"></content> <content select=".b"></content> B <content select=".b"></content>';
}
function tweak() {
document.body.offsetHeight;
@ -105,7 +107,12 @@ div.after::after {content: " Y";}
},0);
}
window.addEventListener("MozReftestInvalidate", tweak, false);
if (document.body.createShadowRoot) {
run();
window.addEventListener("MozReftestInvalidate", tweak, false);
} else {
document.documentElement.removeAttribute("class");
}
</script>
</body>
</html>

View file

@ -7,9 +7,11 @@
<script>
function insertShadowMathML() {
var x = document.getElementById("x");
x.createShadowRoot();
x.shadowRoot.innerHTML =
'<math><msup><mi>X</mi><mi>X</mi></msup></math>';
if (x.createShadowRoot) {
x.createShadowRoot();
x.shadowRoot.innerHTML =
'<math><msup><mi>X</mi><mi>X</mi></msup></math>';
}
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", insertShadowMathML, false);

View file

@ -3,6 +3,11 @@
<head>
<script>
function tweak() {
if (!document.body.createShadowRoot) {
document.documentElement.className = "";
return;
}
var host = document.getElementById("host");
var shadow = host.createShadowRoot();

View file

@ -7,9 +7,11 @@
<script>
var host, root;
host = document.getElementById("host");
root = host.attachShadow({mode: 'open'});
root.innerHTML = 'a <slot></slot> c';
function run() {
host = document.getElementById("host");
root = host.createShadowRoot();
root.innerHTML = 'a <content></content> c';
}
function tweak() {
var span = document.createElement("span");
@ -21,7 +23,12 @@
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", tweak);
if (document.body.createShadowRoot) {
run();
window.addEventListener("MozReftestInvalidate", tweak, false);
} else {
document.documentElement.className = "";
}
</script>
</body>
</html>

View file

@ -7,9 +7,11 @@
<script>
var host, root;
host = document.getElementById("host");
root = host.attachShadow({mode: 'open'});
root.innerHTML = "<span>a</span>";
function run() {
host = document.getElementById("host");
root = host.createShadowRoot();
root.innerHTML = "<span>a</span>";
}
function tweak() {
var span = document.createElement("span");
@ -22,7 +24,12 @@
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", tweak);
if (document.body.createShadowRoot) {
run();
window.addEventListener("MozReftestInvalidate", tweak);
} else {
document.documentElement.className = "";
}
</script>
</body>
</html>

View file

@ -7,9 +7,11 @@
<script>
var host, root;
host = document.getElementById("host");
root = host.attachShadow({mode: 'open'});
root.innerHTML = '<style>input ~ div { background: red; transition: background 100ms; } input:checked ~ div { background: green; }</style><input id="one" type="checkbox"><div style="height: 50px; width: 50px;"></div>';
function run() {
host = document.getElementById("host");
root = host.createShadowRoot();
root.innerHTML = '<style>input ~ div { background: red; transition: background 100ms; } input:checked ~ div { background: green; }</style><input id="one" type="checkbox"><div style="height: 50px; width: 50px;"></div>';
}
function tweak() {
var el = root.getElementById("one");
@ -19,7 +21,12 @@
});
}
window.addEventListener("MozReftestInvalidate", tweak);
if (document.body.createShadowRoot) {
run();
window.addEventListener("MozReftestInvalidate", tweak);
} else {
document.documentElement.className = "";
}
</script>
</body>
</html>

View file

@ -6,8 +6,10 @@
<div id="outer"><span id="distnode">text</span></div>
<script>
var shadowRoot = document.getElementById('outer').attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<div><slot></slot></div>';
function run() {
var shadowRoot = document.getElementById('outer').createShadowRoot();
shadowRoot.innerHTML = '<div><content></content></div>';
}
function tweak() {
var distNode = document.getElementById("distnode");
@ -16,7 +18,12 @@
document.documentElement.removeAttribute("class");
}
if (document.body.createShadowRoot) {
run();
window.addEventListener("MozReftestInvalidate", tweak);
} else {
document.documentElement.className = "";
}
</script>
</body>
</html>