Thanks for the pointer to the linker code, which I skimmed, and to some ideas for a workaround. I'll do some exploring. My guess is that with some kind of meta-object programming (if I used a Nashorn class) I could wrap the browser object inside something that encapsulated the logic that Sundar mentioned. Perhaps it's the Nashorn JSObject to which you allude, or perhaps some other object, but presumably I can wrap the Nashorn-linked quasi-object inside a JSObject that fixes the mistakes in the browser JSObject Java implementation. This is coming from a low-level API of mine so I can wrap it inside something ugly if needed to make it work in a more-expected way outside it.
But alternatively, could the jdk.nashorn.internal.runtime.linker class be modified to work around this issue? I ask without attempting to do any understanding of the code, but it appears at a glance that the linker class is already doing a bunch of this stuff. Since it's already JSObject-specific, it seems like it would make sense to insert the code in there if JSObject has known bugs. And interoperability of the two JavaScript implementations is a big win if it works well (which I presume motivated the development of this special-case linker to begin with). On Fri, Mar 27, 2015 at 10:02 AM, A. Sundararajan <[email protected]> wrote: > Oops. Actually, there is no JSObject.hasMember/hasSlot to check if a named > property or an indexed property exists in a browser JSObject! Unlike > Nashorn's own JSObject interface (jdk.nashorn.api.scripting.JSObject) which > has hasMember, hasSlot! > > So, workaround is to modify the script as follows: > > var WebEngine = Java.type("javafx.scene.web.WebEngine"); > var engine = new WebEngine(); > > var window = engine.executeScript("window"); > > // check if property foo exists by "eval" on browser's JS engine! > var type = window.eval("typeof this.foo"); > > if (type == 'undefined') { > print("no 'foo' on Window"); > } else { > print("there is 'foo' of type " + type); > } > > Hope this helps, > -Sundar > > > On Friday 27 March 2015 07:18 PM, A. Sundararajan wrote: >> >> I think I found the issue with this modified script. >> >> var WebEngine = Java.type("javafx.scene.web.WebEngine"); >> var engine = new WebEngine(); >> >> var window = engine.executeScript("window"); >> >> print(Debug.getClass(window.foo)); >> print("typeof(window.foo) = " + typeof(window.foo)); >> if (window.foo) { >> print("window.foo is truthy"); >> } >> >> We need to run with -J-Dnashorn.debug to enable nashorn debug mode. >> Debug.getClass gets the Java class of the value. Apparently, browser's >> JSObject impl. returns a string with the value "undefined" for undefined >> values! And not a special value or null for undefined... >> >> I think nashorn's BrowserJSObjectLinker has to probably call >> JSObject.hasMember to check existence of a member before calling >> JSObject.getMember. That appears to be the only way to find out if >> "undefined" string is due to missing property or not. >> >> -Sundar >> >> On Friday 27 March 2015 06:22 PM, A. Sundararajan wrote: >>> >>> Browser's DOM objects (like WebEngine's) implement >>> netscape.javascript.JSObject interface. Such objects are treated specially >>> by nashorn's linker. >>> >>> >>> http://hg.openjdk.java.net/jdk9/dev/nashorn/file/ca150ddd536e/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java >>> >>> is the dynalink linker that handles such objects. JSObject.getMember, >>> putMember, call are used to provide property, call access seamlessly. >>> >>> Please check out this example: >>> >>> >>> http://hg.openjdk.java.net/jdk9/dev/nashorn/file/ca150ddd536e/samples/browser_dom.js >>> >>> So, what you're seeing is a bug in the way that linker works. Let me >>> check out and file a bug. >>> >>> Thanks, >>> -Sundar >>> >>> >>> On Friday 27 March 2015 04:41 PM, David P. Caldwell wrote: >>>> >>>> So it's very cool, and unexpected, that JavaScript objects obtained >>>> from a JavaFX WebEngine show up as something like ordinary Nashorn >>>> objects in Nashorn scripts. That's an unexpected bonus (I was planning >>>> on using .setMember() and all that stuff from >>>> netscape.javascript.JSObject). >>>> >>>> The objects behave a bit strangely, though. So I've got a couple of >>>> bug reports, I guess. >>>> >>>> Here's a script that demonstrates the ones I've found so far: >>>> >>>> var WebEngine = Java.type("javafx.scene.web.WebEngine"); >>>> var engine = new WebEngine(); >>>> >>>> var window = engine.executeScript("window"); >>>> >>>> print("foo = " + window.foo); >>>> print("typeof(window.foo) = " + typeof(window.foo)); >>>> if (window.foo) { >>>> print("window.foo is truthy"); >>>> } >>>> >>>> Output: >>>> $ /usr/lib/jvm/jdk1.8.0_40/bin/jjs -fx nashorn.js >>>> foo = undefined >>>> typeof(window.foo) = string >>>> window.foo is truthy >>>> >>>> I actually am using a much more complicated embedding that is done >>>> from Java, so I can tell you the problem is not in the implementation >>>> of the -fx flag. >>>> >>>> Other than that, I can't see much; I haven't delved into the Nashorn >>>> code, let alone whatever magic enables this. >>>> >>>> -- David. >>> >>> >> >
