nsresult nsXBLProtoImpl::Write(nsIScriptContext* aContext, nsIObjectOutputStream* aStream, nsXBLPrototypeBinding* aBinding) { nsresult rv; if (!mClassObject) { rv = CompilePrototypeMembers(aBinding); NS_ENSURE_SUCCESS(rv, rv); } rv = aStream->WriteStringZ(mClassName.get()); NS_ENSURE_SUCCESS(rv, rv); for (nsXBLProtoImplField* curr = mFields; curr; curr = curr->GetNext()) { rv = curr->Write(aContext, aStream); NS_ENSURE_SUCCESS(rv, rv); } for (nsXBLProtoImplMember* curr = mMembers; curr; curr = curr->GetNext()) { if (curr == mConstructor) { rv = mConstructor->Write(aContext, aStream, XBLBinding_Serialize_Constructor); } else if (curr == mDestructor) { rv = mDestructor->Write(aContext, aStream, XBLBinding_Serialize_Destructor); } else { rv = curr->Write(aContext, aStream); } NS_ENSURE_SUCCESS(rv, rv); } return aStream->Write8(XBLBinding_Serialize_NoMoreItems); }
nsresult nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding, nsIScriptContext* aContext, nsIContent* aBoundElement, nsIXPConnectJSObjectHolder** aScriptObjectHolder, JSObject** aTargetClassObject) { nsresult rv = NS_OK; *aScriptObjectHolder = nsnull; if (!mClassObject) { rv = CompilePrototypeMembers(aBinding); // This is the first time we've ever installed this binding on an element. // We need to go ahead and compile all methods and properties on a class // in our prototype binding. if (NS_FAILED(rv)) return rv; if (!mClassObject) return NS_OK; // This can be ok, if all we've got are fields (and no methods/properties). } nsIDocument *ownerDoc = aBoundElement->OwnerDoc(); nsIScriptGlobalObject *sgo; if (!(sgo = ownerDoc->GetScopeObject())) { return NS_ERROR_UNEXPECTED; } // Because our prototype implementation has a class, we need to build up a corresponding // class for the concrete implementation in the bound document. JSContext* jscontext = aContext->GetNativeContext(); JSObject* global = sgo->GetGlobalJSObject(); nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper; jsval v; rv = nsContentUtils::WrapNative(jscontext, global, aBoundElement, &v, getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); // 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); if (NS_FAILED(rv)) { return rv; } nsContentUtils::PreserveWrapper(aBoundElement, aBoundElement); wrapper.swap(*aScriptObjectHolder); return rv; }
nsresult nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding, nsIScriptContext* aContext, nsIContent* aBoundElement, nsIXPConnectJSObjectHolder** aScriptObjectHolder, void** aTargetClassObject) { nsresult rv = NS_OK; *aScriptObjectHolder = nsnull; if (!mClassObject) { rv = CompilePrototypeMembers(aBinding); // This is the first time we've ever installed this binding on an element. // We need to go ahead and compile all methods and properties on a class // in our prototype binding. if (NS_FAILED(rv)) return rv; if (!mClassObject) return NS_OK; // This can be ok, if all we've got are fields (and no methods/properties). } nsIDocument *ownerDoc = aBoundElement->GetOwnerDoc(); nsIScriptGlobalObject *sgo; if (!ownerDoc || !(sgo = ownerDoc->GetScriptGlobalObject())) { NS_ERROR("Can't find global object for bound content!"); return NS_ERROR_UNEXPECTED; } // Because our prototype implementation has a class, we need to build up a corresponding // class for the concrete implementation in the bound document. JSContext* jscontext = (JSContext*)aContext->GetNativeContext(); JSObject* global = sgo->GetGlobalJSObject(); nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper; rv = nsContentUtils::XPConnect()->WrapNative(jscontext, global, aBoundElement, NS_GET_IID(nsISupports), getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); JSObject * object = nsnull; rv = wrapper->GetJSObject(&object); NS_ENSURE_SUCCESS(rv, rv); // 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, object, aTargetClassObject); if (NS_FAILED(rv)) return rv; // Root ourselves in the document. nsIDocument* doc = aBoundElement->GetOwnerDoc(); if (doc) { nsCOMPtr<nsIXPConnectWrappedNative> nativeWrapper(do_QueryInterface(wrapper)); if (nativeWrapper) doc->AddReference(aBoundElement, nativeWrapper); } wrapper.swap(*aScriptObjectHolder); return rv; }