Bug 659350 part 5. The guts of the change to move from storing inline event handlers on the JSObject to storing them in the event listener manager directly, so we can easily set/read them via IDL.
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 24 Aug 2011 15:49:25 -0400
changeset 75838 1f58f9ed470c7f46d05228c219370e2fff81ca4d
parent 75837 e45c1629b10ca98d26310e8019346832eb79d0cc
child 75839 3fbd9eaf9debbc46afac4f2e2189d11b5972e82b
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
bugs659350
milestone9.0a1
Bug 659350 part 5. The guts of the change to move from storing inline event handlers on the JSObject to storing them in the event listener manager directly, so we can easily set/read them via IDL. The changes here are as follows: 1) nsIJSEventListener now stores the handler. This is guaranteed to be already bound properly, if needed, before being set in the nsIJSEventListener. 2) The old classinfo glue to deal with on* properties is gone. 3) IDL-based methods for on* properties have been added.
content/base/public/nsINode.h
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
content/events/src/nsEventListenerService.cpp
content/events/test/test_bug379120.html
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsHTMLBodyElement.cpp
content/html/content/src/nsHTMLFrameSetElement.cpp
content/html/content/src/nsHTMLFrameSetElement.h
content/html/content/test/test_bug389797.html
content/xbl/src/nsXBLPrototypeHandler.cpp
content/xul/content/src/nsXULElement.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsIJSEventListener.h
dom/base/nsIScriptContext.h
dom/base/nsIScriptObjectOwner.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
dom/interfaces/base/nsIDOMWindow.idl
dom/interfaces/core/Makefile.in
dom/interfaces/core/nsIInlineEventHandlers.idl
dom/interfaces/events/nsIDOMTouchEvent.idl
dom/interfaces/html/nsIDOMHTMLBodyElement.idl
dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl
dom/src/events/nsJSEventListener.cpp
dom/src/events/nsJSEventListener.h
dom/tests/mochitest/bugs/test_bug159849.html
dom/tests/mochitest/bugs/test_bug583225.html
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -43,16 +43,17 @@
 #include "nsPropertyTable.h"
 #include "nsTObserverArray.h"
 #include "nsINodeInfo.h"
 #include "nsCOMPtr.h"
 #include "nsWrapperCache.h"
 #include "nsIProgrammingLanguage.h" // for ::JAVASCRIPT
 #include "nsDOMError.h"
 #include "nsDOMString.h"
+#include "jspubtd.h"
 
 class nsIContent;
 class nsIDocument;
 class nsIDOMEvent;
 class nsIDOMNode;
 class nsIDOMNodeList;
 class nsINodeList;
 class nsIPresShell;
@@ -275,18 +276,18 @@ private:
 #define DOM_USER_DATA         1
 #define DOM_USER_DATA_HANDLER 2
 #ifdef MOZ_SMIL
 #define SMIL_MAPPED_ATTR_ANIMVAL 3
 #endif // MOZ_SMIL
 
 // IID for the nsINode interface
 #define NS_INODE_IID \
-{ 0xc7abbb40, 0x2571, 0x4d12, \
- { 0x8f, 0x89, 0x0d, 0x4f, 0x55, 0xc0, 0x92, 0xf6 } }
+{ 0xcdab747e, 0xa58f, 0x4b96, \
+ { 0x8b, 0xae, 0x9d, 0x53, 0xe0, 0xa7, 0x8a, 0x74 } }
 
 /**
  * An internal interface that abstracts some DOMNode-related parts that both
  * nsIContent and nsIDocument share.  An instance of this interface has a list
  * of nsIContent children and provides access to them.
  */
 class nsINode : public nsIDOMEventTarget,
                 public nsWrapperCache
@@ -1361,16 +1362,28 @@ protected:
    * @param aKid The child to insert.
    * @param aIndex The index to insert at.
    * @param aNotify Whether to notify.
    * @param aChildArray The child array to work with
    */
   nsresult doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
                            PRBool aNotify, nsAttrAndChildArray& aChildArray);
 
+  /* Event stuff that documents and elements share.  This needs to be
+     NS_IMETHOD because some subclasses implement DOM methods with
+     this exact name and signature and then the calling convention
+     needs to match. */
+#define EVENT(name_, id_, type_, struct_)                         \
+  NS_IMETHOD GetOn##name_(JSContext *cx, jsval *vp);              \
+  NS_IMETHOD SetOn##name_(JSContext *cx, const jsval &v);
+#define TOUCH_EVENT EVENT
+#include "nsEventNameList.h"
+#undef TOUCH_EVENT
+#undef EVENT  
+
   nsCOMPtr<nsINodeInfo> mNodeInfo;
 
   nsINode* mParent;
 
   PRUint32 mFlags;
 
 private:
   // Boolean flags.
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1697,16 +1697,17 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMEventTarget)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentTouch)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsITouchEventReceiver)
+    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIInlineEventHandlers)
   NS_OFFSET_AND_INTERFACE_TABLE_END
   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDocument)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
                                  new nsNode3Tearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector,
                                  new nsNodeSelectorTearoff(this))
   if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) ||
@@ -8467,8 +8468,19 @@ nsIDocument::SizeOf() const
 PRInt64
 nsDocument::SizeOf() const
 {
   PRInt64 size = MemoryReporter::GetBasicSize<nsDocument, nsIDocument>(this);
   size += mAttrStyleSheet ? mAttrStyleSheet->DOMSizeOf() : 0;
   return size;
 }
 
+#define EVENT(name_, id_, type_, struct_)                                 \
+  NS_IMETHODIMP nsDocument::GetOn##name_(JSContext *cx, jsval *vp) {      \
+    return nsINode::GetOn##name_(cx, vp);                                 \
+  }                                                                       \
+  NS_IMETHODIMP nsDocument::SetOn##name_(JSContext *cx, const jsval &v) { \
+    return nsINode::SetOn##name_(cx, v);                                  \
+  }
+#define TOUCH_EVENT EVENT
+#include "nsEventNameList.h"
+#undef TOUCH_EVENT
+#undef EVENT
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -93,16 +93,17 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsILoadContext.h"
 #include "nsIProgressEventSink.h"
 #include "nsISecurityEventSink.h"
 #include "nsIChannelEventSink.h"
 #include "imgIRequest.h"
 #include "nsIDOMDOMImplementation.h"
 #include "nsIDOMTouchEvent.h"
+#include "nsIInlineEventHandlers.h"
 #include "nsDataHashtable.h"
 #include "TimeStamp.h"
 
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS   (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS      (1 << 1)
 #define XML_DECLARATION_BITS_STANDALONE_EXISTS    (1 << 2)
 #define XML_DECLARATION_BITS_STANDALONE_YES       (1 << 3)
 
@@ -487,17 +488,18 @@ protected:
 class nsDocument : public nsIDocument,
                    public nsIDOMXMLDocument, // inherits nsIDOMDocument
                    public nsIDOMDocumentXBL,
                    public nsSupportsWeakReference,
                    public nsIScriptObjectPrincipal,
                    public nsIRadioGroupContainer,
                    public nsIApplicationCacheContainer,
                    public nsStubMutationObserver,
-                   public nsIDOMDocumentTouch
+                   public nsIDOMDocumentTouch,
+                   public nsIInlineEventHandlers
 {
 public:
   typedef mozilla::dom::Element Element;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
 
   using nsINode::GetScriptTypeID;
@@ -782,16 +784,19 @@ public:
   NS_DECL_NSIAPPLICATIONCACHECONTAINER
 
   // nsITouchEventReceiver
   NS_DECL_NSITOUCHEVENTRECEIVER
 
   // nsIDOMDocumentTouch
   NS_DECL_NSIDOMDOCUMENTTOUCH
 
+  // nsIInlineEventHandlers
+  NS_DECL_NSIINLINEEVENTHANDLERS
+
   virtual nsresult Init();
   
   virtual void AddXMLEventsContent(nsIContent * aXMLEventsElement);
 
   virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
                               PRInt32 aNamespaceID,
                               PRBool aDocumentDefaultType,
                               nsIContent **aResult);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -142,16 +142,18 @@
 #include "mozAutoDocUpdate.h"
 
 #include "nsCSSParser.h"
 #include "prprf.h"
 
 #include "nsSVGFeatures.h"
 #include "nsDOMMemoryReporter.h"
 
+#include "xpcpublic.h"
+
 using namespace mozilla::dom;
 namespace css = mozilla::css;
 
 NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
 
 PRInt32 nsIContent::sTabFocusModel = eTabFocus_any;
 PRBool nsIContent::sTabFocusModelAppliesToXUL = PR_FALSE;
 PRUint32 nsMutationGuard::sMutationCount = 0;
@@ -2156,16 +2158,27 @@ NS_IMPL_CYCLE_COLLECTION_1(nsTouchEventR
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTouchEventReceiverTearoff)
   NS_INTERFACE_MAP_ENTRY(nsITouchEventReceiver)
 NS_INTERFACE_MAP_END_AGGREGATED(mElement)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTouchEventReceiverTearoff)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTouchEventReceiverTearoff)
 
 //----------------------------------------------------------------------
+
+NS_IMPL_CYCLE_COLLECTION_1(nsInlineEventHandlersTearoff, mElement)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsInlineEventHandlersTearoff)
+  NS_INTERFACE_MAP_ENTRY(nsIInlineEventHandlers)
+NS_INTERFACE_MAP_END_AGGREGATED(mElement)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsInlineEventHandlersTearoff)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsInlineEventHandlersTearoff)
+
+//----------------------------------------------------------------------
 nsGenericElement::nsDOMSlots::nsDOMSlots()
   : nsINode::nsSlots(),
     mDataset(nsnull),
     mBindingParent(nsnull)
 {
 }
 
 nsGenericElement::nsDOMSlots::~nsDOMSlots()
@@ -4273,16 +4286,18 @@ NS_INTERFACE_MAP_BEGIN(nsGenericElement)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
                                  new nsNodeSupportsWeakRefTearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector,
                                  new nsNodeSelectorTearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
                                  new nsNode3Tearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsITouchEventReceiver,
                                  new nsTouchEventReceiverTearoff(this))
+  NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIInlineEventHandlers,
+                                 new nsInlineEventHandlersTearoff(this))
   // nsNodeSH::PreCreate() depends on the identity pointer being the
   // same as nsINode (which nsIContent inherits), so if you change the
   // below line, make sure nsNodeSH::PreCreate() still does the right
   // thing!
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericElement)
@@ -5393,8 +5408,35 @@ nsGenericElement::SizeOf() const
   PRInt64 size = MemoryReporter::GetBasicSize<nsGenericElement, Element>(this);
 
   size -= sizeof(mAttrsAndChildren);
   size += mAttrsAndChildren.SizeOf();
 
   return size;
 }
 
+#define EVENT(name_, id_, type_, struct_)                                    \
+  NS_IMETHODIMP nsINode::GetOn##name_(JSContext *cx, jsval *vp) {            \
+    nsEventListenerManager *elm = GetListenerManager(PR_FALSE);              \
+    if (elm) {                                                               \
+      elm->GetJSEventListener(nsGkAtoms::on##name_, vp);                     \
+    } else {                                                                 \
+      *vp = JSVAL_NULL;                                                      \
+    }                                                                        \
+    return NS_OK;                                                            \
+  }                                                                          \
+  NS_IMETHODIMP nsINode::SetOn##name_(JSContext *cx, const jsval &v) {       \
+    nsEventListenerManager *elm = GetListenerManager(PR_TRUE);               \
+    if (!elm) {                                                              \
+      return NS_ERROR_OUT_OF_MEMORY;                                         \
+    }                                                                        \
+                                                                             \
+    JSObject *obj = GetWrapper();                                            \
+    if (!obj) {                                                              \
+      /* Just silently do nothing */                                         \
+      return NS_OK;                                                          \
+    }                                                                        \
+    return elm->SetJSEventListenerToJsval(nsGkAtoms::on##name_, cx, obj, v); \
+}
+#define TOUCH_EVENT EVENT
+#include "nsEventNameList.h"
+#undef TOUCH_EVENT
+#undef EVENT
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -60,16 +60,17 @@
 #include "nsIDocument.h"
 #include "nsIDOMNodeSelector.h"
 #include "nsIDOMXPathNSResolver.h"
 #include "nsPresContext.h"
 #include "nsIDOMDOMStringMap.h"
 #include "nsContentList.h"
 #include "nsDOMClassInfoID.h" // DOMCI_DATA
 #include "nsIDOMTouchEvent.h"
+#include "nsIInlineEventHandlers.h"
 
 #ifdef MOZ_SMIL
 #include "nsISMILAttr.h"
 #endif // MOZ_SMIL
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIFrame;
@@ -221,29 +222,31 @@ private:
 
 private:
   nsCOMPtr<nsINode> mNode;
 };
 
 // Forward declare to allow being a friend
 class nsNSElementTearoff;
 class nsTouchEventReceiverTearoff;
+class nsInlineEventHandlersTearoff;
 
 /**
  * A generic base class for DOM elements, implementing many nsIContent,
  * nsIDOMNode and nsIDOMElement methods.
  */
 class nsGenericElement : public mozilla::dom::Element
 {
 public:
   nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericElement();
 
   friend class nsNSElementTearoff;
   friend class nsTouchEventReceiverTearoff;
+  friend class nsInlineEventHandlersTearoff;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
 
   /**
    * Called during QueryInterface to give the binding manager a chance to
    * get an interface for this element.
@@ -1061,28 +1064,48 @@ private:
 /**
  * Tearoff class to implement nsITouchEventReceiver
  */
 class nsTouchEventReceiverTearoff : public nsITouchEventReceiver
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  NS_DECL_NSITOUCHEVENTRECEIVER
+  NS_FORWARD_NSITOUCHEVENTRECEIVER(mElement->)
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsTouchEventReceiverTearoff)
 
   nsTouchEventReceiverTearoff(nsGenericElement *aElement) : mElement(aElement)
   {
   }
 
 private:
   nsRefPtr<nsGenericElement> mElement;
 };
 
+/**
+ * Tearoff class to implement nsIInlineEventHandlers
+ */
+class nsInlineEventHandlersTearoff : public nsIInlineEventHandlers
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+
+  NS_FORWARD_NSIINLINEEVENTHANDLERS(mElement->)
+
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsInlineEventHandlersTearoff)
+
+  nsInlineEventHandlersTearoff(nsGenericElement *aElement) : mElement(aElement)
+  {
+  }
+
+private:
+  nsRefPtr<nsGenericElement> mElement;
+};
+
 #define NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE                               \
     rv = nsGenericElement::QueryInterface(aIID, aInstancePtr);                \
     if (NS_SUCCEEDED(rv))                                                     \
       return rv;                                                              \
                                                                               \
     NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
 
 #define NS_ELEMENT_INTERFACE_MAP_END                                          \
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -76,16 +76,17 @@
 #include "nsEventDispatcher.h"
 #include "nsDOMJSUtils.h"
 #include "nsDOMScriptObjectHolder.h"
 #include "nsDataHashtable.h"
 #include "nsCOMArray.h"
 #include "nsEventListenerService.h"
 #include "nsDOMEvent.h"
 #include "nsIContentSecurityPolicy.h"
+#include "nsJSEnvironment.h"
 
 using namespace mozilla::dom;
 
 #define EVENT_TYPE_EQUALS( ls, type, userType ) \
   (ls->mEventType == type && \
   (ls->mEventType != NS_USER_DEFINED_EVENT || ls->mTypeAtom == userType))
 
 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
@@ -161,17 +162,16 @@ void
 nsEventListenerManager::RemoveAllListeners()
 {
   mListeners.Clear();
 }
 
 void
 nsEventListenerManager::Shutdown()
 {
-  sAddListenerID = JSID_VOID;
   nsDOMEvent::Shutdown();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventListenerManager)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsEventListenerManager, Release)
 
@@ -372,44 +372,50 @@ nsEventListenerManager::FindJSEventListe
   }
   return nsnull;
 }
 
 nsresult
 nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext,
                                            void *aScopeObject,
                                            nsIAtom* aName,
-                                           PRBool aIsString,
-                                           PRBool aPermitUntrustedEvents)
+                                           JSObject *aHandler,
+                                           PRBool aPermitUntrustedEvents,
+                                           nsListenerStruct **aListenerStruct)
 {
   nsresult rv = NS_OK;
   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, mTarget, aName,
-                               getter_AddRefs(scriptListener));
+                               aHandler, getter_AddRefs(scriptListener));
     if (NS_SUCCEEDED(rv)) {
       AddEventListener(scriptListener, eventType, aName,
                        NS_EVENT_FLAG_BUBBLE | NS_PRIV_EVENT_FLAG_SCRIPT);
 
       ls = FindJSEventListener(eventType, aName);
     }
