author | Olli Pettay <Olli.Pettay@helsinki.fi> |
Wed, 14 Dec 2011 21:53:48 +0200 | |
changeset 82579 | 01a26239462a99c30b0b153f128db081a959845a |
parent 82578 | 4d2921df8f341b1e0d6e35594902875684a6ee77 |
child 82580 | 1ab5ed4f93bf3d395c025ea387858c21c4eb0bf4 |
push id | 21672 |
push user | opettay@mozilla.com |
push date | Wed, 14 Dec 2011 20:37:16 +0000 |
treeherder | mozilla-central@0507a68e994b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jst |
bugs | 675884 |
milestone | 11.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
|
--- 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; +};