Bug 708701 - Implement HTML event ctors, r=jst
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Wed, 14 Dec 2011 21:55:32 +0200
changeset 84220 141ae3a6ccd2dd8074ef3174e791f2831bb86d80
parent 84219 1ab5ed4f93bf3d395c025ea387858c21c4eb0bf4
child 84221 0507a68e994b1b2170d4f260c45f2b6c7654133e
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst
bugs708701
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 708701 - Implement HTML event ctors, r=jst
content/events/public/nsIPrivateDOMEvent.h
content/events/src/nsDOMCloseEvent.cpp
content/events/src/nsDOMCloseEvent.h
content/events/src/nsDOMCustomEvent.cpp
content/events/src/nsDOMCustomEvent.h
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEvent.h
content/events/src/nsDOMHashChangeEvent.cpp
content/events/src/nsDOMHashChangeEvent.h
content/events/src/nsDOMPageTransitionEvent.cpp
content/events/src/nsDOMPageTransitionEvent.h
content/events/src/nsDOMPopStateEvent.cpp
content/events/src/nsDOMPopStateEvent.h
content/events/test/test_eventctors.html
dom/base/nsDOMClassInfo.cpp
dom/interfaces/events/nsIDOMCloseEvent.idl
dom/interfaces/events/nsIDOMHashChangeEvent.idl
dom/interfaces/events/nsIDOMPageTransitionEvent.idl
dom/interfaces/events/nsIDOMPopStateEvent.idl
--- a/content/events/public/nsIPrivateDOMEvent.h
+++ b/content/events/public/nsIPrivateDOMEvent.h
@@ -141,9 +141,13 @@ NS_NewDOMCloseEvent(nsIDOMEvent** aInsta
 nsresult
 NS_NewDOMMozTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsMozTouchEvent* aEvent);
 nsresult
 NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
 nsresult
 NS_NewDOMCustomEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
 nsresult
 NS_NewDOMSmsEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
+nsresult
+NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
+nsresult
+NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
 #endif // nsIPrivateDOMEvent_h__
--- a/content/events/src/nsDOMCloseEvent.cpp
+++ b/content/events/src/nsDOMCloseEvent.cpp
@@ -84,16 +84,44 @@ nsDOMCloseEvent::InitCloseEvent(const ns
   mWasClean = aWasClean;
   mReasonCode = aReasonCode;
   mReason = aReason;
 
   return NS_OK;
 }
 
 nsresult
+nsDOMCloseEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                              JSContext* aCx, JSObject* aObj)
+{
+  nsCOMPtr<nsICloseEventInit> eventInit = do_QueryInterface(aDict);
+  bool bubbles = false;
+  bool cancelable = false;
+  bool wasClean = false;
+  PRUint16 code = 0;
+  nsAutoString reason;
+  if (eventInit) {
+    nsresult rv = eventInit->GetBubbles(&bubbles);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetCancelable(&cancelable);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetWasClean(&wasClean);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetCode(&code);
+    NS_ENSURE_SUCCESS(rv, rv);
+    JSBool found = JS_FALSE;
+    if (JS_HasProperty(aCx, aObj, "reason", &found) && found) {
+      rv = eventInit->GetReason(reason);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }
+  return InitCloseEvent(aType, bubbles, cancelable, wasClean, code, reason);
+}
+
+nsresult
 NS_NewDOMCloseEvent(nsIDOMEvent** aInstancePtrResult,
                     nsPresContext* aPresContext,
                     nsEvent* aEvent) 
 {
   nsDOMCloseEvent* it = new nsDOMCloseEvent(aPresContext, aEvent);
   if (nsnull == it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/content/events/src/nsDOMCloseEvent.h
+++ b/content/events/src/nsDOMCloseEvent.h
@@ -59,15 +59,18 @@ public:
                      
   NS_DECL_ISUPPORTS_INHERITED
 
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
 
   NS_DECL_NSIDOMCLOSEEVENT
 
+  virtual const nsIID& EventInitIID() { return NS_GET_IID(nsICloseEventInit); }
+  virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                JSContext* aCx, JSObject* aObj);
 private:
   bool mWasClean;
   PRUint16 mReasonCode;
   nsString mReason;
 };
 
 #endif // nsDOMCloseEvent_h__
--- a/content/events/src/nsDOMCustomEvent.cpp
+++ b/content/events/src/nsDOMCustomEvent.cpp
@@ -74,17 +74,18 @@ nsDOMCustomEvent::InitCustomEvent(const 
   nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mDetail = aDetail;
   return NS_OK;
 }
 
 nsresult
-nsDOMCustomEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict)
+nsDOMCustomEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                               JSContext* aCx, JSObject* aObj)
 {
   nsCOMPtr<nsICustomEventInit> eventInit = do_QueryInterface(aDict);
   bool bubbles = false;
   bool cancelable = false;
   nsCOMPtr<nsIVariant> detail;
   if (eventInit) {
     nsresult rv = eventInit->GetBubbles(&bubbles);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/content/events/src/nsDOMCustomEvent.h
+++ b/content/events/src/nsDOMCustomEvent.h
@@ -55,14 +55,15 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMCustomEvent, nsDOMEvent)
 
   NS_DECL_NSIDOMCUSTOMEVENT
 
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
 
   virtual const nsIID& EventInitIID() { return NS_GET_IID(nsICustomEventInit); }
-  virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict);
+  virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                JSContext* aCx, JSObject* aObj);
 private:
   nsCOMPtr<nsIVariant> mDetail;
 };
 
 #endif // nsDOMCustomEvent_h__
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -406,30 +406,33 @@ nsDOMEvent::Initialize(nsISupports* aOwn
   }
 
   JS::Anchor<JSString*> deleteProtector(jsstr);
 
   nsDependentJSString type;
   NS_ENSURE_STATE(type.init(aCx, jsstr));
   
   nsCOMPtr<nsISupports> dict;