+  } else {
+    ls->GetJSListener()->SetHandler(aHandler);
   }
 
   if (NS_SUCCEEDED(rv) && ls) {
     // Set flag to indicate possible need for compilation later
-    ls->mHandlerIsString = aIsString;
-
+    ls->mHandlerIsString = !aHandler;
     if (aPermitUntrustedEvents) {
       ls->mFlags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
     }
+
+    *aListenerStruct = ls;
+  } else {
+    *aListenerStruct = nsnull;
   }
 
   return rv;
 }
 
 nsresult
 nsEventListenerManager::AddScriptEventListener(nsIAtom *aName,
                                                const nsAString& aBody,
@@ -511,311 +517,188 @@ nsEventListenerManager::AddScriptEventLi
     // but fall through and let the inevitable failure below handle it.
   }
 
   context = global->GetScriptContext(aLanguage);
   NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
 
   void *scope = global->GetScriptGlobal(aLanguage);
 
-  if (!aDeferCompilation) {
-    nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
-      do_QueryInterface(mTarget);
-
-    nsScriptObjectHolder handler(context);
-    PRBool done = PR_FALSE;
-
-    if (handlerOwner) {
-      rv = handlerOwner->GetCompiledEventHandler(aName, handler);
-      if (NS_SUCCEEDED(rv) && handler) {
-        rv = context->BindCompiledEventHandler(mTarget, scope, aName, handler);
-        if (NS_FAILED(rv))
-          return rv;
-        done = PR_TRUE;
-      }
-    }
-
-    if (!done) {
-      PRUint32 lineNo = 0;
-      nsCAutoString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
-      if (doc) {
-        nsIURI *uri = doc->GetDocumentURI();
-        if (uri) {
-          uri->GetSpec(url);
-          lineNo = 1;
-        }
-      }
+  nsListenerStruct *ls;
+  rv = SetJSEventListener(context, scope, aName, nsnull,
+                          aPermitUntrustedEvents, &ls);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-      if (handlerOwner) {
-        // Always let the handler owner compile the event handler, as
-        // it may want to use a special context or scope object.
-        rv = handlerOwner->CompileEventHandler(context, mTarget, aName,
-                                               aBody, url.get(), lineNo, handler);
-      }
-      else {
-        PRInt32 nameSpace = kNameSpaceID_Unknown;
-        if (node && node->IsNodeOfType(nsINode::eCONTENT)) {
-          nsIContent* content = static_cast<nsIContent*>(node.get());
-          nameSpace = content->GetNameSpaceID();
-        }
-        else if (doc) {
-          Element* root = doc->GetRootElement();
-          if (root)
-            nameSpace = root->GetNameSpaceID();
-        }
-        PRUint32 argCount;
-        const char **argNames;
-        nsContentUtils::GetEventArgNames(nameSpace, aName, &argCount,
-                                         &argNames);
-
-        nsCxPusher pusher;
-        if (!pusher.Push((JSContext*)context->GetNativeContext())) {
-          return NS_ERROR_FAILURE;
-        }
-
-        rv = context->CompileEventHandler(aName, argCount, argNames,
-                                          aBody,
-                                          url.get(), lineNo,
-                                          SCRIPTVERSION_DEFAULT, // for now?
-                                          handler);
-        if (rv == NS_ERROR_ILLEGAL_VALUE) {
-          NS_WARNING("Probably a syntax error in the event handler!");
-          return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
-        }
-        NS_ENSURE_SUCCESS(rv, rv);
-        // And bind it.
-        rv = context->BindCompiledEventHandler(mTarget, scope,
-                                               aName, handler);
-      }
-      if (NS_FAILED(rv)) return rv;
-    }
+  if (!aDeferCompilation) {
+    return CompileEventHandlerInternal(ls, PR_TRUE, &aBody);
   }
 
-  return SetJSEventListener(context, scope, aName, aDeferCompilation,
-                            aPermitUntrustedEvents);
+  return NS_OK;
 }
 
 void
 nsEventListenerManager::RemoveScriptEventListener(nsIAtom* aName)
 {
   PRUint32 eventType = nsContentUtils::GetEventId(aName);
   nsListenerStruct* ls = FindJSEventListener(eventType, aName);
 
   if (ls) {
     mListeners.RemoveElementAt(PRUint32(ls - &mListeners.ElementAt(0)));
     mNoListenerForEvent = NS_EVENT_TYPE_NULL;
     mNoListenerForEventAtom = nsnull;
   }
 }
 
-jsid
-nsEventListenerManager::sAddListenerID = JSID_VOID;
-
 nsresult
-nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext,
-                                                    void *aScope,
-                                                    nsIAtom *aName)
+nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
+                                                    PRBool aNeedsCxPush,
+                                                    const nsAString* aBody)
 {
-  // Check that we have access to set an event listener. Prevents
-  // snooping attacks across domains by setting onkeypress handlers,
-  // for instance.
-  // You'd think it'd work just to get the JSContext from aContext,
-  // but that's actually the JSContext whose private object parents
-  // the object in mTarget.
-  nsresult rv;
-  nsCOMPtr<nsIJSContextStack> stack =
-    do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
-  if (NS_FAILED(rv))
-    return rv;
-  JSContext *cx;
-  if (NS_FAILED(rv = stack->Peek(&cx)))
-    return rv;
-
-  if (cx) {
-    if (sAddListenerID == JSID_VOID) {
-      JSAutoRequest ar(cx);
-      sAddListenerID =
-        INTERNED_STRING_TO_JSID(cx, ::JS_InternString(cx, "addEventListener"));
-    }
+  NS_PRECONDITION(aListenerStruct->GetJSListener(),
+                  "Why do we not have a JS listener?");
+  NS_PRECONDITION(aListenerStruct->mHandlerIsString,
+                  "Why are we compiling a non-string JS listener?");
 
-    if (aContext->GetScriptTypeID() == nsIProgrammingLanguage::JAVASCRIPT) {
-        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-        jsval v;
-        rv = nsContentUtils::WrapNative(cx, (JSObject *)aScope, mTarget, &v,
-                                        getter_AddRefs(holder));
-        NS_ENSURE_SUCCESS(rv, rv);
-      
-        rv = nsContentUtils::GetSecurityManager()->
-          CheckPropertyAccess(cx, JSVAL_TO_OBJECT(v),
-                              "EventTarget",
-                              sAddListenerID,
-                              nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
-        if (NS_FAILED(rv)) {
-          // XXX set pending exception on the native call context?
-          return rv;
-        }
-    } else {
-        NS_WARNING("Skipping CheckPropertyAccess for non JS language");
-    }
-        
-  }
-
-  // Untrusted events are always permitted for non-chrome script
-  // handlers.
-  return SetJSEventListener(aContext, aScope, aName, PR_FALSE,
-                            !nsContentUtils::IsCallerChrome());
-}
-
-nsresult
-nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext, 
-                                                   void *aScope,
-                                                   nsIAtom *aName,
-                                                   PRBool *aDidCompile)
-{
-  nsresult rv = NS_OK;
-  *aDidCompile = PR_FALSE;
-  PRUint32 eventType = nsContentUtils::GetEventId(aName);
-  nsListenerStruct* ls = FindJSEventListener(eventType, aName);
-
-  if (!ls) {
-    //nothing to compile
-    return NS_OK;
-  }
-
-  if (ls->mHandlerIsString) {
-    rv = CompileEventHandlerInternal(aContext, aScope, mTarget, aName,
-                                     ls, /*XXX fixme*/nsnull, PR_TRUE);
-  }
-
-  // Set *aDidCompile to true even if we didn't really compile
-  // anything right now, if we get here it means that this event
-  // handler has been compiled at some point, that's good enough for
-  // us.
-
-  *aDidCompile = PR_TRUE;
-
-  return rv;
-}
-
-nsresult
-nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
-                                                    void *aScope,
-                                                    nsISupports *aObject,
-                                                    nsIAtom *aName,
-                                                    nsListenerStruct *aListenerStruct,
-                                                    nsISupports* aCurrentTarget,
-                                                    PRBool aNeedsCxPush)
-{
   nsresult result = NS_OK;
 
+  nsIJSEventListener *listener = aListenerStruct->GetJSListener();
+  NS_ASSERTION(!listener->GetHandler(), "What is there to compile?");
+
+  nsIScriptContext *context = listener->GetEventContext();
   nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
-    do_QueryInterface(aObject);
-  nsScriptObjectHolder handler(aContext);
+    do_QueryInterface(mTarget);
+  nsScriptObjectHolder handler(context);
 
   if (handlerOwner) {
-    result = handlerOwner->GetCompiledEventHandler(aName,
+    result = handlerOwner->GetCompiledEventHandler(aListenerStruct->mTypeAtom,
                                                    handler);
     if (NS_SUCCEEDED(result) && handler) {
-      // XXXmarkh - why do we bind here, but not after compilation below?
-      result = aContext->BindCompiledEventHandler(aObject, aScope, aName, handler);
       aListenerStruct->mHandlerIsString = PR_FALSE;
+    } else {
+      // Make sure there's nothing in the holder in the failure case
+      handler.set(nsnull);
     }
   }
 
   if (aListenerStruct->mHandlerIsString) {
-    // This should never happen for anything but content
-    // XXX I don't like that we have to reference content
-    // from here. The alternative is to store the event handler
-    // string on the JS object itself.
-    nsCOMPtr<nsIContent> content = do_QueryInterface(aObject);
-    NS_ASSERTION(content, "only content should have event handler attributes");
-    if (content) {
-      nsAutoString handlerBody;
-      nsIAtom* attrName = aName;
-      if (aName == nsGkAtoms::onSVGLoad)
+    // OK, we didn't find an existing compiled event handler.  Flag us
+    // as not a string so we don't keep trying to compile strings
+    // which can't be compiled
+    aListenerStruct->mHandlerIsString = PR_FALSE;
+
+    // mTarget may not be an nsIContent 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 nsIJSEventListener itself, and that still doesn't address
+    // the arg names issue.
+    nsCOMPtr<nsIContent> content = do_QueryInterface(mTarget);
+    nsAutoString handlerBody;
+    const nsAString* body = aBody;
+    if (content && !aBody) {
+      nsIAtom* attrName = aListenerStruct->mTypeAtom;
+      if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGLoad)
         attrName = nsGkAtoms::onload;
-      else if (aName == nsGkAtoms::onSVGUnload)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGUnload)
         attrName = nsGkAtoms::onunload;
-      else if (aName == nsGkAtoms::onSVGAbort)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGAbort)
         attrName = nsGkAtoms::onabort;
-      else if (aName == nsGkAtoms::onSVGError)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGError)
         attrName = nsGkAtoms::onerror;
-      else if (aName == nsGkAtoms::onSVGResize)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGResize)
         attrName = nsGkAtoms::onresize;
-      else if (aName == nsGkAtoms::onSVGScroll)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGScroll)
         attrName = nsGkAtoms::onscroll;
-      else if (aName == nsGkAtoms::onSVGZoom)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGZoom)
         attrName = nsGkAtoms::onzoom;
 #ifdef MOZ_SMIL
-      else if (aName == nsGkAtoms::onbeginEvent)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onbeginEvent)
         attrName = nsGkAtoms::onbegin;
-      else if (aName == nsGkAtoms::onrepeatEvent)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onrepeatEvent)
         attrName = nsGkAtoms::onrepeat;
-      else if (aName == nsGkAtoms::onendEvent)
+      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onendEvent)
         attrName = nsGkAtoms::onend;
 #endif // MOZ_SMIL
 
       content->GetAttr(kNameSpaceID_None, attrName, handlerBody);
+      body = &handlerBody;
+    }
 
