Bug 675884 - Implement Event constructors, part1, r=jst
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Wed, 14 Dec 2011 21:53:48 +0200
changeset 82579 01a26239462a99c30b0b153f128db081a959845a
parent 82578 4d2921df8f341b1e0d6e35594902875684a6ee77
child 82580 1ab5ed4f93bf3d395c025ea387858c21c4eb0bf4
push id21672
push useropettay@mozilla.com
push dateWed, 14 Dec 2011 20:37:16 +0000
treeherdermozilla-central@0507a68e994b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst
bugs675884
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 675884 - Implement Event constructors, part1, r=jst
content/events/src/nsDOMCustomEvent.cpp
content/events/src/nsDOMCustomEvent.h
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEvent.h
content/events/test/Makefile.in
content/events/test/test_eventctors.html
content/events/test/test_eventctors.xul
dom/base/nsDOMClassInfo.cpp
dom/interfaces/events/nsIDOMCustomEvent.idl
dom/interfaces/events/nsIDOMEvent.idl
--- a/content/events/src/nsDOMCustomEvent.cpp
+++ b/content/events/src/nsDOMCustomEvent.cpp
@@ -74,15 +74,33 @@ 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)
+{
+  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);
+    rv = eventInit->GetCancelable(&cancelable);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = eventInit->GetDetail(getter_AddRefs(detail));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return InitCustomEvent(aType, bubbles, cancelable, detail);
+}
+
+nsresult
 NS_NewDOMCustomEvent(nsIDOMEvent** aInstancePtrResult,
                      nsPresContext* aPresContext,
                      nsEvent* aEvent) 
 {
   nsDOMCustomEvent* e = new nsDOMCustomEvent(aPresContext, aEvent);
   return CallQueryInterface(e, aInstancePtrResult);
 }
--- a/content/events/src/nsDOMCustomEvent.h
+++ b/content/events/src/nsDOMCustomEvent.h
@@ -54,13 +54,15 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   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);
 private:
   nsCOMPtr<nsIVariant> mDetail;
 };
 
 #endif // nsDOMCustomEvent_h__
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -117,17 +117,16 @@ static const char* const sEventNames[] =
   "deviceorientation"
 };
 
 static char *sPopupAllowedEvents;
 
 
 nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
 {
-  mPresContext = aPresContext;
   mPrivateDataDuplicated = false;
 
   if (aEvent) {
     mEvent = aEvent;
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
@@ -154,27 +153,34 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aP
           }
           ...
         }
      */
     mEvent = new nsEvent(false, 0);
     mEvent->time = PR_Now();
   }
 
