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
}