+  JSObject* obj = nsnull;
   if (aArgc >= 2 && !JSVAL_IS_PRIMITIVE(aArgv[1])) {
-    nsContentUtils::XPConnect()->WrapJS(aCx, JSVAL_TO_OBJECT(aArgv[1]),
+    obj = JSVAL_TO_OBJECT(aArgv[1]);
+    nsContentUtils::XPConnect()->WrapJS(aCx, obj,
                                         EventInitIID(),
                                         getter_AddRefs(dict));
   }
-  nsresult rv = InitFromCtor(type, dict);
+  nsresult rv = InitFromCtor(type, dict, aCx, obj);
   NS_ENSURE_SUCCESS(rv, rv);
 
   SetTrusted(trusted);
   return NS_OK;
 }
 
 nsresult
-nsDOMEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict)
+nsDOMEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                         JSContext* aCx, JSObject* aObj)
 {
   nsCOMPtr<nsIEventInit> eventInit = do_QueryInterface(aDict);
   bool bubbles = false;
   bool cancelable = false;
   if (eventInit) {
     nsresult rv = eventInit->GetBubbles(&bubbles);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = eventInit->GetCancelable(&cancelable);
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -48,16 +48,18 @@
 #include "nsPoint.h"
 #include "nsGUIEvent.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
 #include "nsIJSNativeInitializer.h"
 
 class nsIContent;
 class nsPresContext;
+class JSContext;
+class JSObject;
  
 class nsDOMEvent : public nsIDOMEvent,
                    public nsIDOMNSEvent,
                    public nsIPrivateDOMEvent,
                    public nsIJSNativeInitializer
 {
 public:
 
@@ -221,17 +223,18 @@ public:
   NS_IMETHOD_(nsEvent*)    GetInternalNSEvent();
   NS_IMETHOD    SetTrusted(bool aTrusted);
 
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
                         PRUint32 aArgc, jsval* aArgv);
 
   virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIEventInit); }
-  virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict);
+  virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                JSContext* aCx, JSObject* aObj);
 
   void InitPresContextData(nsPresContext* aPresContext);
 
   virtual void Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType);
   virtual bool Deserialize(const IPC::Message* aMsg, void** aIter);
 
   static PopupControlState GetEventPopupControlState(nsEvent *aEvent);
 
--- a/content/events/src/nsDOMHashChangeEvent.cpp
+++ b/content/events/src/nsDOMHashChangeEvent.cpp
@@ -73,16 +73,44 @@ nsDOMHashChangeEvent::InitHashChangeEven
   nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mOldURL.Assign(aOldURL);
   mNewURL.Assign(aNewURL);
   return NS_OK;
 }
 