-      PRUint32 lineNo = 0;
-      nsCAutoString url (NS_LITERAL_CSTRING("javascript:alert('TODO: FIXME')"));
-      nsIDocument* doc = nsnull;
-      nsCOMPtr<nsINode> node = do_QueryInterface(aCurrentTarget);
-      if (node) {
-        doc = node->GetOwnerDoc();
+    PRUint32 lineNo = 0;
+    nsCAutoString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
+    nsCOMPtr<nsIDocument> doc;
+    if (content) {
+      doc = content->GetOwnerDoc();
+    } else {
+      nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
+      if (win) {
+        doc = do_QueryInterface(win->GetExtantDocument());
       }
-      if (doc) {
-        nsIURI *uri = doc->GetDocumentURI();
-        if (uri) {
-          uri->GetSpec(url);
-          lineNo = 1;
-        }
+    }
+
+    if (doc) {
+      nsIURI *uri = doc->GetDocumentURI();
+      if (uri) {
+        uri->GetSpec(url);
+        lineNo = 1;
       }
+    }
 
-      nsCxPusher pusher;
-      if (aNeedsCxPush &&
-          !pusher.Push((JSContext*)aContext->GetNativeContext())) {
-        return NS_ERROR_FAILURE;
-      }
+    nsCxPusher pusher;
+    if (aNeedsCxPush &&
+        !pusher.Push((JSContext*)context->GetNativeContext())) {
+      return NS_ERROR_FAILURE;
+    }
 
 
-      if (handlerOwner) {
-        // Always let the handler owner compile the event
-        // handler, as it may want to use a special
-        // context or scope object.
-        result = handlerOwner->CompileEventHandler(aContext, aObject, aName,
-                                                   handlerBody,
-                                                   url.get(), lineNo,
-                                                   handler);
-      }
-      else {
-        PRUint32 argCount;
-        const char **argNames;
-        nsContentUtils::GetEventArgNames(content->GetNameSpaceID(), aName,
-                                         &argCount, &argNames);
+    if (handlerOwner) {
+      // Always let the handler owner compile the event
+      // handler, as it may want to use a special
+      // context or scope object.
+      result = handlerOwner->CompileEventHandler(context,
+                                                 aListenerStruct->mTypeAtom,
+                                                 *body,
+                                                 url.get(), lineNo,
+                                                 handler);
+    } else {
+      PRUint32 argCount;
+      const char **argNames;
+      // If no content, then just use kNameSpaceID_None for the
+      // namespace ID.  In practice, it doesn't matter since SVG is
+      // the only thing with weird arg names and SVG doesn't map event
+      // listeners to the window.
+      nsContentUtils::GetEventArgNames(content ?
+                                         content->GetNameSpaceID() :
+                                         kNameSpaceID_None,
+                                       aListenerStruct->mTypeAtom,
+                                       &argCount, &argNames);
 
-        result = aContext->CompileEventHandler(aName,
-                                               argCount, argNames,
-                                               handlerBody,
-                                               url.get(), lineNo,
-                                               SCRIPTVERSION_DEFAULT, // for now?
-                                               handler);
-        NS_ENSURE_SUCCESS(result, result);
-        // And bind it.
-        result = aContext->BindCompiledEventHandler(aObject, aScope,
-                                                    aName, handler);
-        NS_ENSURE_SUCCESS(result, result);
+      result = context->CompileEventHandler(aListenerStruct->mTypeAtom,
+                                            argCount, argNames,
+                                            *body,
+                                            url.get(), lineNo,
+                                            SCRIPTVERSION_DEFAULT, // for now?
+                                            handler);
+      if (result == NS_ERROR_ILLEGAL_VALUE) {
+        NS_WARNING("Probably a syntax error in the event handler!");
+        return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
       }
-
-      if (NS_SUCCEEDED(result)) {
-        aListenerStruct->mHandlerIsString = PR_FALSE;
-      }
+      NS_ENSURE_SUCCESS(result, result);
     }
   }
 
+  if (handler) {
+    // Bind it
+    nsScriptObjectHolder boundHandler(context);
+    context->BindCompiledEventHandler(mTarget, listener->GetEventScope(),
+                                      handler, boundHandler);
+    listener->SetHandler(boundHandler);
+  }    
+
   return result;
 }
 
 nsresult
 nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
                                            nsIDOMEventListener* aListener,
                                            nsIDOMEvent* aDOMEvent,
                                            nsIDOMEventTarget* aCurrentTarget,
@@ -823,44 +706,21 @@ nsEventListenerManager::HandleEventSubTy
                                            nsCxPusher* aPusher)
 {
   nsresult result = NS_OK;
 
   // If this is a script handler and we haven't yet
   // compiled the event handler itself
   if ((aListenerStruct->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) &&
       aListenerStruct->mHandlerIsString) {
-    nsCOMPtr<nsIJSEventListener> jslistener = do_QueryInterface(aListener);
-    if (jslistener) {
-      // We probably have the atom already.
-      nsCOMPtr<nsIAtom> atom = aListenerStruct->mTypeAtom;
-      if (!atom) {
-        nsAutoString eventString;
-        if (NS_SUCCEEDED(aDOMEvent->GetType(eventString))) {
-          atom = do_GetAtom(NS_LITERAL_STRING("on") + eventString);
-        }
-      }
-
-      if (atom) {
-#ifdef DEBUG
-        nsAutoString type;
-        aDOMEvent->GetType(type);
-        nsCOMPtr<nsIAtom> eventAtom = do_GetAtom(NS_LITERAL_STRING("on") + type);
-        NS_ASSERTION(eventAtom == atom, "Something wrong with event atoms!");
-#endif
-        result = CompileEventHandlerInternal(jslistener->GetEventContext(),
-                                             jslistener->GetEventScope(),
-                                             jslistener->GetEventTarget(),
-                                             atom, aListenerStruct,
-                                             aCurrentTarget,
-                                             !jslistener->GetEventContext() ||
-                                             jslistener->GetEventContext() !=
-                                             aPusher->GetCurrentScriptContext());
-      }
-    }
+    nsIJSEventListener *jslistener = aListenerStruct->GetJSListener();
+    result = CompileEventHandlerInternal(aListenerStruct,
+                                         jslistener->GetEventContext() !=
+                                           aPusher->GetCurrentScriptContext(),
+                                         nsnull);
   }
 
   if (NS_SUCCEEDED(result)) {
     // nsIDOMEvent::currentTarget is set in nsEventDispatcher.
     result = aListener->HandleEvent(aDOMEvent);
   }
 
   return result;
@@ -1035,28 +895,20 @@ nsEventListenerManager::GetListenerInfo(
   aList->Clear();
   PRUint32 count = mListeners.Length();
   for (PRUint32 i = 0; i < count; ++i) {
     const nsListenerStruct& ls = mListeners.ElementAt(i);
     PRBool capturing = !!(ls.mFlags & NS_EVENT_FLAG_CAPTURE);
     PRBool systemGroup = !!(ls.mFlags & NS_EVENT_FLAG_SYSTEM_EVENT);
     PRBool allowsUntrusted = !!(ls.mFlags & NS_PRIV_EVENT_UNTRUSTED_PERMITTED);
     // If this is a script handler and we haven't yet
-    // compiled the event handler itself
+    // compiled the event handler itself go ahead and compile it
     if ((ls.mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) && ls.mHandlerIsString) {
-      nsCOMPtr<nsIJSEventListener> jslistener = do_QueryInterface(ls.mListener);
-      if (jslistener) {
-        CompileEventHandlerInternal(jslistener->GetEventContext(),
-                                    jslistener->GetEventScope(),
-                                    jslistener->GetEventTarget(),
-                                    ls.mTypeAtom,
-                                    const_cast<nsListenerStruct*>(&ls),
-                                    mTarget,
-                                    PR_TRUE);
-      }
+      CompileEventHandlerInternal(const_cast<nsListenerStruct*>(&ls),
+                                  PR_TRUE, nsnull);
     }
     const nsDependentSubstring& eventType =
       Substring(nsDependentAtomString(ls.mTypeAtom), 2);
     nsRefPtr<nsEventListenerInfo> info =
       new nsEventListenerInfo(eventType, ls.mListener, capturing,
                               allowsUntrusted, systemGroup);
     NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY);
     aList->AppendObject(info);
@@ -1072,8 +924,57 @@ nsEventListenerManager::HasUnloadListene
     nsListenerStruct* ls = &mListeners.ElementAt(i);
     if (ls->mEventType == NS_PAGE_UNLOAD ||
         ls->mEventType == NS_BEFORE_PAGE_UNLOAD) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
+
+nsresult
+nsEventListenerManager::SetJSEventListenerToJsval(nsIAtom *aEventName,
+                                                  JSContext *cx,
+                                                  JSObject* aScope,
+                                                  const jsval & v)
+{
+  JSObject *handler;
+  if (JSVAL_IS_PRIMITIVE(v) ||
+      !JS_ObjectIsCallable(cx, handler = JSVAL_TO_OBJECT(v))) {
+    RemoveScriptEventListener(aEventName);
+    return NS_OK;
+  }
+
+  nsIScriptContext *context = nsJSUtils::GetStaticScriptContext(cx, aScope);
+  JSObject *scope = ::JS_GetGlobalForObject(cx, aScope);
+  // Untrusted events are always permitted for non-chrome script
+  // handlers.
+  nsListenerStruct *ignored;
+  return SetJSEventListener(context, scope, aEventName, handler,
+                            !nsContentUtils::IsCallerChrome(), &ignored);
+}
+
+void
+nsEventListenerManager::GetJSEventListener(nsIAtom *aEventName, jsval *vp)
+{
+  PRUint32 eventType = nsContentUtils::GetEventId(aEventName);
+  nsListenerStruct* ls = FindJSEventListener(eventType, aEventName);
+
+  *vp = JSVAL_NULL;
+
+  if (!ls) {
+    return;
+  }
+
+  nsIJSEventListener *listener = ls->GetJSListener();
+  if (listener->GetEventContext()->GetScriptTypeID() !=
+        nsIProgrammingLanguage::JAVASCRIPT) {
+    // Not JS, so no point doing anything with it.
+    return;
+  }
+    
+  if (ls->mHandlerIsString) {
+    CompileEventHandlerInternal(ls, PR_TRUE, nsnull);
+  }
+
+  *vp = OBJECT_TO_JSVAL(static_cast<JSObject*>(listener->GetHandler()));
+}
+
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -45,33 +45,40 @@
 #include "nsIDOMEventListener.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsHashtable.h"
 #include "nsIScriptContext.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsTObserverArray.h"
 #include "nsGUIEvent.h"
+#include "nsIJSEventListener.h"
 
 class nsIDOMEvent;
 class nsIAtom;
 class nsIWidget;
 struct nsPoint;
 struct EventTypeData;
 class nsEventTargetChainItem;
 class nsPIDOMWindow;
 class nsCxPusher;
 class nsIEventListenerInfo;
+class nsIDocument;
 
 typedef struct {
   nsRefPtr<nsIDOMEventListener> mListener;
   PRUint32                      mEventType;
   nsCOMPtr<nsIAtom>             mTypeAtom;
   PRUint16                      mFlags;
-  PRBool                        mHandlerIsString;
+  PRPackedBool                  mHandlerIsString;
+
+  nsIJSEventListener* GetJSListener() const {
+    return (mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) ?
+      static_cast<nsIJSEventListener *>(mListener.get()) : nsnull;
+  }
 } nsListenerStruct;
 
 /*
  * Event listener manager
  */
 
 class nsEventListenerManager
 {
@@ -97,28 +104,34 @@ public:
   * @param an event listener
   */
   void AddEventListenerByType(nsIDOMEventListener *aListener,
                               const nsAString& type,
                               PRInt32 aFlags);
   void RemoveEventListenerByType(nsIDOMEventListener *aListener,
                                  const nsAString& type,
                                  PRInt32 aFlags);
+
+  /**
+   * Sets the current "inline" event listener for aName to be a
+   * function compiled from aFunc if !aDeferCompilation.  If
+   * aDeferCompilation, then we assume that we can get the string from
+   * mTarget later and compile lazily.
+   */
+  // XXXbz does that play correctly with nodes being adopted across
+  // documents?  Need to double-check the spec here.
   nsresult AddScriptEventListener(nsIAtom *aName,
                                   const nsAString& aFunc,
                                   PRUint32 aLanguage,
                                   PRBool aDeferCompilation,
                                   PRBool aPermitUntrustedEvents);
-  nsresult RegisterScriptEventListener(nsIScriptContext *aContext,
-                                       void *aScopeObject,
-                                       nsIAtom* aName);
+  /**
+   * Remove the current "inline" event listener for aName.
+   */
   void RemoveScriptEventListener(nsIAtom *aName);
-  nsresult CompileScriptEventListener(nsIScriptContext *aContext,
-                                      void *aScopeObject,
-                                      nsIAtom* aName, PRBool *aDidCompile);
 
   void HandleEvent(nsPresContext* aPresContext,
                    nsEvent* aEvent, 
                    nsIDOMEvent** aDOMEvent,
                    nsIDOMEventTarget* aCurrentTarget,
                    PRUint32 aFlags,
                    nsEventStatus* aEventStatus,
                    nsCxPusher* aPusher)
@@ -150,28 +163,56 @@ public:
   void HandleEventInternal(nsPresContext* aPresContext,
                            nsEvent* aEvent, 
                            nsIDOMEvent** aDOMEvent,
                            nsIDOMEventTarget* aCurrentTarget,
                            PRUint32 aFlags,
                            nsEventStatus* aEventStatus,
                            nsCxPusher* aPusher);
 
+  /**
+   * Tells the event listener manager that its target (which owns it) is
+   * no longer using it (and could go away).
+   */
   void Disconnect();
 
+  /**
+   * Allows us to quickly determine if we have mutation listeners registered.
+   */
   PRBool HasMutationListeners();
 
+  /**
+   * Allows us to quickly determine whether we have unload or beforeunload
+   * listeners registered.
+   */
   PRBool HasUnloadListeners();
 
+  /**
+   * Returns the mutation bits depending on which mutation listeners are
+   * registered to this listener manager.
+   * @note If a listener is an nsIDOMMutationListener, all possible mutation
+   *       event bits are returned. All bits are also returned if one of the
+   *       event listeners is registered to handle DOMSubtreeModified events.
+   */
   PRUint32 MutationListenerBits();
 
+  /**
+   * Returns PR_TRUE if there is at least one event listener for aEventName.
+   */
   PRBool HasListenersFor(const nsAString& aEventName);
 
+  /**
+   * Returns PR_TRUE if there is at least one event listener.
+   */
   PRBool HasListeners();
 
+  /**
+   * Sets aList to the list of nsIEventListenerInfo objects representing the
+   * listeners managed by this listener manager.
+   */
   nsresult GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList);
 
   PRUint32 GetIdentifierForEvent(nsIAtom* aEvent);
 
   static void Shutdown();
 
   /**
    * Returns PR_TRUE if there may be a paint event listener registered,
@@ -193,28 +234,59 @@ public:
 
 protected:
   nsresult HandleEventSubType(nsListenerStruct* aListenerStruct,
                               nsIDOMEventListener* aListener,
                               nsIDOMEvent* aDOMEvent,
                               nsIDOMEventTarget* aCurrentTarget,
                               PRUint32 aPhaseFlags,
                               nsCxPusher* aPusher);
-  nsresult CompileEventHandlerInternal(nsIScriptContext *aContext,
-                                       void *aScopeObject,
-                                       nsISupports *aObject,
-                                       nsIAtom *aName,
-                                       nsListenerStruct *aListenerStruct,
-                                       nsISupports* aCurrentTarget,
-                                       PRBool aNeedsCxPush);
+
+  /**
+   * Compile the "inline" event listener for aListenerStruct.  The
+   * body of the listener can be provided in aBody; if this is null we
+   * will look for it on mTarget.
+   */
+  nsresult CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
+                                       PRBool aNeedsCxPush,
+                                       const nsAString* aBody);
+
+  /**
+   * Find the nsListenerStruct for the "inline" event listener for aTypeAtom.
+   */
   nsListenerStruct* FindJSEventListener(PRUint32 aEventType, nsIAtom* aTypeAtom);
+
+  /**
+   * Set the "inline" event listener for aName to aHandler.  aHandler
+   * may be null to indicate that we should lazily get and compile the
+   * string for this listener.  The nsListenerStruct that results, if
+   * any, is returned in aListenerStruct.
+   */
   nsresult SetJSEventListener(nsIScriptContext *aContext,
                               void *aScopeGlobal,
-                              nsIAtom* aName, PRBool aIsString,
-                              PRBool aPermitUntrustedEvents);
+                              nsIAtom* aName,
+                              JSObject *aHandler,
+                              PRBool aPermitUntrustedEvents,
+                              nsListenerStruct **aListenerStruct);
+
+public:
+  /**
+   * Set the "inline" event listener for aEventName to |v|.  This
+   * might actually remove the event listener, depending on the value
+   * of |v|.
+   */
+  nsresult SetJSEventListenerToJsval(nsIAtom *aEventName, JSContext *cx,
+                                     JSObject *aScope, const jsval &v);
+  /**
+   * Get the value of the "inline" event listener for aEventName.
+   * This may cause lazy compilation if the listener is uncompiled.
+   */
+  void GetJSEventListener(nsIAtom *aEventName, jsval *vp);
+
+protected:
   void AddEventListener(nsIDOMEventListener *aListener, 
                         PRUint32 aType,
                         nsIAtom* aTypeAtom,
                         PRInt32 aFlags);
   void RemoveEventListener(nsIDOMEventListener *aListener,
                            PRUint32 aType,
                            nsIAtom* aUserType,
                            PRInt32 aFlags);
