8024615: Refactor ScriptObjectMirror and JSObject to support external JSObject implementations

Wed, 11 Sep 2013 20:49:28 +0530

author
sundar
date
Wed, 11 Sep 2013 20:49:28 +0530
changeset 546
2d4c8fa8a5f4
parent 545
badf750dda21
child 547
66db7354e7e2

8024615: Refactor ScriptObjectMirror and JSObject to support external JSObject implementations
Reviewed-by: jlaskey, hannesw

src/jdk/nashorn/api/scripting/JSObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/api/scripting/NashornScriptEngine.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/api/scripting/ScriptObjectMirror.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/IdentNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/lookup/MethodHandleFactory.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeArray.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeFunction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptRuntime.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/JSObjectIterator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ReverseJSObjectIterator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/Bootstrap.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java file | annotate | diff | comparison | revisions
     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  }

mercurial