+nsresult
+nsDOMHashChangeEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                   JSContext* aCx, JSObject* aObj)
+{
+  nsCOMPtr<nsIHashChangeEventInit> eventInit = do_QueryInterface(aDict);
+  bool bubbles = false;
+  bool cancelable = false;
+  nsAutoString oldURL;
+  nsAutoString newURL;
+  if (eventInit) {
+    nsresult rv = eventInit->GetBubbles(&bubbles);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetCancelable(&cancelable);
+    NS_ENSURE_SUCCESS(rv, rv);
+    JSBool found = JS_FALSE;
+    if (JS_HasProperty(aCx, aObj, "oldURL", &found) && found) {
+      rv = eventInit->GetOldURL(oldURL);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+    found = JS_FALSE;
+    if (JS_HasProperty(aCx, aObj, "newURL", &found) && found) {
+      rv = eventInit->GetNewURL(newURL);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }
+  return InitHashChangeEvent(aType, bubbles, cancelable, oldURL, newURL);
+}
+
 nsresult NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult,
                                 nsPresContext* aPresContext,
                                 nsEvent* aEvent)
 {
   nsDOMHashChangeEvent* event =
     new nsDOMHashChangeEvent(aPresContext, aEvent);
 
   return CallQueryInterface(event, aInstancePtrResult);
--- a/content/events/src/nsDOMHashChangeEvent.h
+++ b/content/events/src/nsDOMHashChangeEvent.h
@@ -53,18 +53,17 @@ public:
 
   virtual ~nsDOMHashChangeEvent();
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMHASHCHANGEEVENT
 
   NS_FORWARD_TO_NSDOMEVENT
 
+  virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIHashChangeEventInit); }
+  virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                JSContext* aCx, JSObject* aObj);
 protected:
   nsString mOldURL;
   nsString mNewURL;
 };
 
-nsresult NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult,
-                                  nsPresContext* aPresContext,
-                                  nsEvent* aEvent);
-
 #endif // nsDOMHashChangeEvent_h__
--- a/content/events/src/nsDOMPageTransitionEvent.cpp
+++ b/content/events/src/nsDOMPageTransitionEvent.cpp
@@ -64,16 +64,35 @@ nsDOMPageTransitionEvent::InitPageTransi
 {
   nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mPersisted = aPersisted;
   return NS_OK;
 }
 
+nsresult
+nsDOMPageTransitionEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                       JSContext* aCx, JSObject* aObj)
+{
+  nsCOMPtr<nsIPageTransitionEventInit> eventInit = do_QueryInterface(aDict);
+  bool bubbles = false;
+  bool cancelable = false;
+  bool persisted = false;
+  if (eventInit) {
+    nsresult rv = eventInit->GetBubbles(&bubbles);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetCancelable(&cancelable);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetPersisted(&persisted);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return InitPageTransitionEvent(aType, bubbles, cancelable, persisted);
+}
+
 nsresult NS_NewDOMPageTransitionEvent(nsIDOMEvent** aInstancePtrResult,
                                       nsPresContext* aPresContext,
                                       nsEvent *aEvent) 
 {
   nsDOMPageTransitionEvent* it =
     new nsDOMPageTransitionEvent(aPresContext, aEvent);
   if (nsnull == it) {
     return NS_ERROR_OUT_OF_MEMORY;
--- a/content/events/src/nsDOMPageTransitionEvent.h
+++ b/content/events/src/nsDOMPageTransitionEvent.h
@@ -50,13 +50,17 @@ public:
   nsDOMEvent(aPresContext, aEvent), mPersisted(false) {}
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIDOMPAGETRANSITIONEVENT
 
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
+
+  virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIPageTransitionEventInit); }
+  virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                JSContext* aCx, JSObject* aObj);
 protected:
   bool mPersisted;
 };
 
 #endif // nsDOMPageTransitionEvent_h__
--- a/content/events/src/nsDOMPopStateEvent.cpp
+++ b/content/events/src/nsDOMPopStateEvent.cpp
@@ -78,16 +78,35 @@ nsDOMPopStateEvent::InitPopStateEvent(co
 {
   nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mState = aStateArg;
   return NS_OK;
 }
 
+nsresult
+nsDOMPopStateEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                 JSContext* aCx, JSObject* aObj)
+{
+  nsCOMPtr<nsIPopStateEventInit> eventInit = do_QueryInterface(aDict);
+  bool bubbles = false;
+  bool cancelable = false;
+  nsCOMPtr<nsIVariant> state;
+  if (eventInit) {
+    nsresult rv = eventInit->GetBubbles(&bubbles);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetCancelable(&cancelable);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetState(getter_AddRefs(state));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return InitPopStateEvent(aType, bubbles, cancelable, state);
+}
+
 nsresult NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult,
                                 nsPresContext* aPresContext,
                                 nsEvent* aEvent)
 {
   nsDOMPopStateEvent* event =
     new nsDOMPopStateEvent(aPresContext, aEvent);
 
   if (!event) {
--- a/content/events/src/nsDOMPopStateEvent.h
+++ b/content/events/src/nsDOMPopStateEvent.h
@@ -55,17 +55,16 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMPopStateEvent, nsDOMEvent)
 
   NS_DECL_NSIDOMPOPSTATEEVENT
 
   NS_FORWARD_TO_NSDOMEVENT
 
+  virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIPopStateEventInit); }
+  virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
+                                JSContext* aCx, JSObject* aObj);
 protected:
   nsCOMPtr<nsIVariant> mState;
 };
 
