示例#1
0
bool
WrapperAnswer::RecvGetOwnPropertyDescriptor(const ObjectId& objId, const JSIDVariant& idVar,
                                            ReturnStatus* rs, PPropertyDescriptor* out)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();
    EmptyDesc(out);

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.getOwnPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));

    RootedId id(cx);
    if (!fromJSIDVariant(cx, idVar, &id))
        return fail(jsapi, rs);

    Rooted<PropertyDescriptor> desc(cx);
    if (!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc))
        return fail(jsapi, rs);

    if (!fromDescriptor(cx, desc, out))
        return fail(jsapi, rs);

    return ok(rs);
}
示例#2
0
bool
WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
                                  nsString* source, uint32_t* flags)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    RootedString sourceJSStr(cx, JS_GetRegExpSource(cx, obj));
    if (!sourceJSStr)
        return fail(jsapi, rs);
    nsAutoJSString sourceStr;
    if (!sourceStr.init(cx, sourceJSStr))
        return fail(jsapi, rs);
    source->Assign(sourceStr);

    *flags = JS_GetRegExpFlags(cx, obj);

    return ok(rs);
}
示例#3
0
bool
WrapperAnswer::RecvIsArray(const ObjectId& objId, ReturnStatus* rs,
                           uint32_t* ans)
{
    *ans = uint32_t(IsArrayAnswer::NotArray);

    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.isArray()", ReceiverObj(objId));

    IsArrayAnswer answer;
    if (!JS::IsArray(cx, obj, &answer))
        return fail(jsapi, rs);

    *ans = uint32_t(answer);
    return ok(rs);
}
示例#4
0
nsresult
MediaKeyStatusMap::UpdateInternal(const nsTArray<CDMCaps::KeyStatus>& keys)
{
  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(mParent))) {
    return NS_ERROR_FAILURE;
  }

  jsapi.TakeOwnershipOfErrorReporting();
  JSContext* cx = jsapi.cx();
  JS::Rooted<JSObject*> map(cx, mMap);
  if (!JS::MapClear(cx, map)) {
    return NS_ERROR_FAILURE;
  }

  for (size_t i = 0; i < keys.Length(); i++) {
    const auto& ks = keys[i];
    JS::Rooted<JS::Value> key(cx);
    JS::Rooted<JS::Value> val(cx);
    if (!ToJSValue(cx, TypedArrayCreator<ArrayBuffer>(ks.mId), &key) ||
        !ToJSString(cx, ks.mStatus, &val) ||
        !JS::MapSet(cx, map, key, val)) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
  }

  return NS_OK;
}
示例#5
0
bool
WrapperAnswer::RecvInstanceOf(const ObjectId& objId, const JSIID& iid, ReturnStatus* rs,
                              bool* instanceof)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    *instanceof = false;

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.instanceOf()", ReceiverObj(objId));

    nsID nsiid;
    ConvertID(iid, &nsiid);

    nsresult rv = xpc::HasInstance(cx, obj, &nsiid, instanceof);
    if (rv != NS_OK)
        return fail(jsapi, rs);

    return ok(rs);
}
示例#6
0
bool
WrapperAnswer::RecvGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs,
                                   uint32_t* classValue)
{
    *classValue = js::ESClass_Other;

    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.getBuiltinClass()", ReceiverObj(objId));

    js::ESClassValue cls;
    if (!js::GetBuiltinClass(cx, obj, &cls))
        return fail(jsapi, rs);

    *classValue = cls;
    return ok(rs);
}
示例#7
0
nsresult
nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
{
  // We want to pre-compile our implementation's members against a "prototype context". Then when we actually 
  // bind the prototype to a real xbl instance, we'll clone the pre-compiled JS into the real instance's 
  // context.
  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(xpc::CompilationScope())))
    return NS_ERROR_FAILURE;
  jsapi.TakeOwnershipOfErrorReporting();
  JSContext* cx = jsapi.cx();

  mPrecompiledMemberHolder = JS_NewObjectWithGivenProto(cx, nullptr, nullptr);
  if (!mPrecompiledMemberHolder)
    return NS_ERROR_OUT_OF_MEMORY;

  // Now that we have a class object installed, we walk our member list and compile each of our
  // properties and methods in turn.
  JS::Rooted<JSObject*> rootedHolder(cx, mPrecompiledMemberHolder);
  for (nsXBLProtoImplMember* curr = mMembers;
       curr;
       curr = curr->GetNext()) {
    nsresult rv = curr->CompileMember(jsapi, mClassName, rootedHolder);
    if (NS_FAILED(rv)) {
      DestroyMembers();
      return rv;
    }
  }

  return NS_OK;
}
示例#8
0
bool
WrapperAnswer::RecvHasOwn(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs,
                          bool* foundp)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();
    *foundp = false;

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.hasOwn(%s)", ReceiverObj(objId), Identifier(idVar));

    RootedId id(cx);
    if (!fromJSIDVariant(cx, idVar, &id))
        return fail(jsapi, rs);

    if (!JS_HasOwnPropertyById(cx, obj, id, foundp))
        return fail(jsapi, rs);
    return ok(rs);
}
示例#9
0
bool
WrapperAnswer::RecvDefineProperty(const ObjectId& objId, const JSIDVariant& idVar,
                                  const PPropertyDescriptor& descriptor, ReturnStatus* rs)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("define %s[%s]", ReceiverObj(objId), Identifier(idVar));

    RootedId id(cx);
    if (!fromJSIDVariant(cx, idVar, &id))
        return fail(jsapi, rs);

    Rooted<PropertyDescriptor> desc(cx);
    if (!toDescriptor(cx, descriptor, &desc))
        return fail(jsapi, rs);

    ObjectOpResult success;
    if (!JS_DefinePropertyById(cx, obj, id, desc, success))
        return fail(jsapi, rs);
    return ok(rs, success);
}
示例#10
0
bool
WrapperAnswer::RecvGetPropertyKeys(const ObjectId& objId, const uint32_t& flags,
                                   ReturnStatus* rs, nsTArray<JSIDVariant>* ids)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.getPropertyKeys()", ReceiverObj(objId));

    AutoIdVector props(cx);
    if (!js::GetPropertyKeys(cx, obj, flags, &props))
        return fail(jsapi, rs);

    for (size_t i = 0; i < props.length(); i++) {
        JSIDVariant id;
        if (!toJSIDVariant(cx, props[i], &id))
            return fail(jsapi, rs);

        ids->AppendElement(id);
    }

    return ok(rs);
}
示例#11
0
bool
WrapperAnswer::RecvGetPrototype(const ObjectId& objId, ReturnStatus* rs, ObjectOrNullVariant* result)
{
    *result = NullVariant();

    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    JS::RootedObject proto(cx);
    if (!JS_GetPrototype(cx, obj, &proto))
        return fail(jsapi, rs);

    if (!toObjectOrNullVariant(cx, proto, result))
        return fail(jsapi, rs);

    LOG("getPrototype(%s)", ReceiverObj(objId));

    return ok(rs);
}
示例#12
0
void
ThrowAndReport(nsPIDOMWindow* aWindow, nsresult aRv, const char* aMessage)
{
  MOZ_ASSERT(aRv != NS_ERROR_UNCATCHABLE_EXCEPTION,
             "Doesn't make sense to report uncatchable exceptions!");
  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(aWindow))) {
    return;
  }
  jsapi.TakeOwnershipOfErrorReporting();

  Throw(jsapi.cx(), aRv, aMessage);
}
示例#13
0
bool
WrapperAnswer::RecvClassName(const ObjectId& objId, nsCString* name)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj) {
        // This is very unfortunate, but we have no choice.
        return "<dead CPOW>";
    }

    LOG("%s.className()", ReceiverObj(objId));

    *name = js::ObjectClassName(cx, obj);
    return true;
}
示例#14
0
bool
WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    ObjectOpResult success;
    if (!JS_PreventExtensions(cx, obj, success))
        return fail(jsapi, rs);

    LOG("%s.preventExtensions()", ReceiverObj(objId));
    return ok(rs, success);
}
示例#15
0
bool
WrapperAnswer::RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs, bool* result)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();
    *result = false;

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.isExtensible()", ReceiverObj(objId));

    bool extensible;
    if (!JS_IsExtensible(cx, obj, &extensible))
        return fail(jsapi, rs);

    *result = !!extensible;
    return ok(rs);
}
示例#16
0
bool
WrapperAnswer::RecvDOMInstanceOf(const ObjectId& objId, const int& prototypeID,
                                 const int& depth, ReturnStatus* rs, bool* instanceof)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();
    *instanceof = false;

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.domInstanceOf()", ReceiverObj(objId));

    bool tmp;
    if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp))
        return fail(jsapi, rs);
    *instanceof = tmp;

    return ok(rs);
}
示例#17
0
bool
WrapperAnswer::RecvHasInstance(const ObjectId& objId, const JSVariant& vVar, ReturnStatus* rs, bool* bp)
{
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
        return false;
    jsapi.TakeOwnershipOfErrorReporting();
    JSContext* cx = jsapi.cx();

    RootedObject obj(cx, findObjectById(cx, objId));
    if (!obj)
        return fail(jsapi, rs);

    LOG("%s.hasInstance(%s)", ReceiverObj(objId), InVariant(vVar));

    RootedValue val(cx);
    if (!fromVariant(cx, vVar, &val))
        return fail(jsapi, rs);

    if (!JS_HasInstance(cx, obj, val, bp))
        return fail(jsapi, rs);

    return ok(rs);
}
示例#18
0
nsresult
nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
                                      nsIDOMEvent* aEvent)
{
  nsresult rv = NS_ERROR_FAILURE;

  // Prevent default action?
  if (mType & NS_HANDLER_TYPE_PREVENTDEFAULT) {
    aEvent->PreventDefault();
    // If we prevent default, then it's okay for
    // mHandlerElement and mHandlerText to be null
    rv = NS_OK;
  }

  if (!mHandlerElement) // This works for both types of handlers.  In both cases, the union's var should be defined.
    return rv;

  // See if our event receiver is a content node (and not us).
  bool isXULKey = !!(mType & NS_HANDLER_TYPE_XUL);
  bool isXBLCommand = !!(mType & NS_HANDLER_TYPE_XBL_COMMAND);
  NS_ASSERTION(!(isXULKey && isXBLCommand),
               "can't be both a key and xbl command handler");

  // XUL handlers and commands shouldn't be triggered by non-trusted
  // events.
  if (isXULKey || isXBLCommand) {
    bool trustedEvent = false;
    aEvent->GetIsTrusted(&trustedEvent);

    if (!trustedEvent)
      return NS_OK;
  }
    
  if (isXBLCommand) {
    return DispatchXBLCommand(aTarget, aEvent);
  }

  // If we're executing on a XUL key element, just dispatch a command
  // event at the element.  It will take care of retargeting it to its
  // command element, if applicable, and executing the event handler.
  if (isXULKey) {
    return DispatchXULKeyCommand(aEvent);
  }

  // Look for a compiled handler on the element. 
  // Should be compiled and bound with "on" in front of the name.
  nsCOMPtr<nsIAtom> onEventAtom = do_GetAtom(NS_LITERAL_STRING("onxbl") +
                                             nsDependentAtomString(mEventName));

  // Compile the handler and bind it to the element.
  nsCOMPtr<nsIScriptGlobalObject> boundGlobal;
  nsCOMPtr<nsPIWindowRoot> winRoot(do_QueryInterface(aTarget));
  nsCOMPtr<nsPIDOMWindow> window;

  if (winRoot) {
    window = winRoot->GetWindow();
  }

  if (window) {
    window = window->GetCurrentInnerWindow();
    NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);

    boundGlobal = do_QueryInterface(window->GetPrivateRoot());
  }
  else boundGlobal = do_QueryInterface(aTarget);

  if (!boundGlobal) {
    nsCOMPtr<nsIDocument> boundDocument(do_QueryInterface(aTarget));
    if (!boundDocument) {
      // We must be an element.
      nsCOMPtr<nsIContent> content(do_QueryInterface(aTarget));
      if (!content)
        return NS_OK;
      boundDocument = content->OwnerDoc();
    }

    boundGlobal = do_QueryInterface(boundDocument->GetScopeObject());
  }

  if (!boundGlobal)
    return NS_OK;

  nsISupports *scriptTarget;

  if (winRoot) {
    scriptTarget = boundGlobal;
  } else {
    scriptTarget = aTarget;
  }

  // We're about to create a new JSEventHandler, which means that we need to
  // Initiatize an AutoJSAPI with aTarget's bound global to make sure any errors
  // are reported to the correct place.
  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(boundGlobal))) {
    return NS_OK;
  }
  jsapi.TakeOwnershipOfErrorReporting();
  JSContext* cx = jsapi.cx();
  JS::Rooted<JSObject*> handler(cx);

  rv = EnsureEventHandler(jsapi, onEventAtom, &handler);
  NS_ENSURE_SUCCESS(rv, rv);

  JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());

  JS::Rooted<JSObject*> globalObject(cx, boundGlobal->GetGlobalJSObject());
  JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
  NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);

  // Bind it to the bound element. Note that if we're using a separate XBL scope,
  // we'll actually be binding the event handler to a cross-compartment wrapper
  // to the bound element's reflector.

  // First, enter our XBL scope. This is where the generic handler should have
  // been compiled, above.
  JSAutoCompartment ac(cx, scopeObject);
  JS::Rooted<JSObject*> genericHandler(cx, handler.get());
  bool ok = JS_WrapObject(cx, &genericHandler);
  NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
  MOZ_ASSERT(!js::IsCrossCompartmentWrapper(genericHandler));

  // Build a scope chain in the XBL scope.
  nsRefPtr<Element> targetElement = do_QueryObject(scriptTarget);
  JS::AutoObjectVector scopeChain(cx);
  ok = nsJSUtils::GetScopeChainForElement(cx, targetElement, scopeChain);
  NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);

  // Next, clone the generic handler with our desired scope chain.
  JS::Rooted<JSObject*> bound(cx, JS::CloneFunctionObject(cx, genericHandler,
                                                          scopeChain));
  NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);

  nsRefPtr<EventHandlerNonNull> handlerCallback =
    new EventHandlerNonNull(nullptr, bound, /* aIncumbentGlobal = */ nullptr);

  TypedEventHandler typedHandler(handlerCallback);

  // Execute it.
  nsCOMPtr<JSEventHandler> jsEventHandler;
  rv = NS_NewJSEventHandler(scriptTarget, onEventAtom,
                            typedHandler,
                            getter_AddRefs(jsEventHandler));
  NS_ENSURE_SUCCESS(rv, rv);

  // Handle the event.
  jsEventHandler->HandleEvent(aEvent);
  jsEventHandler->Disconnect();
  return NS_OK;
}
示例#19
0
nsresult
EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
                                                  const nsAString* aBody,
                                                  Element* aElement)
{
  MOZ_ASSERT(aListener->GetJSEventHandler());
  MOZ_ASSERT(aListener->mHandlerIsString, "Why are we compiling a non-string JS listener?");
  JSEventHandler* jsEventHandler = aListener->GetJSEventHandler();
  MOZ_ASSERT(!jsEventHandler->GetTypedEventHandler().HasEventHandler(),
             "What is there to compile?");

  nsresult result = NS_OK;
  nsCOMPtr<nsIDocument> doc;
  nsCOMPtr<nsIScriptGlobalObject> global =
    GetScriptGlobalAndDocument(getter_AddRefs(doc));
  NS_ENSURE_STATE(global);

  // Activate JSAPI, and make sure that exceptions are reported on the right
  // Window.
  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(global))) {
    return NS_ERROR_UNEXPECTED;
  }
  jsapi.TakeOwnershipOfErrorReporting();
  JSContext* cx = jsapi.cx();

  nsCOMPtr<nsIAtom> typeAtom = aListener->mTypeAtom;
  nsIAtom* attrName = typeAtom;

  // Flag us as not a string so we don't keep trying to compile strings which
  // can't be compiled.
  aListener->mHandlerIsString = false;

  // mTarget may not be an Element if it's a window and we're
  // getting an inline event listener forwarded from <html:body> or
  // <html:frameset> or <xul:window> or the like.
  // XXX I don't like that we have to reference content from
  // here. The alternative is to store the event handler string on
  // the JSEventHandler itself, and that still doesn't address
  // the arg names issue.
  nsCOMPtr<Element> element = do_QueryInterface(mTarget);
  MOZ_ASSERT(element || aBody, "Where will we get our body?");
  nsAutoString handlerBody;
  const nsAString* body = aBody;
  if (!aBody) {
    if (aListener->mTypeAtom == nsGkAtoms::onSVGLoad) {
      attrName = nsGkAtoms::onload;
    } else if (aListener->mTypeAtom == nsGkAtoms::onSVGUnload) {
      attrName = nsGkAtoms::onunload;
    } else if (aListener->mTypeAtom == nsGkAtoms::onSVGResize) {
      attrName = nsGkAtoms::onresize;
    } else if (aListener->mTypeAtom == nsGkAtoms::onSVGScroll) {
      attrName = nsGkAtoms::onscroll;
    } else if (aListener->mTypeAtom == nsGkAtoms::onSVGZoom) {
      attrName = nsGkAtoms::onzoom;
    } else if (aListener->mTypeAtom == nsGkAtoms::onbeginEvent) {
      attrName = nsGkAtoms::onbegin;
    } else if (aListener->mTypeAtom == nsGkAtoms::onrepeatEvent) {
      attrName = nsGkAtoms::onrepeat;
    } else if (aListener->mTypeAtom == nsGkAtoms::onendEvent) {
      attrName = nsGkAtoms::onend;
    }

    element->GetAttr(kNameSpaceID_None, attrName, handlerBody);
    body = &handlerBody;
    aElement = element;
  }
  aListener = nullptr;

  uint32_t lineNo = 0;
  nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
  MOZ_ASSERT(body);
  MOZ_ASSERT(aElement);
  nsIURI *uri = aElement->OwnerDoc()->GetDocumentURI();
  if (uri) {
    uri->GetSpec(url);
    lineNo = 1;
  }

  nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
  uint32_t argCount;
  const char **argNames;
  nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(),
                                   typeAtom, win,
                                   &argCount, &argNames);

  JSAddonId *addonId = MapURIToAddonID(uri);

  // Wrap the event target, so that we can use it as the scope for the event
  // handler. Note that mTarget is different from aElement in the <body> case,
  // where mTarget is a Window.
  //
  // The wrapScope doesn't really matter here, because the target will create
  // its reflector in the proper scope, and then we'll enter that compartment.
  JS::Rooted<JSObject*> wrapScope(cx, global->GetGlobalJSObject());
  JS::Rooted<JS::Value> v(cx);
  {
    JSAutoCompartment ac(cx, wrapScope);
    nsresult rv = nsContentUtils::WrapNative(cx, mTarget, &v,
                                             /* aAllowWrapping = */ false);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
  }

  if (addonId) {
    JS::Rooted<JSObject*> vObj(cx, &v.toObject());
    JS::Rooted<JSObject*> addonScope(cx, xpc::GetAddonScope(cx, vObj, addonId));
    if (!addonScope) {
      return NS_ERROR_FAILURE;
    }
    JSAutoCompartment ac(cx, addonScope);

    // Wrap our event target into the addon scope, since that's where we want to
    // do all our work.
    if (!JS_WrapValue(cx, &v)) {
      return NS_ERROR_FAILURE;
    }
  }
  JS::Rooted<JSObject*> target(cx, &v.toObject());
  JSAutoCompartment ac(cx, target);

  // Now that we've entered the compartment we actually care about, create our
  // scope chain.  Note that we start with |element|, not aElement, because
  // mTarget is different from aElement in the <body> case, where mTarget is a
  // Window, and in that case we do not want the scope chain to include the body
  // or the document.
  JS::AutoObjectVector scopeChain(cx);
  if (!nsJSUtils::GetScopeChainForElement(cx, element, scopeChain)) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  nsDependentAtomString str(attrName);
  // Most of our names are short enough that we don't even have to malloc
  // the JS string stuff, so don't worry about playing games with
  // refcounting XPCOM stringbuffers.
  JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
                                                      str.BeginReading(),
                                                      str.Length()));
  NS_ENSURE_TRUE(jsStr, NS_ERROR_OUT_OF_MEMORY);

  // Get the reflector for |aElement|, so that we can pass to setElement.
  if (NS_WARN_IF(!GetOrCreateDOMReflector(cx, target, aElement, &v))) {
    return NS_ERROR_FAILURE;
  }
  JS::CompileOptions options(cx);
  options.setIntroductionType("eventHandler")
         .setFileAndLine(url.get(), lineNo)
         .setVersion(JSVERSION_DEFAULT)
         .setElement(&v.toObject())
         .setElementAttributeName(jsStr);

  JS::Rooted<JSObject*> handler(cx);
  result = nsJSUtils::CompileFunction(jsapi, scopeChain, options,
                                      nsAtomCString(typeAtom),
                                      argCount, argNames, *body, handler.address());
  NS_ENSURE_SUCCESS(result, result);
  NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);

  if (jsEventHandler->EventName() == nsGkAtoms::onerror && win) {
    nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
      new OnErrorEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
    jsEventHandler->SetHandler(handlerCallback);
  } else if (jsEventHandler->EventName() == nsGkAtoms::onbeforeunload && win) {
    nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
      new OnBeforeUnloadEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
    jsEventHandler->SetHandler(handlerCallback);
  } else {
    nsRefPtr<EventHandlerNonNull> handlerCallback =
      new EventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
    jsEventHandler->SetHandler(handlerCallback);
  }

  return result;
}