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;
}