+  InitPresContextData(aPresContext);
+
+  NS_ASSERTION(mEvent->message != NS_PAINT, "Trying to create a DOM paint event!");
+}
+
+void
+nsDOMEvent::InitPresContextData(nsPresContext* aPresContext)
+{
+  mPresContext = aPresContext;
   // Get the explicit original target (if it's anonymous make it null)
   {
     nsCOMPtr<nsIContent> content = GetTargetFromFrame();
     mTmpRealOriginalTarget = do_QueryInterface(content);
     mExplicitOriginalTarget = mTmpRealOriginalTarget;
     if (content && content->IsInAnonymousSubtree()) {
       mExplicitOriginalTarget = nsnull;
     }
   }
-
-  NS_ASSERTION(mEvent->message != NS_PAINT, "Trying to create a DOM paint event!");
 }
 
 nsDOMEvent::~nsDOMEvent() 
 {
   NS_ASSERT_OWNINGTHREAD(nsDOMEvent);
 
   if (mEventIsInternal && mEvent) {
     delete mEvent;
@@ -185,16 +191,17 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEven
 
 DOMCI_DATA(Event, nsDOMEvent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEvent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNSEvent)
   NS_INTERFACE_MAP_ENTRY(nsIPrivateDOMEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Event)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEvent)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEvent)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent)
   if (tmp->mEventIsInternal) {
@@ -368,16 +375,80 @@ nsDOMEvent::SetTrusted(bool aTrusted)
   } else {
     mEvent->flags &= ~NS_EVENT_FLAG_TRUSTED;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMEvent::Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
+                       PRUint32 aArgc, jsval* aArgv)
+{
+  NS_ENSURE_TRUE(aArgc >= 1, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+  bool trusted = false;
+  nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aOwner);
+  if (w) {
+    nsCOMPtr<nsIDocument> d = do_QueryInterface(w->GetExtantDocument());
+    if (d) {
+      trusted = nsContentUtils::IsChromeDoc(d);
+      nsIPresShell* s = d->GetShell();
+      if (s) {
+        InitPresContextData(s->GetPresContext());
+      }
+    }
+  }
+
+  JSAutoRequest ar(aCx);
+  JSString* jsstr = JS_ValueToString(aCx, aArgv[0]);
+  if (!jsstr) {
+    return NS_ERROR_DOM_SYNTAX_ERR;
+  }
+
+  JS::Anchor<JSString*> deleteProtector(jsstr);
+  size_t length;
+  const jschar* chars = JS_GetStringCharsAndLength(aCx, jsstr, &length);
+  if (!chars) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  nsAutoString type;
+  type.Assign(chars, length);
+  deleteProtector.clear();
+  
+  nsCOMPtr<nsISupports> dict;
+  if (aArgc >= 2 && !JSVAL_IS_PRIMITIVE(aArgv[1])) {
+    nsContentUtils::XPConnect()->WrapJS(aCx, JSVAL_TO_OBJECT(aArgv[1]),
+                                        EventInitIID(),
+                                        getter_AddRefs(dict));
+  }
+  nsresult rv = InitFromCtor(type, dict);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  SetTrusted(trusted);
+  return NS_OK;
+}
+
+nsresult
+nsDOMEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict)
+{
+  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);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return InitEvent(aType, bubbles, cancelable);
+}
+
+NS_IMETHODIMP
 nsDOMEvent::GetEventPhase(PRUint16* aEventPhase)
 {
   // Note, remember to check that this works also
   // if or when Bug 235441 is fixed.
   if (mEvent->currentTarget == mEvent->target ||
       ((mEvent->flags & NS_EVENT_FLAG_CAPTURE) &&
        (mEvent->flags & NS_EVENT_FLAG_BUBBLE))) {
     *aEventPhase = nsIDOMEvent::AT_TARGET;
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -44,23 +44,25 @@
 #include "nsIPrivateDOMEvent.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMEventTarget.h"
 #include "nsPIDOMWindow.h"
 #include "nsPoint.h"
 #include "nsGUIEvent.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
+#include "nsIJSNativeInitializer.h"
 
 class nsIContent;
 class nsPresContext;
  
 class nsDOMEvent : public nsIDOMEvent,
                    public nsIDOMNSEvent,
-                   public nsIPrivateDOMEvent
+                   public nsIPrivateDOMEvent,
+                   public nsIJSNativeInitializer
 {
 public:
 
   // Note: this enum must be kept in sync with sEventNames in nsDOMEvent.cpp
   enum nsDOMEvents {
     eDOMEvents_mousedown=0,
     eDOMEvents_mouseup,
     eDOMEvents_click,
@@ -214,16 +216,25 @@ public:
 
   // nsIPrivateDOMEvent interface
   NS_IMETHOD    DuplicatePrivateData();
   NS_IMETHOD    SetTarget(nsIDOMEventTarget* aTarget);
   NS_IMETHOD_(bool)    IsDispatchStopped();
   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);
+
+  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);
 
   static void PopupAllowedEventsChanged();
 
   static void Shutdown();
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -107,16 +107,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug659350.html \
 		test_bug662678.html \
 		test_bug667919-1.html \
 		test_bug667919-2.html \
 		test_bug667612.html \
 		empty.js \
 		test_bug689564.html \
 		test_bug698929.html \
+		test_eventctors.html \
 		$(NULL)
 
 #bug 585630
 ifneq (mobile,$(MOZ_BUILD_APP))
 _TEST_FILES += \
 		test_dragstart.html \
 		$(NULL)
 endif
@@ -139,15 +140,16 @@ endif
 		test_bug591249.xul \
 		bug591249_iframe.xul \
 		bug602962.xul \
 		test_bug602962.xul \
 		test_bug617528.xul \
 		window_bug617528.xul \
 		test_bug679494.xul \
 		file_bug679494.html \
+		test_eventctors.xul \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_eventctors.html
@@ -0,0 +1,117 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=675884
+-->
+<head>
+  <title>Test for Bug 675884</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=675884">Mozilla Bug 675884</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 675884 **/
+
+var receivedEvent;
+document.addEventListener("hello", function(e) { receivedEvent = e; }, true);
+
+// Event
+var e;
+var ex = false;
+try {
+  e = new Event();
+} catch(exp) {
+  ex = true;
+}
+ok(ex, "First parameter is required!");
+ex = false;
+
+e = new Event("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!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new Event("hello", { bubbles: true, cancelable: 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!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+// CustomEvent
+
+try {
+  e = new CustomEvent();
+} catch(exp) {
+  ex = true;
+}
+ok(ex, "First parameter is required!");
+ex = false;
+
+e = new CustomEvent("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!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new CustomEvent("hello", { bubbles: true, cancelable: true, detail: 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.detail, window , "Wrong event.detail!");
+document.dispatchEvent(e);
+is(receivedEvent, e, "Wrong event!");
+
+e = new CustomEvent("hello", { cancelable: true, detail: 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 should be cancelable!");
+is(e.detail, window , "Wrong event.detail!");
+
+e = new CustomEvent("hello", { detail: 123 });
+is(e.detail, 123, "Wrong event.detail!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+
+var dict = { get detail() { return document.body } };
+e = new CustomEvent("hello", dict);
+is(e.detail, dict.detail, "Wrong event.detail!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+
+e = new CustomEvent("hello", 1234);
+is(e.detail, null, "Wrong event.detail!");
+ok(!e.bubbles, "Event shouldn't bubble!");
+ok(!e.cancelable, "Event shouldn't be cancelable!");
+
+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;
+
+SimpleTest.finish();
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_eventctors.xul
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=675884
+-->
+<window title="Mozilla Bug 675884"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=675884"
+     target="_blank">Mozilla Bug 675884</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 675884 **/
+  
+  // Most of the tests are in .html file, but test here that
+  // isTrusted is handled correctly in chrome.
+
+  var receivedEvent;
+  document.addEventListener("hello", function(e) { receivedEvent = e; }, true);
+  
+  // Event
+  var e;
+  var ex = false;
+  try {
+    e = new Event();
+  } catch(exp) {
+    ex = true;
+  }
+  ok(ex, "First parameter is required!");
+  ex = false;
+  
+  e = new Event("hello");
+  ok(e.type, "hello", "Wrong event type!");
+  ok(e.isTrusted, "Event should be trusted!");
+  ok(!e.bubbles, "Event shouldn't bubble!");
+  ok(!e.cancelable, "Event shouldn't be cancelable!");
+  document.dispatchEvent(e);
+  is(receivedEvent, e, "Wrong event!");
+  
+  SimpleTest.finish();
+
+  ]]>
+  </script>
+</window>
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -509,16 +509,17 @@
 #include "nsWrapperCacheInlines.h"
 #include "dombindings.h"
 
 #include "nsIDOMBatteryManager.h"
 #include "BatteryManager.h"
 #include "nsIDOMSmsManager.h"
 #include "nsIDOMSmsMessage.h"
 #include "nsIDOMSmsEvent.h"
+#include "nsIPrivateDOMEvent.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
@@ -1569,29 +1570,47 @@ static const nsContractIDMapData kConstr
   NS_DEFINE_CONSTRUCTOR_DATA(XMLHttpRequest, NS_XMLHTTPREQUEST_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(MozWebSocket, NS_WEBSOCKET_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(XPathEvaluator, NS_XPATH_EVALUATOR_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(XSLTProcessor,
                              "@mozilla.org/document-transformer;1?type=xslt")
   NS_DEFINE_CONSTRUCTOR_DATA(EventSource, NS_EVENTSOURCE_CONTRACTID)
 };
 
+#define NS_DEFINE_EVENT_CTOR(_class)                        \
+  nsresult                                                  \
+  NS_DOM##_class##Ctor(nsISupports** aInstancePtrResult)    \
+  {                                                         \
+    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)
+
 struct nsConstructorFuncMapData
 {
   PRInt32 mDOMClassInfoID;
   nsDOMConstructorFunc mConstructorFunc;
 };
 
 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func)                        \
   { eDOMClassInfo_##_class##_id, _func },
 
+#define NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(_class)   \
+  { 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)
 };
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull;
 bool nsDOMClassInfo::sIsInitialized = false;
 bool nsDOMClassInfo::sDisableDocumentAllSupport = false;
 bool nsDOMClassInfo::sDisableGlobalScopePollutionSupport = false;
 
--- a/dom/interfaces/events/nsIDOMCustomEvent.idl
+++ b/dom/interfaces/events/nsIDOMCustomEvent.idl
@@ -44,8 +44,14 @@ interface nsIDOMCustomEvent : nsIDOMEven
 
   readonly attribute nsIVariant detail;
 
   void initCustomEvent(in DOMString  typeArg, 
                        in boolean    canBubbleArg, 
                        in boolean    cancelableArg, 
                        in nsIVariant detailArg);
 };
+
+[scriptable, uuid(8c166794-06af-4eac-b76b-bc132e421b06)]
+interface nsICustomEventInit : nsIEventInit
+{
+  attribute nsIVariant detail;
+};
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -176,8 +176,15 @@ interface nsIDOMEvent : nsISupports
   readonly attribute boolean defaultPrevented;
 
   /**
    * Prevents other event listeners from being triggered and,
    * unlike Event.stopPropagation() its effect is immediate.
    */
   void                       stopImmediatePropagation();
 };
+
+[scriptable, uuid(fe864f0f-45df-404a-bb27-83c5d08be8d1)]
+interface nsIEventInit : nsISupports
+{
+  attribute boolean bubbles;
+  attribute boolean cancelable;
+};