Closed Bug 660603 Opened 13 years ago Closed 6 years ago

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

Categories

(Core :: XPConnect, defect)

defect
Not set
normal

Tracking

()

RESOLVED INACTIVE

People

(Reporter: tabutils+bugzilla, Unassigned)

Details

Attachments

(1 file)

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
Version: unspecified → Trunk
Assignee: general → nobody
Component: JavaScript Engine → XPConnect
QA Contact: general → xpconnect
Attached file Simple testcase
This test fails and warrants investigation.
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.
So is it intended or a bug?
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?
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.
(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.
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
Per policy at https://wiki.mozilla.org/Bug_Triage/Projects/Bug_Handling/Bug_Husbandry#Inactive_Bugs. If this bug is not an enhancement request or a bug not present in a supported release of Firefox, then it may be reopened.
Status: UNCONFIRMED → RESOLVED
Closed: 6 years ago
Resolution: --- → INACTIVE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: