EventListenerManager::Listener*
EventListenerManager::SetEventHandlerInternal(
                        JS::Handle<JSObject*> aScopeObject,
                        nsIAtom* aName,
                        const nsAString& aTypeString,
                        const nsEventHandler& aHandler,
                        bool aPermitUntrustedEvents)
{
  MOZ_ASSERT(aScopeObject || aHandler.HasEventHandler(),
             "Must have one or the other!");
  MOZ_ASSERT(aName || !aTypeString.IsEmpty());

  uint32_t eventType = nsContentUtils::GetEventId(aName);
  Listener* listener = FindEventHandler(eventType, aName, aTypeString);

  if (!listener) {
    // If we didn't find a script listener or no listeners existed
    // create and add a new one.
    EventListenerFlags flags;
    flags.mListenerIsJSListener = true;

    nsCOMPtr<nsIJSEventListener> jsListener;
    NS_NewJSEventListener(aScopeObject, mTarget, aName,
                          aHandler, getter_AddRefs(jsListener));
    EventListenerHolder listenerHolder(jsListener);
    AddEventListenerInternal(listenerHolder, eventType, aName, aTypeString,
                             flags, true);

    listener = FindEventHandler(eventType, aName, aTypeString);
  } else {
    nsIJSEventListener* jsListener = listener->GetJSListener();
    MOZ_ASSERT(jsListener,
               "How can we have an event handler with no nsIJSEventListener?");

    bool same = jsListener->GetHandler() == aHandler;
    // Possibly the same listener, but update still the context and scope.
    jsListener->SetHandler(aHandler, aScopeObject);
    if (mTarget && !same && aName) {
      mTarget->EventListenerRemoved(aName);
      mTarget->EventListenerAdded(aName);
    }
  }

  // Set flag to indicate possible need for compilation later
  listener->mHandlerIsString = !aHandler.HasEventHandler();
  if (aPermitUntrustedEvents) {
    listener->mFlags.mAllowUntrustedEvents = true;
  }

  return listener;
}
const nsEventHandler*
EventListenerManager::GetEventHandlerInternal(nsIAtom* aEventName,
                                              const nsAString& aTypeString)
{
  uint32_t eventType = nsContentUtils::GetEventId(aEventName);
  Listener* listener = FindEventHandler(eventType, aEventName, aTypeString);

  if (!listener) {
    return nullptr;
  }

  nsIJSEventListener* jsListener = listener->GetJSListener();

  if (listener->mHandlerIsString) {
    CompileEventHandlerInternal(listener, nullptr, nullptr);
  }

  const nsEventHandler& handler = jsListener->GetHandler();
  if (handler.HasEventHandler()) {
    return &handler;
  }

  return nullptr;
}