Bug 855411 - Root Init{JS}Class. r=bz,terrence

This commit is contained in:
Tom Schuster 2013-04-05 15:21:01 +02:00
parent a3d84dfa88
commit b59efb4448
5 changed files with 50 additions and 40 deletions

View File

@ -1077,22 +1077,25 @@ nsXBLBinding::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, void* aData)
// static
nsresult
nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
nsXBLBinding::DoInitJSClass(JSContext *cx, JS::Handle<JSObject*> global,
JS::Handle<JSObject*> obj,
const nsAFlatCString& aClassName,
nsXBLPrototypeBinding* aProtoBinding,
JSObject** aClassObject, bool* aNew)
JS::MutableHandle<JSObject*> aClassObject,
bool* aNew)
{
// First ensure our JS class is initialized.
nsAutoCString className(aClassName);
nsAutoCString xblKey(aClassName);
JSObject* parent_proto = nullptr; // If we have an "obj" we can set this
JSAutoRequest ar(cx);
JSAutoRequest ar(cx);
JSAutoCompartment ac(cx, global);
JS::Rooted<JSObject*> parent_proto(cx, nullptr);
nsXBLJSClass* c = nullptr;
if (obj) {
// Retrieve the current prototype of obj.
if (!JS_GetPrototype(cx, obj, &parent_proto)) {
if (!JS_GetPrototype(cx, obj, parent_proto.address())) {
return NS_ERROR_FAILURE;
}
if (parent_proto) {
@ -1100,8 +1103,8 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
// id. Append a space (an invalid URI character) to ensure that
// we don't have accidental collisions with the case when parent_proto is
// null and aClassName ends in some bizarre numbers (yeah, it's unlikely).
jsid parent_proto_id;
if (!::JS_GetObjectId(cx, parent_proto, &parent_proto_id)) {
JS::Rooted<jsid> parent_proto_id(cx);
if (!::JS_GetObjectId(cx, parent_proto, parent_proto_id.address())) {
// Probably OOM
return NS_ERROR_OUT_OF_MEMORY;
}
@ -1112,10 +1115,10 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
// provided).
char buf[20];
if (sizeof(jsid) == 4) {
PR_snprintf(buf, sizeof(buf), " %lx", parent_proto_id);
PR_snprintf(buf, sizeof(buf), " %lx", parent_proto_id.get());
} else {
MOZ_ASSERT(sizeof(jsid) == 8);
PR_snprintf(buf, sizeof(buf), " %llx", parent_proto_id);
PR_snprintf(buf, sizeof(buf), " %llx", parent_proto_id.get());
}
xblKey.Append(buf);
nsCStringKey key(xblKey);
@ -1131,10 +1134,16 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
}
}
JS::Value val;
JSObject* proto = nullptr;
if ((!::JS_LookupPropertyWithFlags(cx, global, className.get(), 0, &val)) ||
JSVAL_IS_PRIMITIVE(val)) {
JS::Rooted<JSObject*> proto(cx);
JS::Rooted<JS::Value> val(cx);
if (!::JS_LookupPropertyWithFlags(cx, global, className.get(), 0, val.address()))
return NS_ERROR_OUT_OF_MEMORY;
if (val.isObject()) {
*aNew = false;
proto = &val.toObject();
} else {
// We need to initialize the class.
*aNew = true;
@ -1213,14 +1222,9 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
NS_ADDREF(docInfo);
::JS_SetReservedSlot(proto, 0, PRIVATE_TO_JSVAL(aProtoBinding));
}
else {
*aNew = false;
proto = JSVAL_TO_OBJECT(val);
}
*aClassObject = proto;
aClassObject.set(proto);
if (obj) {
// Set the prototype of our object to be the new class.

View File

@ -143,10 +143,12 @@ public:
nsINodeList* GetAnonymousNodes();
static nsresult DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
static nsresult DoInitJSClass(JSContext *cx, JS::Handle<JSObject*> global,
JS::Handle<JSObject*> obj,
const nsAFlatCString& aClassName,
nsXBLPrototypeBinding* aProtoBinding,
JSObject** aClassObject, bool* aNew);
JS::MutableHandle<JSObject*> aClassObject,
bool* aNew);
bool AllowScripts(); // XXX make const

View File

@ -172,24 +172,29 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
// Because our prototype implementation has a class, we need to build up a corresponding
// class for the concrete implementation in the bound document.
AutoPushJSContext jscontext(aContext->GetNativeContext());
JSObject* global = sgo->GetGlobalJSObject();
AutoPushJSContext cx(aContext->GetNativeContext());
JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject());
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
JS::Value v;
rv = nsContentUtils::WrapNative(jscontext, global, aBoundElement, &v,
rv = nsContentUtils::WrapNative(cx, global, aBoundElement, &v,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JSObject*> value(cx, &v.toObject());
JS::Rooted<JSObject*> targetClassObject(cx, *aTargetClassObject);
// All of the above code was just obtaining the bound element's script object and its immediate
// concrete base class. We need to alter the object so that our concrete class is interposed
// between the object and its base class. We become the new base class of the object, and the
// object's old base class becomes the new class' base class.
rv = aBinding->InitClass(mClassName, jscontext, global, JSVAL_TO_OBJECT(v),
aTargetClassObject, aTargetIsNew);
rv = aBinding->InitClass(mClassName, cx, global, value,
&targetClassObject, aTargetIsNew);
if (NS_FAILED(rv)) {
return rv;
}
*aTargetClassObject = targetClassObject;
nsContentUtils::PreserveWrapper(aBoundElement, aBoundElement);
wrapper.swap(*aScriptObjectHolder);
@ -205,6 +210,7 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
// context.
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner(
do_QueryObject(aBinding->XBLDocumentInfo()));
nsIScriptGlobalObject* globalObject = globalOwner->GetScriptGlobalObject();
NS_ENSURE_TRUE(globalObject, NS_ERROR_UNEXPECTED);
@ -212,10 +218,9 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
NS_ENSURE_TRUE(context, NS_ERROR_OUT_OF_MEMORY);
AutoPushJSContext cx(context->GetNativeContext());
JSObject *global = globalObject->GetGlobalJSObject();
JSObject* classObject;
JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
JS::Rooted<JSObject*> classObject(cx);
bool classObjectIsNew = false;
nsresult rv = aBinding->InitClass(mClassName, cx, global, global,
&classObject, &classObjectIsNew);
@ -349,9 +354,9 @@ nsXBLProtoImpl::Read(nsIScriptContext* aContext,
{
// Set up a class object first so that deserialization is possible
AutoPushJSContext cx(aContext->GetNativeContext());
JSObject *global = aGlobal->GetGlobalJSObject();
JS::Rooted<JSObject*> global(cx, aGlobal->GetGlobalJSObject());
JSObject* classObject;
JS::Rooted<JSObject*> classObject(cx);
bool classObjectIsNew = false;
nsresult rv = aBinding->InitClass(mClassName, cx, global, global, &classObject,
&classObjectIsNew);

View File

@ -726,15 +726,12 @@ nsXBLPrototypeBinding::GetImmediateChild(nsIAtom* aTag)
nsresult
nsXBLPrototypeBinding::InitClass(const nsCString& aClassName,
JSContext * aContext, JSObject * aGlobal,
JSObject * aScriptObject,
JSObject** aClassObject,
JSContext * aContext,
JS::Handle<JSObject*> aGlobal,
JS::Handle<JSObject*> aScriptObject,
JS::MutableHandle<JSObject*> aClassObject,
bool* aNew)
{
NS_ENSURE_ARG_POINTER(aClassObject);
*aClassObject = nullptr;
return nsXBLBinding::DoInitJSClass(aContext, aGlobal, aScriptObject,
aClassName, this, aClassObject, aNew);
}

View File

@ -119,8 +119,10 @@ public:
}
nsresult InitClass(const nsCString& aClassName, JSContext * aContext,
JSObject * aGlobal, JSObject * aScriptObject,
JSObject** aClassObject, bool* aNew);
JS::Handle<JSObject*> aGlobal,
JS::Handle<JSObject*> aScriptObject,
JS::MutableHandle<JSObject*> aClassObject,
bool* aNew);
nsresult ConstructInterfaceTable(const nsAString& aImpls);