instanceof doesn't work with QueryInterface generated by XPCOMUtils.generateQI

UNCONFIRMED
Unassigned

Status

()

Core
XPConnect
UNCONFIRMED
7 years ago
2 years ago

People

(Reporter: ithinc, Unassigned)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

7 years ago
User-Agent:       Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Build Identifier: 

It is said that "obj instanceof xpcomInterface (e.g. Components.interfaces.nsIFile) calls obj.QueryInterface(xpcomInterface) and returns true if QueryInterface succeeded" at https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/instanceof. But it doesn't work with QueryInterface generated by XPCOMUtils.generateQI. For example, PlacesStarButton.QueryInterface(Ci.nsINavBookmarkObserver) is successful, but PlacesStarButton instanceof Ci.nsINavBookmarkObserver returns false.

Reproducible: Always
(Reporter)

Updated

7 years ago
Version: unspecified → Trunk

Updated

7 years ago
Assignee: general → nobody
Component: JavaScript Engine → XPConnect
QA Contact: general → xpconnect

Comment 1

7 years ago
Created attachment 536317 [details]
Simple testcase

This test fails and warrants investigation.

Comment 2

7 years ago
This is the stack that I'm looking at when executing |do_check_true(ConsoleObserver instanceof Ci.nsIObserver)|:

#0  nsJSIID::HasInstance (this=0x832ed28, wrapper=0x8351ce0, cx=0x82cfa08, obj=0xb4030bd0 [Object nsJSIID], val=..., bp=0xbfffd9f4, _retval=0xbfffd7b4) at /home/t_mattjo/src/firefox/mozilla-central/js/src/xpconnect/src/xpcjsid.cpp:507
#1  0x020a926c in XPC_WN_Helper_HasInstance (cx=0x82cfa08, obj=0xb4030bd0 [Object nsJSIID], valp=0xb41fe108, bp=0xbfffd9f4) at /home/t_mattjo/src/firefox/mozilla-central/js/src/xpconnect/src/xpcwrappednativejsops.cpp:1071
#2  0x02c9ebce in js::HasInstance (cx=0x82cfa08, obj=0xb4030bd0 [Object nsJSIID], v=0xb41fe108, bp=0xbfffd9f4) at /home/t_mattjo/src/firefox/mozilla-central/js/src/jsinterp.cpp:1059
#3  0x02eef977 in js::Interpret (cx=0x82cfa08, entryFrame=0xb41fe030, inlineCallCount=2, interpMode=JSINTERP_NORMAL) at /home/t_mattjo/src/firefox/mozilla-central/js/src/jsinterp.cpp:6130
#4  0x02c9d63c in js::RunScript (cx=0x82cfa08, script=0x8325ca8, fp=0xb41fe030) at /home/t_mattjo/src/firefox/mozilla-central/js/src/jsinterp.cpp:613
#5  0x02c9e884 in js::Execute (cx=0x82cfa08, chain=..., script=0x8325ca8, prev=0x0, flags=0, result=0xbfffe9c0) at /home/t_mattjo/src/firefox/mozilla-central/js/src/jsinterp.cpp:974
#6  0x02c06841 in EvaluateUCScriptForPrincipalsCommon (cx=0x82cfa08, obj=0xb4009050 [Object BackstagePass], principals=0x82b7434, chars=0x8338f48, length=25, filename=0x805c3a5 "-e", lineno=1, rval=0xbfffe9c0, compileVersion=JSVERSION_ECMA_5)
    at /home/t_mattjo/src/firefox/mozilla-central/js/src/jsapi.cpp:4972
#7  0x02c06953 in JS_EvaluateUCScriptForPrincipals (cx=0x82cfa08, obj=0xb4009050 [Object BackstagePass], principals=0x82b7434, chars=0x8338f48, length=25, filename=0x805c3a5 "-e", lineno=1, rval=0xbfffe9c0)
    at /home/t_mattjo/src/firefox/mozilla-central/js/src/jsapi.cpp:4999
#8  0x02c06a96 in JS_EvaluateScriptForPrincipals (cx=0x82cfa08, obj=0xb4009050 [Object BackstagePass], principals=0x82b7434, bytes=0xbffff186 "_execute_test(); quit(0);", nbytes=25, filename=0x805c3a5 "-e", lineno=1, rval=0xbfffe9c0)
    at /home/t_mattjo/src/firefox/mozilla-central/js/src/jsapi.cpp:5022
#9  0x0804df75 in ProcessArgs (cx=0x82cfa08, obj=0xb4009050 [Object BackstagePass], argv=0xbfffec08, argc=18) at /home/t_mattjo/src/firefox/mozilla-central/js/src/xpconnect/shell/xpcshell.cpp:1288
#10 0x0804f7f3 in main (argc=18, argv=0xbfffec08, envp=0xbfffec54) at /home/t_mattjo/src/firefox/mozilla-central/js/src/xpconnect/shell/xpcshell.cpp:1990

val is the observer object, but it fails the |if (IS_SLIM_WRAPPER(obj))| check, and |XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj)| returns null, so we bail.
(Reporter)

Comment 3

7 years ago
So is it intended or a bug?

Comment 4

7 years ago
That would be a good thing to establish before I spend any more time digging. Blake, thoughts?
Josh, looking at your testcase, I wouldn't expect it to pass. |obj instanceof xpcomInterface| expects an XPCOM/XPConnected wrapped object on the left side of the instanceof operator. You're giving it a plain ol' JS object.

If you change your testcase so you get your object back out of XPConnect via an interface that returns an |nsIObserver|, do things work as expected?

Comment 6

7 years ago
Ok, so if that's the specced behaviour, we should probably update the docs quoted in comment 0. Blake, are you saying that if I create some interface that allows me to add an nsIObserver in C++, then return the observer added, doing an instanceof on that should succeed? That makes sense; but really goes outside the scope of what the reporter was asking. Looks like this is mainly just a documentation issue, in the end.
(Reporter)

Comment 7

7 years ago
(In reply to comment #5)
> Josh, looking at your testcase, I wouldn't expect it to pass. |obj
> instanceof xpcomInterface| expects an XPCOM/XPConnected wrapped object on
> the left side of the instanceof operator. You're giving it a plain ol' JS
> object.

I understand this, but I would like to see it fixed for a plain object.

Comment 8

2 years ago
Old bug, but ...

I'm trying to figure out how to properly define XPCOM components in JS as part of the migration of some Thunderbird-related C++ code to JS XPCOM components. Unfortunately there are two conflicting issues, this being one of them.

There is lots of code that looks something like if (someItem instanceof Components.interfaces.someInterface) ... and this fails to work if someItem is an object that implements someInterface, including a proper QI, which is this bug.

OK, so create the object using XPCONNECT instead. Now the problem is that any attempt to pass an error result from the object, caught by the caller JS, now generates an error message to the error console, JavaScript error: uncaught exception ...

Perhaps this could be prevented using Components.returnCode, and this may work if the caller is C++, but if the caller is JS then there is no way I have figured out to detect the returnCode unless an exception is thrown.

So I cannot figure out a way to use mixed JS/CPP XPCOM components, with mixed JS/CPP callers, with all of the following true:

1) Instanceof Components.interface.someInterface works
2) No console message for caught errors passed as Components.results.NS_SOME_ERROR
You need to log in before you can comment on or make changes to this bug.