-nsresult NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult,
-                                nsPresContext* aPresContext,
-                                nsEvent* aEvent);
-
 #endif // nsDOMPopStateEvent_h__
--- a/content/events/test/test_eventctors.html
+++ b/content/events/test/test_eventctors.html
@@ -104,14 +104,180 @@ var dict = { get detail() { throw "foo";
 try {
   e = new CustomEvent("hello", dict);
 } catch (exp) {
   ex = true;
 }
 ok(ex, "Should have thrown an exception!");
 ex = false;
 
+// CloseEvent
+
+try {
+  e = new CloseEvent();
+} catch(exp) {
+  ex = true;
+}
+ok(ex, "First parameter is required!");
+ex = false;
+
+e = new CloseEvent("hello");
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+is(e.wasClean, false, "wasClean should be false!");
+is(e.code, 0, "code should be 0!");
+is(e.reason, "", "reason should be ''!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new CloseEvent("hello",
+  { bubbles: true, cancelable: true, wasClean: true, code: 1, reason: "foo" });
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(e.bubbles, "Event should bubble!");
+ok(e.cancelable, "Event should be cancelable!");
+is(e.wasClean, true, "wasClean should be true!");
+is(e.code, 1, "code should be 1!");
+is(e.reason, "foo", "reason should be 'foo'!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new CloseEvent("hello",
+  { bubbles: true, cancelable: true, wasClean: true, code: 1 });
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(e.bubbles, "Event should bubble!");
+ok(e.cancelable, "Event should be cancelable!");
+is(e.wasClean, true, "wasClean should be true!");
+is(e.code, 1, "code should be 1!");
+is(e.reason, "", "reason should be ''!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+
+// HashChangeEvent
+
+try {
+  e = new HashChangeEvent();
+} catch(exp) {
+  ex = true;
+}
+ok(ex, "First parameter is required!");
+ex = false;
+
+e = new HashChangeEvent("hello");
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+is(e.oldURL, "", "oldURL should be ''");
+is(e.newURL, "", "newURL should be ''");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new HashChangeEvent("hello",
+  { bubbles: true, cancelable: true, oldURL: "old", newURL: "new" });
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(e.bubbles, "Event should bubble!");
+ok(e.cancelable, "Event should be cancelable!");
+is(e.oldURL, "old", "oldURL should be 'old'");
+is(e.newURL, "new", "newURL should be 'new'");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new HashChangeEvent("hello",
+  { bubbles: true, cancelable: true, newURL: "new" });
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(e.bubbles, "Event should bubble!");
+ok(e.cancelable, "Event should be cancelable!");
+is(e.oldURL, "", "oldURL should be ''");
+is(e.newURL, "new", "newURL should be 'new'");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+// PageTransitionEvent
+
+try {
+  e = new PageTransitionEvent();
+} catch(exp) {
+  ex = true;
+}
+ok(ex, "First parameter is required!");
+ex = false;
+
+e = new PageTransitionEvent("hello");
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+is(e.persisted, false, "persisted should be false");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new PageTransitionEvent("hello",
+  { bubbles: true, cancelable: true, persisted: true});
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(e.bubbles, "Event should bubble!");
+ok(e.cancelable, "Event should be cancelable!");
+is(e.persisted, true, "persisted should be true");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new PageTransitionEvent("hello", { persisted: true});
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+is(e.persisted, true, "persisted should be true");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+// PopStateEvent
+
+try {
+  e = new PopStateEvent();
+} catch(exp) {
+  ex = true;
+}
+ok(ex, "First parameter is required!");
+ex = false;
+
+e = new PopStateEvent("hello");
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+is(e.state, null, "persisted should be null");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new PopStateEvent("hello",
+  { bubbles: true, cancelable: true, state: window});
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(e.bubbles, "Event should bubble!");
+ok(e.cancelable, "Event should be cancelable!");
+is(e.state, window, "persisted should be window");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+
+e = new PopStateEvent("hello", { state: window});
+ok(e.type, "hello", "Wrong event type!");
+ok(!e.isTrusted, "Event shouldn't be trusted!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+is(e.state, window, "persisted should be window");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+
 SimpleTest.finish();
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1582,16 +1582,20 @@ static const nsContractIDMapData kConstr
     nsIDOMEvent* e = nsnull;                                \
     nsresult rv = NS_NewDOM##_class(&e, nsnull, nsnull);    \
     *aInstancePtrResult = e;                                \
     return rv;                                              \
   }
 
 NS_DEFINE_EVENT_CTOR(Event)
 NS_DEFINE_EVENT_CTOR(CustomEvent)
+NS_DEFINE_EVENT_CTOR(PopStateEvent)
+NS_DEFINE_EVENT_CTOR(HashChangeEvent)
+NS_DEFINE_EVENT_CTOR(PageTransitionEvent)
+NS_DEFINE_EVENT_CTOR(CloseEvent)
 
 struct nsConstructorFuncMapData
 {
   PRInt32 mDOMClassInfoID;
   nsDOMConstructorFunc mConstructorFunc;
 };
 
 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func)                        \
@@ -1601,16 +1605,20 @@ struct nsConstructorFuncMapData
   { eDOMClassInfo_##_class##_id, NS_DOM##_class##Ctor },
 
 static const nsConstructorFuncMapData kConstructorFuncMap[] =
 {
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFileFile::NewFile)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozBlobBuilder, NS_NewBlobBuilder)
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(Event)
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(CustomEvent)
+  NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(PopStateEvent)
+  NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(HashChangeEvent)
+  NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(PageTransitionEvent)
+  NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(CloseEvent)
 };
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull;
 bool nsDOMClassInfo::sIsInitialized = false;
 bool nsDOMClassInfo::sDisableDocumentAllSupport = false;
 bool nsDOMClassInfo::sDisableGlobalScopePollutionSupport = false;
 
--- a/dom/interfaces/events/nsIDOMCloseEvent.idl
+++ b/dom/interfaces/events/nsIDOMCloseEvent.idl
@@ -54,8 +54,16 @@ interface nsIDOMCloseEvent : nsIDOMEvent
 
   void initCloseEvent(in DOMString aType,
                       in boolean aCanBubble,
                       in boolean aCancelable,
                       in boolean aWasClean,
                       in unsigned short aReasonCode,
                       in DOMString aReason);
 };
