diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 51fe90c57c8..9da53e78597 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -65,7 +65,8 @@ const char* XPCJSRuntime::mStrings[] = { "__scriptOnly__", // IDX_SCRIPTONLY "baseURIObject", // IDX_BASEURIOBJECT "nodePrincipal", // IDX_NODEPRINCIPAL - "documentURIObject" // IDX_DOCUMENTURIOBJECT + "documentURIObject", // IDX_DOCUMENTURIOBJECT + "mozMatchesSelector" // IDX_MOZMATCHESSELECTOR }; /***************************************************************************/ diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index e0091373fdb..50c6ab441b5 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -730,6 +730,7 @@ public: IDX_BASEURIOBJECT , IDX_NODEPRINCIPAL , IDX_DOCUMENTURIOBJECT , + IDX_MOZMATCHESSELECTOR , IDX_TOTAL_COUNT // just a count of the above }; diff --git a/js/xpconnect/tests/chrome/Makefile.in b/js/xpconnect/tests/chrome/Makefile.in index 17eb76441e4..76ce9cf5d91 100644 --- a/js/xpconnect/tests/chrome/Makefile.in +++ b/js/xpconnect/tests/chrome/Makefile.in @@ -52,6 +52,7 @@ MOCHITEST_CHROME_FILES = \ test_expandosharing.xul \ file_expandosharing.jsm \ test_getweakmapkeys.xul \ + test_mozMatchesSelector.xul \ test_nodelists.xul \ test_precisegc.xul \ test_sandboxImport.xul \ diff --git a/js/xpconnect/tests/chrome/test_mozMatchesSelector.xul b/js/xpconnect/tests/chrome/test_mozMatchesSelector.xul new file mode 100644 index 00000000000..3c38456588e --- /dev/null +++ b/js/xpconnect/tests/chrome/test_mozMatchesSelector.xul @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + diff --git a/js/xpconnect/tests/mochitest/Makefile.in b/js/xpconnect/tests/mochitest/Makefile.in index 74ef1269563..fc1e1c897f3 100644 --- a/js/xpconnect/tests/mochitest/Makefile.in +++ b/js/xpconnect/tests/mochitest/Makefile.in @@ -73,6 +73,7 @@ MOCHITEST_FILES = bug500931_helper.html \ file_documentdomain.html \ test_lookupMethod.html \ file_bug738244.html \ + file_mozMatchesSelector.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/js/xpconnect/tests/mochitest/file_mozMatchesSelector.html b/js/xpconnect/tests/mochitest/file_mozMatchesSelector.html new file mode 100644 index 00000000000..0dc101b5335 --- /dev/null +++ b/js/xpconnect/tests/mochitest/file_mozMatchesSelector.html @@ -0,0 +1 @@ + diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 4db3d84b764..47185cca48a 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -18,6 +18,7 @@ #include "xpcprivate.h" #include "jsapi.h" +#include "nsJSUtils.h" #include "mozilla/dom/BindingUtils.h" @@ -634,14 +635,96 @@ XPCWrappedNativeXrayTraits::resolveDOMCollectionProperty(JSContext *cx, JSObject return true; } +template +static bool +Is(JSObject *wrapper) +{ + JSObject *holder = GetHolder(wrapper); + XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); + nsCOMPtr native = do_QueryWrappedNative(wn); + return !!native; +} + +// Helper function to work around some limitations of the current XPC +// calling mechanism. See: bug 763897. +// The idea is that we unwrap the 'this' object, and find the wrapped +// native that belongs to it. Then we simply make the call directly +// on it after a Query Interface. +static JSBool +mozMatchesSelectorStub(JSContext *cx, unsigned argc, jsval *vp) +{ + if (argc < 1) + JS_ReportError(cx, "Not enough arguments"); + + JSObject *wrapper = JS_THIS_OBJECT(cx, vp); + JSString *selector = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]); + nsDependentJSString selectorStr; + NS_ENSURE_TRUE(selectorStr.init(cx, selector), false); + + nsCOMPtr element; + if (IsWrapper(wrapper) && WrapperFactory::IsXrayWrapper(wrapper)) { + // If it's xray wrapped we can get the wn directly. + JSObject *holder = GetHolder(wrapper); + XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); + element = do_QueryWrappedNative(wn); + } else { + // Else we can use the XPC utility function for unwrapping it. + nsCOMPtr iwn; + nsIXPConnect *xpc = nsXPConnect::GetXPConnect(); + nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, wrapper, + getter_AddRefs(iwn)); + if (NS_FAILED(rv) || !iwn) { + JS_ReportError(cx, "Unexpected object"); + return false; + } + element = do_QueryWrappedNative(iwn); + } + + if (!element) { + JS_ReportError(cx, "Unexpected object"); + return false; + } + + bool ret; + nsresult rv = element->MozMatchesSelector(selectorStr, &ret); + if (NS_FAILED(rv)) { + XPCThrower::Throw(rv, cx); + return false; + } + + JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(ret)); + return true; +} + bool XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, JSObject *wrapper, JSObject *holder, jsid id, bool set, JSPropertyDescriptor *desc) { + MOZ_ASSERT(js::GetObjectJSClass(holder) == &HolderClass); + XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); + if (!set && + id == rt->GetStringID(XPCJSRuntime::IDX_MOZMATCHESSELECTOR) && + Is(wrapper)) + { + // XPC calling mechanism cannot handle call/bind properly in some cases + // especially through xray wrappers. This is a temoorary work around for + // this problem for mozMatchesSelector. See: bug 763897. + desc->obj = wrapper; + desc->attrs = JSPROP_ENUMERATE; + JSFunction *fun = JS_NewFunction(cx, mozMatchesSelectorStub, + 1, 0, JS_GetPrototype(wrapper), + "mozMatchesSelector"); + NS_ENSURE_TRUE(fun, false); + desc->value = OBJECT_TO_JSVAL(JS_GetFunctionObject(fun)); + desc->getter = NULL; + desc->setter = NULL; + desc->shortid = 0; + return true; + } + desc->obj = NULL; - MOZ_ASSERT(js::GetObjectJSClass(holder) == &HolderClass); JSObject *wnObject = GetWrappedNativeObjectFromHolder(holder); XPCWrappedNative *wn = GetWrappedNative(wnObject); @@ -735,16 +818,6 @@ wrappedJSObject_getter(JSContext *cx, JSHandleObject wrapper, JSHandleId id, JSM return WrapperFactory::WaiveXrayAndWrap(cx, vp.address()); } -template -static bool -Is(JSObject *wrapper) -{ - JSObject *holder = GetHolder(wrapper); - XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); - nsCOMPtr native = do_QueryWrappedNative(wn); - return !!native; -} - static JSBool WrapURI(JSContext *cx, nsIURI *uri, jsval *vp) { @@ -933,13 +1006,9 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, js::Wrapper &jsWra return false; } - if (!pobj) { - return true; - } - #ifdef DEBUG - NS_ASSERTION(JS_HasPropertyById(cx, holder, id, &hasProp) && - hasProp, "id got defined somewhere else?"); + NS_ASSERTION(!pobj || (JS_HasPropertyById(cx, holder, id, &hasProp) && + hasProp), "id got defined somewhere else?"); #endif }