void nsXBLProtoImplMethod::AddParameter(const nsAString& aText) { NS_PRECONDITION(!IsCompiled(), "Must not be compiled when accessing uncompiled method"); if (aText.IsEmpty()) { NS_WARNING("Empty name attribute in xbl:parameter!"); return; } nsXBLUncompiledMethod* uncompiledMethod = GetUncompiledMethod(); if (!uncompiledMethod) { uncompiledMethod = new nsXBLUncompiledMethod(); if (!uncompiledMethod) return; SetUncompiledMethod(uncompiledMethod); } uncompiledMethod->AddParameter(aText); }
nsresult nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr, JSObject* aClassObject) { NS_TIME_FUNCTION_MIN(5); NS_PRECONDITION(!IsCompiled(), "Trying to compile an already-compiled method"); NS_PRECONDITION(aClassObject, "Must have class object to compile"); nsXBLUncompiledMethod* uncompiledMethod = GetUncompiledMethod(); // No parameters or body was supplied, so don't install method. if (!uncompiledMethod) { // Early return after which we consider ourselves compiled. mJSMethodObject = nsnull; return NS_OK; } // Don't install method if no name was supplied. if (!mName) { delete uncompiledMethod; // Early return after which we consider ourselves compiled. mJSMethodObject = nsnull; return NS_OK; } // We have a method. // Allocate an array for our arguments. PRInt32 paramCount = uncompiledMethod->GetParameterCount(); char** args = nsnull; if (paramCount > 0) { args = new char*[paramCount]; if (!args) return NS_ERROR_OUT_OF_MEMORY; // Add our parameters to our args array. PRInt32 argPos = 0; for (nsXBLParameter* curr = uncompiledMethod->mParameters; curr; curr = curr->mNext) { args[argPos] = curr->mName; argPos++; } } // Get the body nsDependentString body; PRUnichar *bodyText = uncompiledMethod->mBodyText.GetText(); if (bodyText) body.Rebind(bodyText); // Now that we have a body and args, compile the function // and then define it. NS_ConvertUTF16toUTF8 cname(mName); nsCAutoString functionUri(aClassStr); PRInt32 hash = functionUri.RFindChar('#'); if (hash != kNotFound) { functionUri.Truncate(hash); } JSObject* methodObject = nsnull; nsresult rv = aContext->CompileFunction(aClassObject, cname, paramCount, const_cast<const char**>(args), body, functionUri.get(), uncompiledMethod->mBodyText.GetLineNumber(), JSVERSION_LATEST, true, &methodObject); // Destroy our uncompiled method and delete our arg list. delete uncompiledMethod; delete [] args; if (NS_FAILED(rv)) { SetUncompiledMethod(nsnull); return rv; } mJSMethodObject = methodObject; return NS_OK; }
nsresult nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr, JSObject* aClassObject) { NS_PRECONDITION(!IsCompiled(), "Trying to compile an already-compiled method"); NS_PRECONDITION(aClassObject, "Must have class object to compile"); nsXBLUncompiledMethod* uncompiledMethod = GetUncompiledMethod(); // No parameters or body was supplied, so don't install method. if (!uncompiledMethod) { // Early return after which we consider ourselves compiled. mJSMethodObject = nullptr; return NS_OK; } // Don't install method if no name was supplied. if (!mName) { delete uncompiledMethod; // Early return after which we consider ourselves compiled. mJSMethodObject = nullptr; return NS_OK; } // We have a method. // Allocate an array for our arguments. int32_t paramCount = uncompiledMethod->GetParameterCount(); char** args = nullptr; if (paramCount > 0) { args = new char*[paramCount]; if (!args) return NS_ERROR_OUT_OF_MEMORY; // Add our parameters to our args array. int32_t argPos = 0; for (nsXBLParameter* curr = uncompiledMethod->mParameters; curr; curr = curr->mNext) { args[argPos] = curr->mName; argPos++; } } // Get the body nsDependentString body; PRUnichar *bodyText = uncompiledMethod->mBodyText.GetText(); if (bodyText) body.Rebind(bodyText); // Now that we have a body and args, compile the function // and then define it. NS_ConvertUTF16toUTF8 cname(mName); nsAutoCString functionUri(aClassStr); int32_t hash = functionUri.RFindChar('#'); if (hash != kNotFound) { functionUri.Truncate(hash); } JSObject* methodObject = nullptr; JSContext* cx = aContext->GetNativeContext(); JSAutoRequest ar(cx); JSAutoCompartment ac(cx, aClassObject); JS::CompileOptions options(cx); options.setFileAndLine(functionUri.get(), uncompiledMethod->mBodyText.GetLineNumber()) .setVersion(JSVERSION_LATEST) .setUserBit(true); // Flag us as XBL js::RootedObject rootedNull(cx, nullptr); // See bug 781070. nsresult rv = nsJSUtils::CompileFunction(cx, rootedNull, options, cname, paramCount, const_cast<const char**>(args), body, &methodObject); // Destroy our uncompiled method and delete our arg list. delete uncompiledMethod; delete [] args; if (NS_FAILED(rv)) { SetUncompiledMethod(nullptr); return rv; } mJSMethodObject = methodObject; return NS_OK; }