mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 506961 - Add a method to get jsdIValue from JS implemented event listeners, r=bz
--HG-- extra : rebase_source : 93d446c1c94512be8cc0dc208c0bf8f1cd3cc936
This commit is contained in:
parent
547f5923a6
commit
79701a2085
@ -43,7 +43,7 @@ interface nsIDOMEventTarget;
|
||||
* An instance of this interface describes how an event listener
|
||||
* was added to an event target.
|
||||
*/
|
||||
[scriptable, uuid(4f132988-4709-44e5-985c-9e16d0f7c954)]
|
||||
[scriptable, uuid(cbc2ea6e-4043-4435-ba8f-64cbf6638622)]
|
||||
interface nsIEventListenerInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -59,6 +59,12 @@ interface nsIEventListenerInfo : nsISupports
|
||||
* (for example with C++ listeners).
|
||||
*/
|
||||
AString toSource();
|
||||
|
||||
/**
|
||||
* If jsdIDebuggerService is active and the listener is implemented in JS,
|
||||
* this returns the listener as a jsdIValue. Otherwise null.
|
||||
*/
|
||||
nsISupports getDebugObject();
|
||||
};
|
||||
|
||||
[scriptable, uuid(551cac0f-31ed-45e0-8d67-bc0d6e117b31)]
|
||||
|
@ -100,3 +100,9 @@ LOCAL_INCLUDES = \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
||||
ifdef MOZ_JSDEBUGGER
|
||||
DEFINES += -DMOZ_JSDEBUGGER
|
||||
endif
|
||||
|
||||
|
||||
|
@ -51,6 +51,9 @@
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsIJSEventListener.h"
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
#include "jsdIDebuggerService.h"
|
||||
#endif
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_1(nsEventListenerInfo, mListener)
|
||||
|
||||
@ -93,37 +96,85 @@ nsEventListenerInfo::GetInSystemEventGroup(PRBool* aInSystemEventGroup)
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsEventListenerService, nsIEventListenerService)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEventListenerInfo::ToSource(nsAString& aResult)
|
||||
// Caller must root *aJSVal!
|
||||
PRBool
|
||||
nsEventListenerInfo::GetJSVal(jsval* aJSVal)
|
||||
{
|
||||
aResult.SetIsVoid(PR_TRUE);
|
||||
*aJSVal = JSVAL_NULL;
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(mListener);
|
||||
if (wrappedJS) {
|
||||
JSObject* object = nsnull;
|
||||
wrappedJS->GetJSObject(&object);
|
||||
if (object) {
|
||||
nsCOMPtr<nsIThreadJSContextStack> stack =
|
||||
nsContentUtils::ThreadJSContextStack();
|
||||
if (stack) {
|
||||
JSContext* cx = nsnull;
|
||||
stack->GetSafeJSContext(&cx);
|
||||
if (cx && NS_SUCCEEDED(stack->Push(cx))) {
|
||||
JSAutoRequest ar(cx);
|
||||
jsval v = OBJECT_TO_JSVAL(object);
|
||||
JSString* str = JS_ValueToSource(cx, v);
|
||||
if (str) {
|
||||
aResult.Assign(nsDependentJSString(str));
|
||||
}
|
||||
stack->Pop(&cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIJSEventListener> jsl = do_QueryInterface(mListener);
|
||||
if (jsl) {
|
||||
jsl->ToString(mType, aResult);
|
||||
*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)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEventListenerInfo::ToSource(nsAString& aResult)
|
||||
{
|
||||
aResult.SetIsVoid(PR_TRUE);
|
||||
|
||||
nsresult rv;
|
||||
jsval v = JSVAL_NULL;
|
||||
nsAutoGCRoot root(&v, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (GetJSVal(&v)) {
|
||||
nsCOMPtr<nsIThreadJSContextStack> stack =
|
||||
nsContentUtils::ThreadJSContextStack();
|
||||
if (stack) {
|
||||
JSContext* cx = nsnull;
|
||||
stack->GetSafeJSContext(&cx);
|
||||
if (cx && NS_SUCCEEDED(stack->Push(cx))) {
|
||||
JSAutoRequest ar(cx);
|
||||
JSString* str = JS_ValueToSource(cx, v);
|
||||
if (str) {
|
||||
aResult.Assign(nsDependentJSString(str));
|
||||
}
|
||||
stack->Pop(&cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEventListenerInfo::GetDebugObject(nsISupports** aRetVal)
|
||||
{
|
||||
*aRetVal = nsnull;
|
||||
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
nsresult rv = NS_OK;
|
||||
jsval v = JSVAL_NULL;
|
||||
nsAutoGCRoot root(&v, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (GetJSVal(&v)) {
|
||||
nsCOMPtr<jsdIDebuggerService> jsd =
|
||||
do_GetService("@mozilla.org/js/jsd/debugger-service;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
PRBool isOn = PR_FALSE;
|
||||
jsd->GetIsOn(&isOn);
|
||||
NS_ENSURE_TRUE(isOn, NS_OK);
|
||||
|
||||
nsCOMPtr<jsdIValue> jsdValue;
|
||||
jsd->WrapJSValue(v, getter_AddRefs(jsdValue));
|
||||
*aRetVal = jsdValue.forget().get();
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include "nsString.h"
|
||||
#include "nsPIDOMEventTarget.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
|
||||
class nsEventListenerInfo : public nsIEventListenerInfo
|
||||
{
|
||||
@ -59,6 +61,8 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsEventListenerInfo)
|
||||
NS_DECL_NSIEVENTLISTENERINFO
|
||||
protected:
|
||||
PRBool GetJSVal(jsval* aJSVal);
|
||||
|
||||
nsString mType;
|
||||
// nsReftPtr because that is what nsListenerStruct uses too.
|
||||
nsRefPtr<nsIDOMEventListener> mListener;
|
||||
|
@ -23,6 +23,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=448602
|
||||
|
||||
function runTests() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var jsdIDebuggerService = Components.interfaces.jsdIDebuggerService;
|
||||
var jsd = Components.classes['@mozilla.org/js/jsd/debugger-service;1']
|
||||
.getService(jsdIDebuggerService);
|
||||
var els = Components.classes["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Components.interfaces.nsIEventListenerService);
|
||||
|
||||
@ -41,6 +44,16 @@ function runTests() {
|
||||
is(infos[0].capturing, false, "Wrong phase (1)");
|
||||
is(infos[0].allowsUntrusted, true, "Should allow untrusted events (1)");
|
||||
|
||||
var jsdOn = jsd.isOn;
|
||||
if (!jsdOn) {
|
||||
is(infos[0].getDebugObject(), null,
|
||||
"If JSD isn't running, getDebugObject() should return null.")
|
||||
jsd.on();
|
||||
ok(jsd.isOn, "JSD should be running.");
|
||||
}
|
||||
var jsdvalue = infos[0].getDebugObject().QueryInterface(Components.interfaces.jsdIValue);
|
||||
is(jsdvalue.jsType, 3, "Event listener should be a function! (1)");
|
||||
|
||||
root.removeAttribute("onclick");
|
||||
infos = els.getListenerInfoFor(root, {});
|
||||
is(infos.length, 0, "Element shouldn't have listeners (2)");
|
||||
@ -55,12 +68,19 @@ function runTests() {
|
||||
is(infos[0].type, "foo", "Wrong type (2)");
|
||||
is(infos[0].capturing, true, "Wrong phase (2)");
|
||||
is(infos[0].allowsUntrusted, true, "Should allow untrusted events (2)");
|
||||
jsdvalue = infos[0].getDebugObject().QueryInterface(Components.interfaces.jsdIValue);
|
||||
is(jsdvalue.jsType, 3, "Event listener should be a function!(2)");
|
||||
is(jsdvalue.getWrappedValue(), l, "Wrong JS value! (1)");
|
||||
|
||||
is(infos[1].toSource(), "(function (e) {alert(e);})",
|
||||
"Unexpected serialization (3)");
|
||||
is(infos[1].type, "foo", "Wrong type (3)");
|
||||
is(infos[1].capturing, false, "Wrong phase (3)");
|
||||
is(infos[1].allowsUntrusted, false, "Shouldn't allow untrusted events (1)");
|
||||
|
||||
jsdvalue2 = infos[1].getDebugObject().QueryInterface(Components.interfaces.jsdIValue);
|
||||
is(jsdvalue2.jsType, 3, "Event listener should be a function! (3)");
|
||||
is(jsdvalue2.getWrappedValue(), l, "Wrong JS value! (2)");
|
||||
root.removeEventListener("foo", l, true);
|
||||
root.removeEventListener("foo", l, false);
|
||||
infos = els.getListenerInfoFor(root, {});
|
||||
@ -99,6 +119,12 @@ function runTests() {
|
||||
ok(hasDocumentInChain, "Should have document in event target chain!");
|
||||
ok(hasWindowInChain, "Should have window in event target chain!");
|
||||
|
||||
if (!jsdOn) {
|
||||
jsd.off();
|
||||
ok(!jsd.isOn, "JSD shouldn't be running anymore.");
|
||||
}
|
||||
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -39,14 +39,15 @@
|
||||
#define nsIJSEventListener_h__
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsIScriptObjectOwner;
|
||||
class nsIDOMEventListener;
|
||||
class nsIAtom;
|
||||
|
||||
#define NS_IJSEVENTLISTENER_IID \
|
||||
{ 0xe16e7146, 0x109d, 0x4f54, \
|
||||
{ 0x94, 0x78, 0xda, 0xc4, 0x3a, 0x71, 0x0b, 0x52 } }
|
||||
{ 0x8b4f3ad1, 0x1c2a, 0x43f0, \
|
||||
{ 0xac, 0x6c, 0x83, 0x33, 0xe9, 0xe1, 0xcb, 0x7e } }
|
||||
|
||||
// Implemented by script event listeners. Used to retrieve the
|
||||
// script object corresponding to the event target.
|
||||
@ -81,7 +82,7 @@ public:
|
||||
|
||||
virtual void SetEventName(nsIAtom* aName) = 0;
|
||||
|
||||
virtual void ToString(const nsAString& aEventName, nsAString& aResult) = 0;
|
||||
virtual nsresult GetJSVal(const nsAString& aEventName, jsval* aJSVal) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~nsIJSEventListener()
|
||||
|
@ -140,33 +140,23 @@ nsJSEventListener::SetEventName(nsIAtom* aName)
|
||||
mEventName = aName;
|
||||
}
|
||||
|
||||
void
|
||||
nsJSEventListener::ToString(const nsAString& aEventName, nsAString& aResult)
|
||||
nsresult
|
||||
nsJSEventListener::GetJSVal(const nsAString& aEventName, jsval* aJSVal)
|
||||
{
|
||||
aResult.Truncate();
|
||||
nsCOMPtr<nsIThreadJSContextStack> stack = nsContentUtils::ThreadJSContextStack();
|
||||
nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(mTarget);
|
||||
if (target && stack && mContext) {
|
||||
JSContext* cx = static_cast<JSContext*>(mContext->GetNativeContext());
|
||||
if (cx && NS_SUCCEEDED(stack->Push(cx))) {
|
||||
JSAutoRequest ar(cx);
|
||||
nsAutoString eventString = NS_LITERAL_STRING("on") + aEventName;
|
||||
nsCOMPtr<nsIAtom> atomName = do_GetAtom(eventString);
|
||||
nsScriptObjectHolder funcval(mContext);
|
||||
mContext->GetBoundEventHandler(mTarget, mScopeObject, atomName,
|
||||
funcval);
|
||||
jsval funval =
|
||||
OBJECT_TO_JSVAL(static_cast<JSObject*>(static_cast<void*>(funcval)));
|
||||
|
||||
JSString* str =
|
||||
JS_ValueToSource(static_cast<JSContext*>(mContext->GetNativeContext()),
|
||||
funval);
|
||||
if (str) {
|
||||
aResult.Assign(nsDependentJSString(str));
|
||||
}
|
||||
stack->Pop(&cx);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
// nsIJSEventListener interface
|
||||
virtual void SetEventName(nsIAtom* aName);
|
||||
|
||||
virtual void ToString(const nsAString& aEventName, nsAString& aResult);
|
||||
virtual nsresult GetJSVal(const nsAString& aEventName, jsval* aJSVal);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSEventListener,
|
||||
nsIDOMEventListener)
|
||||
|
@ -53,6 +53,7 @@
|
||||
[ptr] native JSDValue(JSDValue);
|
||||
[ptr] native JSRuntime(JSRuntime);
|
||||
[ptr] native JSContext(JSContext);
|
||||
native JSVal(jsval);
|
||||
|
||||
/* interfaces we declare in this file */
|
||||
interface jsdIDebuggerService;
|
||||
@ -77,7 +78,7 @@ interface jsdIProperty;
|
||||
* Debugger service. It's not a good idea to have more than one active client of
|
||||
* the debugger service.
|
||||
*/
|
||||
[scriptable, uuid(e86c0173-49e2-48f3-b53f-b5b2691a7e45)]
|
||||
[scriptable, uuid(dc0a24db-f8ac-4889-80d0-6016545a2dda)]
|
||||
interface jsdIDebuggerService : nsISupports
|
||||
{
|
||||
/** Internal use only. */
|
||||
@ -359,6 +360,11 @@ interface jsdIDebuggerService : nsISupports
|
||||
* defined error code.
|
||||
*/
|
||||
jsdIValue wrapValue (/*in jsvalue value*/);
|
||||
|
||||
/**
|
||||
* The same as above but to be called from C++.
|
||||
*/
|
||||
[noscript] jsdIValue wrapJSValue (in JSVal value);
|
||||
|
||||
/* XXX these two routines are candidates for refactoring. The only problem
|
||||
* is that it is not clear where and how they should land.
|
||||
|
@ -2938,7 +2938,13 @@ jsdService::WrapValue(jsdIValue **_rval)
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
JSDValue *jsdv = JSD_NewValue (mCx, argv[0]);
|
||||
return WrapJSValue(argv[0], _rval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
jsdService::WrapJSValue(jsval value, jsdIValue** _rval)
|
||||
{
|
||||
JSDValue *jsdv = JSD_NewValue(mCx, value);
|
||||
if (!jsdv)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user