summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 660222058..1c1e3d6ae 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);
}