Wed, 11 Sep 2013 20:49:28 +0530
8024615: Refactor ScriptObjectMirror and JSObject to support external JSObject implementations
Reviewed-by: jlaskey, hannesw
1.1 --- a/src/jdk/nashorn/api/scripting/JSObject.java Wed Sep 11 10:27:25 2013 +0200 1.2 +++ b/src/jdk/nashorn/api/scripting/JSObject.java Wed Sep 11 20:49:28 2013 +0530 1.3 @@ -25,73 +25,210 @@ 1.4 1.5 package jdk.nashorn.api.scripting; 1.6 1.7 +import java.util.Collection; 1.8 +import java.util.Collections; 1.9 +import java.util.Set; 1.10 + 1.11 /** 1.12 - * netscape.javascript.JSObject-like interface for nashorn script objects. 1.13 + * This is the base class for nashorn ScriptObjectMirror class. 1.14 + * 1.15 + * This class can also be subclassed by an arbitrary Java class. Nashorn will 1.16 + * treat objects of such classes just like nashorn script objects. Usual nashorn 1.17 + * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued 1.18 + * to appropriate method call of this class. 1.19 */ 1.20 public abstract class JSObject { 1.21 /** 1.22 - * Call a JavaScript function 1.23 + * Call this object as a JavaScript function. This is equivalent to 1.24 + * 'func.apply(thiz, args)' in JavaScript. 1.25 * 1.26 - * @param functionName name of function 1.27 + * @param thiz 'this' object to be passed to the function 1.28 * @param args arguments to method 1.29 * @return result of call 1.30 */ 1.31 - public abstract Object call(String functionName, Object... args); 1.32 + public Object call(Object thiz, Object... args) { 1.33 + throw new UnsupportedOperationException("call"); 1.34 + } 1.35 1.36 /** 1.37 - * Call a JavaScript method as a constructor. This is equivalent to 1.38 - * calling new obj.Method(arg1, arg2...) in JavaScript. 1.39 + * Call this 'constructor' JavaScript function to create a new object. 1.40 + * This is equivalent to 'new func(arg1, arg2...)' in JavaScript. 1.41 * 1.42 - * @param functionName name of function 1.43 * @param args arguments to method 1.44 * @return result of constructor call 1.45 */ 1.46 - public abstract Object newObject(String functionName, Object... args); 1.47 + public Object newObject(Object... args) { 1.48 + throw new UnsupportedOperationException("newObject"); 1.49 + } 1.50 1.51 /** 1.52 - * Evaluate a JavaScript expression 1.53 + * Evaluate a JavaScript expression. 1.54 * 1.55 * @param s JavaScript expression to evaluate 1.56 * @return evaluation result 1.57 */ 1.58 - public abstract Object eval(String s); 1.59 + public Object eval(String s) { 1.60 + throw new UnsupportedOperationException("eval"); 1.61 + } 1.62 1.63 /** 1.64 - * Retrieves a named member of a JavaScript object. 1.65 + * Call a JavaScript function member of this object. 1.66 + * 1.67 + * @param name name of the member function to call 1.68 + * @param args arguments to be passed to the member function 1.69 + * @return result of call 1.70 + */ 1.71 + public Object callMember(String name, Object... args) { 1.72 + throw new UnsupportedOperationException("call"); 1.73 + } 1.74 + 1.75 + /** 1.76 + * Retrieves a named member of this JavaScript object. 1.77 * 1.78 * @param name of member 1.79 * @return member 1.80 */ 1.81 - public abstract Object getMember(String name); 1.82 + public Object getMember(String name) { 1.83 + return null; 1.84 + } 1.85 1.86 /** 1.87 - * Retrieves an indexed member of a JavaScript object. 1.88 + * Retrieves an indexed member of this JavaScript object. 1.89 * 1.90 - * @param index index of member slot 1.91 + * @param index index slot to retrieve 1.92 * @return member 1.93 */ 1.94 - public abstract Object getSlot(int index); 1.95 + public Object getSlot(int index) { 1.96 + return null; 1.97 + } 1.98 1.99 /** 1.100 - * Remove a named member from a JavaScript object 1.101 + * Does this object have a named member? 1.102 * 1.103 * @param name name of member 1.104 + * @return true if this object has a member of the given name 1.105 */ 1.106 - public abstract void removeMember(String name); 1.107 + public boolean hasMember(String name) { 1.108 + return false; 1.109 + } 1.110 1.111 /** 1.112 - * Set a named member in a JavaScript object 1.113 + * Does this object have a indexed property? 1.114 * 1.115 - * @param name name of member 1.116 - * @param value value of member 1.117 + * @param slot index to check 1.118 + * @return true if this object has a slot 1.119 */ 1.120 - public abstract void setMember(String name, Object value); 1.121 + public boolean hasSlot(int slot) { 1.122 + return false; 1.123 + } 1.124 1.125 /** 1.126 - * Set an indexed member in a JavaScript object 1.127 + * Remove a named member from this JavaScript object 1.128 * 1.129 - * @param index index of member slot 1.130 - * @param value value of member 1.131 + * @param name name of the member 1.132 */ 1.133 - public abstract void setSlot(int index, Object value); 1.134 + public void removeMember(String name) { 1.135 + } 1.136 + 1.137 + /** 1.138 + * Set a named member in this JavaScript object 1.139 + * 1.140 + * @param name name of the member 1.141 + * @param value value of the member 1.142 + */ 1.143 + public void setMember(String name, Object value) { 1.144 + } 1.145 + 1.146 + /** 1.147 + * Set an indexed member in this JavaScript object 1.148 + * 1.149 + * @param index index of the member slot 1.150 + * @param value value of the member 1.151 + */ 1.152 + public void setSlot(int index, Object value) { 1.153 + } 1.154 + 1.155 + // property and value iteration 1.156 + 1.157 + /** 1.158 + * Returns the set of all property names of this object. 1.159 + * 1.160 + * @return set of property names 1.161 + */ 1.162 + @SuppressWarnings("unchecked") 1.163 + public Set<String> keySet() { 1.164 + return Collections.EMPTY_SET; 1.165 + } 1.166 + 1.167 + /** 1.168 + * Returns the set of all property values of this object. 1.169 + * 1.170 + * @return set of property values. 1.171 + */ 1.172 + @SuppressWarnings("unchecked") 1.173 + public Collection<Object> values() { 1.174 + return Collections.EMPTY_SET; 1.175 + } 1.176 + 1.177 + // JavaScript instanceof check 1.178 + 1.179 + /** 1.180 + * Checking whether the given object is an instance of 'this' object. 1.181 + * 1.182 + * @param instance instace to check 1.183 + * @return true if the given 'instance' is an instance of this 'function' object 1.184 + */ 1.185 + public boolean isInstance(final Object instance) { 1.186 + return false; 1.187 + } 1.188 + 1.189 + /** 1.190 + * Checking whether this object is an instance of the given 'clazz' object. 1.191 + * 1.192 + * @param clazz clazz to check 1.193 + * @return true if this object is an instance of the given 'clazz' 1.194 + */ 1.195 + public boolean isInstanceOf(final Object clazz) { 1.196 + if (clazz instanceof JSObject) { 1.197 + return ((JSObject)clazz).isInstance(this); 1.198 + } 1.199 + 1.200 + return false; 1.201 + } 1.202 + 1.203 + /** 1.204 + * ECMA [[Class]] property 1.205 + * 1.206 + * @return ECMA [[Class]] property value of this object 1.207 + */ 1.208 + public String getClassName() { 1.209 + return getClass().getName(); 1.210 + } 1.211 + 1.212 + /** 1.213 + * Is this a function object? 1.214 + * 1.215 + * @return if this mirror wraps a ECMAScript function instance 1.216 + */ 1.217 + public boolean isFunction() { 1.218 + return false; 1.219 + } 1.220 + 1.221 + /** 1.222 + * Is this a 'use strict' function object? 1.223 + * 1.224 + * @return true if this mirror represents a ECMAScript 'use strict' function 1.225 + */ 1.226 + public boolean isStrictFunction() { 1.227 + return false; 1.228 + } 1.229 + 1.230 + /** 1.231 + * Is this an array object? 1.232 + * 1.233 + * @return if this mirror wraps a ECMAScript array object 1.234 + */ 1.235 + public boolean isArray() { 1.236 + return false; 1.237 + } 1.238 }
2.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Sep 11 10:27:25 2013 +0200 2.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Wed Sep 11 20:49:28 2013 +0530 2.3 @@ -494,7 +494,7 @@ 2.4 2.5 if (selfMirror != null) { 2.6 try { 2.7 - return ScriptObjectMirror.translateUndefined(selfMirror.call(name, args)); 2.8 + return ScriptObjectMirror.translateUndefined(selfMirror.callMember(name, args)); 2.9 } catch (final Exception e) { 2.10 final Throwable cause = e.getCause(); 2.11 if (cause instanceof NoSuchMethodException) {
3.1 --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Wed Sep 11 10:27:25 2013 +0200 3.2 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java Wed Sep 11 20:49:28 2013 +0530 3.3 @@ -48,9 +48,7 @@ 3.4 import jdk.nashorn.internal.runtime.ScriptRuntime; 3.5 3.6 /** 3.7 - * Mirror object that wraps a given ScriptObject instance. User can 3.8 - * access ScriptObject via the javax.script.Bindings interface or 3.9 - * netscape.javascript.JSObject interface. 3.10 + * Mirror object that wraps a given Nashorn Script object. 3.11 */ 3.12 public final class ScriptObjectMirror extends JSObject implements Bindings { 3.13 private static AccessControlContext getContextAccCtxt() { 3.14 @@ -90,8 +88,9 @@ 3.15 } 3.16 3.17 // JSObject methods 3.18 + 3.19 @Override 3.20 - public Object call(final String functionName, final Object... args) { 3.21 + public Object call(final Object thiz, final Object... args) { 3.22 final ScriptObject oldGlobal = Context.getGlobal(); 3.23 final boolean globalChanged = (oldGlobal != global); 3.24 3.25 @@ -100,15 +99,13 @@ 3.26 Context.setGlobal(global); 3.27 } 3.28 3.29 - final Object val = functionName == null? sobj : sobj.get(functionName); 3.30 - if (val instanceof ScriptFunction) { 3.31 + if (sobj instanceof ScriptFunction) { 3.32 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; 3.33 - return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global); 3.34 - } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) { 3.35 - return ((ScriptObjectMirror)val).call(null, args); 3.36 + final Object self = globalChanged? wrap(thiz, oldGlobal) : thiz; 3.37 + return wrap(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)), global); 3.38 } 3.39 3.40 - throw new NoSuchMethodException("No such function " + ((functionName != null)? functionName : "")); 3.41 + throw new RuntimeException("not a function: " + toString()); 3.42 } catch (final RuntimeException | Error e) { 3.43 throw e; 3.44 } catch (final Throwable t) { 3.45 @@ -121,7 +118,7 @@ 3.46 } 3.47 3.48 @Override 3.49 - public Object newObject(final String functionName, final Object... args) { 3.50 + public Object newObject(final Object... args) { 3.51 final ScriptObject oldGlobal = Context.getGlobal(); 3.52 final boolean globalChanged = (oldGlobal != global); 3.53 3.54 @@ -130,15 +127,12 @@ 3.55 Context.setGlobal(global); 3.56 } 3.57 3.58 - final Object val = functionName == null? sobj : sobj.get(functionName); 3.59 - if (val instanceof ScriptFunction) { 3.60 + if (sobj instanceof ScriptFunction) { 3.61 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; 3.62 - return wrap(ScriptRuntime.construct((ScriptFunction)val, unwrapArray(modArgs, global)), global); 3.63 - } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) { 3.64 - return ((ScriptObjectMirror)val).newObject(null, args); 3.65 + return wrap(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)), global); 3.66 } 3.67 3.68 - throw new RuntimeException("not a constructor " + ((functionName != null)? functionName : "")); 3.69 + throw new RuntimeException("not a constructor: " + toString()); 3.70 } catch (final RuntimeException | Error e) { 3.71 throw e; 3.72 } catch (final Throwable t) { 3.73 @@ -168,7 +162,39 @@ 3.74 } 3.75 3.76 @Override 3.77 + public Object callMember(final String functionName, final Object... args) { 3.78 + functionName.getClass(); // null check 3.79 + final ScriptObject oldGlobal = Context.getGlobal(); 3.80 + final boolean globalChanged = (oldGlobal != global); 3.81 + 3.82 + try { 3.83 + if (globalChanged) { 3.84 + Context.setGlobal(global); 3.85 + } 3.86 + 3.87 + final Object val = sobj.get(functionName); 3.88 + if (val instanceof ScriptFunction) { 3.89 + final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; 3.90 + return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global); 3.91 + } else if (val instanceof JSObject && ((JSObject)val).isFunction()) { 3.92 + return ((JSObject)val).call(sobj, args); 3.93 + } 3.94 + 3.95 + throw new NoSuchMethodException("No such function " + functionName); 3.96 + } catch (final RuntimeException | Error e) { 3.97 + throw e; 3.98 + } catch (final Throwable t) { 3.99 + throw new RuntimeException(t); 3.100 + } finally { 3.101 + if (globalChanged) { 3.102 + Context.setGlobal(oldGlobal); 3.103 + } 3.104 + } 3.105 + } 3.106 + 3.107 + @Override 3.108 public Object getMember(final String name) { 3.109 + name.getClass(); 3.110 return inGlobal(new Callable<Object>() { 3.111 @Override public Object call() { 3.112 return wrap(sobj.get(name), global); 3.113 @@ -186,12 +212,33 @@ 3.114 } 3.115 3.116 @Override 3.117 + public boolean hasMember(final String name) { 3.118 + name.getClass(); 3.119 + return inGlobal(new Callable<Boolean>() { 3.120 + @Override public Boolean call() { 3.121 + return sobj.has(name); 3.122 + } 3.123 + }); 3.124 + } 3.125 + 3.126 + @Override 3.127 + public boolean hasSlot(final int slot) { 3.128 + return inGlobal(new Callable<Boolean>() { 3.129 + @Override public Boolean call() { 3.130 + return sobj.has(slot); 3.131 + } 3.132 + }); 3.133 + } 3.134 + 3.135 + @Override 3.136 public void removeMember(final String name) { 3.137 + name.getClass(); 3.138 remove(name); 3.139 } 3.140 3.141 @Override 3.142 public void setMember(final String name, final Object value) { 3.143 + name.getClass(); 3.144 put(name, value); 3.145 } 3.146 3.147 @@ -205,6 +252,45 @@ 3.148 }); 3.149 } 3.150 3.151 + @Override 3.152 + public boolean isInstance(final Object obj) { 3.153 + if (! (obj instanceof ScriptObjectMirror)) { 3.154 + return false; 3.155 + } 3.156 + 3.157 + final ScriptObjectMirror instance = (ScriptObjectMirror)obj; 3.158 + // if not belongs to my global scope, return false 3.159 + if (global != instance.global) { 3.160 + return false; 3.161 + } 3.162 + 3.163 + return inGlobal(new Callable<Boolean>() { 3.164 + @Override public Boolean call() { 3.165 + return sobj.isInstance(instance.sobj); 3.166 + } 3.167 + }); 3.168 + } 3.169 + 3.170 + @Override 3.171 + public String getClassName() { 3.172 + return sobj.getClassName(); 3.173 + } 3.174 + 3.175 + @Override 3.176 + public boolean isFunction() { 3.177 + return sobj instanceof ScriptFunction; 3.178 + } 3.179 + 3.180 + @Override 3.181 + public boolean isStrictFunction() { 3.182 + return isFunction() && ((ScriptFunction)sobj).isStrict(); 3.183 + } 3.184 + 3.185 + @Override 3.186 + public boolean isArray() { 3.187 + return sobj.isArray(); 3.188 + } 3.189 + 3.190 // javax.script.Bindings methods 3.191 3.192 @Override 3.193 @@ -392,15 +478,6 @@ 3.194 } 3.195 3.196 /** 3.197 - * ECMA [[Class]] property 3.198 - * 3.199 - * @return ECMA [[Class]] property value of this object 3.200 - */ 3.201 - public String getClassName() { 3.202 - return sobj.getClassName(); 3.203 - } 3.204 - 3.205 - /** 3.206 * ECMA 8.12.1 [[GetOwnProperty]] (P) 3.207 * 3.208 * @param key property key 3.209 @@ -506,55 +583,6 @@ 3.210 }); 3.211 } 3.212 3.213 - // ECMAScript instanceof check 3.214 - 3.215 - /** 3.216 - * Checking whether a script object is an instance of another by 3.217 - * walking the proto chain 3.218 - * 3.219 - * @param instance instace to check 3.220 - * @return true if 'instance' is an instance of this object 3.221 - */ 3.222 - public boolean isInstance(final ScriptObjectMirror instance) { 3.223 - // if not belongs to my global scope, return false 3.224 - if (instance == null || global != instance.global) { 3.225 - return false; 3.226 - } 3.227 - 3.228 - return inGlobal(new Callable<Boolean>() { 3.229 - @Override public Boolean call() { 3.230 - return sobj.isInstance(instance.sobj); 3.231 - } 3.232 - }); 3.233 - } 3.234 - 3.235 - /** 3.236 - * is this a function object? 3.237 - * 3.238 - * @return if this mirror wraps a ECMAScript function instance 3.239 - */ 3.240 - public boolean isFunction() { 3.241 - return sobj instanceof ScriptFunction; 3.242 - } 3.243 - 3.244 - /** 3.245 - * is this a 'use strict' function object? 3.246 - * 3.247 - * @return true if this mirror represents a ECMAScript 'use strict' function 3.248 - */ 3.249 - public boolean isStrictFunction() { 3.250 - return isFunction() && ((ScriptFunction)sobj).isStrict(); 3.251 - } 3.252 - 3.253 - /** 3.254 - * is this an array object? 3.255 - * 3.256 - * @return if this mirror wraps a ECMAScript array object 3.257 - */ 3.258 - public boolean isArray() { 3.259 - return sobj.isArray(); 3.260 - } 3.261 - 3.262 /** 3.263 * Utility to check if given object is ECMAScript undefined value 3.264 *
4.1 --- a/src/jdk/nashorn/internal/ir/IdentNode.java Wed Sep 11 10:27:25 2013 +0200 4.2 +++ b/src/jdk/nashorn/internal/ir/IdentNode.java Wed Sep 11 20:49:28 2013 +0530 4.3 @@ -168,6 +168,7 @@ 4.4 * return 3; 4.5 * } 4.6 * } 4.7 + * </pre> 4.8 * 4.9 * @return true if can have callsite type 4.10 */
5.1 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Wed Sep 11 10:27:25 2013 +0200 5.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Wed Sep 11 20:49:28 2013 +0530 5.3 @@ -565,7 +565,7 @@ 5.4 5.5 @Override 5.6 public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) { 5.7 - final MethodHandle mh = super.asCollector(handle, arrayType, arrayLength); 5.8 + final MethodHandle mh = super.asSpreader(handle, arrayType, arrayLength); 5.9 return debug(mh, "asSpreader", handle, arrayType, arrayLength); 5.10 } 5.11
6.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java Wed Sep 11 10:27:25 2013 +0200 6.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Wed Sep 11 20:49:28 2013 +0530 6.3 @@ -41,7 +41,7 @@ 6.4 import java.util.List; 6.5 import java.util.concurrent.Callable; 6.6 6.7 -import jdk.nashorn.api.scripting.ScriptObjectMirror; 6.8 +import jdk.nashorn.api.scripting.JSObject; 6.9 import jdk.nashorn.internal.objects.annotations.Attribute; 6.10 import jdk.nashorn.internal.objects.annotations.Constructor; 6.11 import jdk.nashorn.internal.objects.annotations.Function; 6.12 @@ -374,7 +374,7 @@ 6.13 public static Object isArray(final Object self, final Object arg) { 6.14 return isArray(arg) || (arg == Global.instance().getArrayPrototype()) 6.15 || (arg instanceof NativeRegExpExecResult) 6.16 - || (arg instanceof ScriptObjectMirror && ((ScriptObjectMirror)arg).isArray()); 6.17 + || (arg instanceof JSObject && ((JSObject)arg).isArray()); 6.18 } 6.19 6.20 /**
7.1 --- a/src/jdk/nashorn/internal/objects/NativeFunction.java Wed Sep 11 10:27:25 2013 +0200 7.2 +++ b/src/jdk/nashorn/internal/objects/NativeFunction.java Wed Sep 11 20:49:28 2013 +0530 7.3 @@ -30,7 +30,7 @@ 7.4 7.5 import java.util.List; 7.6 7.7 -import jdk.nashorn.api.scripting.ScriptObjectMirror; 7.8 +import jdk.nashorn.api.scripting.JSObject; 7.9 import jdk.nashorn.internal.objects.annotations.Attribute; 7.10 import jdk.nashorn.internal.objects.annotations.Constructor; 7.11 import jdk.nashorn.internal.objects.annotations.Function; 7.12 @@ -88,7 +88,7 @@ 7.13 */ 7.14 @Function(attributes = Attribute.NOT_ENUMERABLE) 7.15 public static Object apply(final Object self, final Object thiz, final Object array) { 7.16 - if (!(self instanceof ScriptFunction)) { 7.17 + if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) { 7.18 throw typeError("not.a.function", ScriptRuntime.safeToString(self)); 7.19 } 7.20 7.21 @@ -111,21 +111,27 @@ 7.22 list.toArray(args = new Object[list.size()]); 7.23 } else if (array == null || array == UNDEFINED) { 7.24 args = ScriptRuntime.EMPTY_ARRAY; 7.25 - } else if (array instanceof ScriptObjectMirror) { 7.26 - // look for array-like ScriptObjectMirror object 7.27 - final ScriptObjectMirror mirror = (ScriptObjectMirror)array; 7.28 - final Object len = mirror.containsKey("length")? mirror.getMember("length") : Integer.valueOf(0); 7.29 + } else if (array instanceof JSObject) { 7.30 + // look for array-like JSObject object 7.31 + final JSObject jsObj = (JSObject)array; 7.32 + final Object len = jsObj.hasMember("length")? jsObj.getMember("length") : Integer.valueOf(0); 7.33 final int n = (int)JSType.toUint32(len); 7.34 7.35 args = new Object[n]; 7.36 for (int i = 0; i < args.length; i++) { 7.37 - args[i] = mirror.containsKey(i)? mirror.getSlot(i) : UNDEFINED; 7.38 + args[i] = jsObj.hasSlot(i)? jsObj.getSlot(i) : UNDEFINED; 7.39 } 7.40 } else { 7.41 throw typeError("function.apply.expects.array"); 7.42 } 7.43 7.44 - return ScriptRuntime.apply((ScriptFunction)self, thiz, args); 7.45 + if (self instanceof ScriptFunction) { 7.46 + return ScriptRuntime.apply((ScriptFunction)self, thiz, args); 7.47 + } else if (self instanceof JSObject) { 7.48 + return ((JSObject)self).call(thiz, args); 7.49 + } 7.50 + 7.51 + throw new AssertionError("should not reach here"); 7.52 } 7.53 7.54 /** 7.55 @@ -137,7 +143,7 @@ 7.56 */ 7.57 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 7.58 public static Object call(final Object self, final Object... args) { 7.59 - if (!(self instanceof ScriptFunction)) { 7.60 + if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) { 7.61 throw typeError("not.a.function", ScriptRuntime.safeToString(self)); 7.62 } 7.63 7.64 @@ -151,7 +157,13 @@ 7.65 arguments = ScriptRuntime.EMPTY_ARRAY; 7.66 } 7.67 7.68 - return ScriptRuntime.apply((ScriptFunction)self, thiz, arguments); 7.69 + if (self instanceof ScriptFunction) { 7.70 + return ScriptRuntime.apply((ScriptFunction)self, thiz, arguments); 7.71 + } else if (self instanceof JSObject) { 7.72 + return ((JSObject)self).call(thiz, arguments); 7.73 + } 7.74 + 7.75 + throw new AssertionError("should not reach here"); 7.76 } 7.77 7.78 /**
8.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Sep 11 10:27:25 2013 +0200 8.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Sep 11 20:49:28 2013 +0530 8.3 @@ -43,6 +43,7 @@ 8.4 import java.util.NoSuchElementException; 8.5 import java.util.Objects; 8.6 import jdk.internal.dynalink.beans.StaticClass; 8.7 +import jdk.nashorn.api.scripting.JSObject; 8.8 import jdk.nashorn.api.scripting.ScriptObjectMirror; 8.9 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 8.10 import jdk.nashorn.internal.ir.debug.JSONWriter; 8.11 @@ -190,8 +191,8 @@ 8.12 case FUNCTION: 8.13 if (self instanceof ScriptObject) { 8.14 className = ((ScriptObject)self).getClassName(); 8.15 - } else if (self instanceof ScriptObjectMirror) { 8.16 - className = ((ScriptObjectMirror)self).getClassName(); 8.17 + } else if (self instanceof JSObject) { 8.18 + className = ((JSObject)self).getClassName(); 8.19 } else { 8.20 className = self.getClass().getName(); 8.21 } 8.22 @@ -245,8 +246,8 @@ 8.23 return new RangeIterator(Array.getLength(obj)); 8.24 } 8.25 8.26 - if (obj instanceof ScriptObjectMirror) { 8.27 - return ((ScriptObjectMirror)obj).keySet().iterator(); 8.28 + if (obj instanceof JSObject) { 8.29 + return ((JSObject)obj).keySet().iterator(); 8.30 } 8.31 8.32 if (obj instanceof List) { 8.33 @@ -323,8 +324,8 @@ 8.34 }; 8.35 } 8.36 8.37 - if (obj instanceof ScriptObjectMirror) { 8.38 - return ((ScriptObjectMirror)obj).values().iterator(); 8.39 + if (obj instanceof JSObject) { 8.40 + return ((JSObject)obj).values().iterator(); 8.41 } 8.42 8.43 if (obj instanceof Map) { 8.44 @@ -571,8 +572,8 @@ 8.45 throw typeError("cant.get.property", safeToString(property), "null"); 8.46 } else if (JSType.isPrimitive(obj)) { 8.47 obj = ((ScriptObject)JSType.toScriptObject(obj)).get(property); 8.48 - } else if (obj instanceof ScriptObjectMirror) { 8.49 - obj = ((ScriptObjectMirror)obj).getMember(property.toString()); 8.50 + } else if (obj instanceof JSObject) { 8.51 + obj = ((JSObject)obj).getMember(property.toString()); 8.52 } else { 8.53 obj = UNDEFINED; 8.54 } 8.55 @@ -624,6 +625,11 @@ 8.56 return ((ScriptObject) JSType.toScriptObject(obj)).delete(property, Boolean.TRUE.equals(strict)); 8.57 } 8.58 8.59 + if (obj instanceof JSObject) { 8.60 + ((JSObject)obj).removeMember(Objects.toString(property)); 8.61 + return true; 8.62 + } 8.63 + 8.64 // if object is not reference type, vacuously delete is successful. 8.65 return true; 8.66 } 8.67 @@ -815,6 +821,10 @@ 8.68 return ((ScriptObject)obj).has(property); 8.69 } 8.70 8.71 + if (obj instanceof JSObject) { 8.72 + return ((JSObject)obj).hasMember(Objects.toString(property)); 8.73 + } 8.74 + 8.75 return false; 8.76 } 8.77 8.78 @@ -841,11 +851,13 @@ 8.79 return ((StaticClass)clazz).getRepresentedClass().isInstance(obj); 8.80 } 8.81 8.82 - if (clazz instanceof ScriptObjectMirror) { 8.83 - if (obj instanceof ScriptObjectMirror) { 8.84 - return ((ScriptObjectMirror)clazz).isInstance((ScriptObjectMirror)obj); 8.85 - } 8.86 - return false; 8.87 + if (clazz instanceof JSObject) { 8.88 + return ((JSObject)clazz).isInstance(obj); 8.89 + } 8.90 + 8.91 + // provide for reverse hook 8.92 + if (obj instanceof JSObject) { 8.93 + return ((JSObject)obj).isInstanceOf(clazz); 8.94 } 8.95 8.96 throw typeError("instanceof.on.non.object");
9.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java Wed Sep 11 10:27:25 2013 +0200 9.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java Wed Sep 11 20:49:28 2013 +0530 9.3 @@ -27,7 +27,7 @@ 9.4 9.5 import java.util.Iterator; 9.6 import java.util.List; 9.7 -import jdk.nashorn.api.scripting.ScriptObjectMirror; 9.8 +import jdk.nashorn.api.scripting.JSObject; 9.9 import jdk.nashorn.internal.runtime.JSType; 9.10 import jdk.nashorn.internal.runtime.ScriptObject; 9.11 9.12 @@ -127,8 +127,8 @@ 9.13 return new ScriptObjectIterator((ScriptObject)obj, includeUndefined); 9.14 } 9.15 9.16 - if (obj instanceof ScriptObjectMirror) { 9.17 - return new ScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined); 9.18 + if (obj instanceof JSObject) { 9.19 + return new JSObjectIterator((JSObject)obj, includeUndefined); 9.20 } 9.21 9.22 if (obj instanceof List) { 9.23 @@ -160,8 +160,8 @@ 9.24 return new ReverseScriptObjectIterator((ScriptObject)obj, includeUndefined); 9.25 } 9.26 9.27 - if (obj instanceof ScriptObjectMirror) { 9.28 - return new ReverseScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined); 9.29 + if (obj instanceof JSObject) { 9.30 + return new ReverseJSObjectIterator((JSObject)obj, includeUndefined); 9.31 } 9.32 9.33 if (obj instanceof List) {
10.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java Wed Sep 11 10:27:25 2013 +0200 10.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java Wed Sep 11 20:49:28 2013 +0530 10.3 @@ -27,7 +27,7 @@ 10.4 10.5 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 10.6 10.7 -import jdk.nashorn.api.scripting.ScriptObjectMirror; 10.8 +import jdk.nashorn.api.scripting.JSObject; 10.9 import jdk.nashorn.internal.runtime.Context; 10.10 import jdk.nashorn.internal.runtime.ScriptFunction; 10.11 import jdk.nashorn.internal.runtime.ScriptRuntime; 10.12 @@ -101,9 +101,9 @@ 10.13 final boolean strict; 10.14 if (callbackfn instanceof ScriptFunction) { 10.15 strict = ((ScriptFunction)callbackfn).isStrict(); 10.16 - } else if (callbackfn instanceof ScriptObjectMirror && 10.17 - ((ScriptObjectMirror)callbackfn).isFunction()) { 10.18 - strict = ((ScriptObjectMirror)callbackfn).isStrictFunction(); 10.19 + } else if (callbackfn instanceof JSObject && 10.20 + ((JSObject)callbackfn).isFunction()) { 10.21 + strict = ((JSObject)callbackfn).isStrictFunction(); 10.22 } else if (Bootstrap.isDynamicMethod(callbackfn) || Bootstrap.isFunctionalInterfaceObject(callbackfn)) { 10.23 strict = false; 10.24 } else {
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/JSObjectIterator.java Wed Sep 11 20:49:28 2013 +0530 11.3 @@ -0,0 +1,81 @@ 11.4 +/* 11.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. Oracle designates this 11.11 + * particular file as subject to the "Classpath" exception as provided 11.12 + * by Oracle in the LICENSE file that accompanied this code. 11.13 + * 11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.17 + * version 2 for more details (a copy is included in the LICENSE file that 11.18 + * accompanied this code). 11.19 + * 11.20 + * You should have received a copy of the GNU General Public License version 11.21 + * 2 along with this work; if not, write to the Free Software Foundation, 11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.23 + * 11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 11.25 + * or visit www.oracle.com if you need additional information or have any 11.26 + * questions. 11.27 + */ 11.28 + 11.29 +package jdk.nashorn.internal.runtime.arrays; 11.30 + 11.31 +import java.util.NoSuchElementException; 11.32 +import jdk.nashorn.api.scripting.JSObject; 11.33 +import jdk.nashorn.internal.runtime.JSType; 11.34 + 11.35 +/** 11.36 + * Iterator over a ScriptObjectMirror 11.37 + */ 11.38 +class JSObjectIterator extends ArrayLikeIterator<Object> { 11.39 + 11.40 + protected final JSObject obj; 11.41 + private final long length; 11.42 + 11.43 + JSObjectIterator(final JSObject obj, final boolean includeUndefined) { 11.44 + super(includeUndefined); 11.45 + this.obj = obj; 11.46 + this.length = JSType.toUint32(obj.hasMember("length")? obj.getMember("length") : 0); 11.47 + this.index = 0; 11.48 + } 11.49 + 11.50 + protected boolean indexInArray() { 11.51 + return index < length; 11.52 + } 11.53 + 11.54 + @Override 11.55 + public long getLength() { 11.56 + return length; 11.57 + } 11.58 + 11.59 + @Override 11.60 + public boolean hasNext() { 11.61 + if (length == 0L) { 11.62 + return false; //return empty string if toUint32(length) == 0 11.63 + } 11.64 + 11.65 + while (indexInArray()) { 11.66 + if (obj.hasSlot((int)index) || includeUndefined) { 11.67 + break; 11.68 + } 11.69 + bumpIndex(); 11.70 + } 11.71 + 11.72 + return indexInArray(); 11.73 + } 11.74 + 11.75 + @Override 11.76 + public Object next() { 11.77 + if (indexInArray()) { 11.78 + return obj.getSlot((int)bumpIndex()); 11.79 + } 11.80 + 11.81 + throw new NoSuchElementException(); 11.82 + } 11.83 +} 11.84 +
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ReverseJSObjectIterator.java Wed Sep 11 20:49:28 2013 +0530 12.3 @@ -0,0 +1,56 @@ 12.4 +/* 12.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.7 + * 12.8 + * This code is free software; you can redistribute it and/or modify it 12.9 + * under the terms of the GNU General Public License version 2 only, as 12.10 + * published by the Free Software Foundation. Oracle designates this 12.11 + * particular file as subject to the "Classpath" exception as provided 12.12 + * by Oracle in the LICENSE file that accompanied this code. 12.13 + * 12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12.17 + * version 2 for more details (a copy is included in the LICENSE file that 12.18 + * accompanied this code). 12.19 + * 12.20 + * You should have received a copy of the GNU General Public License version 12.21 + * 2 along with this work; if not, write to the Free Software Foundation, 12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 12.23 + * 12.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 12.25 + * or visit www.oracle.com if you need additional information or have any 12.26 + * questions. 12.27 + */ 12.28 + 12.29 +package jdk.nashorn.internal.runtime.arrays; 12.30 + 12.31 +import jdk.nashorn.api.scripting.JSObject; 12.32 +import jdk.nashorn.internal.runtime.JSType; 12.33 + 12.34 +/** 12.35 + * Reverse iterator over a ScriptObjectMirror 12.36 + */ 12.37 +final class ReverseJSObjectIterator extends JSObjectIterator { 12.38 + 12.39 + ReverseJSObjectIterator(final JSObject obj, final boolean includeUndefined) { 12.40 + super(obj, includeUndefined); 12.41 + this.index = JSType.toUint32(obj.hasMember("length")? obj.getMember("length") : 0) - 1; 12.42 + } 12.43 + 12.44 + @Override 12.45 + public boolean isReverse() { 12.46 + return true; 12.47 + } 12.48 + 12.49 + @Override 12.50 + protected boolean indexInArray() { 12.51 + return index >= 0; 12.52 + } 12.53 + 12.54 + @Override 12.55 + protected long bumpIndex() { 12.56 + return index--; 12.57 + } 12.58 +} 12.59 +
13.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java Wed Sep 11 10:27:25 2013 +0200 13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 13.3 @@ -1,56 +0,0 @@ 13.4 -/* 13.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 13.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 13.7 - * 13.8 - * This code is free software; you can redistribute it and/or modify it 13.9 - * under the terms of the GNU General Public License version 2 only, as 13.10 - * published by the Free Software Foundation. Oracle designates this 13.11 - * particular file as subject to the "Classpath" exception as provided 13.12 - * by Oracle in the LICENSE file that accompanied this code. 13.13 - * 13.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 13.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13.17 - * version 2 for more details (a copy is included in the LICENSE file that 13.18 - * accompanied this code). 13.19 - * 13.20 - * You should have received a copy of the GNU General Public License version 13.21 - * 2 along with this work; if not, write to the Free Software Foundation, 13.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 13.23 - * 13.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 13.25 - * or visit www.oracle.com if you need additional information or have any 13.26 - * questions. 13.27 - */ 13.28 - 13.29 -package jdk.nashorn.internal.runtime.arrays; 13.30 - 13.31 -import jdk.nashorn.api.scripting.ScriptObjectMirror; 13.32 -import jdk.nashorn.internal.runtime.JSType; 13.33 - 13.34 -/** 13.35 - * Reverse iterator over a ScriptObjectMirror 13.36 - */ 13.37 -final class ReverseScriptObjectMirrorIterator extends ScriptObjectMirrorIterator { 13.38 - 13.39 - ReverseScriptObjectMirrorIterator(final ScriptObjectMirror obj, final boolean includeUndefined) { 13.40 - super(obj, includeUndefined); 13.41 - this.index = JSType.toUint32(obj.containsKey("length")? obj.getMember("length") : 0) - 1; 13.42 - } 13.43 - 13.44 - @Override 13.45 - public boolean isReverse() { 13.46 - return true; 13.47 - } 13.48 - 13.49 - @Override 13.50 - protected boolean indexInArray() { 13.51 - return index >= 0; 13.52 - } 13.53 - 13.54 - @Override 13.55 - protected long bumpIndex() { 13.56 - return index--; 13.57 - } 13.58 -} 13.59 -
14.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java Wed Sep 11 10:27:25 2013 +0200 14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 14.3 @@ -1,81 +0,0 @@ 14.4 -/* 14.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 14.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.7 - * 14.8 - * This code is free software; you can redistribute it and/or modify it 14.9 - * under the terms of the GNU General Public License version 2 only, as 14.10 - * published by the Free Software Foundation. Oracle designates this 14.11 - * particular file as subject to the "Classpath" exception as provided 14.12 - * by Oracle in the LICENSE file that accompanied this code. 14.13 - * 14.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 14.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14.17 - * version 2 for more details (a copy is included in the LICENSE file that 14.18 - * accompanied this code). 14.19 - * 14.20 - * You should have received a copy of the GNU General Public License version 14.21 - * 2 along with this work; if not, write to the Free Software Foundation, 14.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 14.23 - * 14.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 14.25 - * or visit www.oracle.com if you need additional information or have any 14.26 - * questions. 14.27 - */ 14.28 - 14.29 -package jdk.nashorn.internal.runtime.arrays; 14.30 - 14.31 -import java.util.NoSuchElementException; 14.32 -import jdk.nashorn.api.scripting.ScriptObjectMirror; 14.33 -import jdk.nashorn.internal.runtime.JSType; 14.34 - 14.35 -/** 14.36 - * Iterator over a ScriptObjectMirror 14.37 - */ 14.38 -class ScriptObjectMirrorIterator extends ArrayLikeIterator<Object> { 14.39 - 14.40 - protected final ScriptObjectMirror obj; 14.41 - private final long length; 14.42 - 14.43 - ScriptObjectMirrorIterator(final ScriptObjectMirror obj, final boolean includeUndefined) { 14.44 - super(includeUndefined); 14.45 - this.obj = obj; 14.46 - this.length = JSType.toUint32(obj.containsKey("length")? obj.getMember("length") : 0); 14.47 - this.index = 0; 14.48 - } 14.49 - 14.50 - protected boolean indexInArray() { 14.51 - return index < length; 14.52 - } 14.53 - 14.54 - @Override 14.55 - public long getLength() { 14.56 - return length; 14.57 - } 14.58 - 14.59 - @Override 14.60 - public boolean hasNext() { 14.61 - if (length == 0L) { 14.62 - return false; //return empty string if toUint32(length) == 0 14.63 - } 14.64 - 14.65 - while (indexInArray()) { 14.66 - if (obj.containsKey(index) || includeUndefined) { 14.67 - break; 14.68 - } 14.69 - bumpIndex(); 14.70 - } 14.71 - 14.72 - return indexInArray(); 14.73 - } 14.74 - 14.75 - @Override 14.76 - public Object next() { 14.77 - if (indexInArray()) { 14.78 - return obj.get(bumpIndex()); 14.79 - } 14.80 - 14.81 - throw new NoSuchElementException(); 14.82 - } 14.83 -} 14.84 -
15.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Sep 11 10:27:25 2013 +0200 15.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Sep 11 20:49:28 2013 +0530 15.3 @@ -39,7 +39,7 @@ 15.4 import jdk.internal.dynalink.beans.StaticClass; 15.5 import jdk.internal.dynalink.linker.GuardedInvocation; 15.6 import jdk.internal.dynalink.linker.LinkerServices; 15.7 -import jdk.nashorn.api.scripting.ScriptObjectMirror; 15.8 +import jdk.nashorn.api.scripting.JSObject; 15.9 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 15.10 import jdk.nashorn.internal.codegen.RuntimeCallSite; 15.11 import jdk.nashorn.internal.runtime.JSType; 15.12 @@ -87,7 +87,7 @@ 15.13 } 15.14 15.15 return obj instanceof ScriptFunction || 15.16 - ((obj instanceof ScriptObjectMirror) && ((ScriptObjectMirror)obj).isFunction()) || 15.17 + ((obj instanceof JSObject) && ((JSObject)obj).isFunction()) || 15.18 isDynamicMethod(obj) || 15.19 isFunctionalInterfaceObject(obj) || 15.20 obj instanceof StaticClass;
16.1 --- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Sep 11 10:27:25 2013 +0200 16.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Sep 11 20:49:28 2013 +0530 16.3 @@ -30,7 +30,6 @@ 16.4 import java.lang.invoke.MethodHandle; 16.5 import java.lang.invoke.MethodHandles; 16.6 import java.lang.invoke.MethodType; 16.7 -import java.util.Objects; 16.8 import jdk.internal.dynalink.CallSiteDescriptor; 16.9 import jdk.internal.dynalink.linker.GuardedInvocation; 16.10 import jdk.internal.dynalink.linker.LinkRequest; 16.11 @@ -88,8 +87,9 @@ 16.12 case "setElem": 16.13 return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); 16.14 case "call": 16.15 + return findCallMethod(desc, operator); 16.16 case "callMethod": 16.17 - return findCallMethod(desc, operator); 16.18 + return findCallMethodMethod(desc, operator); 16.19 case "new": 16.20 return findNewMethod(desc); 16.21 default: 16.22 @@ -98,33 +98,37 @@ 16.23 } 16.24 16.25 private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) { 16.26 - final MethodHandle getter = MH.insertArguments(JSOBJECT_GET, 1, desc.getNameToken(2)); 16.27 + final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, desc.getNameToken(2)); 16.28 return new GuardedInvocation(getter, null, IS_JSOBJECT_GUARD); 16.29 } 16.30 16.31 private static GuardedInvocation findGetIndexMethod() { 16.32 - return new GuardedInvocation(JSOBJECT_GET, null, IS_JSOBJECT_GUARD); 16.33 + return new GuardedInvocation(JSOBJECTLINKER_GET, null, IS_JSOBJECT_GUARD); 16.34 } 16.35 16.36 private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) { 16.37 - final MethodHandle getter = MH.insertArguments(JSOBJECT_PUT, 1, desc.getNameToken(2)); 16.38 + final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2)); 16.39 return new GuardedInvocation(getter, null, IS_JSOBJECT_GUARD); 16.40 } 16.41 16.42 private static GuardedInvocation findSetIndexMethod() { 16.43 - return new GuardedInvocation(JSOBJECT_PUT, null, IS_JSOBJECT_GUARD); 16.44 + return new GuardedInvocation(JSOBJECTLINKER_PUT, null, IS_JSOBJECT_GUARD); 16.45 } 16.46 16.47 - private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final String operator) { 16.48 - // if operator is "call", then 'self' is a JSObject function object already. Use 'call' as the method name 16.49 - final String methodName = "callMethod".equals(operator)? desc.getNameToken(2) : "call"; 16.50 - MethodHandle func = MH.insertArguments(JSOBJECT_CALL, 1, methodName); 16.51 + private static GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final String operator) { 16.52 + final String methodName = desc.getNameToken(2); 16.53 + MethodHandle func = MH.insertArguments(JSOBJECT_CALLMEMBER, 1, methodName); 16.54 func = MH.asCollector(func, Object[].class, desc.getMethodType().parameterCount() - 1); 16.55 return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD); 16.56 } 16.57 16.58 + private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final String operator) { 16.59 + final MethodHandle func = MH.asCollector(JSOBJECT_CALL, Object[].class, desc.getMethodType().parameterCount() - 2); 16.60 + return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD); 16.61 + } 16.62 + 16.63 private static GuardedInvocation findNewMethod(final CallSiteDescriptor desc) { 16.64 - MethodHandle func = MH.asCollector(JSOBJECT_NEW, Object[].class, desc.getMethodType().parameterCount() - 1); 16.65 + final MethodHandle func = MH.asCollector(JSOBJECT_NEW, Object[].class, desc.getMethodType().parameterCount() - 1); 16.66 return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD); 16.67 } 16.68 16.69 @@ -135,36 +139,30 @@ 16.70 16.71 @SuppressWarnings("unused") 16.72 private static Object get(final Object jsobj, final Object key) { 16.73 - if (key instanceof String) { 16.74 - return ((JSObject)jsobj).getMember((String)key); 16.75 + if (key instanceof Integer) { 16.76 + return ((JSObject)jsobj).getSlot((int)(Integer)key); 16.77 } else if (key instanceof Number) { 16.78 final int index = getIndex((Number)key); 16.79 if (index > -1) { 16.80 return ((JSObject)jsobj).getSlot(index); 16.81 } 16.82 + } else if (key instanceof String) { 16.83 + return ((JSObject)jsobj).getMember((String)key); 16.84 } 16.85 return null; 16.86 } 16.87 16.88 @SuppressWarnings("unused") 16.89 private static void put(final Object jsobj, final Object key, final Object value) { 16.90 - if (key instanceof String) { 16.91 - ((JSObject)jsobj).setMember((String)key, value); 16.92 + if (key instanceof Integer) { 16.93 + ((JSObject)jsobj).setSlot((int)(Integer)key, value); 16.94 } else if (key instanceof Number) { 16.95 ((JSObject)jsobj).setSlot(getIndex((Number)key), value); 16.96 + } else if (key instanceof String) { 16.97 + ((JSObject)jsobj).setMember((String)key, value); 16.98 } 16.99 } 16.100 16.101 - @SuppressWarnings("unused") 16.102 - private static Object call(final Object jsobj, final Object method, final Object... args) { 16.103 - return ((JSObject)jsobj).call(Objects.toString(method), args); 16.104 - } 16.105 - 16.106 - @SuppressWarnings("unused") 16.107 - private static Object newObject(final Object jsobj, final Object... args) { 16.108 - return ((JSObject)jsobj).newObject(null, args); 16.109 - } 16.110 - 16.111 private static int getIndex(final Number n) { 16.112 final double value = n.doubleValue(); 16.113 return JSType.isRepresentableAsInt(value) ? (int)value : -1; 16.114 @@ -172,11 +170,17 @@ 16.115 16.116 private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality(); 16.117 16.118 - private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH("isJSObject", boolean.class, Object.class); 16.119 - private static final MethodHandle JSOBJECT_GET = findOwnMH("get", Object.class, Object.class, Object.class); 16.120 - private static final MethodHandle JSOBJECT_PUT = findOwnMH("put", Void.TYPE, Object.class, Object.class, Object.class); 16.121 - private static final MethodHandle JSOBJECT_CALL = findOwnMH("call", Object.class, Object.class, Object.class, Object[].class); 16.122 - private static final MethodHandle JSOBJECT_NEW = findOwnMH("newObject", Object.class, Object.class, Object[].class); 16.123 + // method handles of the current class 16.124 + private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH("isJSObject", boolean.class, Object.class); 16.125 + private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH("get", Object.class, Object.class, Object.class); 16.126 + private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH("put", Void.TYPE, Object.class, Object.class, Object.class); 16.127 + 16.128 + // method handles of JSObject class 16.129 + private static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH("getMember", Object.class, String.class); 16.130 + private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH("setMember", Void.TYPE, String.class, Object.class); 16.131 + private static final MethodHandle JSOBJECT_CALLMEMBER = findJSObjectMH("callMember", Object.class, String.class, Object[].class); 16.132 + private static final MethodHandle JSOBJECT_CALL = findJSObjectMH("call", Object.class, Object.class, Object[].class); 16.133 + private static final MethodHandle JSOBJECT_NEW = findJSObjectMH("newObject", Object.class, Object[].class); 16.134 16.135 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 16.136 final Class<?> own = JSObjectLinker.class; 16.137 @@ -187,4 +191,14 @@ 16.138 return MH.findVirtual(MethodHandles.lookup(), own, name, mt); 16.139 } 16.140 } 16.141 + 16.142 + private static MethodHandle findJSObjectMH(final String name, final Class<?> rtype, final Class<?>... types) { 16.143 + final Class<?> own = JSObject.class; 16.144 + final MethodType mt = MH.type(rtype, types); 16.145 + try { 16.146 + return MH.findVirtual(MethodHandles.publicLookup(), own, name, mt); 16.147 + } catch (final MethodHandleFactory.LookupException e) { 16.148 + return MH.findVirtual(MethodHandles.lookup(), own, name, mt); 16.149 + } 16.150 + } 16.151 }
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Wed Sep 11 20:49:28 2013 +0530 17.3 @@ -0,0 +1,257 @@ 17.4 +/* 17.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 17.7 + * 17.8 + * This code is free software; you can redistribute it and/or modify it 17.9 + * under the terms of the GNU General Public License version 2 only, as 17.10 + * published by the Free Software Foundation. Oracle designates this 17.11 + * particular file as subject to the "Classpath" exception as provided 17.12 + * by Oracle in the LICENSE file that accompanied this code. 17.13 + * 17.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 17.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17.17 + * version 2 for more details (a copy is included in the LICENSE file that 17.18 + * accompanied this code). 17.19 + * 17.20 + * You should have received a copy of the GNU General Public License version 17.21 + * 2 along with this work; if not, write to the Free Software Foundation, 17.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17.23 + * 17.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 17.25 + * or visit www.oracle.com if you need additional information or have any 17.26 + * questions. 17.27 + */ 17.28 + 17.29 +package jdk.nashorn.api.scripting; 17.30 + 17.31 +import java.nio.IntBuffer; 17.32 +import java.util.Collection; 17.33 +import java.util.HashMap; 17.34 +import java.util.Set; 17.35 +import javax.script.ScriptEngine; 17.36 +import javax.script.ScriptEngineManager; 17.37 +import javax.script.ScriptException; 17.38 +import static org.testng.Assert.assertEquals; 17.39 +import static org.testng.Assert.assertTrue; 17.40 +import static org.testng.Assert.assertFalse; 17.41 +import static org.testng.Assert.fail; 17.42 +import org.testng.annotations.Test; 17.43 + 17.44 +/** 17.45 + * Tests for pluggable external impls. of jdk.nashorn.api.scripting.JSObject. 17.46 + * 17.47 + * JDK-8024615: Refactor ScriptObjectMirror and JSObject to support external 17.48 + * JSObject implementations. 17.49 + */ 17.50 +public class PluggableJSObjectTest { 17.51 + public static class MapWrapperObject extends JSObject { 17.52 + private final HashMap<String, Object> map = new HashMap<>(); 17.53 + 17.54 + public HashMap<String, Object> getMap() { 17.55 + return map; 17.56 + } 17.57 + 17.58 + @Override 17.59 + public Object getMember(String name) { 17.60 + return map.get(name); 17.61 + } 17.62 + 17.63 + @Override 17.64 + public void setMember(String name, Object value) { 17.65 + map.put(name, value); 17.66 + } 17.67 + 17.68 + @Override 17.69 + public boolean hasMember(String name) { 17.70 + return map.containsKey(name); 17.71 + } 17.72 + 17.73 + @Override 17.74 + public void removeMember(String name) { 17.75 + map.remove(name); 17.76 + } 17.77 + 17.78 + @Override 17.79 + public Set<String> keySet() { 17.80 + return map.keySet(); 17.81 + } 17.82 + 17.83 + @Override 17.84 + public Collection<Object> values() { 17.85 + return map.values(); 17.86 + } 17.87 + } 17.88 + 17.89 + @Test 17.90 + // Named property access on a JSObject 17.91 + public void namedAccessTest() { 17.92 + final ScriptEngineManager m = new ScriptEngineManager(); 17.93 + final ScriptEngine e = m.getEngineByName("nashorn"); 17.94 + try { 17.95 + final MapWrapperObject obj = new MapWrapperObject(); 17.96 + e.put("obj", obj); 17.97 + obj.getMap().put("foo", "bar"); 17.98 + 17.99 + // property-like access on MapWrapperObject objects 17.100 + assertEquals(e.eval("obj.foo"), "bar"); 17.101 + e.eval("obj.foo = 'hello'"); 17.102 + assertEquals(e.eval("'foo' in obj"), Boolean.TRUE); 17.103 + assertEquals(e.eval("obj.foo"), "hello"); 17.104 + assertEquals(obj.getMap().get("foo"), "hello"); 17.105 + e.eval("delete obj.foo"); 17.106 + assertFalse(obj.getMap().containsKey("foo")); 17.107 + assertEquals(e.eval("'foo' in obj"), Boolean.FALSE); 17.108 + } catch (final Exception exp) { 17.109 + exp.printStackTrace(); 17.110 + fail(exp.getMessage()); 17.111 + } 17.112 + } 17.113 + 17.114 + public static class BufferObject extends JSObject { 17.115 + private final IntBuffer buf; 17.116 + 17.117 + public BufferObject(int size) { 17.118 + buf = IntBuffer.allocate(size); 17.119 + } 17.120 + 17.121 + public IntBuffer getBuffer() { 17.122 + return buf; 17.123 + } 17.124 + 17.125 + @Override 17.126 + public Object getMember(String name) { 17.127 + return name.equals("length")? buf.capacity() : null; 17.128 + } 17.129 + 17.130 + @Override 17.131 + public boolean hasSlot(int i) { 17.132 + return i > -1 && i < buf.capacity(); 17.133 + } 17.134 + 17.135 + @Override 17.136 + public Object getSlot(int i) { 17.137 + return buf.get(i); 17.138 + } 17.139 + 17.140 + @Override 17.141 + public void setSlot(int i, Object value) { 17.142 + buf.put(i, ((Number)value).intValue()); 17.143 + } 17.144 + 17.145 + @Override 17.146 + public boolean isArray() { 17.147 + return true; 17.148 + } 17.149 + } 17.150 + 17.151 + @Test 17.152 + // array-like indexed access for a JSObject 17.153 + public void indexedAccessTest() { 17.154 + final ScriptEngineManager m = new ScriptEngineManager(); 17.155 + final ScriptEngine e = m.getEngineByName("nashorn"); 17.156 + try { 17.157 + final BufferObject buf = new BufferObject(2); 17.158 + e.put("buf", buf); 17.159 + 17.160 + // array-like access on BufferObject objects 17.161 + assertEquals(e.eval("buf.length"), buf.getBuffer().capacity()); 17.162 + e.eval("buf[0] = 23"); 17.163 + assertEquals(buf.getBuffer().get(0), 23); 17.164 + assertEquals(e.eval("buf[0]"), 23); 17.165 + assertEquals(e.eval("buf[1]"), 0); 17.166 + buf.getBuffer().put(1, 42); 17.167 + assertEquals(e.eval("buf[1]"), 42); 17.168 + assertEquals(e.eval("Array.isArray(buf)"), Boolean.TRUE); 17.169 + } catch (final Exception exp) { 17.170 + exp.printStackTrace(); 17.171 + fail(exp.getMessage()); 17.172 + } 17.173 + } 17.174 + 17.175 + public static class Adder extends JSObject { 17.176 + @Override 17.177 + public Object call(Object thiz, Object... args) { 17.178 + double res = 0.0; 17.179 + for (Object arg : args) { 17.180 + res += ((Number)arg).doubleValue(); 17.181 + } 17.182 + return res; 17.183 + } 17.184 + 17.185 + @Override 17.186 + public boolean isFunction() { 17.187 + return true; 17.188 + } 17.189 + } 17.190 + 17.191 + @Test 17.192 + // a callable JSObject 17.193 + public void callableJSObjectTest() { 17.194 + final ScriptEngineManager m = new ScriptEngineManager(); 17.195 + final ScriptEngine e = m.getEngineByName("nashorn"); 17.196 + try { 17.197 + e.put("sum", new Adder()); 17.198 + // check callability of Adder objects 17.199 + assertEquals(e.eval("typeof sum"), "function"); 17.200 + assertEquals(((Number)e.eval("sum(1, 2, 3, 4, 5)")).intValue(), 15); 17.201 + } catch (final Exception exp) { 17.202 + exp.printStackTrace(); 17.203 + fail(exp.getMessage()); 17.204 + } 17.205 + } 17.206 + 17.207 + public static class Factory extends JSObject { 17.208 + @Override 17.209 + public Object newObject(Object... args) { 17.210 + return new HashMap<Object, Object>(); 17.211 + } 17.212 + 17.213 + @Override 17.214 + public boolean isFunction() { 17.215 + return true; 17.216 + } 17.217 + } 17.218 + 17.219 + @Test 17.220 + // a factory JSObject 17.221 + public void factoryJSObjectTest() { 17.222 + final ScriptEngineManager m = new ScriptEngineManager(); 17.223 + final ScriptEngine e = m.getEngineByName("nashorn"); 17.224 + try { 17.225 + e.put("Factory", new Factory()); 17.226 + 17.227 + // check new on Factory 17.228 + assertEquals(e.eval("typeof Factory"), "function"); 17.229 + assertEquals(e.eval("typeof new Factory()"), "object"); 17.230 + assertEquals(e.eval("(new Factory()) instanceof java.util.Map"), Boolean.TRUE); 17.231 + } catch (final Exception exp) { 17.232 + exp.printStackTrace(); 17.233 + fail(exp.getMessage()); 17.234 + } 17.235 + } 17.236 + 17.237 + @Test 17.238 + // iteration tests 17.239 + public void iteratingJSObjectTest() { 17.240 + final ScriptEngineManager m = new ScriptEngineManager(); 17.241 + final ScriptEngine e = m.getEngineByName("nashorn"); 17.242 + try { 17.243 + final MapWrapperObject obj = new MapWrapperObject(); 17.244 + obj.setMember("foo", "hello"); 17.245 + obj.setMember("bar", "world"); 17.246 + e.put("obj", obj); 17.247 + 17.248 + // check for..in 17.249 + Object val = e.eval("var str = ''; for (i in obj) str += i; str"); 17.250 + assertEquals(val.toString(), "foobar"); 17.251 + 17.252 + // check for..each..in 17.253 + val = e.eval("var str = ''; for each (i in obj) str += i; str"); 17.254 + assertEquals(val.toString(), "helloworld"); 17.255 + } catch (final Exception exp) { 17.256 + exp.printStackTrace(); 17.257 + fail(exp.getMessage()); 17.258 + } 17.259 + } 17.260 +}
18.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Wed Sep 11 10:27:25 2013 +0200 18.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Wed Sep 11 20:49:28 2013 +0530 18.3 @@ -140,8 +140,8 @@ 18.4 fail("obj[1] != 'world'"); 18.5 } 18.6 18.7 - if (!obj.call("func", new Object[0]).equals("hello")) { 18.8 - fail("obj.call('func') != 'hello'"); 18.9 + if (!obj.callMember("func", new Object[0]).equals("hello")) { 18.10 + fail("obj.func() != 'hello'"); 18.11 } 18.12 18.13 // try setting properties 18.14 @@ -210,8 +210,8 @@ 18.15 18.16 e.eval("function func() {}"); 18.17 e2.put("foo", e.get("func")); 18.18 - final Object e2global = e2.eval("this"); 18.19 - final Object newObj = ((ScriptObjectMirror) e2global).newObject("foo"); 18.20 + final ScriptObjectMirror e2global = (ScriptObjectMirror)e2.eval("this"); 18.21 + final Object newObj = ((ScriptObjectMirror)e2global.getMember("foo")).newObject(); 18.22 assertTrue(newObj instanceof ScriptObjectMirror); 18.23 } 18.24 18.25 @@ -223,8 +223,8 @@ 18.26 18.27 e.eval("function func() {}"); 18.28 e2.put("func", e.get("func")); 18.29 - final Object e2obj = e2.eval("({ foo: func })"); 18.30 - final Object newObj = ((ScriptObjectMirror) e2obj).newObject("foo"); 18.31 + final ScriptObjectMirror e2obj = (ScriptObjectMirror)e2.eval("({ foo: func })"); 18.32 + final Object newObj = ((ScriptObjectMirror)e2obj.getMember("foo")).newObject(); 18.33 assertTrue(newObj instanceof ScriptObjectMirror); 18.34 } 18.35 }