--- a/content/events/src/nsEventListenerService.cpp
+++ b/content/events/src/nsEventListenerService.cpp
@@ -107,18 +107,19 @@ nsEventListenerInfo::GetJSVal(jsval* aJS
     JSObject* object = nsnull;
     wrappedJS->GetJSObject(&object);
     *aJSVal = OBJECT_TO_JSVAL(object);
     return PR_TRUE;
   }
 
   nsCOMPtr<nsIJSEventListener> jsl = do_QueryInterface(mListener);
   if (jsl) {
-    nsresult rv = jsl->GetJSVal(mType, aJSVal);
-    if (NS_SUCCEEDED(rv)) {
+    void *handler = jsl->GetHandler();
+    if (handler) {
+      *aJSVal = OBJECT_TO_JSVAL(static_cast<JSObject*>(handler));
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 NS_IMETHODIMP
 nsEventListenerInfo::ToSource(nsAString& aResult)
--- a/content/events/test/test_bug379120.html
+++ b/content/events/test/test_bug379120.html
@@ -42,15 +42,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     var processor = new XSLTProcessor();
 
     var targetDocument;
     processor.importStylesheet (stylesheet);
     var transformedDocument = processor.transformToDocument (originalDoc);
     is(transformedDocument.documentElement.getAttribute("onload"),
        "var i = 1");
-    ok(transformedDocument.documentElement.onload === undefined,
-       "Shouldn't have onload handler");
+    ok(transformedDocument.documentElement.onload === null,
+       "Shouldn't have onload handler",
+       "got " + repr(transformedDocument.documentElement.onload) +
+       ", expected null");;
 </script>
 </pre>
 </body>
 </html>
 
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1240,17 +1240,18 @@ nsGenericHTMLElement::GetEventListenerMa
     // normal.
     // XXXbz sXBL/XBL2 issue: should we instead use GetCurrentDoc() here,
     // override BindToTree for those classes and munge event listeners there?
     nsIDocument *document = GetOwnerDoc();
 
     // FIXME (https://bugzilla.mozilla.org/show_bug.cgi?id=431767)
     // nsDocument::GetInnerWindow can return an outer window in some cases,
     // we don't want to stick an event listener on an outer window, so
-    // bail if it does.
+    // bail if it does.  See similar code in nsHTMLBodyElement and
+    // nsHTMLFramesetElement
     *aDefer = PR_FALSE;
     if (document &&
         (win = document->GetInnerWindow()) && win->IsInnerWindow()) {
       nsCOMPtr<nsIDOMEventTarget> piTarget(do_QueryInterface(win));
 
       return piTarget->GetListenerManager(PR_TRUE);
     }
 
--- a/content/html/content/src/nsHTMLBodyElement.cpp
+++ b/content/html/content/src/nsHTMLBodyElement.cpp
@@ -52,16 +52,17 @@
 #include "nsIMarkupDocumentViewer.h"
 #include "nsMappedAttributes.h"
 #include "nsRuleData.h"
 #include "nsIFrame.h"
 #include "nsIDocShell.h"
 #include "nsIEditorDocShell.h"
 #include "nsCOMPtr.h"
 #include "nsRuleWalker.h"
+#include "jsapi.h"
 
 //----------------------------------------------------------------------
 
 class nsHTMLBodyElement;
 
 class BodyRule: public nsIStyleRule {
 public:
   BodyRule(nsHTMLBodyElement* aPart);
@@ -100,16 +101,26 @@ public:
   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLBodyElement
   NS_DECL_NSIDOMHTMLBODYELEMENT
 
+  // Event listener stuff; we need to declare only the ones we need to
+  // forward to window that don't come from nsIDOMHTMLBodyElement.
+#define EVENT(name_, id_, type_, struct_) /* nothing; handled by the shim */
+#define FORWARDED_EVENT(name_, id_, type_, struct_)               \
+    NS_IMETHOD GetOn##name_(JSContext *cx, jsval *vp);            \
+    NS_IMETHOD SetOn##name_(JSContext *cx, const jsval &v);
+#include "nsEventNameList.h"
+#undef FORWARDED_EVENT
+#undef EVENT
+
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
                               PRBool aNullParent = PR_TRUE);
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
@@ -483,8 +494,59 @@ nsHTMLBodyElement::GetAssociatedEditor()
   nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(container);
   if (!editorDocShell) {
     return nsnull;
   }
 
   editorDocShell->GetEditor(&editor);
   return editor;
 }
+
+// Event listener stuff
+// FIXME (https://bugzilla.mozilla.org/show_bug.cgi?id=431767)
+// nsDocument::GetInnerWindow can return an outer window in some
+// cases.  We don't want to stick an event listener on an outer
+// window, so bail if it does.  See also similar code in
+// nsGenericHTMLElement::GetEventListenerManagerForAttr.
+#define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */
+#define FORWARDED_EVENT(name_, id_, type_, struct_)                 \
+  NS_IMETHODIMP nsHTMLBodyElement::GetOn##name_(JSContext *cx,      \
+                                           jsval *vp) {             \
+    /* XXXbz note to self: add tests for this! */                   \
+    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();           \
+    if (win && win->IsInnerWindow()) {                              \
+      nsCOMPtr<nsIInlineEventHandlers> ev = do_QueryInterface(win); \
+      return ev->GetOn##name_(cx, vp);                              \
+    }                                                               \
+    *vp = JSVAL_NULL;                                               \
+    return NS_OK;                                                   \
+  }                                                                 \
+  NS_IMETHODIMP nsHTMLBodyElement::SetOn##name_(JSContext *cx,      \
+                                           const jsval &v) {        \
+    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();           \
+    if (win && win->IsInnerWindow()) {                              \
+      nsCOMPtr<nsIInlineEventHandlers> ev = do_QueryInterface(win); \
+      return ev->SetOn##name_(cx, v);                               \
+    }                                                               \
+    return NS_OK;                                                   \
+  }
+#define WINDOW_EVENT(name_, id_, type_, struct_)                  \
+  NS_IMETHODIMP nsHTMLBodyElement::GetOn##name_(JSContext *cx,    \
+                                                jsval *vp) {      \
+    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();         \
+    if (win && win->IsInnerWindow()) {                            \
+      return win->GetOn##name_(cx, vp);                           \
+    }                                                             \
+    *vp = JSVAL_NULL;                                             \
+    return NS_OK;                                                 \
+  }                                                               \
+  NS_IMETHODIMP nsHTMLBodyElement::SetOn##name_(JSContext *cx,    \
+                                                const jsval &v) { \
+    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();         \
+    if (win && win->IsInnerWindow()) {                            \
+      return win->SetOn##name_(cx, v);                            \
+    }                                                             \
+    return NS_OK;                                                 \
+  }
+#include "nsEventNameList.h"
+#undef WINDOW_EVENT
+#undef FORWARDED_EVENT
+#undef EVENT
--- a/content/html/content/src/nsHTMLFrameSetElement.cpp
+++ b/content/html/content/src/nsHTMLFrameSetElement.cpp
@@ -31,16 +31,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHTMLFrameSetElement.h"
+#include "jsapi.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(FrameSet)
 
 
 nsHTMLFrameSetElement::nsHTMLFrameSetElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo), mNumRows(0), mNumCols(0),
     mCurrentRowColHint(NS_STYLE_HINT_REFLOW)
 {
@@ -342,8 +343,60 @@ nsHTMLFrameSetElement::ParseRowCol(const
   }
 
   aNumSpecs = count;
   // Transfer ownership to caller here
   *aSpecs = specs;
   
   return NS_OK;
 }
+
+// Event listener stuff
+// FIXME (https://bugzilla.mozilla.org/show_bug.cgi?id=431767)
+// nsDocument::GetInnerWindow can return an outer window in some
+// cases.  We don't want to stick an event listener on an outer
+// window, so bail if it does.  See also similar code in
+// nsGenericHTMLElement::GetEventListenerManagerForAttr.
+#define EVENT(name_, id_, type_, struct_) /* nothing; handled by the shim */
+#define FORWARDED_EVENT(name_, id_, type_, struct_)                   \
+  NS_IMETHODIMP nsHTMLFrameSetElement::GetOn##name_(JSContext *cx,    \
+                                               jsval *vp) {           \
+    /* XXXbz note to self: add tests for this! */                     \
+    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();             \
+    if (win && win->IsInnerWindow()) {                                \
+      nsCOMPtr<nsIInlineEventHandlers> ev = do_QueryInterface(win);   \
+      return ev->GetOn##name_(cx, vp);                                \
+    }                                                                 \
+    *vp = JSVAL_NULL;                                                 \
+    return NS_OK;                                                     \
+  }                                                                   \
+  NS_IMETHODIMP nsHTMLFrameSetElement::SetOn##name_(JSContext *cx,    \
+                                               const jsval &v) {      \
+    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();             \
+    if (win && win->IsInnerWindow()) {                                \
+      nsCOMPtr<nsIInlineEventHandlers> ev = do_QueryInterface(win);   \
+      return ev->SetOn##name_(cx, v);                                 \
+    }                                                                 \
+    return NS_OK;                                                     \
+  }
+#define WINDOW_EVENT(name_, id_, type_, struct_)                      \
+  NS_IMETHODIMP nsHTMLFrameSetElement::GetOn##name_(JSContext *cx,    \
+                                                    jsval *vp) {      \
+    /* XXXbz note to self: add tests for this! */                     \
+    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();             \
+    if (win && win->IsInnerWindow()) {                                \
+      return win->GetOn##name_(cx, vp);                               \
+    }                                                                 \
+    *vp = JSVAL_NULL;                                                 \
+    return NS_OK;                                                     \
+  }                                                                   \
+  NS_IMETHODIMP nsHTMLFrameSetElement::SetOn##name_(JSContext *cx,    \
+                                                    const jsval &v) { \
+    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();             \
+    if (win && win->IsInnerWindow()) {                                \
+      return win->SetOn##name_(cx, v);                                \
+    }                                                                 \
+    return NS_OK;                                                     \
+  }
+#include "nsEventNameList.h"
+#undef WINDOW_EVENT
+#undef FORWARDED_EVENT
+#undef EVENT
--- a/content/html/content/src/nsHTMLFrameSetElement.h
+++ b/content/html/content/src/nsHTMLFrameSetElement.h
@@ -69,16 +69,18 @@ struct nsFramesetSpec {
 };
 
 /**
  * The maximum number of entries allowed in the frame set element row
  * or column spec.
  */
 #define NS_MAX_FRAMESET_SPEC_COUNT 16000
 
+//----------------------------------------------------------------------
+
 class nsHTMLFrameSetElement : public nsGenericHTMLElement,
                               public nsIDOMHTMLFrameSetElement
 {
 public:
   nsHTMLFrameSetElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLFrameSetElement();
 
   // nsISupports
@@ -91,16 +93,26 @@ public:
   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLFrameSetElement
   NS_DECL_NSIDOMHTMLFRAMESETELEMENT
 
+  // Event listener stuff; we need to declare only the ones we need to
+  // forward to window that don't come from nsIDOMHTMLFrameSetElement.
+#define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */
+#define FORWARDED_EVENT(name_, id_, type_, struct_)                     \
+    NS_IMETHOD GetOn##name_(JSContext *cx, jsval *vp);            \
+    NS_IMETHOD SetOn##name_(JSContext *cx, const jsval &v);
+#include "nsEventNameList.h"
+#undef FORWARDED_EVENT
+#undef EVENT
+
   // These override the SetAttr methods in nsGenericHTMLElement (need
   // both here to silence compiler warnings).
   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, PRBool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -31,17 +31,18 @@ function HTML_TAG(aTagName, aImplClass) 
   allTags.push(aTagName);
   classInfos[aTagName] = aImplClass;
   interfaces[aTagName] =
     [ "nsIDOMNSElement",
       "nsIDOMEventTarget",
       "nsIDOMNSHTMLElement",
       "nsIDOMElementCSSInlineStyle",
       "nsIDOMNodeSelector",
-      "nsITouchEventReceiver" ];
+      "nsITouchEventReceiver",
+      "nsIInlineEventHandlers" ];
 
   // Some interfaces don't appear in classinfo because other interfaces that
   // inherit from them do.
   interfacesNonClassinfo[aTagName] =
     [ "nsIDOMNode",
       "nsIDOMElement",
       "nsISupportsWeakReference" ];
 
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -313,27 +313,29 @@ nsXBLPrototypeHandler::ExecuteHandler(ns
     scriptTarget = boundGlobal;
   } else {
     scriptTarget = aTarget;
   }
 
   rv = EnsureEventHandler(boundGlobal, boundContext, onEventAtom, handler);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Temporarily bind it to the bound element
+  // Bind it to the bound element
   void *scope = boundGlobal->GetScriptGlobal(stID);
+  nsScriptObjectHolder boundHandler(boundContext);
   rv = boundContext->BindCompiledEventHandler(scriptTarget, scope,
-                                              onEventAtom, handler);
+                                              handler, boundHandler);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Execute it.
   nsCOMPtr<nsIDOMEventListener> eventListener;
-  NS_NewJSEventListener(boundContext, scope,
-                        scriptTarget, onEventAtom,
-                        getter_AddRefs(eventListener));
+  rv = NS_NewJSEventListener(boundContext, scope,
+                             scriptTarget, onEventAtom,
+                             boundHandler, getter_AddRefs(eventListener));
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // Handle the event.
   eventListener->HandleEvent(aEvent);
   return NS_OK;
 }
 
 nsresult
 nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -154,17 +154,16 @@ public:
     nsScriptEventHandlerOwnerTearoff(nsXULElement* aElement)
     : mElement(aElement) {}
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptEventHandlerOwnerTearoff)
 
     // nsIScriptEventHandlerOwner
     virtual nsresult CompileEventHandler(nsIScriptContext* aContext,
-                                         nsISupports* aTarget,
                                          nsIAtom *aName,
                                          const nsAString& aBody,
                                          const char* aURL,
                                          PRUint32 aLineNo,
                                          nsScriptObjectHolder &aHandler);
     virtual nsresult GetCompiledEventHandler(nsIAtom *aName,
                                              nsScriptObjectHolder &aHandler);
 
@@ -738,17 +737,16 @@ nsScriptEventHandlerOwnerTearoff::GetCom
     }
 
     return NS_OK;
 }
 
 nsresult
 nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
                                                 nsIScriptContext* aContext,
-                                                nsISupports* aTarget,
                                                 nsIAtom *aName,
                                                 const nsAString& aBody,
                                                 const char* aURL,
                                                 PRUint32 aLineNo,
                                                 nsScriptObjectHolder &aHandler)
 {
     nsresult rv;
 
@@ -781,18 +779,16 @@ nsScriptEventHandlerOwnerTearoff::Compil
         // It could be possible the language has been setup on aContext but
         // not on the global - we don't demand-create language contexts on the
         // nsGlobalWindow
         NS_ASSERTION(context,
                      "Failed to get a language context from the global!?");
         NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
     }
     else {
-        // We don't have a prototype, so the passed context is ok.
-        NS_ASSERTION(aTarget != nsnull, "no prototype and no target?!");
         context = aContext;
     }
 
     // Compile the event handler
     PRUint32 argCount;
     const char **argNames;
     nsContentUtils::GetEventArgNames(kNameSpaceID_XUL, aName, &argCount,
                                      &argNames);
@@ -803,22 +799,16 @@ nsScriptEventHandlerOwnerTearoff::Compil
     }
 
     rv = context->CompileEventHandler(aName, argCount, argNames,
                                       aBody, aURL, aLineNo,
                                       SCRIPTVERSION_DEFAULT,  // for now?
                                       aHandler);
     if (NS_FAILED(rv)) return rv;
 
-    // XXX: Shouldn't this use context and not aContext?
-    // XXXmarkh - is GetNativeGlobal() the correct scope?
-    rv = aContext->BindCompiledEventHandler(aTarget, aContext->GetNativeGlobal(),
-                                            aName, aHandler);
-    if (NS_FAILED(rv)) return rv;
-
     nsXULPrototypeAttribute *attr =
         mElement->FindPrototypeAttribute(kNameSpaceID_None, aName);
     if (attr) {
         XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
         // take a copy of the event handler, and tell the language about it.
         if (aHandler) {
             NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -518,17 +518,16 @@ static const char kDOMStringBundleURL[] 
 
 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
 //       are defined in nsIDOMClassInfo.h.
 
 #define WINDOW_SCRIPTABLE_FLAGS                                               \
  (nsIXPCScriptable::WANT_GETPROPERTY |                                        \
   nsIXPCScriptable::WANT_SETPROPERTY |                                        \
   nsIXPCScriptable::WANT_PRECREATE |                                          \
-  nsIXPCScriptable::WANT_ADDPROPERTY |                                        \
   nsIXPCScriptable::WANT_FINALIZE |                                           \
   nsIXPCScriptable::WANT_EQUALITY |                                           \
   nsIXPCScriptable::WANT_ENUMERATE |                                          \
   nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |                               \
   nsIXPCScriptable::WANT_OUTER_OBJECT)
 
 #define NODE_SCRIPTABLE_FLAGS                                                 \
  ((DOM_DEFAULT_SCRIPTABLE_FLAGS |                                             \
@@ -783,17 +782,17 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(HTMLAppletElement, nsHTMLPluginObjElementSH,
                            EXTERNAL_OBJ_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLAreaElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLBRElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLBaseElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(HTMLBodyElement, nsHTMLBodyElementSH,
+  NS_DEFINE_CLASSINFO_DATA(HTMLBodyElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLButtonElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLDataListElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLDListElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLDirectoryElement, nsElementSH,
@@ -1620,25 +1619,18 @@ jsid nsDOMClassInfo::sNodePrincipal_id  
 jsid nsDOMClassInfo::sDocumentURIObject_id=JSID_VOID;
 jsid nsDOMClassInfo::sJava_id            = JSID_VOID;
 jsid nsDOMClassInfo::sPackages_id        = JSID_VOID;
 jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
 jsid nsDOMClassInfo::sURL_id             = JSID_VOID;
 jsid nsDOMClassInfo::sKeyPath_id         = JSID_VOID;
 jsid nsDOMClassInfo::sAutoIncrement_id   = JSID_VOID;
 jsid nsDOMClassInfo::sUnique_id          = JSID_VOID;
-
-#define EVENT(name_, id_, type_, struct_)             \
-jsid nsDOMClassInfo::sOn##name_##_id     = JSID_VOID;
-#define WINDOW_ONLY_EVENT EVENT
-#define TOUCH_EVENT EVENT
-#include "nsEventNameList.h"
-#undef TOUCH_EVENT
-#undef WINDOW_ONLY_EVENT
-#undef EVENT
+jsid nsDOMClassInfo::sOnload_id          = JSID_VOID;
+jsid nsDOMClassInfo::sOnerror_id         = JSID_VOID;
 
 static const JSClass *sObjectClass = nsnull;
 
 /**
  * Set our JSClass pointer for the Object class
  */
 static void
 FindObjectClass(JSObject* aGlobalObject)
@@ -1890,26 +1882,19 @@ nsDOMClassInfo::DefineStaticJSVals(JSCon
   SET_JSID_TO_STRING(sDocumentURIObject_id,cx,"documentURIObject");
   SET_JSID_TO_STRING(sJava_id,            cx, "java");
   SET_JSID_TO_STRING(sPackages_id,        cx, "Packages");
   SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
   SET_JSID_TO_STRING(sURL_id,             cx, "URL");
   SET_JSID_TO_STRING(sKeyPath_id,         cx, "keyPath");
   SET_JSID_TO_STRING(sAutoIncrement_id,   cx, "autoIncrement");
   SET_JSID_TO_STRING(sUnique_id,          cx, "unique");
-
-#define EVENT(name_, id_, type_, struct_)               \
-  SET_JSID_TO_STRING(sOn##name_##_id, cx, "on" #name_); 
-#define WINDOW_ONLY_EVENT EVENT
-#define TOUCH_EVENT EVENT
-#include "nsEventNameList.h"
-#undef TOUCH_EVENT
-#undef WINDOW_ONLY_EVENT
-#undef EVENT 
-  
+  SET_JSID_TO_STRING(sOnload_id,          cx, "onload");
+  SET_JSID_TO_STRING(sOnerror_id,         cx, "onerror");
+
   return NS_OK;
 }
 
 static nsresult
 CreateExceptionFromResult(JSContext *cx, nsresult aResult)
 {
   nsCOMPtr<nsIExceptionService> xs =
     do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
@@ -2196,26 +2181,28 @@ nsDOMClassInfo::RegisterExternalClasses(
     d.mInterfaces = interface_list;                                           \
   }
 
 #define DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES                                    \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentXBL)                                \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)                                \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathEvaluator)                             \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)                               \
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)                           \
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMDocumentTouch,                  \
                                         nsDOMTouchEvent::PrefEnabled())
 
 
 #define DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES                                \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLElement)                              \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementCSSInlineStyle)                      \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)                                \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)                                  \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)                               \
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)                           \
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver,                \
                                         nsDOMTouchEvent::PrefEnabled())
 
 #define DOM_CLASSINFO_EVENT_MAP_ENTRIES                                       \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)                                      \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEvent)                                    \
 
 #define DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES                                    \
@@ -2263,16 +2250,17 @@ nsDOMClassInfo::Init()
 
   rv = stack->GetSafeJSContext(&cx);
   NS_ENSURE_SUCCESS(rv, rv);
 
   DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMStorageIndexedDB,
                                         nsGlobalWindow::HasIndexedDBSupport())
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDOMWindowPerformance,
                                         nsGlobalWindow::HasPerformanceSupport())
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver,
                                         nsDOMTouchEvent::PrefEnabled())
   DOM_CLASSINFO_MAP_END
 
@@ -2381,16 +2369,17 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Element, nsIDOMElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver,
                                         nsDOMTouchEvent::PrefEnabled())
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Attr, nsIDOMAttr)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMAttr)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
@@ -2914,16 +2903,17 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(XULElement, nsIDOMXULElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementCSSInlineStyle)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver,
                                         nsDOMTouchEvent::PrefEnabled())
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(XULCommandDispatcher, nsIDOMXULCommandDispatcher)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandDispatcher)
   DOM_CLASSINFO_MAP_END
 #endif
