mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-12 23:12:21 +00:00
Bug 821850 - Make DoInitJSClass unconditionally fill in aClassObject. r=bz
Right now, DoInitJSClass only returns non-null if the class object is new (and thus needs to have members installed on it). The code then goes and unconditionally tries to install the members, null-checking and aborting each time. Instead, let's use an explicit boolean and one early return. This lets us get a reference to our JSClass no matter what, which we need.
This commit is contained in:
parent
9069c014a7
commit
225d119eed
@ -1352,7 +1352,7 @@ nsresult
|
||||
nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
|
||||
const nsAFlatCString& aClassName,
|
||||
nsXBLPrototypeBinding* aProtoBinding,
|
||||
JSObject** aClassObject)
|
||||
JSObject** aClassObject, bool* aNew)
|
||||
{
|
||||
// First ensure our JS class is initialized.
|
||||
nsAutoCString className(aClassName);
|
||||
@ -1408,6 +1408,7 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
|
||||
if ((!::JS_LookupPropertyWithFlags(cx, global, className.get(), 0, &val)) ||
|
||||
JSVAL_IS_PRIMITIVE(val)) {
|
||||
// We need to initialize the class.
|
||||
*aNew = true;
|
||||
|
||||
nsCStringKey key(xblKey);
|
||||
if (!c) {
|
||||
@ -1485,12 +1486,14 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
|
||||
|
||||
::JS_SetReservedSlot(proto, 0, PRIVATE_TO_JSVAL(aProtoBinding));
|
||||
|
||||
*aClassObject = proto;
|
||||
}
|
||||
else {
|
||||
*aNew = false;
|
||||
proto = JSVAL_TO_OBJECT(val);
|
||||
}
|
||||
|
||||
*aClassObject = proto;
|
||||
|
||||
if (obj) {
|
||||
// Set the prototype of our object to be the new class.
|
||||
if (!::JS_SetPrototype(cx, obj, proto)) {
|
||||
|
@ -114,7 +114,7 @@ public:
|
||||
static nsresult DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
|
||||
const nsAFlatCString& aClassName,
|
||||
nsXBLPrototypeBinding* aProtoBinding,
|
||||
JSObject** aClassObject);
|
||||
JSObject** aClassObject, bool* aNew);
|
||||
|
||||
bool AllowScripts(); // XXX make const
|
||||
|
||||
|
@ -68,10 +68,17 @@ nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding,
|
||||
// not been built already.
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
JSObject* targetClassObject = nullptr;
|
||||
bool targetObjectIsNew = false;
|
||||
nsresult rv = InitTargetObjects(aPrototypeBinding, context,
|
||||
aBinding->GetBoundElement(),
|
||||
getter_AddRefs(holder), &targetClassObject);
|
||||
getter_AddRefs(holder), &targetClassObject,
|
||||
&targetObjectIsNew);
|
||||
NS_ENSURE_SUCCESS(rv, rv); // kick out if we were unable to properly intialize our target objects
|
||||
MOZ_ASSERT(targetClassObject);
|
||||
|
||||
// If the prototype already existed, we don't need to install anything. return early.
|
||||
if (!targetObjectIsNew)
|
||||
return NS_OK;
|
||||
|
||||
JSObject * targetScriptObject;
|
||||
holder->GetJSObject(&targetScriptObject);
|
||||
@ -95,7 +102,8 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
|
||||
nsIScriptContext* aContext,
|
||||
nsIContent* aBoundElement,
|
||||
nsIXPConnectJSObjectHolder** aScriptObjectHolder,
|
||||
JSObject** aTargetClassObject)
|
||||
JSObject** aTargetClassObject,
|
||||
bool* aTargetIsNew)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
*aScriptObjectHolder = nullptr;
|
||||
@ -132,7 +140,7 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
|
||||
// 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);
|
||||
aTargetClassObject, aTargetIsNew);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -163,14 +171,15 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
|
||||
|
||||
|
||||
JSObject* classObject;
|
||||
bool classObjectIsNew = false;
|
||||
nsresult rv = aBinding->InitClass(mClassName, cx, global, global,
|
||||
&classObject);
|
||||
&classObject, &classObjectIsNew);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
MOZ_ASSERT(classObjectIsNew);
|
||||
MOZ_ASSERT(classObject);
|
||||
mClassObject = classObject;
|
||||
if (!mClassObject)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
AutoVersionChecker avc(cx);
|
||||
|
||||
@ -284,9 +293,12 @@ nsXBLProtoImpl::Read(nsIScriptContext* aContext,
|
||||
JSObject *global = aGlobal->GetGlobalJSObject();
|
||||
|
||||
JSObject* classObject;
|
||||
nsresult rv = aBinding->InitClass(mClassName, cx, global, global, &classObject);
|
||||
bool classObjectIsNew = false;
|
||||
nsresult rv = aBinding->InitClass(mClassName, cx, global, global, &classObject,
|
||||
&classObjectIsNew);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(classObject, NS_ERROR_FAILURE);
|
||||
MOZ_ASSERT(classObject);
|
||||
MOZ_ASSERT(classObjectIsNew);
|
||||
|
||||
mClassObject = classObject;
|
||||
|
||||
|
@ -41,7 +41,8 @@ public:
|
||||
nsresult InitTargetObjects(nsXBLPrototypeBinding* aBinding, nsIScriptContext* aContext,
|
||||
nsIContent* aBoundElement,
|
||||
nsIXPConnectJSObjectHolder** aScriptObjectHolder,
|
||||
JSObject** aTargetClassObject);
|
||||
JSObject** aTargetClassObject,
|
||||
bool* aTargetIsNew);
|
||||
nsresult CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding);
|
||||
|
||||
void SetMemberList(nsXBLProtoImplMember* aMemberList)
|
||||
|
@ -115,7 +115,7 @@ nsXBLProtoImplMethod::InstallMember(nsIScriptContext* aContext,
|
||||
JSObject* globalObject = sgo->GetGlobalJSObject();
|
||||
|
||||
// now we want to reevaluate our property using aContext and the script object for this window...
|
||||
if (mJSMethodObject && aTargetClassObject) {
|
||||
if (mJSMethodObject) {
|
||||
nsDependentString name(mName);
|
||||
JSAutoRequest ar(cx);
|
||||
JSAutoCompartment ac(cx, globalObject);
|
||||
|
@ -158,7 +158,7 @@ nsXBLProtoImplProperty::InstallMember(nsIScriptContext* aContext,
|
||||
JSObject * globalObject = sgo->GetGlobalJSObject();
|
||||
|
||||
// now we want to reevaluate our property using aContext and the script object for this window...
|
||||
if ((mJSGetterObject || mJSSetterObject) && aTargetClassObject) {
|
||||
if (mJSGetterObject || mJSSetterObject) {
|
||||
JSObject * getter = nullptr;
|
||||
JSAutoRequest ar(cx);
|
||||
JSAutoCompartment ac(cx, globalObject);
|
||||
|
@ -841,14 +841,15 @@ nsresult
|
||||
nsXBLPrototypeBinding::InitClass(const nsCString& aClassName,
|
||||
JSContext * aContext, JSObject * aGlobal,
|
||||
JSObject * aScriptObject,
|
||||
JSObject** aClassObject)
|
||||
JSObject** aClassObject,
|
||||
bool* aNew)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aClassObject);
|
||||
|
||||
*aClassObject = nullptr;
|
||||
|
||||
return nsXBLBinding::DoInitJSClass(aContext, aGlobal, aScriptObject,
|
||||
aClassName, this, aClassObject);
|
||||
aClassName, this, aClassObject, aNew);
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
|
@ -121,7 +121,7 @@ public:
|
||||
|
||||
nsresult InitClass(const nsCString& aClassName, JSContext * aContext,
|
||||
JSObject * aGlobal, JSObject * aScriptObject,
|
||||
JSObject** aClassObject);
|
||||
JSObject** aClassObject, bool* aNew);
|
||||
|
||||
nsresult ConstructInterfaceTable(const nsAString& aImpls);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user