diff options
Diffstat (limited to 'dom/base/CustomElementRegistry.cpp')
-rw-r--r-- | dom/base/CustomElementRegistry.cpp | 40 |
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); } |