Nashorn JSObject with JDK 9

Florian Beese florian.beese at
Fri Nov 18 09:36:36 UTC 2016

Hi together,

I got a question relating the usage of JSObject Interface and
AbstractJSObject class with JDK 9. I hope you can tell me where to look or
whom to talk to.

My problem is, that when I want to access ScriptRuntime.UNDEFINED to be
abled to return "undefined" for members of my object, that do not exist, I
cannot access that class attribute as the ScriptRuntime class is not
exported. How shall I then tell the engine, that a member does not exist?
(null is not an option as this is not compatible to normal JS behavior).

See the following code example, which runs with JDK 8, but not with JDK 9

Thanks in advance and best regards

============ Code Example ==============

package com.your.test.package;

import static org.junit.Assert.assertEquals;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.junit.Test;

import jdk.nashorn.api.scripting.AbstractJSObject;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;

/* see the JSMapWrapper.getMember() method to understand the problem */
public class NashornWrapMapTest {

private class JSMapWrapper extends AbstractJSObject implements JSObject {
protected Map<String, Object> wrappedMap = null;

public JSMapWrapper(Map<String, Object> mapToWrap) {
wrappedMap = mapToWrap;

public Map<String, Object> getMap() {
return wrappedMap;

public Object call(Object thiz, Object... args) { return,
args); }

public Object newObject(Object... args) { return super.newObject(args); }

public Object eval(String s) { return super.eval(s); }

public Object getMember(String name) {
if (!wrappedMap.containsKey(name)) {
/* HERE is the problem with JDK as ScriptRuntime is not Exported */
return ScriptRuntime.UNDEFINED;
return wrappedMap.get(name);

public Object getSlot(int index) { return null; }

public boolean hasMember(String name) { return
wrappedMap.containsKey(name); }

public boolean hasSlot(int slot) { return false; }
public void removeMember(String name) { wrappedMap.remove(name); }

public void setMember(String name, Object value) { wrappedMap.put(name,
value); }

public void setSlot(int index, Object value) { super.setSlot(index, value);

public Set<String> keySet() { return wrappedMap.keySet(); }

public Collection<Object> values() { return wrappedMap.values(); }

public boolean isInstance(Object instance) { return
super.isInstance(instance); }

public boolean isInstanceOf(Object clazz) { return
super.isInstanceOf(clazz); }

public String getClassName() { return super.getClassName(); }

public boolean isFunction() { return false; }

public boolean isStrictFunction() { return false; }

public double toNumber() { return super.toNumber(); }

public boolean isArray() { return false; }

public String toString() {
String s = "Object(Map) : {";
boolean isFirst = true;
for (Map.Entry<String, Object> entry : wrappedMap.entrySet()) {
if (!isFirst) {
s += ", ";
isFirst = false;
s += entry.getKey() + ": " + entry.getValue().toString();
s += "}";
return s;

public void testUndefinedValue() throws ScriptException,
NoSuchMethodException {
final ScriptEngine engine = new
final Compilable compilable = (Compilable) engine;
final Invocable invocable = (Invocable) engine;

final String okReturn = "OK: did not contain testKey2";

final String scriptFunction = "function testMap(map) { "
+ "if (typeof map.testKey2 === 'undefined') { return '" + okReturn
+ "'; } return 'ERROR: should not happen: ' + map.testKey; };";
final CompiledScript compiled = compilable.compile(scriptFunction);


Map<String, Object> map = new HashMap<String, Object>();
map.put("testKey", "testVal"); //change the key to testKey2 to see the test

JSMapWrapper wrapper = new JSMapWrapper(map);

String ret = (String) invocable.invokeFunction("testMap", wrapper);

assertEquals(okReturn, ret);

More information about the nashorn-dev mailing list