@@ -2964,16 +2954,17 @@ nsDOMClassInfo::Init()
   // FIXME: bug 680903. Should ChromeWindow really not have touch,
   // performance apis?
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeWindow, nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(RangeException, nsIDOMRangeException)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMRangeException)
     DOM_CLASSINFO_MAP_ENTRY(nsIException)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentList, nsIDOMHTMLCollection)
@@ -3025,16 +3016,17 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
 #define DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES                           \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)                          \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGElement)                           \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)                            \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)                         \
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)                     \
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver,          \
                                         nsDOMTouchEvent::PrefEnabled())
 
 #define DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGLocatable)       \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTransformable)   \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)        \
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
@@ -3850,16 +3842,17 @@ nsDOMClassInfo::Init()
   // FIXME: Bug 680903.  Should ModalContentWindow really not have
   // touch, performance apis and have unconditional indexeddb??
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DataContainerEvent, nsIDOMDataContainerEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataContainerEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MessageEvent, nsIDOMMessageEvent)
@@ -3961,16 +3954,17 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(MathMLElement, nsIDOMElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
+    DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers)
     DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver,
                                         nsDOMTouchEvent::PrefEnabled())
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLRenderingContext, nsIDOMWebGLRenderingContext)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWebGLRenderingContext)
   DOM_CLASSINFO_MAP_END
 
@@ -4883,25 +4877,18 @@ nsDOMClassInfo::ShutDown()
   sNodePrincipal_id   = JSID_VOID;
   sDocumentURIObject_id=JSID_VOID;
   sJava_id            = JSID_VOID;
   sPackages_id        = JSID_VOID;
   sWrappedJSObject_id = JSID_VOID;
   sKeyPath_id         = JSID_VOID;
   sAutoIncrement_id   = JSID_VOID;
   sUnique_id          = JSID_VOID;
-
-#define EVENT(name_, id_, type_, struct_)       \
-  sOn##name_##_id     = JSID_VOID;
-#define WINDOW_ONLY_EVENT EVENT
-#define TOUCH_EVENT EVENT
-#include "nsEventNameList.h"
-#undef TOUCH_EVENT
-#undef WINDOW_ONLY_EVENT
-#undef EVENT
+  sOnload_id          = JSID_VOID;
+  sOnerror_id         = JSID_VOID;
 
   NS_IF_RELEASE(sXPConnect);
   NS_IF_RELEASE(sSecMan);
   sIsInitialized = PR_FALSE;
 }
 
 // Window helper
 
@@ -5322,17 +5309,17 @@ nsWindowSH::SetProperty(nsIXPConnectWrap
     nsDependentJSString depStr;
     NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
 
     rv = location->SetHref(depStr);
 
     return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
   }
 
-  return nsEventReceiverSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindowSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                       JSObject *obj, PRBool *_retval)
 {
   if (!ObjectIsNativeWrapper(cx, obj)) {
     *_retval = JS_EnumerateStandardClasses(cx, obj);
@@ -5518,72 +5505,16 @@ DefineInterfaceConstants(JSContext *cx, 
                              JSPROP_ENUMERATE)) {
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHTMLBodyElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext
-                                *cx, JSObject *obj, jsid id, PRUint32 flags,
-                                JSObject **objp, PRBool *_retval)
-{
-  if (id == sOnhashchange_id) {
-    // Special handling so |"onhashchange" in document.body| returns true.
-    if (!JS_DefinePropertyById(cx, obj, id, JSVAL_VOID,
-                               nsnull, nsnull, JSPROP_ENUMERATE)) {
-      *_retval = PR_FALSE;
-      return NS_ERROR_FAILURE;
-    }
-
-    *objp = obj;
-    return NS_OK;
-  }
-
-  return nsElementSH::NewResolve(wrapper, cx, obj, id, flags, objp, _retval);
-}
-
-NS_IMETHODIMP
-nsHTMLBodyElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
-                                 JSContext *cx, JSObject *obj, jsid id,
-                                 jsval *vp, PRBool *_retval)
-{
-  if (id == sOnhashchange_id) {
-    // Forward the request to the Window.
-    if (!JS_GetPropertyById(cx, JS_GetGlobalForObject(cx, obj), id, vp)) {
-      *_retval = PR_FALSE;
-      return NS_ERROR_FAILURE;
-    }
-
-    return NS_OK;
-  }
-
-  return nsElementSH::GetProperty(wrapper, cx, obj, id, vp, _retval);
-}
-
-NS_IMETHODIMP
-nsHTMLBodyElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
-                                 JSContext *cx, JSObject *obj,
-                                 jsid id, jsval *vp, PRBool *_retval)
-{
-  if (id == sOnhashchange_id) {
-    // Forward the request to the Window.
-    if (!JS_SetPropertyById(cx, JS_GetGlobalForObject(cx, obj), id, vp)) {
-      *_retval = PR_FALSE;
-      return NS_ERROR_FAILURE;
-    }
-
-    return NS_OK;
-  }
-
-  return nsElementSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
-}
-
 class nsDOMConstructor : public nsIDOMDOMConstructor
 {
 protected:
   nsDOMConstructor(const PRUnichar* aName,
                    PRBool aIsConstructable,
                    nsPIDOMWindow* aOwner)
     : mClassName(aName),
       mConstructable(aIsConstructable),
@@ -6751,28 +6682,16 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       return NS_ERROR_FAILURE;
     }
 
     *objp = obj;
 
     return NS_OK;
   }
 
-  if (id == sOnhashchange_id) {
-    // Special handling so |"onhashchange" in window| returns true
-    if (!JS_DefinePropertyById(cx, obj, id, JSVAL_VOID,
-                                nsnull, nsnull, JSPROP_ENUMERATE)) {
-      *_retval = PR_FALSE;
-      return NS_ERROR_FAILURE;
-    }
-
-    *objp = obj;
-    return NS_OK;
-  }
-
   if (flags & JSRESOLVE_ASSIGNING) {
     if (IsReadonlyReplaceable(id) ||
         (!(flags & JSRESOLVE_QUALIFIED) && IsWritableReplaceable(id))) {
       // A readonly "replaceable" property is being set, or a
       // readwrite "replaceable" property is being set w/o being
       // fully qualified. Define the property on obj with the value
       // undefined to override the predefined property. This is done
       // for compatibility with other browsers.
@@ -6885,18 +6804,18 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
         *objp = obj;
       }
 
       return NS_OK;
     }
   }
 
   JSObject *oldobj = *objp;
-  rv = nsEventReceiverSH::NewResolve(wrapper, cx, obj, id, flags, objp,
-                                     _retval);
+  rv = nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, flags, objp,
+                                  _retval);
 
   if (NS_FAILED(rv) || *objp != oldobj) {
     // Something went wrong, or the property got resolved. Return.
     return rv;
   }
 
   // Make a fast expando if we're assigning to (not declaring or
   // binding a name) a new undefined property that's not already
