diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 340f130cb165..c32fade0845a 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -1596,14 +1596,43 @@ InterfaceHasInstance(JSContext* cx, JSHandleObject obj, JSObject* instance, const DOMIfaceAndProtoJSClass* clasp = DOMIfaceAndProtoJSClass::FromJSClass(js::GetObjectClass(obj)); - const DOMClass* domClass = GetDOMClass(instance); + const DOMClass* domClass = GetDOMClass(js::UnwrapObject(instance)); MOZ_ASSERT(!domClass || clasp->mPrototypeID != prototypes::id::_ID_Count, "Why do we have a hasInstance hook if we don't have a prototype " "ID?"); - *bp = domClass && - domClass->mInterfaceChain[clasp->mDepth] == clasp->mPrototypeID; + if (domClass && + domClass->mInterfaceChain[clasp->mDepth] == clasp->mPrototypeID) { + *bp = true; + return true; + } + + jsval protov; + DebugOnly ok = JS_GetProperty(cx, obj, "prototype", &protov); + MOZ_ASSERT(ok, "Someone messed with our prototype property?"); + + JSObject *interfacePrototype = &protov.toObject(); + MOZ_ASSERT(IsDOMIfaceAndProtoClass(js::GetObjectClass(interfacePrototype)), + "Someone messed with our prototype property?"); + + JSObject* proto; + if (!JS_GetPrototype(cx, instance, &proto)) { + return false; + } + + while (proto) { + if (proto == interfacePrototype) { + *bp = true; + return true; + } + + if (!JS_GetPrototype(cx, proto, &proto)) { + return false; + } + } + + *bp = false; return true; } @@ -1616,7 +1645,7 @@ InterfaceHasInstance(JSContext* cx, JSHandleObject obj, JSMutableHandleValue vp, return true; } - return InterfaceHasInstance(cx, obj, js::UnwrapObject(&vp.toObject()), bp); + return InterfaceHasInstance(cx, obj, &vp.toObject(), bp); } } // namespace dom diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index ebf11b2eeb27..60c664e6b243 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -1047,8 +1047,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod): return true; } - JSObject* instance = js::UnwrapObject(&vp.toObject()); - + JSObject* instance = &vp.toObject(); bool ok = InterfaceHasInstance(cx, obj, instance, bp); if (!ok || *bp) { return ok; @@ -1056,7 +1055,8 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod): // FIXME Limit this to chrome by checking xpc::AccessCheck::isChrome(obj). nsISupports* native = - nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, instance); + nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, + js::UnwrapObject(instance)); nsCOMPtr qiResult = do_QueryInterface(native); *bp = !!qiResult; return true;""" % self.descriptor.interface.identifier.name diff --git a/dom/bindings/test/Makefile.in b/dom/bindings/test/Makefile.in index 1e8b2c095b1a..be30ea2fcc08 100644 --- a/dom/bindings/test/Makefile.in +++ b/dom/bindings/test/Makefile.in @@ -55,6 +55,7 @@ MOCHITEST_FILES := \ test_interfaceToString.html \ test_lookupGetter.html \ test_InstanceOf.html \ + file_InstanceOf.html \ test_traceProtos.html \ test_forOf.html \ forOf_iframe.html \ diff --git a/dom/bindings/test/file_InstanceOf.html b/dom/bindings/test/file_InstanceOf.html new file mode 100644 index 000000000000..487010fa4288 --- /dev/null +++ b/dom/bindings/test/file_InstanceOf.html @@ -0,0 +1,12 @@ + + + + + + diff --git a/dom/bindings/test/test_InstanceOf.html b/dom/bindings/test/test_InstanceOf.html index 3a5a76b1b212..514ec1b2aa4b 100644 --- a/dom/bindings/test/test_InstanceOf.html +++ b/dom/bindings/test/test_InstanceOf.html @@ -13,16 +13,42 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=748983 Mozilla Bug 748983

 
 
+