summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2020-01-05 10:32:10 -0500
committerGaming4JC <g4jc@hyperbola.info>2020-01-26 15:50:24 -0500
commit515c46e695f6cf0a66273e4744330ad7d23fe2cc (patch)
treeab7208457bbf0dc1e1449981405a8708e7c48764
parentd7e5ad445cc8cb3f3f04e7c177350fcf1c12c62f (diff)
downloaduxp-515c46e695f6cf0a66273e4744330ad7d23fe2cc.tar.gz
Bug 1353647 - Fix the custom elements v0 upgrade inconsistency;
There are two places doing prototype setup in old upgrade, - If definition comes after JS reflector creation, CustomElementRegistry::Upgrade will do prototype swizzling. - If definition comes before JS reflector creation, Element::WrapObject will set up the prototype. The later one does SubsumesConsideringDomain, but the former doesn't not. This patch is to fix the inconsistency, i.e. the former case should also do SubsumesConsideringDomain. Tag UXP Issue #1344
-rw-r--r--dom/base/CustomElementRegistry.cpp40
1 files changed, 25 insertions, 15 deletions
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
index 6602220580..1c1e3d6ae9 100644
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -798,30 +798,40 @@ CustomElementRegistry::Upgrade(Element* aElement,
}
MOZ_ASSERT(aElement->IsHTMLElement(aDefinition->mLocalName));
- nsWrapperCache* cache;
- CallQueryInterface(aElement, &cache);
- MOZ_ASSERT(cache, "Element doesn't support wrapper cache?");
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mWindow))) {
return;
}
- JSContext *cx = jsapi.cx();
- // We want to set the custom prototype in the the compartment of define()'s caller.
- // We store the prototype from define() directly,
- // hence the prototype's compartment is the caller's compartment.
- JS::RootedObject wrapper(cx);
- JS::Rooted<JSObject*> prototype(cx, aDefinition->mPrototype);
- { // Enter prototype's compartment.
- JSAutoCompartment ac(cx, prototype);
-
- if ((wrapper = cache->GetWrapper()) && JS_WrapObject(cx, &wrapper)) {
- if (!JS_SetPrototype(cx, wrapper, prototype)) {
+ JSContext* cx = jsapi.cx();
+
+ JS::Rooted<JSObject*> reflector(cx, aElement->GetWrapper());
+ if (reflector) {
+ Maybe<JSAutoCompartment> ac;
+ JS::Rooted<JSObject*> prototype(cx, aDefinition->mPrototype);
+ if (aElement->NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(prototype))) {
+ ac.emplace(cx, reflector);
+ if (!JS_WrapObject(cx, &prototype) ||
+ !JS_SetPrototype(cx, reflector, prototype)) {
+ return;
+ }
+ } else {
+ // We want to set the custom prototype in the compartment where it was
+ // registered. We store the prototype from define() without unwrapped,
+ // hence the prototype's compartment is the compartment where it was
+ // registered.
+ // In the case that |reflector| and |prototype| are in different
+ // compartments, this will set the prototype on the |reflector|'s wrapper
+ // and thus only visible in the wrapper's compartment, since we know
+ // reflector's principal does not subsume prototype's in this case.
+ ac.emplace(cx, prototype);
+ if (!JS_WrapObject(cx, &reflector) ||
+ !JS_SetPrototype(cx, reflector, prototype)) {
return;
}
}
- } // Leave prototype's compartment.
+ }
EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, aDefinition);
}