Fix for bug 842799 (|Document.prototype instanceof Node| inside <script> returns false). r=bz.

This commit is contained in:
Peter Van der Beken 2013-02-22 10:25:24 +01:00
parent 1e841b852a
commit 74a5cb5265
5 changed files with 78 additions and 10 deletions

View File

@ -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<bool> 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

View File

@ -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<nsIDOM%s> qiResult = do_QueryInterface(native);
*bp = !!qiResult;
return true;""" % self.descriptor.interface.identifier.name

View File

@ -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 \

View File

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html>
<body>
<script type="application/javascript">
function runTest()
{
return [ parent.HTMLElement.prototype instanceof Element,
parent.HTMLElement.prototype instanceof parent.Element ];
}
</script>
</body>
</html>

View File

@ -13,16 +13,42 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=748983
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=748983">Mozilla Bug 748983</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 748983 **/
ok(document instanceof EventTarget, "document is an event target")
ok(new XMLHttpRequest() instanceof XMLHttpRequest, "instanceof should work on XHR");
SimpleTest.waitForExplicitFinish();
function runTest()
{
ok(document instanceof EventTarget, "document is an event target")
ok(new XMLHttpRequest() instanceof XMLHttpRequest, "instanceof should work on XHR");
ok(HTMLElement.prototype instanceof Node, "instanceof needs to walk the prototype chain")
var otherWin = document.getElementById("testFrame").contentWindow;
ok(otherWin.HTMLElement.prototype instanceof otherWin.Node, "Same-origin instanceof of a interface prototype object should work, even if called cross-origin");
ok(!(otherWin.HTMLElement.prototype instanceof Node), "Cross-origin instanceof of a interface prototype object shouldn't work");
// We need to reset HTMLElement.prototype.__proto__ to the original value
// before using anything from the harness, otherwise the harness code breaks
// in weird ways.
HTMLElement.prototype.__proto__ = otherWin.Element.prototype;
var [ shouldSucceed, shouldFail ] = otherWin.runTest();
shouldSucceed = shouldSucceed && HTMLElement.prototype instanceof otherWin.Element;
shouldFail = shouldFail && HTMLElement.prototype instanceof Element;
HTMLElement.prototype.__proto__ = Element.prototype;
ok(shouldSucceed, "If an interface prototype object is on the protochain then instanceof with the interface object should succeed");
ok(!shouldFail, "If an interface prototype object is not on the protochain then instanceof with the interface object should succeed");
SimpleTest.finish();
}
</script>
</pre>
<iframe id="testFrame" src="file_InstanceOf.html" onload="runTest()"></iframe>
</body>
</html>