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 9fb24e2658
commit 17e46d2f65

View File

@ -408,28 +408,43 @@ Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
JSObject* JSObject*
Element::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) 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) { if (!obj) {
return nullptr; return nullptr;
} }
// Custom element prototype swizzling. if (customProto) {
CustomElementData* data = GetCustomElementData(); // We want to set the custom prototype in the compartment where it was
if (obj && data) { // registered. In the case that |obj| and |prototype| are in different
// If this is a registered custom element then fix the prototype. // compartments, this will set the prototype on the |obj|'s wrapper and
nsDocument* document = static_cast<nsDocument*>(OwnerDoc()); // thus only visible in the wrapper's compartment, since we know obj's
JS::Rooted<JSObject*> prototype(aCx); // principal does not subsume customProto's in this case.
document->GetCustomPrototype(NodeInfo()->NamespaceID(), data->mType, &prototype); JSAutoCompartment ac(aCx, customProto);
if (prototype) { JS::Rooted<JSObject*> wrappedObj(aCx, obj);
// We want to set the custom prototype in the compartment where it was if (!JS_WrapObject(aCx, &wrappedObj) ||
// registered. In the case that |obj| and |prototype| are in different !JS_SetPrototype(aCx, wrappedObj, customProto)) {
// compartments, this will set the prototype on the |obj|'s wrapper and return nullptr;
// 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;
}
} }
} }