Bug 1145017. Use the new proto setup for custom element prototypes when possible. r=wchen,bholley

Note that with this patch I'm also changing the priority order of the given
proto and the custom proto; the former takes priority.  This makes sense to me:
if the caller is doing |new Foo| they really should get something with
Foo.prototype as its proto.  This should not be a problem for custom elements
in general so far, because nodes/elements are mostly not constructible anyway.
For now.  When they become that way, I think this is the behavior we'll want.
This commit is contained in:
Boris Zbarsky 2015-03-20 00:34:08 -04:00
parent 457c7466d5
commit 60ca8ac291

View File

@ -408,28 +408,43 @@ Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
JSObject*
Element::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
{
JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx, aGivenProto));
JS::Rooted<JSObject*> givenProto(aCx, aGivenProto);
JS::Rooted<JSObject*> customProto(aCx);
if (!givenProto) {
// Custom element prototype swizzling.
CustomElementData* data = GetCustomElementData();
if (data) {
// If this is a registered custom element then fix the prototype.
nsDocument* document = static_cast<nsDocument*>(OwnerDoc());
document->GetCustomPrototype(NodeInfo()->NamespaceID(), data->mType, &customProto);
if (customProto &&
NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(customProto))) {
// Just go ahead and create with the right proto up front. Set
// customProto to null to flag that we don't need to do any post-facto
// proto fixups here.
givenProto = customProto;
customProto = nullptr;
}
}
}
JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx, givenProto));
if (!obj) {
return nullptr;
}
// Custom element prototype swizzling.
CustomElementData* data = GetCustomElementData();
if (obj && data) {
// If this is a registered custom element then fix the prototype.
nsDocument* document = static_cast<nsDocument*>(OwnerDoc());
JS::Rooted<JSObject*> prototype(aCx);
document->GetCustomPrototype(NodeInfo()->NamespaceID(), data->mType, &prototype);
if (prototype) {
// We want to set the custom prototype in the compartment where it was
// registered. In the case that |obj| and |prototype| are in different
// compartments, this will set the prototype on the |obj|'s wrapper and
// thus only visible in the wrapper's compartment.
JSAutoCompartment ac(aCx, prototype);
if (!JS_WrapObject(aCx, &obj) || !JS_SetPrototype(aCx, obj, prototype)) {
dom::Throw(aCx, NS_ERROR_FAILURE);
return nullptr;
}
if (customProto) {
// We want to set the custom prototype in the compartment where it was
// registered. In the case that |obj| and |prototype| are in different
// compartments, this will set the prototype on the |obj|'s wrapper and
// thus only visible in the wrapper's compartment, since we know obj's
// principal does not subsume customProto's in this case.
JSAutoCompartment ac(aCx, customProto);
JS::Rooted<JSObject*> wrappedObj(aCx, obj);
if (!JS_WrapObject(aCx, &wrappedObj) ||
!JS_SetPrototype(aCx, wrappedObj, customProto)) {
return nullptr;
}
}