@@ -7290,37 +7209,41 @@ nsNodeSH::PreCreate(nsISupports *nativeO
     NS_SUCCESS_CHROME_ACCESS_ONLY : NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
 }
 
 NS_IMETHODIMP
 nsNodeSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                       JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
 {
   nsNodeSH::PreserveWrapper(GetNative(wrapper, obj));
-  return nsEventReceiverSH::AddProperty(wrapper, cx, obj, id, vp, _retval);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNodeSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                      JSObject *obj, jsid id, PRUint32 flags,
                      JSObject **objp, PRBool *_retval)
 {
   if ((id == sBaseURIObject_id || id == sNodePrincipal_id) &&
       IsPrivilegedScript()) {
     return DefineVoidProp(cx, obj, id, objp);
   }
 
   if (id == sOnload_id || id == sOnerror_id) {
     // Make sure that this node can't go away while waiting for a
     // network load that could fire an event handler.
+    // XXXbz won't this fail if the listener is added using
+    // addEventListener?  On the other hand, even if I comment this
+    // code out I can't seem to reproduce the bug it was trying to
+    // fix....
     nsNodeSH::PreserveWrapper(GetNative(wrapper, obj));
   }
 
-  return nsEventReceiverSH::NewResolve(wrapper, cx, obj, id, flags, objp,
-                                       _retval);
+  return nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, flags, objp,
+                                    _retval);
 }
 
 NS_IMETHODIMP
 nsNodeSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                       JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
 {
   if (id == sBaseURIObject_id && IsPrivilegedScript()) {
     // I wish GetBaseURI lived on nsINode
@@ -7367,17 +7290,17 @@ nsNodeSH::SetProperty(nsIXPConnectWrappe
       IsPrivilegedScript()) {
     // We don't want privileged script that can read this property to set it,
     // but _do_ want to allow everyone else to set a value they can then read.
     //
     // XXXbz Is there a better error we could use here?
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 
-  return nsEventReceiverSH::SetProperty(wrapper, cx, obj, id, vp,_retval);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNodeSH::GetFlags(PRUint32 *aFlags)
 {
   *aFlags = DOMCLASSINFO_STANDARD_FLAGS | nsIClassInfo::CONTENT_NODE;
 
   return NS_OK;
@@ -7385,259 +7308,16 @@ nsNodeSH::GetFlags(PRUint32 *aFlags)
 
 void
 nsNodeSH::PreserveWrapper(nsISupports *aNative)
 {
   nsINode *node = static_cast<nsINode*>(aNative);
   nsContentUtils::PreserveWrapper(aNative, node);
 }
 
-// EventReceiver helper
-
-// static
-PRBool
-nsEventReceiverSH::ReallyIsEventName(jsid id, jschar aFirstChar)
-{
-  // I wonder if this is faster than using a hash...
-
-  switch (aFirstChar) {
-  case 'a' :
-    return (id == sOnabort_id ||
-            id == sOnafterscriptexecute_id ||
-            id == sOnafterprint_id);
-  case 'b' :
-    return (id == sOnbeforeunload_id ||
-            id == sOnbeforescriptexecute_id ||
-            id == sOnblur_id ||
-            id == sOnbeforeprint_id);
-  case 'c' :
-    return (id == sOnchange_id       ||
-            id == sOnclick_id        ||
-            id == sOncontextmenu_id  ||
-            id == sOncopy_id         ||
-            id == sOncut_id          ||
-            id == sOncanplay_id      ||
-            id == sOncanplaythrough_id);
-  case 'd' :
-    return (id == sOndblclick_id     || 
-            id == sOndrag_id         ||
-            id == sOndragend_id      ||
-            id == sOndragenter_id    ||
-            id == sOndragleave_id    ||
-            id == sOndragover_id     ||
-            id == sOndragstart_id    ||
-            id == sOndrop_id         ||
-            id == sOndurationchange_id ||
-            id == sOndeviceorientation_id ||
-            id == sOndevicemotion_id );
-  case 'e' :
-    return (id == sOnerror_id ||
-            id == sOnemptied_id ||
-            id == sOnended_id);
-  case 'f' :
-    return id == sOnfocus_id;
-  case 'h' :
-    return id == sOnhashchange_id;
-  case 'i' :
-    return (id == sOninput_id ||
-            id == sOninvalid_id);
-  case 'k' :
-    return (id == sOnkeydown_id      ||
-            id == sOnkeypress_id     ||
-            id == sOnkeyup_id);
-  case 'l' :
-    return (id == sOnload_id           ||
-            id == sOnloadeddata_id     ||
-            id == sOnloadedmetadata_id ||
-            id == sOnloadstart_id);
-  case 'm' :
-    return (id == sOnmousemove_id    ||
-            id == sOnmouseout_id     ||
-            id == sOnmouseover_id    ||
-            id == sOnmouseup_id      ||
-            id == sOnmousedown_id    ||
-            id == sOnmessage_id);
-  case 'p' :
-    return (id == sOnpageshow_id     ||
-            id == sOnpagehide_id     ||
-            id == sOnpaste_id        ||
-            id == sOnpopstate_id     ||
-            id == sOnpause_id        ||
-            id == sOnplay_id         ||
-            id == sOnplaying_id      ||
-            id == sOnprogress_id);
-  case 'r' :
-    return (id == sOnreadystatechange_id ||
-            id == sOnreset_id            ||
-            id == sOnresize_id           ||
-            id == sOnratechange_id);
-  case 's' :
-    return (id == sOnscroll_id       ||
-            id == sOnshow_id         ||
-            id == sOnselect_id       ||
-            id == sOnsubmit_id       || 
-            id == sOnseeked_id       ||
-            id == sOnseeking_id      ||
-            id == sOnstalled_id      ||
-            id == sOnsuspend_id);
-  case 't':
-    return id == sOntimeupdate_id ||
-      (nsDOMTouchEvent::PrefEnabled() &&
-       (id == sOntouchstart_id ||
-        id == sOntouchend_id ||
-        id == sOntouchmove_id ||
-        id == sOntouchenter_id ||
-        id == sOntouchleave_id ||
-        id == sOntouchcancel_id));
-    
-  case 'u' :
-    return id == sOnunload_id;
-  case 'v':
-    return id == sOnvolumechange_id;
-  case 'w':
-    return id == sOnwaiting_id;
-  }
-
-  return PR_FALSE;
-}
-
-nsresult
-nsEventReceiverSH::RegisterCompileHandler(nsIXPConnectWrappedNative *wrapper,
-                                          JSContext *cx, JSObject *obj,
-                                          jsid id, PRBool compile,
-                                          PRBool remove,
-                                          PRBool *did_define)
-{
-  NS_PRECONDITION(!compile || !remove,
-                  "Can't both compile and remove at the same time");
-  *did_define = PR_FALSE;
-
-  if (!IsEventName(id)) {
-    return NS_OK;
-  }
-
-  if (ObjectIsNativeWrapper(cx, obj)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  nsIScriptContext *script_cx = nsJSUtils::GetStaticScriptContext(cx, obj);
-  NS_ENSURE_TRUE(script_cx, NS_ERROR_UNEXPECTED);
-
-  nsCOMPtr<nsIDOMEventTarget> target =
-    do_QueryWrappedNative(wrapper, obj);
-  if (!target) {
-    // Doesn't do events
-    NS_WARNING("Doesn't QI to nsIDOMEventTarget?");
-    return NS_OK;
-  }
-  
-  nsEventListenerManager* manager = target->GetListenerManager(PR_TRUE);
-  NS_ENSURE_TRUE(manager, NS_ERROR_UNEXPECTED);
-
-  nsCOMPtr<nsIAtom> atom(do_GetAtom(nsDependentJSString(id)));
-  NS_ENSURE_TRUE(atom, NS_ERROR_OUT_OF_MEMORY);
-
-  JSObject *scope = ::JS_GetGlobalForObject(cx, obj);
-
-  if (compile) {
-    nsresult rv = manager->CompileScriptEventListener(script_cx, scope,
-                                                      atom, did_define);
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else if (remove) {
-    manager->RemoveScriptEventListener(atom);
-  } else {
-    manager->RegisterScriptEventListener(script_cx, scope, atom);
-  }
-
-  return NS_SUCCESS_I_DID_SOMETHING;
-}
-
-NS_IMETHODIMP
-nsEventReceiverSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
-                              JSContext *cx, JSObject *obj, jsid id,
-                              PRUint32 flags, JSObject **objp, PRBool *_retval)
-{
-  if (!JSID_IS_STRING(id)) {
-    return NS_OK;
-  }
-
-  if (flags & JSRESOLVE_ASSIGNING) {
-    if (!IsEventName(id)) {
-      // Bail out.  We don't care about this assignment.
-      return NS_OK;
-    }
-
-    // If we're assigning to an on* property, just resolve to null for
-    // now; the assignment will then set the right value. Only do this
-    // in the case where the property isn't already defined on the
-    // object's prototype chain though.
-    JSAutoRequest ar(cx);
-
-    JSObject *proto = ::JS_GetPrototype(cx, obj);
-    PRBool ok = PR_TRUE;
-    JSBool hasProp = JS_FALSE;
-    if (!proto || ((ok = ::JS_HasPropertyById(cx, proto, id, &hasProp)) &&
-                   !hasProp)) {
-      // Make sure the flags here match those in
-      // nsJSContext::BindCompiledEventHandler
-      if (!::JS_DefinePropertyById(cx, obj, id, JSVAL_NULL, nsnull, nsnull,
-                                   JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
-        return NS_ERROR_FAILURE;
-      }
-
-      *objp = obj;
-      return NS_OK;
-    }
-
-    return ok ? NS_OK : NS_ERROR_FAILURE;
-  }
-
-  if (id == sAddEventListener_id) {
-    return NS_OK;
-  }
-
-  PRBool did_define = PR_FALSE;
-  nsresult rv = RegisterCompileHandler(wrapper, cx, obj, id, PR_TRUE, PR_FALSE,
-                                       &did_define);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (did_define) {
-    *objp = obj;
-  }
-
-  return nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, flags, objp,
-                                    _retval);
-}
-
-NS_IMETHODIMP
-nsEventReceiverSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
-                               JSContext *cx, JSObject *obj, jsid id,
-                               jsval *vp, PRBool *_retval)
-{
-  JSAutoRequest ar(cx);
-
-  if ((::JS_TypeOfValue(cx, *vp) != JSTYPE_FUNCTION && !JSVAL_IS_NULL(*vp)) ||
-      !JSID_IS_STRING(id) || id == sAddEventListener_id) {
-    return NS_OK;
-  }
-
-  PRBool did_compile; // Ignored here.
-
-  return RegisterCompileHandler(wrapper, cx, obj, id, PR_FALSE,
-                                JSVAL_IS_NULL(*vp), &did_compile);
-}
-
-NS_IMETHODIMP
-nsEventReceiverSH::AddProperty(nsIXPConnectWrappedNative *wrapper,
-                               JSContext *cx, JSObject *obj, jsid id,
-                               jsval *vp, PRBool *_retval)
-{
-  return nsEventReceiverSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
-}
-
 // EventTarget helper
 
 NS_IMETHODIMP
 nsEventTargetSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                            JSObject *globalObj, JSObject **parentObj)
 {
   nsDOMEventTargetWrapperCache *target =
     nsDOMEventTargetWrapperCache::FromSupports(nativeObj);
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -287,26 +287,19 @@ public:
   static jsid sDocumentURIObject_id;
   static jsid sJava_id;
   static jsid sPackages_id;
   static jsid sWrappedJSObject_id;
   static jsid sURL_id;
   static jsid sKeyPath_id;
   static jsid sAutoIncrement_id;
   static jsid sUnique_id;
+  static jsid sOnload_id;
+  static jsid sOnerror_id;
 
-#define EVENT(name_, id_, type_, struct_)       \
-  static jsid sOn##name_##_id;
-#define WINDOW_ONLY_EVENT EVENT
-#define TOUCH_EVENT EVENT
-#include "nsEventNameList.h"
-#undef TOUCH_EVENT
-#undef WINDOW_ONLY_EVENT
-#undef EVENT
-  
 protected:
   static JSPropertyOp sXPCNativeWrapperGetPropertyOp;
   static JSPropertyOp sXrayWrapperPropertyHolderGetPropertyOp;
 };
 
 
 inline
 const nsQueryInterface
@@ -341,63 +334,16 @@ do_QueryWrapper(JSContext *cx, JSObject 
   nsISupports *native =
     nsDOMClassInfo::XPConnect()->GetNativeOfWrapper(cx, obj);
   return nsQueryInterfaceWithError(native, error);
 }
 
 
 typedef nsDOMClassInfo nsDOMGenericSH;
 
-// EventProp scriptable helper, this class should be the base class of
-// all objects that should support things like
-// obj.onclick=function{...}
-
-class nsEventReceiverSH : public nsDOMGenericSH
-{
-protected:
-  nsEventReceiverSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
-  {
-  }
-
-  virtual ~nsEventReceiverSH()
-  {
-  }
-
-  static PRBool ReallyIsEventName(jsid id, jschar aFirstChar);
-
-  static inline PRBool IsEventName(jsid id)
-  {
-    NS_ASSERTION(JSID_IS_STRING(id), "Don't pass non-string jsid's here!");
-
-    const jschar *str = ::JS_GetInternedStringChars(JSID_TO_STRING(id));
-
-    if (str[0] == 'o' && str[1] == 'n') {
-      return ReallyIsEventName(id, str[2]);
-    }
-
-    return PR_FALSE;
-  }
-
-  nsresult RegisterCompileHandler(nsIXPConnectWrappedNative *wrapper,
-                                  JSContext *cx, JSObject *obj, jsid id,
-                                  PRBool compile, PRBool remove,
-                                  PRBool *did_define);
-
-public:
-  NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                        JSObject *obj, jsid id, PRUint32 flags,
-                        JSObject **objp, PRBool *_retval);
-  NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp,
-                         PRBool *_retval);
-  NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
-};
-
-// Simpler than nsEventReceiverSH
 // Makes sure that the wrapper is preserved if new properties are added.
 class nsEventTargetSH : public nsDOMGenericSH
 {
 protected:
   nsEventTargetSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
   {
   }
 
@@ -415,20 +361,20 @@ public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsEventTargetSH(aData);
   }
 };
 
 // Window scriptable helper
 
-class nsWindowSH : public nsEventReceiverSH
+class nsWindowSH : public nsDOMGenericSH
 {
 protected:
-  nsWindowSH(nsDOMClassInfoData *aData) : nsEventReceiverSH(aData)
+  nsWindowSH(nsDOMClassInfoData *aData) : nsDOMGenericSH(aData)
   {
   }
 
   virtual ~nsWindowSH()
   {
   }
 
   static nsresult GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
@@ -446,17 +392,17 @@ public:
     NS_ASSERTION(!sgo || sgo->GetGlobalJSObject() == nsnull,
                  "Multiple wrappers created for global object!");
 
     return NS_OK;
   }
   NS_IMETHOD GetScriptableFlags(PRUint32 *aFlags)
   {
     PRUint32 flags;
-    nsresult rv = nsEventReceiverSH::GetScriptableFlags(&flags);
+    nsresult rv = nsDOMGenericSH::GetScriptableFlags(&flags);
     if (NS_SUCCEEDED(rv)) {
       *aFlags = flags | nsIXPCScriptable::WANT_POSTCREATE;
     }
 
     return rv;
   }
 #endif
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
@@ -543,20 +489,20 @@ public:
     return new nsNavigatorSH(aData);
   }
 };
 
 
 // DOM Node helper, this class deals with setting the parent for the
 // wrappers
 
-class nsNodeSH : public nsEventReceiverSH
+class nsNodeSH : public nsDOMGenericSH
 {
 protected:
-  nsNodeSH(nsDOMClassInfoData* aData) : nsEventReceiverSH(aData)
+  nsNodeSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
   {
   }
 
   virtual ~nsNodeSH()
   {
   }
 
   // Helper to check whether a capability is enabled
@@ -941,48 +887,16 @@ public:
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsHTMLDocumentSH(aData);
   }
 };
 
 
-// HTMLBodyElement helper
-
-class nsHTMLBodyElementSH : public nsElementSH
-{
-protected:
-  nsHTMLBodyElementSH(nsDOMClassInfoData* aData) : nsElementSH(aData)
-  {
-  }
-
-  virtual ~nsHTMLBodyElementSH()
-  {
-  }
-
-public:
-  NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                        JSObject *obj, jsid id, PRUint32 flags,
-                        JSObject **objp, PRBool *_retval);
-
-  NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp,
-                         PRBool *_retval);
-
-  NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsHTMLBodyElementSH(aData);
-  }
-};
-
-
 // HTMLFormElement helper
 
 class nsHTMLFormElementSH : public nsElementSH
 {
 protected:
   nsHTMLFormElementSH(nsDOMClassInfoData* aData) : nsElementSH(aData)
   {
   }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1362,16 +1362,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow)
   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageIndexedDB)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindowPerformance)
   NS_INTERFACE_MAP_ENTRY(nsITouchEventReceiver)
+  NS_INTERFACE_MAP_ENTRY(nsIInlineEventHandlers)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window)
   OUTER_WINDOW_ONLY
     NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   END_OUTER_WINDOW_ONLY
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindow)
@@ -11351,16 +11352,47 @@ NS_IMETHODIMP nsNavigator::GetMozNotific
   if (!mNotification) {
     return NS_ERROR_FAILURE;
   }
 
   NS_ADDREF(*aRetVal = mNotification);    
   return NS_OK; 
 }
 
+#define EVENT(name_, id_, type_, struct_)                                    \
+  NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx,                  \
+                                             jsval *vp) {                    \
+    nsEventListenerManager *elm = GetListenerManager(PR_FALSE);              \
+    if (elm) {                                                               \
+      elm->GetJSEventListener(nsGkAtoms::on##name_, vp);                     \
+    } else {                                                                 \
+      *vp = JSVAL_NULL;                                                      \
+    }                                                                        \
+    return NS_OK;                                                            \
+  }                                                                          \
+  NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx,                  \
+                                             const jsval &v) {               \
+    nsEventListenerManager *elm = GetListenerManager(PR_TRUE);               \
+    if (!elm) {                                                              \
+      return NS_ERROR_OUT_OF_MEMORY;                                         \
+    }                                                                        \
+                                                                             \
+    JSObject *obj = mJSObject;                                               \
+    if (!obj) {                                                              \
+      return NS_ERROR_UNEXPECTED;                                            \
+    }                                                                        \
+    return elm->SetJSEventListenerToJsval(nsGkAtoms::on##name_, cx, obj, v); \
+  }
+#define WINDOW_ONLY_EVENT EVENT
+#define TOUCH_EVENT EVENT
+#include "nsEventNameList.h"
+#undef TOUCH_EVENT
+#undef WINDOW_ONLY_EVENT
+#undef EVENT
+
 PRInt64
 nsNavigator::SizeOf() const
 {
   PRInt64 size = sizeof(*this);
 
   // TODO: add SizeOf() to nsMimeTypeArray, bug 674113.
   size += mMimeTypes ? sizeof(*mMimeTypes.get()) : 0;
   // TODO: add SizeOf() to nsPluginArray, bug 674114.
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -99,16 +99,17 @@
 #include "nsIDOMStorageIndexedDB.h"
 #include "nsIDOMOfflineResourceList.h"
 #include "nsIArray.h"
 #include "nsIContent.h"
 #include "nsIIDBFactory.h"
 #include "nsFrameMessageManager.h"
 #include "mozilla/TimeStamp.h"
 #include "nsIDOMTouchEvent.h"
+#include "nsIInlineEventHandlers.h"
 
 // JS includes
 #include "jsapi.h"
 #include "jswrapper.h"
 
 #define DEFAULT_HOME_PAGE "www.mozilla.org"
 #define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
 
@@ -275,17 +276,18 @@ class nsGlobalWindow : public nsPIDOMWin
                        public nsIScriptObjectPrincipal,
                        public nsIDOMEventTarget,
                        public nsIDOMStorageIndexedDB,
                        public nsSupportsWeakReference,
                        public nsIInterfaceRequestor,
                        public nsWrapperCache,
                        public PRCListStr,
                        public nsIDOMWindowPerformance,
-                       public nsITouchEventReceiver
+                       public nsITouchEventReceiver,
+                       public nsIInlineEventHandlers
 {
 public:
   friend class nsDOMMozURLProperty;
 
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
   typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindow*> WindowByIdTable;
 
@@ -330,16 +332,19 @@ public:
   NS_DECL_NSIDOMJSWINDOW
 
   // nsIDOMEventTarget
   NS_DECL_NSIDOMEVENTTARGET
 
   // nsITouchEventReceiver
   NS_DECL_NSITOUCHEVENTRECEIVER
 
+  // nsIInlineEventHandlers
+  NS_DECL_NSIINLINEEVENTHANDLERS
+
   // nsPIDOMWindow
   virtual NS_HIDDEN_(nsPIDOMWindow*) GetPrivateRoot();
   virtual NS_HIDDEN_(void) ActivateOrDeactivate(PRBool aActivate);
   virtual NS_HIDDEN_(void) SetActive(PRBool aActive);
   virtual NS_HIDDEN_(void) SetIsBackground(PRBool aIsBackground);
   virtual NS_HIDDEN_(void) SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler);
 
   virtual NS_HIDDEN_(void) SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal);
--- a/dom/base/nsIJSEventListener.h
+++ b/dom/base/nsIJSEventListener.h
@@ -35,67 +35,77 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsIJSEventListener_h__
 #define nsIJSEventListener_h__
 
 #include "nsIScriptContext.h"
 #include "jsapi.h"
+#include "nsIDOMEventListener.h"
 
 class nsIScriptObjectOwner;
-class nsIDOMEventListener;
 class nsIAtom;
 
 #define NS_IJSEVENTLISTENER_IID     \
-{ 0x08ca15c4, 0x1c2d, 0x449e, \
-  { 0x9e, 0x88, 0xaa, 0x8b, 0xbf, 0x00, 0xf7, 0x63 } }
+{ 0xb88fb066, 0xe9f8, 0x45d0, \
+ { 0x92, 0x9a, 0x7d, 0xa8, 0x4c, 0x1f, 0xb5, 0xbc } }
 
 // Implemented by script event listeners. Used to retrieve the
-// script object corresponding to the event target.
+// script object corresponding to the event target and the handler itself.
 // (Note this interface is now used to store script objects for all
 // script languages, so is no longer JS specific)
-class nsIJSEventListener : public nsISupports
+class nsIJSEventListener : public nsIDOMEventListener
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSEVENTLISTENER_IID)
 
   nsIJSEventListener(nsIScriptContext *aContext, void *aScopeObject,
-                     nsISupports *aTarget)
+                     nsISupports *aTarget, void *aHandler)
     : mContext(aContext), mScopeObject(aScopeObject),
-      mTarget(do_QueryInterface(aTarget))
+      mTarget(do_QueryInterface(aTarget)), mHandler(aHandler)
   {
   }
 
-  nsIScriptContext *GetEventContext()
+  nsIScriptContext *GetEventContext() const
   {
     return mContext;
   }
 
-  nsISupports *GetEventTarget()
+  nsISupports *GetEventTarget() const
   {
     return mTarget;
   }
 
