Bug 366478 - consolidate lists of onX event attributes, r=smaug,jwatt,sr=sicking
authorenndeakin@sympatico.ca
Mon, 02 Apr 2007 10:17:36 -0700
changeset 265 cf9e66542422dbc9a99c37a5c3196e1a353f6bd8
parent 264 4cd31f07a14048557e4ae6a73756fd4d13174e82
child 266 36d3af60c2f136f02c9301729b16889db20ebdfb
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, jwatt, sicking
bugs366478
milestone1.9a4pre
Bug 366478 - consolidate lists of onX event attributes, r=smaug,jwatt,sr=sicking
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/events/src/nsEventListenerManager.cpp
content/html/content/src/nsGenericHTMLElement.cpp
content/svg/content/src/nsSVGElement.cpp
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGGraphicElement.cpp
content/svg/content/src/nsSVGSVGElement.cpp
content/svg/content/src/nsSVGTSpanElement.cpp
content/svg/content/src/nsSVGTextPathElement.cpp
content/xul/content/src/nsXULElement.cpp
layout/build/nsLayoutStatics.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -47,16 +47,17 @@
 #include "nsIStatefulFrame.h"
 #include "nsIPref.h"
 #include "nsINodeInfo.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentList.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIClassInfo.h"
 #include "nsIDOM3Node.h"
+#include "nsDataHashtable.h"
 #include "nsIScriptRuntime.h"
 #include "nsIScriptGlobalObject.h"
 
 class nsIDOMScriptObjectFactory;
 class nsIXPConnect;
 class nsINode;
 class nsIContent;
 class nsIDOMNode;
@@ -94,16 +95,32 @@ struct JSRuntime;
 class nsIXTFService;
 #endif
 #ifdef IBMBIDI
 class nsIBidiKeyboard;
 #endif
 
 extern const char kLoadAsData[];
 