+
+[scriptable, uuid(148ed08e-14f1-4be5-b2f8-23f765738379)]
+interface nsICloseEventInit : nsIEventInit
+{
+  attribute boolean wasClean;
+  attribute unsigned short code;
+  attribute DOMString reason;
+};
--- a/dom/interfaces/events/nsIDOMHashChangeEvent.idl
+++ b/dom/interfaces/events/nsIDOMHashChangeEvent.idl
@@ -41,8 +41,15 @@ interface nsIDOMHashChangeEvent : nsIDOM
   readonly attribute DOMString newURL;
 
   void initHashChangeEvent(in DOMString typeArg,
                            in boolean canBubbleArg,
                            in boolean cancelableArg,
                            in DOMString oldURLArg,
                            in DOMString newURLArg);
 };
+
+[scriptable, uuid(e56881c1-3714-45bb-bca3-1453ea24ee90)]
+interface nsIHashChangeEventInit : nsIEventInit
+{
+  attribute DOMString oldURL;
+  attribute DOMString newURL;
+};
--- a/dom/interfaces/events/nsIDOMPageTransitionEvent.idl
+++ b/dom/interfaces/events/nsIDOMPageTransitionEvent.idl
@@ -55,8 +55,14 @@ interface nsIDOMPageTransitionEvent : ns
   readonly attribute boolean persisted;
 
   /* Initialize a new pageshow or pagehide event. */
   void initPageTransitionEvent(in DOMString typeArg,
                                in boolean canBubbleArg,
                                in boolean canCancelArg,
                                in boolean persisted);
 };
+
+[scriptable, uuid(bf3eaa61-5048-48c4-b8b9-9bf833ca63d6)]
+interface nsIPageTransitionEventInit : nsIEventInit
+{
+  attribute boolean persisted;
+};
--- a/dom/interfaces/events/nsIDOMPopStateEvent.idl
+++ b/dom/interfaces/events/nsIDOMPopStateEvent.idl
@@ -44,8 +44,14 @@ interface nsIDOMPopStateEvent : nsIDOMEv
    */
   readonly attribute nsIVariant state;
 
   void initPopStateEvent(in DOMString typeArg,
                          in boolean canBubbleArg,
                          in boolean cancelableArg,
                          in nsIVariant stateArg);
 };
+
+[scriptable, uuid(2300bd68-f6e0-4c58-a1aa-45f94cdabfbd)]
+interface nsIPopStateEventInit : nsIEventInit
+{
+  attribute nsIVariant state;
+};