Bug 708701 - Implement HTML event ctors, r=jst
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Wed, 14 Dec 2011 21:55:32 +0200
changeset 82581 141ae3a6ccd2dd8074ef3174e791f2831bb86d80
parent 82580 1ab5ed4f93bf3d395c025ea387858c21c4eb0bf4
child 82582 0507a68e994b1b2170d4f260c45f2b6c7654133e
push idunknown
push userunknown
push dateunknown
reviewersjst
bugs708701
milestone11.0a1
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;
+};