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 anymore. Thanks in advance and best regards Florian ============ 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 { @SuppressWarnings("restriction") 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; } @Override public Object call(Object thiz, Object... args) { return super.call(thiz, args); } @Override public Object newObject(Object... args) { return super.newObject(args); } @Override public Object eval(String s) { return super.eval(s); } @Override 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); } @Override public Object getSlot(int index) { return null; } @Override public boolean hasMember(String name) { return wrappedMap.containsKey(name); } @Override public boolean hasSlot(int slot) { return false; } @Override public void removeMember(String name) { wrappedMap.remove(name); } @Override public void setMember(String name, Object value) { wrappedMap.put(name, value); } @Override public void setSlot(int index, Object value) { super.setSlot(index, value); } @Override public Set<String> keySet() { return wrappedMap.keySet(); } @Override public Collection<Object> values() { return wrappedMap.values(); } @Override public boolean isInstance(Object instance) { return super.isInstance(instance); } @Override public boolean isInstanceOf(Object clazz) { return super.isInstanceOf(clazz); } @Override public String getClassName() { return super.getClassName(); } @Override public boolean isFunction() { return false; } @Override public boolean isStrictFunction() { return false; } @Override public double toNumber() { return super.toNumber(); } @Override public boolean isArray() { return false; } @Override 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; } } @Test public void testUndefinedValue() throws ScriptException, NoSuchMethodException { final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); 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); compiled.eval(); Map<String, Object> map = new HashMap<String, Object>(); map.put("testKey", "testVal"); //change the key to testKey2 to see the test failing JSMapWrapper wrapper = new JSMapWrapper(map); String ret = (String) invocable.invokeFunction("testMap", wrapper); assertEquals(okReturn, ret); } }