-  void *GetEventScope()
+  void *GetEventScope() const
   {
     return mScopeObject;
   }
 
-  virtual nsresult GetJSVal(const nsAString& aEventName, jsval* aJSVal) = 0;
+  void *GetHandler() const
+  {
+    return mHandler;
+  }
+
+  // Set a handler for this event listener.  Must not be called if
+  // there is already a handler!  The handler must already be bound to
+  // the right target.
+  virtual void SetHandler(void *aHandler) = 0;
 
 protected:
   virtual ~nsIJSEventListener()
   {
   }
   nsCOMPtr<nsIScriptContext> mContext;
   void *mScopeObject;
   nsCOMPtr<nsISupports> mTarget;
+  void *mHandler;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSEventListener, NS_IJSEVENTLISTENER_IID)
 
-/* factory function */
+/* factory function.  aHandler must already be bound to aTarget */
 nsresult NS_NewJSEventListener(nsIScriptContext *aContext,
-                               void *aScopeObject, nsISupports *aObject,
-                               nsIAtom* aType, nsIDOMEventListener **aReturn);
+                               void *aScopeObject, nsISupports *aTarget,
+                               nsIAtom* aType, void *aHandler,
+                               nsIDOMEventListener **aReturn);
 
 #endif // nsIJSEventListener_h__
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -67,20 +67,19 @@ public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
                               NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
-// a7139c0e-962c-44b6-bec3-e4166bfe84eb
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0xa7139c0e, 0x962c, 0x44b6, \
-  { 0xbe, 0xc3, 0xe4, 0x16, 0x6b, 0xfe, 0x84, 0xeb } }
+  { 0xad76079b, 0xd408, 0x4159, \
+    {0xb7, 0x3f, 0x41, 0x08, 0x77, 0xff, 0x9b, 0x47 } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 /**
  * It is used by the application to initialize a runtime and run scripts.
  * A script runtime would implement this interface.
@@ -228,51 +227,40 @@ public:
    *        be an nsIVariant.
    * @param rval out parameter returning result
    **/
   virtual nsresult CallEventHandler(nsISupports* aTarget,
                                     void *aScope, void* aHandler,
                                     nsIArray *argv, nsIVariant **rval) = 0;
 
   /**
-   * Bind an already-compiled event handler function to a name in the given
-   * scope object.  The same restrictions on aName (lowercase ASCII, not too
-   * long) applies here as for CompileEventHandler.  Scripting languages with
-   * static scoping must re-bind the scope chain for aHandler to begin (after
-   * the activation scope for aHandler itself, typically) with aTarget's scope.
+   * Bind an already-compiled event handler function to the given
+   * target.  Scripting languages with static scoping must re-bind the
+   * scope chain for aHandler to begin (after the activation scope for
+   * aHandler itself, typically) with aTarget's scope.
    *
-   * Logically, this 'bind' operation is more of a 'copy' - it simply
-   * stashes/associates the event handler function with the event target, so
-   * it can be fetched later with GetBoundEventHandler().
+   * The result of the bind operation is a new handler object, with
+   * principals now set and scope set as above.  This is returned in
+   * aBoundHandler.  When this function is called, aBoundHandler is
+   * expected to not be holding an object.
    *
    * @param aTarget an object telling the scope in which to bind the compiled
    *        event handler function.  The context will presumably associate
    *        this nsISupports with a native script object.
-   * @param aName an nsIAtom pointer naming the function; it must be lowercase
-   *        and ASCII, and should not be longer than 63 chars.  This bound on
-   *        length is enforced only by assertions, so caveat caller!
-   * @param aHandler the function object to name, created by an earlier call to
+   * @param aScope the scope in which the script object for aTarget should be
+   *        looked for.
+   * @param aHandler the function object to bind, created by an earlier call to
    *        CompileEventHandler
-   * @return NS_OK if the function was successfully bound to the name
-   *
-   * XXXmarkh - fold this in with SetProperty?  Exactly the same concept!
+   * @param aBoundHandler [out] the result of the bind operation.
+   * @return NS_OK if the function was successfully bound
    */
-  virtual nsresult BindCompiledEventHandler(nsISupports* aTarget, void *aScope,
-                                            nsIAtom* aName,
-                                            void* aHandler) = 0;
-
-  /**
-   * Lookup a previously bound event handler for the specified target.  This
-   * will return an object equivilent to the one passed to
-   * BindCompiledEventHandler (although the pointer may not be the same).
-   *
-   */
-  virtual nsresult GetBoundEventHandler(nsISupports* aTarget, void *aScope,
-                                        nsIAtom* aName,
-                                        nsScriptObjectHolder &aHandler) = 0;
+  virtual nsresult BindCompiledEventHandler(nsISupports* aTarget,
+                                            void *aScope,
+                                            void* aHandler,
+                                            nsScriptObjectHolder& aBoundHandler) = 0;
 
   /**
    * Compile a function that isn't used as an event handler.
    *
    * NOTE: Not yet language agnostic (main problem is XBL - not yet agnostic)
    * Caller must make sure aFunctionObject is a JS GC root.
    *
    **/
--- a/dom/base/nsIScriptObjectOwner.h
+++ b/dom/base/nsIScriptObjectOwner.h
@@ -89,45 +89,42 @@ public:
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptObjectOwner,
                               NS_ISCRIPTOBJECTOWNER_IID)
 
 class nsIAtom;
 
 #define NS_ISCRIPTEVENTHANDLEROWNER_IID \
-{ /* 2ad54ae0-a839-11d3-ba97-00104ba02d3d */ \
-0x2ad54ae0, 0xa839, 0x11d3, \
-  {0xba, 0x97, 0x00, 0x10, 0x4b, 0xa0, 0x2d, 0x3d} }
+{ 0x1e2be5d2, 0x381a, 0x46dc, \
+ { 0xae, 0x97, 0xa5, 0x5f, 0x45, 0xfd, 0x36, 0x63 } }
 
 /**
  * Associate a compiled event handler with its target object, which owns it
  * This is an adjunct to nsIScriptObjectOwner that nsEventListenerManager's
  * implementation queries for, in order to avoid recompiling a recurrent or
  * prototype-inherited event handler.
  */
 class nsIScriptEventHandlerOwner : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTEVENTHANDLEROWNER_IID)
 
   /**
-   * Compile the specified event handler, and bind it to aTarget using
-   * aContext.
+   * Compile the specified event handler.  This does NOT bind it to
+   * anything.  That's the caller's responsibility.
    *
    * @param aContext the context to use when creating event handler
-   * @param aTarget the object to which to bind the event handler
    * @param aName the name of the handler
    * @param aBody the handler script body
    * @param aURL the URL or filename for error messages
    * @param aLineNo the starting line number of the script for error messages
-   * @param aHandler the holder for the compiled, bound handler object
+   * @param aHandler the holder for the compiled handler object
    */
   virtual nsresult CompileEventHandler(nsIScriptContext* aContext,
-                                       nsISupports* aTarget,
                                        nsIAtom *aName,
                                        const nsAString& aBody,
                                        const char* aURL,
                                        PRUint32 aLineNo,
                                        nsScriptObjectHolder &aHandler) = 0;
 
   /**
    * Retrieve an already-compiled event handler that can be bound to a
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1930,23 +1930,22 @@ nsJSContext::CallEventHandler(nsISupport
   // ScriptEvaluated needs to come after we pop the stack
   ScriptEvaluated(PR_TRUE);
 
   return rv;
 }
 
 nsresult
 nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, void *aScope,
-                                      nsIAtom *aName,
-                                      void *aHandler)
+                                      void *aHandler,
+                                      nsScriptObjectHolder& aBoundHandler)
 {
   NS_ENSURE_ARG(aHandler);
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
-
-  NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
+  NS_PRECONDITION(!aBoundHandler, "Shouldn't already have a bound handler!");
 
   JSAutoRequest ar(mContext);
 
   // Get the jsobject associated with this target
   JSObject *target = nsnull;
   nsresult rv = JSObjectFromInterface(aTarget, aScope, &target);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1965,82 +1964,28 @@ nsJSContext::BindCompiledEventHandler(ns
   }
 #endif
 
   JSAutoEnterCompartment ac;
   if (!ac.enter(mContext, target)) {
     return NS_ERROR_FAILURE;
   }
 
-  // Push our JSContext on our thread's context stack, in case native code
-  // called from JS calls back into JS via XPConnect.
-  nsCOMPtr<nsIJSContextStack> stack =
-           do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
-  if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
-    return NS_ERROR_FAILURE;
-  }
-
   // Make sure the handler function is parented by its event target object
   if (funobj) { // && ::JS_GetParent(mContext, funobj) != target) {
     funobj = ::JS_CloneFunctionObject(mContext, funobj, target);
     if (!funobj)
       rv = NS_ERROR_OUT_OF_MEMORY;
   }
 
-  if (NS_SUCCEEDED(rv) &&
-      // Make sure the flags here match those in nsEventReceiverSH::NewResolve
-      !::JS_DefineProperty(mContext, target, nsAtomCString(aName).get(),
-                           OBJECT_TO_JSVAL(funobj), nsnull, nsnull,
-                           JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
-    ReportPendingException();
-    rv = NS_ERROR_FAILURE;
-  }
-
-  // XXXmarkh - ideally we should assert that the wrapped native is now
-  // "long lived" - how to do that?
-
-  if (NS_FAILED(stack->Pop(nsnull)) && NS_SUCCEEDED(rv)) {
-    rv = NS_ERROR_FAILURE;
-  }
+  aBoundHandler.set(funobj);
 
   return rv;
 }
 
-nsresult
-nsJSContext::GetBoundEventHandler(nsISupports* aTarget, void *aScope,
-                                  nsIAtom* aName,
-                                  nsScriptObjectHolder &aHandler)
-{
-    NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
-
-    JSAutoRequest ar(mContext);
-    JSObject *obj = nsnull;
-    nsresult rv = JSObjectFromInterface(aTarget, aScope, &obj);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    JSAutoEnterCompartment ac;
-    if (!ac.enter(mContext, obj)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    jsval funval;
-    if (!JS_LookupProperty(mContext, obj,
-                           nsAtomCString(aName).get(), &funval))
-        return NS_ERROR_FAILURE;
-
-    if (JS_TypeOfValue(mContext, funval) != JSTYPE_FUNCTION) {
-        NS_WARNING("Event handler object not a function");
-        aHandler.drop();
-        return NS_OK;
-    }
-    NS_ASSERTION(aHandler.getScriptTypeID()==JAVASCRIPT,
-                 "Expecting JS script object holder");
-    return aHandler.set(JSVAL_TO_OBJECT(funval));
-}
-
 // serialization
 nsresult
 nsJSContext::Serialize(nsIObjectOutputStream* aStream, void *aScriptObject)
 {
     JSObject *mJSObject = (JSObject *)aScriptObject;
     if (!mJSObject)
         return NS_ERROR_FAILURE;
 
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -109,21 +109,18 @@ public:
                                        const char *aURL, PRUint32 aLineNo,
                                        PRUint32 aVersion,
                                        nsScriptObjectHolder &aHandler);
   virtual nsresult CallEventHandler(nsISupports* aTarget, void *aScope,
                                     void* aHandler,
                                     nsIArray *argv, nsIVariant **rv);
   virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
                                             void *aScope,
-                                            nsIAtom *aName,
-                                            void *aHandler);
-  virtual nsresult GetBoundEventHandler(nsISupports* aTarget, void *aScope,
-                                        nsIAtom* aName,
-                                        nsScriptObjectHolder &aHandler);
+                                            void *aHandler,
+                                            nsScriptObjectHolder& aBoundHandler);
   virtual nsresult CompileFunction(void* aTarget,
                                    const nsACString& aName,
                                    PRUint32 aArgCount,
                                    const char** aArgArray,
                                    const nsAString& aBody,
                                    const char* aURL,
                                    PRUint32 aLineNo,
                                    PRUint32 aVersion,
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -65,17 +65,17 @@ interface nsIDOMMozURLProperty : nsISupp
  * The nsIDOMWindow interface is the primary interface for a DOM
  * window object. It represents a single window object that may
  * contain child windows if the document in the window contains a
  * HTML frameset document or if the document contains iframe elements.
  *
  * @see <http://www.whatwg.org/html/#window>
  */
 