+enum EventNameType {
+  EventNameType_None = 0x0000,
+  EventNameType_HTML = 0x0001,
+  EventNameType_XUL = 0x0002,
+  EventNameType_SVGGraphic = 0x0004, // svg graphic elements
+  EventNameType_SVGSVG = 0x0008, // the svg element
+
+  EventNameType_HTMLXUL = 0x0003,
+  EventNameType_All = 0xFFFF
+};
+
+struct EventNameMapping {
+  PRUint32  mId;
+  PRInt32 mType;
+};
+
 class nsContentUtils
 {
 public:
   static nsresult Init();
 
   // You MUST pass the old ownerDocument of aContent in as aOldDocument and the
   // new one as aNewDocument.  aNewParent is allowed to be null; in that case
   // aNewDocument will be assumed to be the parent.  Note that at this point
@@ -777,16 +794,35 @@ public:
   static nsresult DispatchTrustedEvent(nsIDocument* aDoc,
                                        nsISupports* aTarget,
                                        const nsAString& aEventName,
                                        PRBool aCanBubble,
                                        PRBool aCancelable,
                                        PRBool *aDefaultAction = nsnull);
 
   /**
+   * Determines if an event attribute name (such as onclick) is valid for
+   * a given element type. Types are from the EventNameType enumeration
+   * defined above.
+   *
+   * @param aName the event name to look up
+   * @param aType the type of content
+   */
+  static PRBool IsEventAttributeName(nsIAtom* aName, PRInt32 aType);
+
+  /**
+   * Return the event id for the event with the given name. The name is the
+   * event name with the 'on' prefix. Returns NS_USER_DEFINED_EVENT if the
+   * event doesn't match a known event name.
+   *
+   * @param aName the event name to look up
+   */
+  static PRUint32 GetEventId(nsIAtom* aName);
+
+  /**
    * Used only during traversal of the XPCOM graph by the cycle
    * collector: push a pointer to the listener manager onto the
    * children deque, if it exists. Do nothing if there is no listener
    * manager.
    *
    * Crucially: does not perform any refcounting operations.
    *
    * @param aNode The node to traverse.
@@ -979,16 +1015,19 @@ public:
       }
       return rv;
     }
     PRUint32 mLangID;
     void *mObject;
   };
 
 private:
+
+  static PRBool InitializeEventTable();
+
   static nsresult doReparentContentWrapper(nsIContent *aChild,
                                            JSContext *cx,
                                            JSObject *aOldGlobal,
                                            JSObject *aNewGlobal,
                                            nsIDocument *aOldDocument,
                                            nsIDocument *aNewDocument);
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
@@ -1016,16 +1055,18 @@ private:
   static nsIPrefBranch *sPrefBranch;
 
   static nsIPref *sPref;
 
   static imgILoader* sImgLoader;
 
   static nsIConsoleService* sConsoleService;
 
+  static nsDataHashtable<nsISupportsHashKey, EventNameMapping>* sEventTable;
+
   static nsIStringBundleService* sStringBundleService;
   static nsIStringBundle* sStringBundles[PropertiesFile_COUNT];
 
   static nsIContentPolicy* sContentPolicyService;
   static PRBool sTriedToGetContentPolicy;
 
   static nsILineBreaker* sLineBreaker;
   static nsIWordBreaker* sWordBreaker;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -129,16 +129,18 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsEscape.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIEventListenerManager.h"
 #include "nsAttrName.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsIFragmentContentSink.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsTPtrArray.h"
+#include "nsGUIEvent.h"
+#include "nsMutationEvent.h"
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
 #endif
 #include "nsCycleCollectionParticipant.h"
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
@@ -160,16 +162,17 @@ nsINameSpaceManager *nsContentUtils::sNa
 nsIIOService *nsContentUtils::sIOService;
 #ifdef MOZ_XTF
 nsIXTFService *nsContentUtils::sXTFService = nsnull;
 #endif
 nsIPrefBranch *nsContentUtils::sPrefBranch = nsnull;
 nsIPref *nsContentUtils::sPref = nsnull;
 imgILoader *nsContentUtils::sImgLoader;
 nsIConsoleService *nsContentUtils::sConsoleService;
+nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sEventTable = nsnull;
 nsIStringBundleService *nsContentUtils::sStringBundleService;
 nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
 nsIContentPolicy *nsContentUtils::sContentPolicyService;
 PRBool nsContentUtils::sTriedToGetContentPolicy = PR_FALSE;
 nsILineBreaker *nsContentUtils::sLineBreaker;
 nsIWordBreaker *nsContentUtils::sWordBreaker;
 nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease;
 nsIJSRuntimeService *nsContentUtils::sJSRuntimeService;
@@ -274,16 +277,19 @@ nsContentUtils::Init()
     sImgLoader = nsnull;
   }
 
   sPtrsToPtrsToRelease = new nsVoidArray();
   if (!sPtrsToPtrsToRelease) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
+  if (!InitializeEventTable())
+    return NS_ERROR_FAILURE;
+
   if (!sEventListenerManagersHash.ops) {
     static PLDHashTableOps hash_table_ops =
     {
       PL_DHashAllocTable,
       PL_DHashFreeTable,
       PL_DHashVoidPtrKeyStub,
       PL_DHashMatchEntryStub,
       PL_DHashMoveEntryStub,
@@ -300,16 +306,122 @@ nsContentUtils::Init()
     }
   }
 
   sInitialized = PR_TRUE;
 
   return NS_OK;
 }
 
+PRBool
+nsContentUtils::InitializeEventTable() {
+  NS_ASSERTION(!sEventTable, "EventTable already initialized!");
+
+  struct EventItem
+  {
+    nsIAtom** mAtom;
+    EventNameMapping mValue;
+  };
+
+  static const EventItem eventArray[] = {
+    { &nsGkAtoms::onmousedown,                   { NS_MOUSE_BUTTON_DOWN, EventNameType_All }},
+    { &nsGkAtoms::onmouseup,                     { NS_MOUSE_BUTTON_UP, EventNameType_All }},
+    { &nsGkAtoms::onclick,                       { NS_MOUSE_CLICK, EventNameType_All }},
+    { &nsGkAtoms::ondblclick,                    { NS_MOUSE_DOUBLECLICK, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onmouseover,                   { NS_MOUSE_ENTER_SYNTH, EventNameType_All }},
+    { &nsGkAtoms::onmouseout,                    { NS_MOUSE_EXIT_SYNTH, EventNameType_All }},
+    { &nsGkAtoms::onmousemove,                   { NS_MOUSE_MOVE, EventNameType_All }},
+    { &nsGkAtoms::oncontextmenu,                 { NS_CONTEXTMENU, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onkeydown,                     { NS_KEY_DOWN, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onkeyup,                       { NS_KEY_UP, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onkeypress,                    { NS_KEY_PRESS, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onfocus,                       { NS_FOCUS_CONTENT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onblur,                        { NS_BLUR_CONTENT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onoffline,                     { NS_EVENT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::ononline,                      { NS_EVENT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onsubmit,                      { NS_FORM_SUBMIT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onreset,                       { NS_FORM_RESET, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onchange,                      { NS_FORM_CHANGE, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onselect,                      { NS_FORM_SELECTED, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onload,                        { NS_LOAD, EventNameType_All }},
+    { &nsGkAtoms::onunload,                      { NS_PAGE_UNLOAD,
+                                                 (EventNameType_HTMLXUL | EventNameType_SVGSVG) }},
+    { &nsGkAtoms::onbeforeunload,                { NS_BEFORE_PAGE_UNLOAD, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onabort,                       { NS_IMAGE_ABORT,
+                                                 (EventNameType_HTMLXUL | EventNameType_SVGSVG) }},
+    { &nsGkAtoms::onerror,                       { NS_LOAD_ERROR,
+                                                 (EventNameType_HTMLXUL | EventNameType_SVGSVG) }},
+    { &nsGkAtoms::onDOMAttrModified,             { NS_MUTATION_ATTRMODIFIED, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMCharacterDataModified,    { NS_MUTATION_CHARACTERDATAMODIFIED, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMNodeInserted,             { NS_MUTATION_NODEINSERTED, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMNodeRemoved,              { NS_MUTATION_NODEREMOVED, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMNodeInsertedIntoDocument, { NS_MUTATION_NODEINSERTEDINTODOCUMENT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMNodeRemovedFromDocument,  { NS_MUTATION_NODEREMOVEDFROMDOCUMENT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMSubtreeModified,          { NS_MUTATION_SUBTREEMODIFIED, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMActivate,                 { NS_UI_ACTIVATE, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMFocusIn,                  { NS_UI_FOCUSIN, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMFocusOut,                 { NS_UI_FOCUSOUT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onDOMMouseScroll,              { NS_MOUSE_SCROLL, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::oninput,                       { NS_FORM_INPUT, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onpageshow,                    { NS_PAGE_SHOW, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onpagehide,                    { NS_PAGE_HIDE, EventNameType_HTMLXUL }},
+    { &nsGkAtoms::onresize,                      { NS_RESIZE_EVENT,
+                                                 (EventNameType_HTMLXUL | EventNameType_SVGSVG) }},
+    { &nsGkAtoms::onscroll,                      { NS_SCROLL_EVENT,
+                                                 (EventNameType_HTMLXUL | EventNameType_SVGSVG) }},
+    // XUL specific events
+    { &nsGkAtoms::ontext,                        { NS_TEXT_TEXT, EventNameType_XUL }},
+    { &nsGkAtoms::oncompositionstart,            { NS_COMPOSITION_START, EventNameType_XUL }},
+    { &nsGkAtoms::oncompositionend,              { NS_COMPOSITION_END, EventNameType_XUL }},
+    { &nsGkAtoms::onclose,                       { NS_XUL_CLOSE, EventNameType_XUL }},
+    { &nsGkAtoms::onpopupshowing,                { NS_XUL_POPUP_SHOWING, EventNameType_XUL }},
+    { &nsGkAtoms::onpopupshown,                  { NS_XUL_POPUP_SHOWN, EventNameType_XUL }},
+    { &nsGkAtoms::onpopuphiding,                 { NS_XUL_POPUP_HIDING, EventNameType_XUL }},
+    { &nsGkAtoms::onpopuphidden,                 { NS_XUL_POPUP_HIDDEN, EventNameType_XUL }},
+    { &nsGkAtoms::oncommand,                     { NS_XUL_COMMAND, EventNameType_XUL }},
+    { &nsGkAtoms::onbroadcast,                   { NS_XUL_BROADCAST, EventNameType_XUL }},
+    { &nsGkAtoms::oncommandupdate,               { NS_XUL_COMMAND_UPDATE, EventNameType_XUL }},
+    { &nsGkAtoms::ondragenter,                   { NS_DRAGDROP_ENTER, EventNameType_XUL }},
+    { &nsGkAtoms::ondragover,                    { NS_DRAGDROP_OVER_SYNTH, EventNameType_XUL }},
+    { &nsGkAtoms::ondragexit,                    { NS_DRAGDROP_EXIT_SYNTH, EventNameType_XUL }},
+    { &nsGkAtoms::ondragdrop,                    { NS_DRAGDROP_DROP, EventNameType_XUL }},
+    { &nsGkAtoms::ondraggesture,                 { NS_DRAGDROP_GESTURE, EventNameType_XUL }},
+    { &nsGkAtoms::onoverflow,                    { NS_SCROLLPORT_OVERFLOW, EventNameType_XUL }},
+    { &nsGkAtoms::onunderflow,                   { NS_SCROLLPORT_UNDERFLOW, EventNameType_XUL }}
+#ifdef MOZ_SVG
+   ,{ &nsGkAtoms::onSVGLoad,                     { NS_SVG_LOAD, EventNameType_None }},
+    { &nsGkAtoms::onSVGUnload,                   { NS_SVG_UNLOAD, EventNameType_None }},
+    { &nsGkAtoms::onSVGAbort,                    { NS_SVG_ABORT, EventNameType_None }},
+    { &nsGkAtoms::onSVGError,                    { NS_SVG_ERROR, EventNameType_None }},
+    { &nsGkAtoms::onSVGResize,                   { NS_SVG_RESIZE, EventNameType_None }},
+    { &nsGkAtoms::onSVGScroll,                   { NS_SVG_SCROLL, EventNameType_None }},
+    { &nsGkAtoms::onSVGZoom,                     { NS_SVG_ZOOM, EventNameType_None }},
+    { &nsGkAtoms::onzoom,                        { NS_SVG_ZOOM, EventNameType_SVGSVG }}
+#endif // MOZ_SVG
+  };
+
+  sEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>;
+  if (!sEventTable ||
+      !sEventTable->Init(int(NS_ARRAY_LENGTH(eventArray) / 0.75) + 1)) {
+    delete sEventTable;
+    sEventTable = nsnull;
+    return PR_FALSE;
+  }
+
+  for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(eventArray); ++i) {
+    if (!sEventTable->Put(*(eventArray[i].mAtom), eventArray[i].mValue)) {
+      delete sEventTable;
+      sEventTable = nsnull;
+      return PR_FALSE;
+    }
+  }
+
+  return PR_TRUE;
+}
+
 /**
  * Access a cached parser service. Don't addref. We need only one
  * reference to it and this class has that one.
  */
 /* static */
 nsIParserService*
 nsContentUtils::GetParserService()
 {
@@ -552,16 +664,20 @@ nsContentUtils::Shutdown()
   NS_IF_RELEASE(sXTFService);
 #endif
   NS_IF_RELEASE(sImgLoader);
   NS_IF_RELEASE(sPrefBranch);
   NS_IF_RELEASE(sPref);
 #ifdef IBMBIDI
   NS_IF_RELEASE(sBidiKeyboard);
 #endif
+
+  delete sEventTable;
+  sEventTable = nsnull;
+
   if (sPtrsToPtrsToRelease) {
     for (i = 0; i < sPtrsToPtrsToRelease->Count(); ++i) {
       nsISupports** ptrToPtr =
         NS_STATIC_CAST(nsISupports**, sPtrsToPtrsToRelease->ElementAt(i));
       NS_RELEASE(*ptrToPtr);
     }
     delete sPtrsToPtrsToRelease;
     sPtrsToPtrsToRelease = nsnull;
@@ -2567,16 +2683,40 @@ nsContentUtils::RemoveJSGCRoot(void* aPt
     NS_RELEASE(sJSRuntimeService);
     sJSScriptRuntime = nsnull;
   }
 
   return NS_OK;
 }
 
 // static
+PRBool
+nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType)
+{
+  const char* name;
+  aName->GetUTF8String(&name);
+  if (name[0] != 'o' || name[1] != 'n')
+    return PR_FALSE;
+
+  EventNameMapping mapping;
+  return (sEventTable->Get(aName, &mapping) && mapping.mType & aType);
+}
+
+// static
+PRUint32
+nsContentUtils::GetEventId(nsIAtom* aName)
+{
+  EventNameMapping mapping;
+  if (sEventTable->Get(aName, &mapping))
+    return mapping.mId;
+
+  return NS_USER_DEFINED_EVENT;
+}
+
+// static
 nsresult
 nsContentUtils::DispatchTrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
                                      const nsAString& aEventName,
                                      PRBool aCanBubble, PRBool aCancelable,
                                      PRBool *aDefaultAction)
 {
   nsCOMPtr<nsIDOMDocumentEvent> docEvent(do_QueryInterface(aDoc));
   nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(aTarget));
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -420,17 +420,17 @@ nsEventListenerManager::GetTypeDataForII
     }
   }
   return nsnull;
 }
 
 const EventTypeData*
 nsEventListenerManager::GetTypeDataForEventName(nsIAtom* aName)
 {
-  PRUint32 event = GetIdentifierForEvent(aName);
+  PRUint32 event = nsContentUtils::GetEventId(aName);
   if (event != NS_USER_DEFINED_EVENT) {
     for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sEventTypes); ++i) {
       for (PRInt32 j = 0; j < sEventTypes[i].numEvents; ++j) {
          if (event == sEventTypes[i].events[j].message) {
            return &sEventTypes[i];
          }
       }
     }
