Problem with interoperability with JavaFX WebEngine

A. Sundararajan sundararajan.athijegannathan at oracle.com
Fri Mar 27 14:02:14 UTC 2015


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.
>>
>



More information about the nashorn-dev mailing list