-[scriptable, uuid(972cb379-6bdc-4544-8b46-8d721e12e906)]
+[scriptable, uuid(3f5b2af2-604e-4253-8d25-6d3cafc13a69)]
 interface nsIDOMWindow : nsISupports
 {
   // the current browsing context
   readonly attribute nsIDOMWindow                       window;
 
   /* [replaceable] self */
   readonly attribute nsIDOMWindow                       self;
 
@@ -429,16 +429,44 @@ interface nsIDOMWindow : nsISupports
    * @see <http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking>
    */
   readonly attribute nsIDOMMozURLProperty URL;
 
   /**
    * Global storage, accessible by domain.
    */
   readonly attribute nsIDOMStorageList globalStorage;
+
+  /**
+   * HTML5 event attributes that only apply to windows and <body>/<frameset>
+   */
+  [implicit_jscontext] attribute jsval onafterprint;
+  [implicit_jscontext] attribute jsval onbeforeprint;
+  [implicit_jscontext] attribute jsval onbeforeunload;
+  [implicit_jscontext] attribute jsval onhashchange;
+  [implicit_jscontext] attribute jsval onmessage;
+  [implicit_jscontext] attribute jsval onoffline;
+  [implicit_jscontext] attribute jsval ononline;
+  [implicit_jscontext] attribute jsval onpopstate;
+  [implicit_jscontext] attribute jsval onpagehide;
+  [implicit_jscontext] attribute jsval onpageshow;
+  // Not supported yet
+  // [implicit_jscontext] attribute jsval onredo;
+  [implicit_jscontext] attribute jsval onresize;
+  // Not supported yet
+  // [implicit_jscontext] attribute jsval onstorage;
+  // Not supported yet
+  // [implicit_jscontext] attribute jsval onundo;
+  [implicit_jscontext] attribute jsval onunload;
+
+  /**
+   * Non-HTML5 window-specific event attributes
+   */
+  [implicit_jscontext] attribute jsval ondevicemotion;
+  [implicit_jscontext] attribute jsval ondeviceorientation;
 };
 
 [scriptable, uuid(2146c906-57f7-486c-a1b4-8cdb57ef577f)]
 interface nsIDOMWindowPerformance : nsISupports
 {
   /**
    * A namespace to hold performance related data and statistics.
    */
--- a/dom/interfaces/core/Makefile.in
+++ b/dom/interfaces/core/Makefile.in
@@ -69,11 +69,12 @@ XPIDLSRCS =                             
 	nsIDOMNameList.idl			\
 	nsIDOMXMLDocument.idl			\
 	nsIDOMUserDataHandler.idl		\
 	nsIDOMNSEditableElement.idl		\
 	nsIDOMNSElement.idl			\
 	nsIDOMNodeSelector.idl			\
 	nsIDOMDOMTokenList.idl			\
 	nsIDOMDOMSettableTokenList.idl	\
+	nsIInlineEventHandlers.idl              \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/core/nsIInlineEventHandlers.idl
@@ -0,0 +1,110 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *     Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "domstubs.idl"
+
+%{ C++
+#include "jspubtd.h"
+%}
+
+[scriptable, uuid(c3cc4504-1eaf-42e9-8b1b-a3020f6d3a28)]
+interface nsIInlineEventHandlers : nsISupports
+{
+  [implicit_jscontext] attribute jsval onabort;
+  [implicit_jscontext] attribute jsval onblur;
+  [implicit_jscontext] attribute jsval oncanplay;
+  [implicit_jscontext] attribute jsval oncanplaythrough;
+  [implicit_jscontext] attribute jsval onchange;
+  [implicit_jscontext] attribute jsval onclick;
+  [implicit_jscontext] attribute jsval oncontextmenu;
+  // Not supported yet
+  // [implicit_jscontext] attribute jsval oncuechange;
+  [implicit_jscontext] attribute jsval ondblclick;
+  [implicit_jscontext] attribute jsval ondrag;
+  [implicit_jscontext] attribute jsval ondragend;
+  [implicit_jscontext] attribute jsval ondragenter;
+  [implicit_jscontext] attribute jsval ondragleave;
+  [implicit_jscontext] attribute jsval ondragover;
+  [implicit_jscontext] attribute jsval ondragstart;
+  [implicit_jscontext] attribute jsval ondrop;
+  [implicit_jscontext] attribute jsval ondurationchange;
+  [implicit_jscontext] attribute jsval onemptied;
+  [implicit_jscontext] attribute jsval onended;
+  [implicit_jscontext] attribute jsval onerror;
+  [implicit_jscontext] attribute jsval onfocus;
+  [implicit_jscontext] attribute jsval oninput;
+  [implicit_jscontext] attribute jsval oninvalid;
+  [implicit_jscontext] attribute jsval onkeydown;
+  [implicit_jscontext] attribute jsval onkeypress;
+  [implicit_jscontext] attribute jsval onkeyup;
+  [implicit_jscontext] attribute jsval onload;
+  [implicit_jscontext] attribute jsval onloadeddata;
+  [implicit_jscontext] attribute jsval onloadedmetadata;
+  [implicit_jscontext] attribute jsval onloadstart;
+  [implicit_jscontext] attribute jsval onmousedown;
+  [implicit_jscontext] attribute jsval onmousemove;
+  [implicit_jscontext] attribute jsval onmouseout;
+  [implicit_jscontext] attribute jsval onmouseover;
+  [implicit_jscontext] attribute jsval onmouseup;
+  // Not supported yet
+  // [implicit_jscontext] attribute jsval onmousewheel;
+  [implicit_jscontext] attribute jsval onpause;
+  [implicit_jscontext] attribute jsval onplay;
+  [implicit_jscontext] attribute jsval onplaying;
+  [implicit_jscontext] attribute jsval onprogress;
+  [implicit_jscontext] attribute jsval onratechange;
+  [implicit_jscontext] attribute jsval onreadystatechange;
+  [implicit_jscontext] attribute jsval onreset;
+  [implicit_jscontext] attribute jsval onscroll;
+  [implicit_jscontext] attribute jsval onseeked;
+  [implicit_jscontext] attribute jsval onseeking;
+  [implicit_jscontext] attribute jsval onselect;
+  [implicit_jscontext] attribute jsval onshow;
+  [implicit_jscontext] attribute jsval onstalled;
+  [implicit_jscontext] attribute jsval onsubmit;
+  [implicit_jscontext] attribute jsval onsuspend;
+  [implicit_jscontext] attribute jsval ontimeupdate;
+  [implicit_jscontext] attribute jsval onvolumechange;
+  [implicit_jscontext] attribute jsval onwaiting;
+
+  /**
+   * Non-HTML5 event attributes
+   */
+  [implicit_jscontext] attribute jsval oncopy;
+  [implicit_jscontext] attribute jsval oncut;
+  [implicit_jscontext] attribute jsval onpaste;
+  [implicit_jscontext] attribute jsval onbeforescriptexecute;
+  [implicit_jscontext] attribute jsval onafterscriptexecute;  
+};
--- a/dom/interfaces/events/nsIDOMTouchEvent.idl
+++ b/dom/interfaces/events/nsIDOMTouchEvent.idl
@@ -85,16 +85,22 @@ interface nsIDOMTouchEvent : nsIDOMUIEve
                       in boolean metaKey,
                       in nsIDOMTouchList touches,
                       in nsIDOMTouchList targetTouches,
                       in nsIDOMTouchList changedTouches);
 };
 
 [scriptable, uuid(6d5484f7-92ac-45f8-9388-39b5bad055ce)]
 interface nsITouchEventReceiver : nsISupports {
+  [implicit_jscontext] attribute jsval           ontouchstart;
+  [implicit_jscontext] attribute jsval           ontouchend;
+  [implicit_jscontext] attribute jsval           ontouchmove;
+  [implicit_jscontext] attribute jsval           ontouchenter;
+  [implicit_jscontext] attribute jsval           ontouchleave;
+  [implicit_jscontext] attribute jsval           ontouchcancel;
 };
 
 [scriptable, uuid(974cff68-6f0b-4520-8523-fa68b2754656)]
 interface nsIDOMDocumentTouch : nsITouchEventReceiver {
   nsIDOMTouch createTouch([optional] in nsIDOMWindow view,
                           [optional] in nsIDOMEventTarget target,
                           [optional] in long identifier,
                           [optional] in long pageX,
--- a/dom/interfaces/html/nsIDOMHTMLBodyElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLBodyElement.idl
@@ -34,29 +34,52 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMHTMLElement.idl"
 
+%{ C++
+#include "jspubtd.h"
+%}
+
 /**
  * The nsIDOMHTMLBodyElement interface is the interface to a [X]HTML
  * body element.
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
-[scriptable, uuid(87db4ba2-367d-4604-ad36-b97cc09bf3f1)]
+[scriptable, uuid(9569e420-137a-4c7e-a880-288a81f78308)]
 interface nsIDOMHTMLBodyElement : nsIDOMHTMLElement
 {
            attribute DOMString        aLink;
            attribute DOMString        background;
            attribute DOMString        bgColor;
            attribute DOMString        link;
            attribute DOMString        text;
            attribute DOMString        vLink;
+
+           [implicit_jscontext] attribute jsval            onafterprint;
+           [implicit_jscontext] attribute jsval            onbeforeprint;
+           [implicit_jscontext] attribute jsval            onbeforeunload;
+           [implicit_jscontext] attribute jsval            onhashchange;
+           [implicit_jscontext] attribute jsval            onmessage;
+           [implicit_jscontext] attribute jsval            onoffline;
+           [implicit_jscontext] attribute jsval            ononline;
+           [implicit_jscontext] attribute jsval            onpagehide;
+           [implicit_jscontext] attribute jsval            onpageshow;
+           [implicit_jscontext] attribute jsval            onpopstate;
+           // Not supported yet
+           // [implicit_jscontext] attribute jsval            onredo;
+           [implicit_jscontext] attribute jsval            onresize;
+           // Not supported yet
+           // [implicit_jscontext] attribute jsval            onstorage;
+           // Not supported yet
+           // [implicit_jscontext] attribute jsval            onundo;
+           [implicit_jscontext] attribute jsval            onunload;
 };
--- a/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLFrameSetElement.idl
@@ -34,25 +34,48 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMHTMLElement.idl"
 
+%{ C++
+#include "jspubtd.h"
+%}
+
 /**
  * The nsIDOMHTMLFrameSetElement interface is the interface to a
  * [X]HTML frameset element.
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
-[scriptable, uuid(a827ecd2-472d-4cf7-ae3b-21bca7e5c6aa)]
+[scriptable, uuid(d6872633-0f1c-4110-bf49-88713a3cad86)]
 interface nsIDOMHTMLFrameSetElement : nsIDOMHTMLElement
 {
            attribute DOMString        cols;
            attribute DOMString        rows;
+
+           [implicit_jscontext] attribute jsval            onafterprint;
+           [implicit_jscontext] attribute jsval            onbeforeprint;
+           [implicit_jscontext] attribute jsval            onbeforeunload;
+           [implicit_jscontext] attribute jsval            onhashchange;
+           [implicit_jscontext] attribute jsval            onmessage;
+           [implicit_jscontext] attribute jsval            onoffline;
+           [implicit_jscontext] attribute jsval            ononline;
+           [implicit_jscontext] attribute jsval            onpagehide;
+           [implicit_jscontext] attribute jsval            onpageshow;
+           [implicit_jscontext] attribute jsval            onpopstate;
+           // Not supported yet
+           // [implicit_jscontext] attribute jsval            onredo;
+           [implicit_jscontext] attribute jsval            onresize;
+           // Not supported yet
+           // [implicit_jscontext] attribute jsval            onstorage;
+           // Not supported yet
+           // [implicit_jscontext] attribute jsval            onundo;
+           [implicit_jscontext] attribute jsval            onunload;
 };
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -70,33 +70,40 @@ static EventListenerCounter sEventListen
 #endif
 
 /*
  * nsJSEventListener implementation
  */
 nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext,
                                      void *aScopeObject,
                                      nsISupports *aTarget,
-                                     nsIAtom* aType)
-  : nsIJSEventListener(aContext, aScopeObject, aTarget), mEventName(aType)
+                                     nsIAtom* aType,
+                                     void *aHandler)
+  : nsIJSEventListener(aContext, aScopeObject, aTarget, aHandler),
+    mEventName(aType)
 {
   // aScopeObject is the inner window's JS object, which we need to lock
   // until we are done with it.
   NS_ASSERTION(aScopeObject && aContext,
                "EventListener with no context or scope?");
   nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(), this,
                                    &NS_CYCLE_COLLECTION_NAME(nsJSEventListener),
                                    aScopeObject, PR_FALSE);
+  if (aHandler) {
+    nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(), this,
+                                     &NS_CYCLE_COLLECTION_NAME(nsJSEventListener),
+                                     aHandler, PR_TRUE);
+  }
 }
 
 nsJSEventListener::~nsJSEventListener() 
 {
   if (mContext)
     nsContentUtils::DropScriptObjects(mContext->GetScriptTypeID(), this,
-                                &NS_CYCLE_COLLECTION_NAME(nsJSEventListener));
+                                      &NS_CYCLE_COLLECTION_NAME(nsJSEventListener));
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTarget)
   if (tmp->mContext) {
     if (tmp->mContext->GetScriptTypeID() == nsIProgrammingLanguage::JAVASCRIPT) {
       NS_DROP_JS_OBJECTS(tmp, nsJSEventListener);
@@ -113,59 +120,39 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSEventListener)
   NS_IMPL_CYCLE_COLLECTION_TRACE_MEMBER_CALLBACK(tmp->mContext->GetScriptTypeID(),
                                                  mScopeObject)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_MEMBER_CALLBACK(tmp->mContext->GetScriptTypeID(),
+                                                 mHandler)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSEventListener)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
   NS_INTERFACE_MAP_ENTRY(nsIJSEventListener)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSEventListener)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSEventListener)
 
 nsresult
-nsJSEventListener::GetJSVal(const nsAString& aEventName, jsval* aJSVal)
+nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mTarget);
-  if (target && mContext) {
-    nsAutoString eventString = NS_LITERAL_STRING("on") + aEventName;
-    nsCOMPtr<nsIAtom> atomName = do_GetAtom(eventString);
-    nsScriptObjectHolder funcval(mContext);
-    nsresult rv = mContext->GetBoundEventHandler(mTarget, mScopeObject,
-                                                 atomName, funcval);
-    NS_ENSURE_SUCCESS(rv, rv);
-    jsval funval =
-      OBJECT_TO_JSVAL(static_cast<JSObject*>(static_cast<void*>(funcval)));
-    *aJSVal = funval;
-    return NS_OK;
-  }
-  return NS_ERROR_FAILURE;
-}
+  if (!target || !mContext || !mHandler)
+    return NS_ERROR_FAILURE;
 
-nsresult
-nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
-{
   nsresult rv;
   nsCOMPtr<nsIMutableArray> iargv;
 
-  nsScriptObjectHolder funcval(mContext);
-  rv = mContext->GetBoundEventHandler(mTarget, mScopeObject, mEventName,
-                                      funcval);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!funcval)
-    return NS_OK;
-
   PRBool handledScriptError = PR_FALSE;
   if (mEventName == nsGkAtoms::onerror) {
     nsCOMPtr<nsIPrivateDOMEvent> priv(do_QueryInterface(aEvent));
     NS_ENSURE_TRUE(priv, NS_ERROR_UNEXPECTED);
 
     nsEvent *event = priv->GetInternalNSEvent();
     if (event->message == NS_LOAD_ERROR &&
         event->eventStructType == NS_SCRIPT_ERROR_EVENT) {
@@ -215,17 +202,17 @@ nsJSEventListener::HandleEvent(nsIDOMEve
   JSContext* cx = nsnull;
   nsCOMPtr<nsIJSContextStack> stack =
     do_GetService("@mozilla.org/js/xpc/ContextStack;1");
   NS_ASSERTION(stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx &&
                GetScriptContextFromJSContext(cx) == mContext,
                "JSEventListener has wrong script context?");
 #endif
   nsCOMPtr<nsIVariant> vrv;
-  rv = mContext->CallEventHandler(mTarget, mScopeObject, funcval, iargv,
+  rv = mContext->CallEventHandler(mTarget, mScopeObject, mHandler, iargv,
                                   getter_AddRefs(vrv));
 
   if (NS_SUCCEEDED(rv)) {
     PRUint16 dataType = nsIDataType::VTYPE_VOID;
     if (vrv)
       vrv->GetDataType(&dataType);
 
     if (mEventName == nsGkAtoms::onbeforeunload) {
@@ -263,27 +250,40 @@ nsJSEventListener::HandleEvent(nsIDOMEve
         aEvent->PreventDefault();
       }
     }
   }
 
   return rv;
 }
 
+/* virtual */ void
+nsJSEventListener::SetHandler(void *aHandler)
+{
+  // Technically we should drop the old mHandler and hold the new
+  // one... except for JS this is a no-op, and we're really not
+  // pretending very hard to support anything else.  And since we
+  // can't in fact only drop one script object (we'd have to drop
+  // mScope too, and then re-hold it), let's just not worry about it
+  // all.
+  mHandler = aHandler;
+}
+
 /*
  * Factory functions
  */
 
 nsresult
 NS_NewJSEventListener(nsIScriptContext *aContext, void *aScopeObject,
                       nsISupports*aTarget, nsIAtom* aEventType,
-                      nsIDOMEventListener ** aReturn)
+                      void *aHandler, nsIDOMEventListener ** aReturn)
 {
   NS_ENSURE_ARG(aEventType);
   nsJSEventListener* it =
-    new nsJSEventListener(aContext, aScopeObject, aTarget, aEventType);
+    new nsJSEventListener(aContext, aScopeObject, aTarget, aEventType,
+                          aHandler);
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   NS_ADDREF(*aReturn = it);
 
   return NS_OK;
 }
--- a/dom/src/events/nsJSEventListener.h
+++ b/dom/src/events/nsJSEventListener.h
@@ -44,32 +44,30 @@
 #include "jsapi.h"
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 #include "nsIScriptContext.h"
 #include "nsCycleCollectionParticipant.h"
 
 // nsJSEventListener interface
 // misnamed - JS no longer has exclusive rights over this interface!
-class nsJSEventListener : public nsIDOMEventListener,
-                          public nsIJSEventListener
+class nsJSEventListener : public nsIJSEventListener
 {
 public:
   nsJSEventListener(nsIScriptContext *aContext, void *aScopeObject,
-                    nsISupports* aObject, nsIAtom* aType);
+                    nsISupports* aTarget, nsIAtom* aType, void *aHandler);
   virtual ~nsJSEventListener();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMEventListener interface
   NS_DECL_NSIDOMEVENTLISTENER
 
-  // nsIJSEventListener interface
-  virtual nsresult GetJSVal(const nsAString& aEventName, jsval* aJSVal);
+  // nsIJSEventListener
+  virtual void SetHandler(void *aHandler);
 
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSEventListener,
-                                                         nsIDOMEventListener)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsJSEventListener)
 protected:
   nsCOMPtr<nsIAtom> mEventName;
 };
 
 #endif //nsJSEventListener_h__
 
--- a/dom/tests/mochitest/bugs/test_bug159849.html
+++ b/dom/tests/mochitest/bugs/test_bug159849.html
@@ -25,17 +25,17 @@ var c = $("content");
 with (c) {
   onmouseover = testFunc;
   fooExpando = testFunc;
 }
 
 is(c.onmouseover, testFunc, "Event handler should have been set on node");
 ok(c.fooExpando === undefined, "Expando should not have been set on node",
    "got " + repr(c.fooExpando) + ", expected undefined");
-ok(window.onmouseover === undefined,
+ok(window.onmouseover === null,
    "Event handler should not have been set on window",
    "got " + repr(window.onmouseover) + ", expected undefined");
 is(window.fooExpando, testFunc, "Expando should have been set on window");
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/tests/mochitest/bugs/test_bug583225.html
+++ b/dom/tests/mochitest/bugs/test_bug583225.html
@@ -24,17 +24,17 @@ function clicked()
   ok(true, "Event fired on DocumentFragment.");
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 
 var docFragment = document.createDocumentFragment();
 docFragment.foo = "foo";
-docFragment.onclick = clicked;
+docFragment.addEventListener("click", clicked, false);
 var event = document.createEvent('MouseEvent');
 event.initMouseEvent('click', true, true, window,  1, 0, 0, 0, 0, false, false,
                      false, false, 0, docFragment);
 docFragment.dispatchEvent(event);
 
 </script>
 </pre>
 </body>