@@ -602,126 +602,16 @@ nsEventListenerManager::RemoveEventListe
                                                  const nsIID& aIID,
                                                  PRInt32 aFlags)
 {
   RemoveEventListener(aListener, NS_EVENT_TYPE_NULL, nsnull,
                       GetTypeDataForIID(aIID), aFlags, nsnull);
   return NS_OK;
 }
 
-struct EventId {
-  nsIAtom** mAtom;
-  PRUint32  mId;
-};
-
-static void
-InitializeEventIdTable() {
-  NS_ASSERTION(!gEventIdTable, "EventIdTable already initialized!");
-
-  static const EventId eventIdArray[] = {
-    { &nsGkAtoms::onmousedown,                   NS_MOUSE_BUTTON_DOWN },
-    { &nsGkAtoms::onmouseup,                     NS_MOUSE_BUTTON_UP },
-    { &nsGkAtoms::onclick,                       NS_MOUSE_CLICK },
-    { &nsGkAtoms::ondblclick,                    NS_MOUSE_DOUBLECLICK },
-    { &nsGkAtoms::onmouseover,                   NS_MOUSE_ENTER_SYNTH },
-    { &nsGkAtoms::onmouseout,                    NS_MOUSE_EXIT_SYNTH },
-    { &nsGkAtoms::onmousemove,                   NS_MOUSE_MOVE },
-    { &nsGkAtoms::oncontextmenu,                 NS_CONTEXTMENU },
-    { &nsGkAtoms::onkeydown,                     NS_KEY_DOWN },
-    { &nsGkAtoms::onkeyup,                       NS_KEY_UP },
-    { &nsGkAtoms::onkeypress,                    NS_KEY_PRESS },
-    { &nsGkAtoms::oncompositionstart,            NS_COMPOSITION_START },
-    { &nsGkAtoms::oncompositionend,              NS_COMPOSITION_END },
-    { &nsGkAtoms::onfocus,                       NS_FOCUS_CONTENT },
-    { &nsGkAtoms::onblur,                        NS_BLUR_CONTENT },
-    { &nsGkAtoms::onsubmit,                      NS_FORM_SUBMIT },
-    { &nsGkAtoms::onreset,                       NS_FORM_RESET },
-    { &nsGkAtoms::onchange,                      NS_FORM_CHANGE },
-    { &nsGkAtoms::onselect,                      NS_FORM_SELECTED },
-    { &nsGkAtoms::onload,                        NS_LOAD },
-    { &nsGkAtoms::onunload,                      NS_PAGE_UNLOAD },
-    { &nsGkAtoms::onbeforeunload,                NS_BEFORE_PAGE_UNLOAD },
-    { &nsGkAtoms::onabort,                       NS_IMAGE_ABORT },
-    { &nsGkAtoms::onerror,                       NS_LOAD_ERROR },
-    { &nsGkAtoms::onDOMAttrModified,             NS_MUTATION_ATTRMODIFIED },
-    { &nsGkAtoms::onDOMCharacterDataModified,    NS_MUTATION_CHARACTERDATAMODIFIED },
-    { &nsGkAtoms::onDOMNodeInserted,             NS_MUTATION_NODEINSERTED },
-    { &nsGkAtoms::onDOMNodeRemoved,              NS_MUTATION_NODEREMOVED },
-    { &nsGkAtoms::onDOMNodeInsertedIntoDocument, NS_MUTATION_NODEINSERTEDINTODOCUMENT },
-    { &nsGkAtoms::onDOMNodeRemovedFromDocument,  NS_MUTATION_NODEREMOVEDFROMDOCUMENT },
-    { &nsGkAtoms::onDOMSubtreeModified,          NS_MUTATION_SUBTREEMODIFIED },
-    { &nsGkAtoms::onDOMActivate,                 NS_UI_ACTIVATE },
-    { &nsGkAtoms::onDOMFocusIn,                  NS_UI_FOCUSIN },
-    { &nsGkAtoms::onDOMFocusOut,                 NS_UI_FOCUSOUT },
-    { &nsGkAtoms::oninput,                       NS_FORM_INPUT },
-    { &nsGkAtoms::onpageshow,                    NS_PAGE_SHOW },
-    { &nsGkAtoms::onpagehide,                    NS_PAGE_HIDE },
-    { &nsGkAtoms::onclose,                       NS_XUL_CLOSE },
-    { &nsGkAtoms::onpaint,                       NS_PAINT },
-    { &nsGkAtoms::onresize,                      NS_RESIZE_EVENT },
-    { &nsGkAtoms::onscroll,                      NS_SCROLL_EVENT },
-    { &nsGkAtoms::ontext,                        NS_TEXT_TEXT },
-    { &nsGkAtoms::onpopupshowing,                NS_XUL_POPUP_SHOWING },
-    { &nsGkAtoms::onpopupshown,                  NS_XUL_POPUP_SHOWN },
-    { &nsGkAtoms::onpopuphiding,                 NS_XUL_POPUP_HIDING },
-    { &nsGkAtoms::onpopuphidden,                 NS_XUL_POPUP_HIDDEN },
-    { &nsGkAtoms::oncommand,                     NS_XUL_COMMAND },
-    { &nsGkAtoms::onbroadcast,                   NS_XUL_BROADCAST },
-    { &nsGkAtoms::oncommandupdate,               NS_XUL_COMMAND_UPDATE },
-    { &nsGkAtoms::ondragenter,                   NS_DRAGDROP_ENTER },
-    { &nsGkAtoms::ondragover,                    NS_DRAGDROP_OVER_SYNTH },
-    { &nsGkAtoms::ondragexit,                    NS_DRAGDROP_EXIT_SYNTH },
-    { &nsGkAtoms::ondragdrop,                    NS_DRAGDROP_DROP },
-    { &nsGkAtoms::ondraggesture,                 NS_DRAGDROP_GESTURE },
-    { &nsGkAtoms::onoverflow,                    NS_SCROLLPORT_OVERFLOW },
-    { &nsGkAtoms::onunderflow,                   NS_SCROLLPORT_UNDERFLOW },
-    { &nsGkAtoms::onoverflowchanged,             NS_SCROLLPORT_OVERFLOWCHANGED },
-    { &nsGkAtoms::onDOMMouseScroll,              NS_MOUSE_SCROLL }
-#ifdef MOZ_SVG
-   ,{ &nsGkAtoms::onSVGLoad,                     NS_SVG_LOAD },
-    { &nsGkAtoms::onSVGUnload,                   NS_SVG_UNLOAD },
-    { &nsGkAtoms::onSVGAbort,                    NS_SVG_ABORT },
-    { &nsGkAtoms::onSVGError,                    NS_SVG_ERROR },
-    { &nsGkAtoms::onSVGResize,                   NS_SVG_RESIZE },
-    { &nsGkAtoms::onSVGScroll,                   NS_SVG_SCROLL },
-    { &nsGkAtoms::onSVGZoom,                     NS_SVG_ZOOM }
-#endif // MOZ_SVG
-  };
-
-  gEventIdTable = new nsDataHashtable<nsISupportsHashKey, PRUint32>;
-  if (!gEventIdTable ||
-      !gEventIdTable->Init(int(NS_ARRAY_LENGTH(eventIdArray) / 0.75) + 1)) {
-    delete gEventIdTable;
-    gEventIdTable = nsnull;
-    return;
-  }
-
-  for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(eventIdArray); ++i) {
-    if (!gEventIdTable->Put(*(eventIdArray[i].mAtom), eventIdArray[i].mId)) {
-      delete gEventIdTable;
-      gEventIdTable = nsnull;
-      return;
-    }
-  }
-}
-
-PRUint32
-nsEventListenerManager::GetIdentifierForEvent(nsIAtom* aEvent)
-{
-  if (!gEventIdTable) {
-    InitializeEventIdTable();
-  }
-  PRUint32 eventId = NS_USER_DEFINED_EVENT;
-  if (gEventIdTable) {
-    // If the aEvent doesn't exists, eventId is not modified.
-    gEventIdTable->Get(aEvent, &eventId);
-  }
-  return eventId;
-}
-
 PRBool
 nsEventListenerManager::ListenerCanHandle(nsListenerStruct* aLs,
                                           nsEvent* aEvent)
 {
   if (aEvent->message == NS_USER_DEFINED_EVENT) {
     // We don't want to check aLs->mEventType here, bug 276846.
     return (aEvent->userType && aLs->mTypeAtom == aEvent->userType);
   }
@@ -730,29 +620,29 @@ nsEventListenerManager::ListenerCanHandl
 
 NS_IMETHODIMP
 nsEventListenerManager::AddEventListenerByType(nsIDOMEventListener *aListener, 
                                                const nsAString& aType,
                                                PRInt32 aFlags,
                                                nsIDOMEventGroup* aEvtGrp)
 {
   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
-  PRUint32 type = GetIdentifierForEvent(atom);
+  PRUint32 type = nsContentUtils::GetEventId(atom);
   AddEventListener(aListener, type, atom, nsnull, aFlags, aEvtGrp);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventListenerManager::RemoveEventListenerByType(nsIDOMEventListener *aListener, 
                                                   const nsAString& aType,
                                                   PRInt32 aFlags,
                                                   nsIDOMEventGroup* aEvtGrp)
 {
   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aType);
-  PRUint32 type = GetIdentifierForEvent(atom);
+  PRUint32 type = nsContentUtils::GetEventId(atom);
   RemoveEventListener(aListener, type, atom, nsnull, aFlags, aEvtGrp);
   return NS_OK;
 }
 
 nsListenerStruct*
 nsEventListenerManager::FindJSEventListener(PRUint32 aEventType,
                                             nsIAtom* aTypeAtom)
 {
@@ -774,17 +664,17 @@ nsresult
 nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext,
                                            void *aScopeObject,
                                            nsISupports *aObject,
                                            nsIAtom* aName,
                                            PRBool aIsString,
                                            PRBool aPermitUntrustedEvents)
 {
   nsresult rv = NS_OK;
-  PRUint32 eventType = GetIdentifierForEvent(aName);
+  PRUint32 eventType = nsContentUtils::GetEventId(aName);
   nsListenerStruct* ls = FindJSEventListener(eventType, aName);
 
   if (!ls) {
     // If we didn't find a script listener or no listeners existed
     // create and add a new one.
     nsCOMPtr<nsIDOMEventListener> scriptListener;
     rv = NS_NewJSEventListener(aContext, aScopeObject, aObject,
                                getter_AddRefs(scriptListener));
@@ -943,17 +833,17 @@ nsEventListenerManager::AddScriptEventLi
 
   return SetJSEventListener(context, scope, objiSupp, aName, aDeferCompilation,
                             aPermitUntrustedEvents);
 }
 
 nsresult
 nsEventListenerManager::RemoveScriptEventListener(nsIAtom* aName)
 {
-  PRUint32 eventType = GetIdentifierForEvent(aName);
+  PRUint32 eventType = nsContentUtils::GetEventId(aName);
   nsListenerStruct* ls = FindJSEventListener(eventType, aName);
 
   if (ls) {
     mListeners.RemoveElement((void*)ls);
     delete ls;
     mNoListenerForEvent = NS_EVENT_TYPE_NULL;
     mNoListenerForEventAtom = nsnull;
     mListenerRemoved = PR_TRUE;
@@ -1029,17 +919,17 @@ nsresult
 nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext, 
                                                    void *aScope,
                                                    nsISupports *aObject, 
                                                    nsIAtom *aName,
                                                    PRBool *aDidCompile)
 {
   nsresult rv = NS_OK;
   *aDidCompile = PR_FALSE;
-  PRUint32 eventType = GetIdentifierForEvent(aName);
+  PRUint32 eventType = nsContentUtils::GetEventId(aName);
   nsListenerStruct* ls = FindJSEventListener(eventType, aName);
 
   if (!ls) {
     //nothing to compile
     return NS_OK;
   }
 
   if (ls->mHandlerIsString) {
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1318,73 +1318,22 @@ nsGenericHTMLElement::GetHrefURIForAncho
   else {
     // Absolute URI is null to say we have no HREF.
     *aURI = nsnull;
   }
 
   return NS_OK;
 }
 
-PRBool nsGenericHTMLElement::IsEventName(nsIAtom* aName)
-{
-  const char* name;
-  aName->GetUTF8String(&name);
-
-  if (name[0] != 'o' || name[1] != 'n') {
-    return PR_FALSE;
-  }
-
-  return (aName == nsGkAtoms::onclick                       ||
-          aName == nsGkAtoms::ondblclick                    ||
-          aName == nsGkAtoms::onmousedown                   ||
-          aName == nsGkAtoms::onmouseup                     ||
-          aName == nsGkAtoms::onmouseover                   ||
-          aName == nsGkAtoms::onmouseout                    ||
-          aName == nsGkAtoms::onkeydown                     ||
-          aName == nsGkAtoms::onkeyup                       ||
-          aName == nsGkAtoms::onkeypress                    ||
-          aName == nsGkAtoms::onmousemove                   ||
-          aName == nsGkAtoms::onload                        ||
-          aName == nsGkAtoms::onunload                      ||
-          aName == nsGkAtoms::onbeforeunload                ||
-          aName == nsGkAtoms::onpageshow                    ||
-          aName == nsGkAtoms::onpagehide                    ||
-          aName == nsGkAtoms::onabort                       ||
-          aName == nsGkAtoms::onerror                       ||
-          aName == nsGkAtoms::onfocus                       ||
-          aName == nsGkAtoms::onblur                        ||
-          aName == nsGkAtoms::onoffline                     ||
-          aName == nsGkAtoms::ononline                      ||
-          aName == nsGkAtoms::onsubmit                      ||
-          aName == nsGkAtoms::onreset                       ||
-          aName == nsGkAtoms::onchange                      ||
-          aName == nsGkAtoms::onselect                      || 
-          aName == nsGkAtoms::onpaint                       ||
-          aName == nsGkAtoms::onresize                      ||
-          aName == nsGkAtoms::onscroll                      ||
-          aName == nsGkAtoms::oninput                       ||
-          aName == nsGkAtoms::oncontextmenu                 ||
-          aName == nsGkAtoms::onDOMAttrModified             ||
-          aName == nsGkAtoms::onDOMCharacterDataModified    || 
-          aName == nsGkAtoms::onDOMSubtreeModified          ||
-          aName == nsGkAtoms::onDOMNodeInsertedIntoDocument || 
-          aName == nsGkAtoms::onDOMNodeRemovedFromDocument  ||
-          aName == nsGkAtoms::onDOMNodeInserted             || 
-          aName == nsGkAtoms::onDOMNodeRemoved              ||
-          aName == nsGkAtoms::onDOMActivate                 ||
-          aName == nsGkAtoms::onDOMFocusIn                  ||
-          aName == nsGkAtoms::onDOMFocusOut);
-}
-
 nsresult
 nsGenericHTMLElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                    const nsAString* aValue, PRBool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
-    if (IsEventName(aName) && aValue) {
+    if (nsContentUtils::IsEventAttributeName(aName, EventNameType_HTML) && aValue) {
       nsresult rv = AddScriptEventListener(aName, *aValue);
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aNotify && aName == nsGkAtoms::spellcheck) {
       SyncEditorsOnSubtree(this);
     }
   }
 
@@ -1433,17 +1382,17 @@ nsGenericHTMLElement::GetEventListenerMa
 }
 
 nsresult
 nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                                 PRBool aNotify)
 {
   // Check for event handlers
   if (aNameSpaceID == kNameSpaceID_None &&
-      IsEventName(aAttribute)) {
+      nsContentUtils::IsEventAttributeName(aAttribute, EventNameType_HTML)) {
     nsCOMPtr<nsIEventListenerManager> manager;
     GetListenerManager(PR_FALSE, getter_AddRefs(manager));
 
     if (manager) {
       manager->RemoveScriptEventListener(aAttribute);
     }
   }
 
@@ -3785,17 +3734,17 @@ nsGenericHTMLElement::RecompileScriptEve
         const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
 
         // Eventlistenener-attributes are always in the null namespace
         if (!name->IsAtom()) {
             continue;
         }
 
         nsIAtom *attr = name->Atom();
-        if (!IsEventName(attr)) {
+        if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_HTML)) {
             continue;
         }
 
         nsAutoString value;
         GetAttr(kNameSpaceID_None, attr, value);
         AddScriptEventListener(attr, value, PR_TRUE);
     }
 }
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -780,38 +780,16 @@ nsSVGElement::AddMappedSVGValue(nsIAtom*
     rv = mMappedAttributes.SetAndTakeAttr(ni, attrVal);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 /* static */
-PRBool
-nsSVGElement::IsGraphicElementEventName(nsIAtom* aName)
-{
-  const char* name;
-  aName->GetUTF8String(&name);
-
-  if (name[0] != 'o' || name[1] != 'n') {
-    return PR_FALSE;
-  }
-
-  return (aName == nsGkAtoms::onabort     ||
-          aName == nsGkAtoms::onclick     ||
-          aName == nsGkAtoms::onerror     ||
-          aName == nsGkAtoms::onload      ||
-          aName == nsGkAtoms::onmousedown ||
-          aName == nsGkAtoms::onmouseup   ||
-          aName == nsGkAtoms::onmouseover ||
-          aName == nsGkAtoms::onmousemove ||
-          aName == nsGkAtoms::onmouseout);
-}
-
-/* static */
 nsIAtom* nsSVGElement::GetEventNameForAttr(nsIAtom* aAttr)
 {
   if (aAttr == nsGkAtoms::onload)
     return nsGkAtoms::onSVGLoad;
   if (aAttr == nsGkAtoms::onunload)
     return nsGkAtoms::onSVGUnload;
   if (aAttr == nsGkAtoms::onabort)
     return nsGkAtoms::onSVGAbort;
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -132,17 +132,16 @@ protected:
   // Hooks for subclasses
   virtual PRBool IsEventName(nsIAtom* aName);
 
   void UpdateContentStyleRule();
   nsISVGValue* GetMappedAttribute(PRInt32 aNamespaceID, nsIAtom* aName);
   nsresult AddMappedSVGValue(nsIAtom* aName, nsISupports* aValue,
                              PRInt32 aNamespaceID = kNameSpaceID_None);
   
-  static PRBool IsGraphicElementEventName(nsIAtom* aName);
   static nsIAtom* GetEventNameForAttr(nsIAtom* aAttr);
 
   // The following two structures should be protected, but VC6
   // doesn't allow children of nsSVGElement to access them.
 public:
   struct LengthInfo {
     nsIAtom** mName;
     float     mDefaultValue;
--- a/content/svg/content/src/nsSVGGraphicElement.cpp
+++ b/content/svg/content/src/nsSVGGraphicElement.cpp
@@ -275,17 +275,17 @@ nsSVGGraphicElement::IsAttributeMapped(c
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement overrides
 
 PRBool
 nsSVGGraphicElement::IsEventName(nsIAtom* aName)
 {
-  return IsGraphicElementEventName(aName);
+  return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
 }
 
 already_AddRefed<nsIDOMSVGMatrix>
 nsSVGGraphicElement::GetLocalTransformMatrix()
 {
   if (!mTransforms)
     return nsnull;
 
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -1213,27 +1213,24 @@ nsSVGSVGElement::DidModifySVGObservable 
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement overrides
 
 PRBool
 nsSVGSVGElement::IsEventName(nsIAtom* aName)
 {
-  return IsGraphicElementEventName(aName) ||
-
-  /* The following are for events that are only applicable to outermost 'svg'
-     elements. We don't check if we're an outer 'svg' element in case we're not
-     inserted into the document yet, but since the target of the events in
-     question will always be the outermost 'svg' element, this shouldn't cause
-     any real problems.
+  /* The events in EventNameType_SVGSVG are for events that are only
+     applicable to outermost 'svg' elements. We don't check if we're an outer
+     'svg' element in case we're not inserted into the document yet, but since
+     the target of the events in question will always be the outermost 'svg'
+     element, this shouldn't cause any real problems.
   */
-         aName == nsGkAtoms::onunload    ||
-         aName == nsGkAtoms::onscroll    ||
-         aName == nsGkAtoms::onzoom;
+  return nsContentUtils::IsEventAttributeName(aName,
+         (EventNameType_SVGGraphic | EventNameType_SVGSVG));
 }
 
 //----------------------------------------------------------------------
 // public helpers:
 
 nsresult
 nsSVGSVGElement::GetViewboxToViewportTransform(nsIDOMSVGMatrix **_retval)
 {
--- a/content/svg/content/src/nsSVGTSpanElement.cpp
+++ b/content/svg/content/src/nsSVGTSpanElement.cpp
@@ -377,17 +377,17 @@ nsSVGTSpanElement::IsAttributeMapped(con
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement overrides
 
 PRBool
 nsSVGTSpanElement::IsEventName(nsIAtom* aName)
 {
-  return IsGraphicElementEventName(aName);
+  return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
 }
 
 //----------------------------------------------------------------------
 // implementation helpers:
 
 already_AddRefed<nsISVGTextContentMetrics>
 nsSVGTSpanElement::GetTextContentMetrics()
 {
--- a/content/svg/content/src/nsSVGTextPathElement.cpp
+++ b/content/svg/content/src/nsSVGTextPathElement.cpp
@@ -366,17 +366,17 @@ nsSVGTextPathElement::IsAttributeMapped(
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement overrides
 
 PRBool
 nsSVGTextPathElement::IsEventName(nsIAtom* aName)
 {
-  return IsGraphicElementEventName(aName);
+  return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
 }
 
 nsSVGElement::LengthAttributesInfo
 nsSVGTextPathElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               NS_ARRAY_LENGTH(sLengthInfo));
 }
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -199,85 +199,16 @@ private:
 
 //----------------------------------------------------------------------
 
 static NS_DEFINE_CID(kXULPopupListenerCID,        NS_XULPOPUPLISTENER_CID);
 static NS_DEFINE_CID(kCSSOMFactoryCID,            NS_CSSOMFACTORY_CID);
 
 //----------------------------------------------------------------------
 
-
-// XXX This function is called for every attribute on every element for
-// XXX which we SetDocument, among other places.  A linear search might
-// XXX not be what we want.
-static PRBool
-IsEventHandler(nsIAtom* aName)
-{
-    const char* name;
-    aName->GetUTF8String(&name);
-
-    if (name[0] != 'o' || name[1] != 'n') {
-        return PR_FALSE;
-    }
-    
-    return aName == nsGkAtoms::onclick            ||
-           aName == nsGkAtoms::ondblclick         ||
-           aName == nsGkAtoms::onmousedown        ||
-           aName == nsGkAtoms::onmouseup          ||
-           aName == nsGkAtoms::onmouseover        ||
-           aName == nsGkAtoms::onmouseout         ||
-           aName == nsGkAtoms::onmousemove        ||
-
-           aName == nsGkAtoms::onkeydown          ||
-           aName == nsGkAtoms::onkeyup            ||
-           aName == nsGkAtoms::onkeypress         ||
-
-           aName == nsGkAtoms::oncompositionstart ||
-           aName == nsGkAtoms::oncompositionend   ||
-
-           aName == nsGkAtoms::onload             ||
-           aName == nsGkAtoms::onunload           ||
-           aName == nsGkAtoms::onabort            ||
-           aName == nsGkAtoms::onerror            ||
-
-           aName == nsGkAtoms::onpopupshowing     ||
-           aName == nsGkAtoms::onpopupshown       ||
-           aName == nsGkAtoms::onpopuphiding      ||
-           aName == nsGkAtoms::onpopuphidden      ||
-           aName == nsGkAtoms::onclose            ||
-           aName == nsGkAtoms::oncommand          ||
-           aName == nsGkAtoms::onbroadcast        ||
-           aName == nsGkAtoms::oncommandupdate    ||
-
-           aName == nsGkAtoms::onoverflow         ||
-           aName == nsGkAtoms::onunderflow        ||
-           aName == nsGkAtoms::onoverflowchanged  ||
-
-           aName == nsGkAtoms::onfocus            ||
-           aName == nsGkAtoms::onblur             ||
-
-           aName == nsGkAtoms::onsubmit           ||
-           aName == nsGkAtoms::onreset            ||
-           aName == nsGkAtoms::onchange           ||
-           aName == nsGkAtoms::onselect           ||
-           aName == nsGkAtoms::oninput            ||
-
-           aName == nsGkAtoms::onpaint            ||
-
-           aName == nsGkAtoms::ondragenter        ||
-           aName == nsGkAtoms::ondragover         ||
-           aName == nsGkAtoms::ondragexit         ||
-           aName == nsGkAtoms::ondragdrop         ||
-           aName == nsGkAtoms::ondraggesture      ||
-
-           aName == nsGkAtoms::oncontextmenu;
-}
-
-//----------------------------------------------------------------------
-
 #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
 PRUint32             nsXULPrototypeAttribute::gNumElements;
 PRUint32             nsXULPrototypeAttribute::gNumAttributes;
 PRUint32             nsXULPrototypeAttribute::gNumEventHandlers;
 PRUint32             nsXULPrototypeAttribute::gNumCacheTests;
 PRUint32             nsXULPrototypeAttribute::gNumCacheHits;
 PRUint32             nsXULPrototypeAttribute::gNumCacheSets;
 PRUint32             nsXULPrototypeAttribute::gNumCacheFills;
@@ -831,17 +762,18 @@ nsXULElement::AddListenerFor(const nsAtt
 {
     // If appropriate, add a popup listener and/or compile the event
     // handler. Called when we change the element's document, create a
     // new element, change an attribute's value, etc.
     // Eventlistenener-attributes are always in the null namespace
     if (aName.IsAtom()) {
         nsIAtom *attr = aName.Atom();
         MaybeAddPopupListener(attr);
-        if (aCompileEventHandlers && IsEventHandler(attr)) {
+        if (aCompileEventHandlers &&
+            nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
             nsAutoString value;
             GetAttr(kNameSpaceID_None, attr, value);
             AddScriptEventListener(attr, value, PR_TRUE);
         }
     }
 }
 
 void
@@ -1217,17 +1149,17 @@ nsXULElement::AfterSetAttr(PRInt32 aName
                            const nsAString* aValue, PRBool aNotify)
 {
     if (aNamespaceID == kNameSpaceID_None) {
         // XXX UnsetAttr handles more attributes then we do. See bug 233642.
 
         // Add popup and event listeners. We can't call AddListenerFor since
         // the attribute isn't set yet.
         MaybeAddPopupListener(aName);
-        if (IsEventHandler(aName) && aValue) {
+        if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL) && aValue) {
             // If mPrototype->mScriptTypeID != GetScriptTypeID(), it means
             // we are resolving an overlay with a different default script
             // language.  We can't defer compilation of those handlers as
             // we will have lost the script language (storing it on each
             // nsXULPrototypeAttribute is expensive!)
             PRBool defer = mPrototype == nsnull ||
                            mPrototype->mScriptTypeID == GetScriptTypeID();
             AddScriptEventListener(aName, *aValue, defer);
@@ -2414,17 +2346,17 @@ nsXULElement::RecompileScriptEventListen
         const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
 
         // Eventlistenener-attributes are always in the null namespace
         if (!name->IsAtom()) {
             continue;
         }
 
         nsIAtom *attr = name->Atom();
-        if (!IsEventHandler(attr)) {
+        if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
             continue;
         }
 
         nsAutoString value;
         GetAttr(kNameSpaceID_None, attr, value);
         AddScriptEventListener(attr, value, PR_TRUE);
     }
 
@@ -2446,17 +2378,17 @@ nsXULElement::RecompileScriptEventListen
 
             nsIAtom *attr = name.Atom();
 
             // Don't clobber a locally modified attribute.
             if (haveLocalAttributes && mAttrsAndChildren.GetAttr(attr)) {
                 continue;
             }
 
-            if (!IsEventHandler(attr)) {
+            if (!nsContentUtils::IsEventAttributeName(attr, EventNameType_XUL)) {
                 continue;
             }
 
             nsAutoString value;
             GetAttr(kNameSpaceID_None, attr, value);
             AddScriptEventListener(attr, value, PR_TRUE);
         }
     }
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -115,16 +115,25 @@ nsLayoutStatics::Initialize()
                "nsLayoutStatics isn't zero!");
 
   sLayoutStaticRefcnt = 1;
   NS_LOG_ADDREF(&sLayoutStaticRefcnt, sLayoutStaticRefcnt,
                 "nsLayoutStatics", 1);
 
   nsresult rv;
 
+  // Register all of our atoms once
+  nsCSSAnonBoxes::AddRefAtoms();
+  nsCSSPseudoClasses::AddRefAtoms();
+  nsCSSPseudoElements::AddRefAtoms();
+  nsCSSKeywords::AddRefTable();
+  nsCSSProps::AddRefTable();
+  nsColorNames::AddRefTable();
+  nsGkAtoms::AddRefAtoms();
+
   nsDOMScriptObjectFactory::Startup();
   rv = nsContentUtils::Init();
   if (NS_FAILED(rv)) {
     NS_ERROR("Could not initialize nsContentUtils");
     return rv;
   }
 
   rv = nsAttrValue::Init();
@@ -140,25 +149,16 @@ nsLayoutStatics::Initialize()
   }
 
   rv = nsCellMap::Init();
   if (NS_FAILED(rv)) {
     NS_ERROR("Could not initialize nsCellMap");
     return rv;
   }
 
-  // Register all of our atoms once
-  nsCSSAnonBoxes::AddRefAtoms();
-  nsCSSPseudoClasses::AddRefAtoms();
-  nsCSSPseudoElements::AddRefAtoms();
-  nsCSSKeywords::AddRefTable();
-  nsCSSProps::AddRefTable();
-  nsColorNames::AddRefTable();
-  nsGkAtoms::AddRefAtoms();
-
   rv = nsCSSRendering::Init();
   if (NS_FAILED(rv)) {
     NS_ERROR("Could not initialize nsCSSRendering");
     return rv;
   }
 
 #ifndef MOZ_NO_INSPECTOR_APIS
   inDOMView::InitAtoms();