Merge

Fri, 23 Aug 2013 16:44:02 +0530

author
sundar
date
Fri, 23 Aug 2013 16:44:02 +0530
changeset 522
2ce55025a37d
parent 507
e628aefac504
parent 521
f18f2ce1b2dc
child 523
a18f92a0a910

Merge

     1.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Mon Aug 19 19:37:29 2013 +0530
     1.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Fri Aug 23 16:44:02 2013 +0530
     1.3 @@ -55,6 +55,7 @@
     1.4  import javax.script.ScriptEngine;
     1.5  import javax.script.ScriptEngineFactory;
     1.6  import javax.script.ScriptException;
     1.7 +import javax.script.SimpleBindings;
     1.8  import jdk.nashorn.internal.runtime.Context;
     1.9  import jdk.nashorn.internal.runtime.ErrorManager;
    1.10  import jdk.nashorn.internal.runtime.GlobalObject;
    1.11 @@ -74,6 +75,12 @@
    1.12   */
    1.13  
    1.14  public final class NashornScriptEngine extends AbstractScriptEngine implements Compilable, Invocable {
    1.15 +    /**
    1.16 +     * Key used to associate Nashorn global object mirror with arbitrary Bindings instance.
    1.17 +     */
    1.18 +    public static final String NASHORN_GLOBAL = "nashorn.global";
    1.19 +
    1.20 +    // commonly used access control context objects
    1.21      private static AccessControlContext createPermAccCtxt(final String permName) {
    1.22          final Permissions perms = new Permissions();
    1.23          perms.add(new RuntimePermission(permName));
    1.24 @@ -83,16 +90,23 @@
    1.25      private static final AccessControlContext CREATE_CONTEXT_ACC_CTXT = createPermAccCtxt(Context.NASHORN_CREATE_CONTEXT);
    1.26      private static final AccessControlContext CREATE_GLOBAL_ACC_CTXT  = createPermAccCtxt(Context.NASHORN_CREATE_GLOBAL);
    1.27  
    1.28 +    // the factory that created this engine
    1.29      private final ScriptEngineFactory factory;
    1.30 +    // underlying nashorn Context - 1:1 with engine instance
    1.31      private final Context             nashornContext;
    1.32 +    // do we want to share single Nashorn global instance across ENGINE_SCOPEs?
    1.33 +    private final boolean             _global_per_engine;
    1.34 +    // This is the initial default Nashorn global object.
    1.35 +    // This is used as "shared" global if above option is true.
    1.36      private final ScriptObject        global;
    1.37 -    // initialized bit late to be made 'final'. Property object for "context"
    1.38 -    // property of global object
    1.39 -    private Property                  contextProperty;
    1.40 +    // initialized bit late to be made 'final'.
    1.41 +    // Property object for "context" property of global object.
    1.42 +    private volatile Property         contextProperty;
    1.43  
    1.44      // default options passed to Nashorn Options object
    1.45      private static final String[] DEFAULT_OPTIONS = new String[] { "-scripting", "-doe" };
    1.46  
    1.47 +    // Nashorn script engine error message management
    1.48      private static final String MESSAGES_RESOURCE = "jdk.nashorn.api.scripting.resources.Messages";
    1.49  
    1.50      private static final ResourceBundle MESSAGES_BUNDLE;
    1.51 @@ -100,6 +114,7 @@
    1.52          MESSAGES_BUNDLE = ResourceBundle.getBundle(MESSAGES_RESOURCE, Locale.getDefault());
    1.53      }
    1.54  
    1.55 +    // helper to get Nashorn script engine error message
    1.56      private static String getMessage(final String msgId, final String... args) {
    1.57          try {
    1.58              return new MessageFormat(MESSAGES_BUNDLE.getString(msgId)).format(args);
    1.59 @@ -108,6 +123,30 @@
    1.60          }
    1.61      }
    1.62  
    1.63 +    // load engine.js and return content as a char[]
    1.64 +    private static char[] loadEngineJSSource() {
    1.65 +        final String script = "resources/engine.js";
    1.66 +        try {
    1.67 +            final InputStream is = AccessController.doPrivileged(
    1.68 +                    new PrivilegedExceptionAction<InputStream>() {
    1.69 +                        @Override
    1.70 +                        public InputStream run() throws Exception {
    1.71 +                            final URL url = NashornScriptEngine.class.getResource(script);
    1.72 +                            return url.openStream();
    1.73 +                        }
    1.74 +                    });
    1.75 +            return Source.readFully(new InputStreamReader(is));
    1.76 +        } catch (final PrivilegedActionException | IOException e) {
    1.77 +            if (Context.DEBUG) {
    1.78 +                e.printStackTrace();
    1.79 +            }
    1.80 +            throw new RuntimeException(e);
    1.81 +        }
    1.82 +    }
    1.83 +
    1.84 +    // Source object for engine.js
    1.85 +    private static final Source ENGINE_SCRIPT_SRC = new Source(NashornException.ENGINE_SCRIPT_SOURCE_NAME, loadEngineJSSource());
    1.86 +
    1.87      NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
    1.88          this(factory, DEFAULT_OPTIONS, appLoader);
    1.89      }
    1.90 @@ -134,20 +173,13 @@
    1.91              }
    1.92          }, CREATE_CONTEXT_ACC_CTXT);
    1.93  
    1.94 +        // cache this option that is used often
    1.95 +        this._global_per_engine = nashornContext.getEnv()._global_per_engine;
    1.96 +
    1.97          // create new global object
    1.98 -        this.global = createNashornGlobal();
    1.99 -        // set the default engine scope for the default context
   1.100 +        this.global = createNashornGlobal(context);
   1.101 +        // set the default ENGINE_SCOPE object for the default context
   1.102          context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
   1.103 -
   1.104 -        // evaluate engine initial script
   1.105 -        try {
   1.106 -            evalEngineScript();
   1.107 -        } catch (final ScriptException e) {
   1.108 -            if (Context.DEBUG) {
   1.109 -                e.printStackTrace();
   1.110 -            }
   1.111 -            throw new RuntimeException(e);
   1.112 -        }
   1.113      }
   1.114  
   1.115      @Override
   1.116 @@ -176,8 +208,13 @@
   1.117  
   1.118      @Override
   1.119      public Bindings createBindings() {
   1.120 -        final ScriptObject newGlobal = createNashornGlobal();
   1.121 -        return new ScriptObjectMirror(newGlobal, newGlobal);
   1.122 +        if (_global_per_engine) {
   1.123 +            // just create normal SimpleBindings.
   1.124 +            // We use same 'global' for all Bindings.
   1.125 +            return new SimpleBindings();
   1.126 +        } else {
   1.127 +            return createGlobalMirror(null);
   1.128 +        }
   1.129      }
   1.130  
   1.131      // Compilable methods
   1.132 @@ -213,6 +250,48 @@
   1.133          return invokeImpl(thiz, name, args);
   1.134      }
   1.135  
   1.136 +    @Override
   1.137 +    public <T> T getInterface(final Class<T> clazz) {
   1.138 +        return getInterfaceInner(null, clazz);
   1.139 +    }
   1.140 +
   1.141 +    @Override
   1.142 +    public <T> T getInterface(final Object thiz, final Class<T> clazz) {
   1.143 +        if (thiz == null) {
   1.144 +            throw new IllegalArgumentException(getMessage("thiz.cannot.be.null"));
   1.145 +        }
   1.146 +        return getInterfaceInner(thiz, clazz);
   1.147 +    }
   1.148 +
   1.149 +    // These are called from the "engine.js" script
   1.150 +
   1.151 +    /**
   1.152 +     * This hook is used to search js global variables exposed from Java code.
   1.153 +     *
   1.154 +     * @param self 'this' passed from the script
   1.155 +     * @param ctxt current ScriptContext in which name is searched
   1.156 +     * @param name name of the variable searched
   1.157 +     * @return the value of the named variable
   1.158 +     */
   1.159 +    public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
   1.160 +        if (ctxt != null) {
   1.161 +            final int scope = ctxt.getAttributesScope(name);
   1.162 +            final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
   1.163 +            if (scope != -1) {
   1.164 +                return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
   1.165 +            }
   1.166 +
   1.167 +            if (self == UNDEFINED) {
   1.168 +                // scope access and so throw ReferenceError
   1.169 +                throw referenceError(ctxtGlobal, "not.defined", name);
   1.170 +            }
   1.171 +        }
   1.172 +
   1.173 +        return UNDEFINED;
   1.174 +    }
   1.175 +
   1.176 +    // Implementation only below this point
   1.177 +
   1.178      private <T> T getInterfaceInner(final Object thiz, final Class<T> clazz) {
   1.179          if (clazz == null || !clazz.isInterface()) {
   1.180              throw new IllegalArgumentException(getMessage("interface.class.expected"));
   1.181 @@ -280,58 +359,56 @@
   1.182          }
   1.183      }
   1.184  
   1.185 -    @Override
   1.186 -    public <T> T getInterface(final Class<T> clazz) {
   1.187 -        return getInterfaceInner(null, clazz);
   1.188 +    // Retrieve nashorn Global object for a given ScriptContext object
   1.189 +    private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) {
   1.190 +        if (_global_per_engine) {
   1.191 +            // shared single global object for all ENGINE_SCOPE Bindings
   1.192 +            return global;
   1.193 +        }
   1.194 +
   1.195 +        final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE);
   1.196 +        // is this Nashorn's own Bindings implementation?
   1.197 +        if (bindings instanceof ScriptObjectMirror) {
   1.198 +            final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)bindings);
   1.199 +            if (sobj != null) {
   1.200 +                return sobj;
   1.201 +            }
   1.202 +        }
   1.203 +
   1.204 +        // Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
   1.205 +        Object scope = bindings.get(NASHORN_GLOBAL);
   1.206 +        if (scope instanceof ScriptObjectMirror) {
   1.207 +            final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)scope);
   1.208 +            if (sobj != null) {
   1.209 +                return sobj;
   1.210 +            }
   1.211 +        }
   1.212 +
   1.213 +        // We didn't find associated nashorn global mirror in the Bindings given!
   1.214 +        // Create new global instance mirror and associate with the Bindings.
   1.215 +        final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
   1.216 +        bindings.put(NASHORN_GLOBAL, mirror);
   1.217 +        return mirror.getScriptObject();
   1.218      }
   1.219  
   1.220 -    @Override
   1.221 -    public <T> T getInterface(final Object thiz, final Class<T> clazz) {
   1.222 -        if (thiz == null) {
   1.223 -            throw new IllegalArgumentException(getMessage("thiz.cannot.be.null"));
   1.224 +    // Retrieve nashorn Global object from a given ScriptObjectMirror
   1.225 +    private ScriptObject globalFromMirror(final ScriptObjectMirror mirror) {
   1.226 +        ScriptObject sobj = mirror.getScriptObject();
   1.227 +        if (sobj instanceof GlobalObject && sobj.isOfContext(nashornContext)) {
   1.228 +            return sobj;
   1.229          }
   1.230 -        return getInterfaceInner(thiz, clazz);
   1.231 +
   1.232 +        return null;
   1.233      }
   1.234  
   1.235 -    // These are called from the "engine.js" script
   1.236 -
   1.237 -    /**
   1.238 -     * This hook is used to search js global variables exposed from Java code.
   1.239 -     *
   1.240 -     * @param self 'this' passed from the script
   1.241 -     * @param ctxt current ScriptContext in which name is searched
   1.242 -     * @param name name of the variable searched
   1.243 -     * @return the value of the named variable
   1.244 -     */
   1.245 -    public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
   1.246 -        final int scope = ctxt.getAttributesScope(name);
   1.247 -        final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
   1.248 -        if (scope != -1) {
   1.249 -            return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
   1.250 -        }
   1.251 -
   1.252 -        if (self == UNDEFINED) {
   1.253 -            // scope access and so throw ReferenceError
   1.254 -            throw referenceError(ctxtGlobal, "not.defined", name);
   1.255 -        }
   1.256 -
   1.257 -        return UNDEFINED;
   1.258 +    // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
   1.259 +    private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
   1.260 +        final ScriptObject newGlobal = createNashornGlobal(ctxt);
   1.261 +        return new ScriptObjectMirror(newGlobal, newGlobal);
   1.262      }
   1.263  
   1.264 -    private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) {
   1.265 -        final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE);
   1.266 -        if (bindings instanceof ScriptObjectMirror) {
   1.267 -             ScriptObject sobj = ((ScriptObjectMirror)bindings).getScriptObject();
   1.268 -             if (sobj instanceof GlobalObject) {
   1.269 -                 return sobj;
   1.270 -             }
   1.271 -        }
   1.272 -
   1.273 -        // didn't find global object from context given - return the engine-wide global
   1.274 -        return global;
   1.275 -    }
   1.276 -
   1.277 -    private ScriptObject createNashornGlobal() {
   1.278 +    // Create a new Nashorn Global object
   1.279 +    private ScriptObject createNashornGlobal(final ScriptContext ctxt) {
   1.280          final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
   1.281              @Override
   1.282              public ScriptObject run() {
   1.283 @@ -352,7 +429,7 @@
   1.284          // current ScriptContext exposed as "context"
   1.285          // "context" is non-writable from script - but script engine still
   1.286          // needs to set it and so save the context Property object
   1.287 -        contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, UNDEFINED);
   1.288 +        contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, null);
   1.289          // current ScriptEngine instance exposed as "engine". We added @SuppressWarnings("LeakingThisInConstructor") as
   1.290          // NetBeans identifies this assignment as such a leak - this is a false positive as we're setting this property
   1.291          // in the Global of a Context we just created - both the Context and the Global were just created and can not be
   1.292 @@ -362,38 +439,17 @@
   1.293          newGlobal.addOwnProperty("arguments", Property.NOT_ENUMERABLE, UNDEFINED);
   1.294          // file name default is null
   1.295          newGlobal.addOwnProperty(ScriptEngine.FILENAME, Property.NOT_ENUMERABLE, null);
   1.296 +        // evaluate engine.js initialization script this new global object
   1.297 +        try {
   1.298 +            evalImpl(compileImpl(ENGINE_SCRIPT_SRC, newGlobal), ctxt, newGlobal);
   1.299 +        } catch (final ScriptException exp) {
   1.300 +            throw new RuntimeException(exp);
   1.301 +        }
   1.302          return newGlobal;
   1.303      }
   1.304  
   1.305 -    private void evalEngineScript() throws ScriptException {
   1.306 -        final String script = "resources/engine.js";
   1.307 -        final String name   = NashornException.ENGINE_SCRIPT_SOURCE_NAME;
   1.308 -        try {
   1.309 -            final InputStream is = AccessController.doPrivileged(
   1.310 -                    new PrivilegedExceptionAction<InputStream>() {
   1.311 -                        @Override
   1.312 -                        public InputStream run() throws Exception {
   1.313 -                            final URL url = NashornScriptEngine.class.getResource(script);
   1.314 -                            return url.openStream();
   1.315 -                        }
   1.316 -                    });
   1.317 -            put(ScriptEngine.FILENAME, name);
   1.318 -            try (final InputStreamReader isr = new InputStreamReader(is)) {
   1.319 -                eval(isr);
   1.320 -            }
   1.321 -        } catch (final PrivilegedActionException | IOException e) {
   1.322 -            if (Context.DEBUG) {
   1.323 -                e.printStackTrace();
   1.324 -            }
   1.325 -            throw new ScriptException(e);
   1.326 -        } finally {
   1.327 -            put(ScriptEngine.FILENAME, null);
   1.328 -        }
   1.329 -    }
   1.330 -
   1.331 -    // scripts should see "context" and "engine" as variables
   1.332 -    private void setContextVariables(final ScriptContext ctxt) {
   1.333 -        final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
   1.334 +    // scripts should see "context" and "engine" as variables in the given global object
   1.335 +    private void setContextVariables(final ScriptObject ctxtGlobal, final ScriptContext ctxt) {
   1.336          // set "context" global variable via contextProperty - because this
   1.337          // property is non-writable
   1.338          contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
   1.339 @@ -402,8 +458,10 @@
   1.340              args = ScriptRuntime.EMPTY_ARRAY;
   1.341          }
   1.342          // if no arguments passed, expose it
   1.343 -        args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
   1.344 -        ctxtGlobal.set("arguments", args, false);
   1.345 +        if (! (args instanceof ScriptObject)) {
   1.346 +            args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
   1.347 +            ctxtGlobal.set("arguments", args, false);
   1.348 +        }
   1.349      }
   1.350  
   1.351      private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
   1.352 @@ -456,18 +514,24 @@
   1.353      }
   1.354  
   1.355      private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt) throws ScriptException {
   1.356 +        return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
   1.357 +    }
   1.358 +
   1.359 +    private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final ScriptObject ctxtGlobal) throws ScriptException {
   1.360          if (script == null) {
   1.361              return null;
   1.362          }
   1.363          final ScriptObject oldGlobal = Context.getGlobal();
   1.364 -        final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
   1.365          final boolean globalChanged = (oldGlobal != ctxtGlobal);
   1.366          try {
   1.367              if (globalChanged) {
   1.368                  Context.setGlobal(ctxtGlobal);
   1.369              }
   1.370  
   1.371 -            setContextVariables(ctxt);
   1.372 +            // set ScriptContext variables if ctxt is non-null
   1.373 +            if (ctxt != null) {
   1.374 +                setContextVariables(ctxtGlobal, ctxt);
   1.375 +            }
   1.376              return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
   1.377          } catch (final Exception e) {
   1.378              throwAsScriptException(e);
   1.379 @@ -517,15 +581,18 @@
   1.380      }
   1.381  
   1.382      private ScriptFunction compileImpl(final Source source, final ScriptContext ctxt) throws ScriptException {
   1.383 +        return compileImpl(source, getNashornGlobalFrom(ctxt));
   1.384 +    }
   1.385 +
   1.386 +    private ScriptFunction compileImpl(final Source source, final ScriptObject newGlobal) throws ScriptException {
   1.387          final ScriptObject oldGlobal = Context.getGlobal();
   1.388 -        final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
   1.389 -        final boolean globalChanged = (oldGlobal != ctxtGlobal);
   1.390 +        final boolean globalChanged = (oldGlobal != newGlobal);
   1.391          try {
   1.392              if (globalChanged) {
   1.393 -                Context.setGlobal(ctxtGlobal);
   1.394 +                Context.setGlobal(newGlobal);
   1.395              }
   1.396  
   1.397 -            return nashornContext.compileScript(source, ctxtGlobal);
   1.398 +            return nashornContext.compileScript(source, newGlobal);
   1.399          } catch (final Exception e) {
   1.400              throwAsScriptException(e);
   1.401              throw new AssertionError("should not reach here");
     2.1 --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Mon Aug 19 19:37:29 2013 +0530
     2.2 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Fri Aug 23 16:44:02 2013 +0530
     2.3 @@ -99,12 +99,14 @@
     2.4              }
     2.5  
     2.6              final Object val = functionName == null? sobj : sobj.get(functionName);
     2.7 -            if (! (val instanceof ScriptFunction)) {
     2.8 -                throw new NoSuchMethodException("No such function " + ((functionName != null)? functionName : ""));
     2.9 +            if (val instanceof ScriptFunction) {
    2.10 +                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
    2.11 +                return wrap(ScriptRuntime.checkAndApply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
    2.12 +            } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) {
    2.13 +                return ((ScriptObjectMirror)val).call(null, args);
    2.14              }
    2.15  
    2.16 -            final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
    2.17 -            return wrap(ScriptRuntime.checkAndApply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
    2.18 +            throw new NoSuchMethodException("No such function " + ((functionName != null)? functionName : ""));
    2.19          } catch (final RuntimeException | Error e) {
    2.20              throw e;
    2.21          } catch (final Throwable t) {
    2.22 @@ -127,12 +129,14 @@
    2.23              }
    2.24  
    2.25              final Object val = functionName == null? sobj : sobj.get(functionName);
    2.26 -            if (! (val instanceof ScriptFunction)) {
    2.27 -                throw new RuntimeException("not a constructor " + ((functionName != null)? functionName : ""));
    2.28 +            if (val instanceof ScriptFunction) {
    2.29 +                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
    2.30 +                return wrap(ScriptRuntime.checkAndConstruct((ScriptFunction)val, unwrapArray(modArgs, global)), global);
    2.31 +            } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) {
    2.32 +                return ((ScriptObjectMirror)val).newObject(null, args);
    2.33              }
    2.34  
    2.35 -            final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
    2.36 -            return wrap(ScriptRuntime.checkAndConstruct((ScriptFunction)val, unwrapArray(modArgs, global)), global);
    2.37 +            throw new RuntimeException("not a constructor " + ((functionName != null)? functionName : ""));
    2.38          } catch (final RuntimeException | Error e) {
    2.39              throw e;
    2.40          } catch (final Throwable t) {
    2.41 @@ -374,6 +378,19 @@
    2.42      }
    2.43  
    2.44      /**
    2.45 +     * Set the __proto__ of this object.
    2.46 +     * @param proto new proto for this object
    2.47 +     */
    2.48 +    public void setProto(final Object proto) {
    2.49 +        inGlobal(new Callable<Void>() {
    2.50 +            @Override public Void call() {
    2.51 +                sobj.setProtoCheck(unwrap(proto, global));
    2.52 +                return null;
    2.53 +            }
    2.54 +        });
    2.55 +    }
    2.56 +
    2.57 +    /**
    2.58       * ECMA 8.12.1 [[GetOwnProperty]] (P)
    2.59       *
    2.60       * @param key property key
     3.1 --- a/src/jdk/nashorn/api/scripting/resources/engine.js	Mon Aug 19 19:37:29 2013 +0530
     3.2 +++ b/src/jdk/nashorn/api/scripting/resources/engine.js	Fri Aug 23 16:44:02 2013 +0530
     3.3 @@ -23,10 +23,9 @@
     3.4  
     3.5  /**
     3.6   * This script file is executed by script engine at the construction
     3.7 - * of the engine. The functions here assume global variables "context"
     3.8 - * of type javax.script.ScriptContext and "engine" of the type
     3.9 + * of the every new Global object. The functions here assume global variables
    3.10 + * "context" of type javax.script.ScriptContext and "engine" of the type
    3.11   * jdk.nashorn.api.scripting.NashornScriptEngine.
    3.12 - *
    3.13   **/
    3.14  
    3.15  Object.defineProperty(this, "__noSuchProperty__", {
    3.16 @@ -40,7 +39,7 @@
    3.17  });
    3.18  
    3.19  function print() {
    3.20 -    var writer = context.getWriter();
    3.21 +    var writer = context != null? context.writer : engine.context.writer;
    3.22      if (! (writer instanceof java.io.PrintWriter)) {
    3.23          writer = new java.io.PrintWriter(writer);
    3.24      }
     4.1 --- a/src/jdk/nashorn/internal/codegen/Attr.java	Mon Aug 19 19:37:29 2013 +0530
     4.2 +++ b/src/jdk/nashorn/internal/codegen/Attr.java	Fri Aug 23 16:44:02 2013 +0530
     4.3 @@ -543,8 +543,6 @@
     4.4      public Node leaveIdentNode(final IdentNode identNode) {
     4.5          final String name = identNode.getName();
     4.6  
     4.7 -        start(identNode);
     4.8 -
     4.9          if (identNode.isPropertyName()) {
    4.10              // assign a pseudo symbol to property name
    4.11              final Symbol pseudoSymbol = pseudoSymbol(name);
    4.12 @@ -1850,9 +1848,10 @@
    4.13                  append("] ").
    4.14                  append(printNode ? node.toString() : "").
    4.15                  append(" in '").
    4.16 -                append(lc.getCurrentFunction().getName());
    4.17 +                append(lc.getCurrentFunction().getName()).
    4.18 +                append('\'');
    4.19  
    4.20 -            if(node instanceof Expression) {
    4.21 +            if (node instanceof Expression) {
    4.22                  final Symbol symbol = ((Expression)node).getSymbol();
    4.23                  if (symbol == null) {
    4.24                      sb.append(" <NO SYMBOL>");
     5.1 --- a/src/jdk/nashorn/internal/objects/NativeJava.java	Mon Aug 19 19:37:29 2013 +0530
     5.2 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java	Fri Aug 23 16:44:02 2013 +0530
     5.3 @@ -32,7 +32,6 @@
     5.4  import java.util.Collection;
     5.5  import java.util.Deque;
     5.6  import java.util.List;
     5.7 -
     5.8  import jdk.internal.dynalink.beans.StaticClass;
     5.9  import jdk.internal.dynalink.support.TypeUtilities;
    5.10  import jdk.nashorn.internal.objects.annotations.Attribute;
    5.11 @@ -44,6 +43,7 @@
    5.12  import jdk.nashorn.internal.runtime.ListAdapter;
    5.13  import jdk.nashorn.internal.runtime.PropertyMap;
    5.14  import jdk.nashorn.internal.runtime.ScriptObject;
    5.15 +import jdk.nashorn.internal.runtime.linker.Bootstrap;
    5.16  import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
    5.17  
    5.18  /**
    5.19 @@ -539,4 +539,25 @@
    5.20          }
    5.21          return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides);
    5.22      }
    5.23 +
    5.24 +    /**
    5.25 +     * When given an object created using {@code Java.extend()} or equivalent mechanism (that is, any JavaScript-to-Java
    5.26 +     * adapter), returns an object that can be used to invoke superclass methods on that object. E.g.:
    5.27 +     * <pre>
    5.28 +     * var cw = new FilterWriterAdapter(sw) {
    5.29 +     *     write: function(s, off, len) {
    5.30 +     *         s = capitalize(s, off, len)
    5.31 +     *         cw_super.write(s, 0, s.length())
    5.32 +     *     }
    5.33 +     * }
    5.34 +     * var cw_super = Java.super(cw)
    5.35 +     * </pre>
    5.36 +     * @param self the {@code Java} object itself - not used.
    5.37 +     * @param adapter the original Java adapter instance for which the super adapter is created.
    5.38 +     * @return a super adapter for the original adapter
    5.39 +     */
    5.40 +    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR, name="super")
    5.41 +    public static Object _super(final Object self, final Object adapter) {
    5.42 +        return Bootstrap.createSuperAdapter(adapter);
    5.43 +    }
    5.44  }
     6.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java	Mon Aug 19 19:37:29 2013 +0530
     6.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java	Fri Aug 23 16:44:02 2013 +0530
     6.3 @@ -125,6 +125,28 @@
     6.4      }
     6.5  
     6.6      /**
     6.7 +     * Nashorn extension: Object.setPrototypeOf ( O, proto )
     6.8 +     * Also found in ES6 draft specification.
     6.9 +     *
    6.10 +     * @param  self self reference
    6.11 +     * @param  obj object to set prototype for
    6.12 +     * @param  proto prototype object to be used
    6.13 +     * @return object whose prototype is set
    6.14 +     */
    6.15 +    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    6.16 +    public static Object setPrototypeOf(final Object self, final Object obj, final Object proto) {
    6.17 +        if (obj instanceof ScriptObject) {
    6.18 +            ((ScriptObject)obj).setProtoCheck(proto);
    6.19 +            return obj;
    6.20 +        } else if (obj instanceof ScriptObjectMirror) {
    6.21 +            ((ScriptObjectMirror)obj).setProto(proto);
    6.22 +            return obj;
    6.23 +        }
    6.24 +
    6.25 +        throw notAnObject(obj);
    6.26 +    }
    6.27 +
    6.28 +    /**
    6.29       * ECMA 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P )
    6.30       *
    6.31       * @param self  self reference
    6.32 @@ -184,7 +206,7 @@
    6.33          // FIXME: should we create a proper object with correct number of
    6.34          // properties?
    6.35          final ScriptObject newObj = Global.newEmptyInstance();
    6.36 -        newObj.setProtoCheck(proto);
    6.37 +        newObj.setProto((ScriptObject)proto);
    6.38          if (props != UNDEFINED) {
    6.39              NativeObject.defineProperties(self, newObj, props);
    6.40          }
     7.1 --- a/src/jdk/nashorn/internal/runtime/Context.java	Mon Aug 19 19:37:29 2013 +0530
     7.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java	Fri Aug 23 16:44:02 2013 +0530
     7.3 @@ -91,6 +91,11 @@
     7.4       */
     7.5      public static final String NASHORN_JAVA_REFLECTION = "nashorn.JavaReflection";
     7.6  
     7.7 +    /* Force DebuggerSupport to be loaded. */
     7.8 +    static {
     7.9 +        DebuggerSupport.FORCELOAD = true;
    7.10 +    }
    7.11 +
    7.12      /**
    7.13       * ContextCodeInstaller that has the privilege of installing classes in the Context.
    7.14       * Can only be instantiated from inside the context and is opaque to other classes
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java	Fri Aug 23 16:44:02 2013 +0530
     8.3 @@ -0,0 +1,310 @@
     8.4 +/*
     8.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General  License version 2 only, as
    8.10 + * published by the Free Software Foundation.  Oracle designates this
    8.11 + * particular file as subject to the "Classpath" exception as provided
    8.12 + * by Oracle in the LICENSE file that accompanied this code.
    8.13 + *
    8.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General  License
    8.17 + * version 2 for more details (a copy is included in the LICENSE file that
    8.18 + * accompanied this code).
    8.19 + *
    8.20 + * You should have received a copy of the GNU General  License version
    8.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.23 + *
    8.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.25 + * or visit www.oracle.com if you need additional information or have any
    8.26 + * questions.
    8.27 + */
    8.28 +
    8.29 +package jdk.nashorn.internal.runtime;
    8.30 +
    8.31 +import java.util.HashSet;
    8.32 +import java.util.Set;
    8.33 +
    8.34 +/**
    8.35 + * This class provides support for external debuggers.  Its primary purpose is
    8.36 + * is to simplify the debugger tasks and provide better performance.
    8.37 + */
    8.38 +final class DebuggerSupport {
    8.39 +    /**
    8.40 +     * Hook to force the loading of the DebuggerSupport class so that it is
    8.41 +     * available to external debuggers.
    8.42 +     */
    8.43 +    static boolean FORCELOAD = true;
    8.44 +
    8.45 +    static {
    8.46 +        /**
    8.47 +         * Hook to force the loading of the DebuggerValueDesc class so that it is
    8.48 +         * available to external debuggers.
    8.49 +         */
    8.50 +        DebuggerValueDesc forceLoad = new DebuggerValueDesc(null, false, null, null);
    8.51 +    }
    8.52 +
    8.53 +    /** This class is used to send a bulk description of a value. */
    8.54 +    static class DebuggerValueDesc {
    8.55 +        /** Property key (or index) or field name. */
    8.56 +        final String key;
    8.57 +
    8.58 +        /** If the value is expandable. */
    8.59 +        final boolean expandable;
    8.60 +
    8.61 +        /** Property or field value as object. */
    8.62 +        final Object valueAsObject;
    8.63 +
    8.64 +        /** Property or field value as string. */
    8.65 +        final String valueAsString;
    8.66 +
    8.67 +        DebuggerValueDesc(final String key, final boolean expandable, final Object valueAsObject, final String valueAsString) {
    8.68 +            this.key           = key;
    8.69 +            this.expandable    = expandable;
    8.70 +            this.valueAsObject = valueAsObject;
    8.71 +            this.valueAsString = valueAsString;
    8.72 +        }
    8.73 +    }
    8.74 +
    8.75 +    /**
    8.76 +     * Return the current context global.
    8.77 +     * @return context global.
    8.78 +     */
    8.79 +    static Object getGlobal() {
    8.80 +        return Context.getGlobalTrusted();
    8.81 +    }
    8.82 +
    8.83 +    /**
    8.84 +     * This method returns a bulk description of an object's properties.
    8.85 +     * @param object Script object to be displayed by the debugger.
    8.86 +     * @param all    true if to include non-enumerable values.
    8.87 +     * @return An array of DebuggerValueDesc.
    8.88 +     */
    8.89 +    static DebuggerValueDesc[] valueInfos(final Object object, final boolean all) {
    8.90 +        assert object instanceof ScriptObject;
    8.91 +        return getDebuggerValueDescs((ScriptObject)object, all, new HashSet<>());
    8.92 +    }
    8.93 +
    8.94 +    /**
    8.95 +     * This method returns a debugger description of the value.
    8.96 +     * @param name  Name of value (property name).
    8.97 +     * @param value Data value.
    8.98 +     * @param all   true if to include non-enumerable values.
    8.99 +     * @return A DebuggerValueDesc.
   8.100 +     */
   8.101 +    static DebuggerValueDesc valueInfo(final String name, final Object value, final boolean all) {
   8.102 +        return valueInfo(name, value, all, new HashSet<>());
   8.103 +    }
   8.104 +
   8.105 +   /**
   8.106 +     * This method returns a debugger description of the value.
   8.107 +     * @param name       Name of value (property name).
   8.108 +     * @param value      Data value.
   8.109 +     * @param all        true if to include non-enumerable values.
   8.110 +     * @param duplicates Duplication set to avoid cycles.
   8.111 +     * @return A DebuggerValueDesc.
   8.112 +     */
   8.113 +    private static DebuggerValueDesc valueInfo(final String name, final Object value, final boolean all, final Set<Object> duplicates) {
   8.114 +        if (value instanceof ScriptObject && !(value instanceof ScriptFunction)) {
   8.115 +            final ScriptObject object = (ScriptObject)value;
   8.116 +            return new DebuggerValueDesc(name, !object.isEmpty(), value, objectAsString(object, all, duplicates));
   8.117 +        } else {
   8.118 +            return new DebuggerValueDesc(name, false, value, valueAsString(value));
   8.119 +        }
   8.120 +    }
   8.121 +
   8.122 +    /**
   8.123 +     * Generate the descriptions for an object's properties.
   8.124 +     * @param object     Object to introspect.
   8.125 +     * @param all        true if to include non-enumerable values.
   8.126 +     * @param duplicates Duplication set to avoid cycles.
   8.127 +     * @return An array of DebuggerValueDesc.
   8.128 +     */
   8.129 +    private static DebuggerValueDesc[] getDebuggerValueDescs(final ScriptObject object, final boolean all, final Set<Object> duplicates) {
   8.130 +        if (duplicates.contains(object)) {
   8.131 +            return null;
   8.132 +        }
   8.133 +
   8.134 +        duplicates.add(object);
   8.135 +
   8.136 +        final String[] keys = object.getOwnKeys(all);
   8.137 +        final DebuggerValueDesc[] descs = new DebuggerValueDesc[keys.length];
   8.138 +
   8.139 +        for (int i = 0; i < keys.length; i++) {
   8.140 +            final String key = keys[i];
   8.141 +            descs[i] = valueInfo(key, object.get(key), true, duplicates);
   8.142 +        }
   8.143 +
   8.144 +        duplicates.remove(object);
   8.145 +
   8.146 +        return descs;
   8.147 +    }
   8.148 +
   8.149 +    /**
   8.150 +     * Generate a string representation of a Script object.
   8.151 +     * @param object     Script object to represent.
   8.152 +     * @param all        true if to include non-enumerable values.
   8.153 +     * @param duplicates Duplication set to avoid cycles.
   8.154 +     * @return String representation.
   8.155 +     */
   8.156 +    private static String objectAsString(final ScriptObject object, final boolean all, final Set<Object> duplicates) {
   8.157 +        final StringBuilder sb = new StringBuilder();
   8.158 +
   8.159 +        if (ScriptObject.isArray(object)) {
   8.160 +            sb.append('[');
   8.161 +            final long length = object.getLong("length");
   8.162 +
   8.163 +            for (long i = 0; i < length; i++) {
   8.164 +                if (object.has(i)) {
   8.165 +                    final Object valueAsObject = object.get(i);
   8.166 +                    final boolean isUndefined = JSType.of(valueAsObject) == JSType.UNDEFINED;
   8.167 +
   8.168 +                    if (isUndefined) {
   8.169 +                        if (i != 0) {
   8.170 +                            sb.append(",");
   8.171 +                        }
   8.172 +                    } else {
   8.173 +                        if (i != 0) {
   8.174 +                            sb.append(", ");
   8.175 +                        }
   8.176 +
   8.177 +                        if (valueAsObject instanceof ScriptObject && !(valueAsObject instanceof ScriptFunction)) {
   8.178 +                            final String objectString = objectAsString((ScriptObject)valueAsObject, true, duplicates);
   8.179 +                            sb.append(objectString != null ? objectString : "{...}");
   8.180 +                        } else {
   8.181 +                            sb.append(valueAsString(valueAsObject));
   8.182 +                        }
   8.183 +                    }
   8.184 +                } else {
   8.185 +                    if (i != 0) {
   8.186 +                        sb.append(',');
   8.187 +                    }
   8.188 +                }
   8.189 +            }
   8.190 +
   8.191 +            sb.append(']');
   8.192 +        } else {
   8.193 +            sb.append('{');
   8.194 +            final DebuggerValueDesc[] descs = getDebuggerValueDescs(object, all, duplicates);
   8.195 +
   8.196 +            if (descs != null) {
   8.197 +                for (int i = 0; i < descs.length; i++) {
   8.198 +                    if (i != 0) {
   8.199 +                        sb.append(", ");
   8.200 +                    }
   8.201 +
   8.202 +                    final String valueAsString = descs[i].valueAsString;
   8.203 +                    sb.append(descs[i].key);
   8.204 +                    sb.append(": ");
   8.205 +                    sb.append(descs[i].valueAsString);
   8.206 +                }
   8.207 +            }
   8.208 +
   8.209 +            sb.append('}');
   8.210 +        }
   8.211 +
   8.212 +        return sb.toString();
   8.213 +    }
   8.214 +
   8.215 +    /**
   8.216 +     * This method returns a string representation of a value.
   8.217 +     * @param value Arbitrary value to be displayed by the debugger.
   8.218 +     * @return A string representation of the value or an array of DebuggerValueDesc.
   8.219 +     */
   8.220 +    private static String valueAsString(final Object value) {
   8.221 +        final JSType type = JSType.of(value);
   8.222 +
   8.223 +        switch (type) {
   8.224 +        case BOOLEAN:
   8.225 +            return value.toString();
   8.226 +
   8.227 +        case STRING:
   8.228 +            return escape((String)value);
   8.229 +
   8.230 +        case NUMBER:
   8.231 +            return JSType.toString(((Number)value).doubleValue());
   8.232 +
   8.233 +        case NULL:
   8.234 +            return "null";
   8.235 +
   8.236 +        case UNDEFINED:
   8.237 +            return "undefined";
   8.238 +
   8.239 +        case OBJECT:
   8.240 +            return ScriptRuntime.safeToString(value);
   8.241 +
   8.242 +        case FUNCTION:
   8.243 +            if (value instanceof ScriptFunction) {
   8.244 +                return ((ScriptFunction)value).toSource();
   8.245 +            } else {
   8.246 +                return value.toString();
   8.247 +            }
   8.248 +
   8.249 +        default:
   8.250 +            return value.toString();
   8.251 +        }
   8.252 +    }
   8.253 +
   8.254 +    /**
   8.255 +     * Escape a string into a form that can be parsed by JavaScript.
   8.256 +     * @param value String to be escaped.
   8.257 +     * @return Escaped string.
   8.258 +     */
   8.259 +    private static String escape(final String value) {
   8.260 +        final StringBuilder sb = new StringBuilder();
   8.261 +
   8.262 +        sb.append("\"");
   8.263 +
   8.264 +        for (final char ch : value.toCharArray()) {
   8.265 +            switch (ch) {
   8.266 +            case '\\':
   8.267 +                sb.append("\\\\");
   8.268 +                break;
   8.269 +            case '"':
   8.270 +                sb.append("\\\"");
   8.271 +                break;
   8.272 +            case '\'':
   8.273 +                sb.append("\\\'");
   8.274 +                break;
   8.275 +            case '\b':
   8.276 +                sb.append("\\b");
   8.277 +                break;
   8.278 +            case '\f':
   8.279 +                sb.append("\\f");
   8.280 +                break;
   8.281 +            case '\n':
   8.282 +                sb.append("\\n");
   8.283 +                break;
   8.284 +            case '\r':
   8.285 +                sb.append("\\r");
   8.286 +                break;
   8.287 +            case '\t':
   8.288 +                sb.append("\\t");
   8.289 +                break;
   8.290 +            default:
   8.291 +                if (ch < ' ' || ch >= 0xFF) {
   8.292 +                    sb.append("\\u");
   8.293 +
   8.294 +                    final String hex = Integer.toHexString(ch);
   8.295 +                    for (int i = hex.length(); i < 4; i++) {
   8.296 +                        sb.append('0');
   8.297 +                    }
   8.298 +                    sb.append(hex);
   8.299 +                } else {
   8.300 +                    sb.append(ch);
   8.301 +                }
   8.302 +
   8.303 +                break;
   8.304 +            }
   8.305 +        }
   8.306 +
   8.307 +        sb.append("\"");
   8.308 +
   8.309 +        return sb.toString();
   8.310 +    }
   8.311 +}
   8.312 +
   8.313 +
     9.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java	Mon Aug 19 19:37:29 2013 +0530
     9.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java	Fri Aug 23 16:44:02 2013 +0530
     9.3 @@ -30,11 +30,10 @@
     9.4  
     9.5  import java.lang.invoke.MethodHandles;
     9.6  import java.util.Locale;
     9.7 -import jdk.internal.dynalink.beans.BeansLinker;
     9.8  import jdk.internal.dynalink.beans.StaticClass;
     9.9 -import jdk.nashorn.api.scripting.ScriptObjectMirror;
    9.10  import jdk.nashorn.internal.codegen.CompilerConstants.Call;
    9.11  import jdk.nashorn.internal.parser.Lexer;
    9.12 +import jdk.nashorn.internal.runtime.linker.Bootstrap;
    9.13  
    9.14  /**
    9.15   * Representation for ECMAScript types - this maps directly to the ECMA script standard
    9.16 @@ -148,22 +147,10 @@
    9.17              return JSType.STRING;
    9.18          }
    9.19  
    9.20 -        if (obj instanceof ScriptObject) {
    9.21 -            return (obj instanceof ScriptFunction) ? JSType.FUNCTION : JSType.OBJECT;
    9.22 -        }
    9.23 -
    9.24 -        if (obj instanceof StaticClass) {
    9.25 +        if (Bootstrap.isCallable(obj)) {
    9.26              return JSType.FUNCTION;
    9.27          }
    9.28  
    9.29 -        if (BeansLinker.isDynamicMethod(obj)) {
    9.30 -            return JSType.FUNCTION;
    9.31 -        }
    9.32 -
    9.33 -        if (obj instanceof ScriptObjectMirror) {
    9.34 -            return ((ScriptObjectMirror)obj).isFunction()? JSType.FUNCTION : JSType.OBJECT;
    9.35 -        }
    9.36 -
    9.37          return JSType.OBJECT;
    9.38      }
    9.39  
    10.1 --- a/src/jdk/nashorn/internal/runtime/PropertyListener.java	Mon Aug 19 19:37:29 2013 +0530
    10.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyListener.java	Fri Aug 23 16:44:02 2013 +0530
    10.3 @@ -54,4 +54,13 @@
    10.4       *
    10.5       */
    10.6      public void propertyModified(ScriptObject object, Property oldProp, Property newProp);
    10.7 +
    10.8 +    /**
    10.9 +     * Given object's __proto__ has changed.
   10.10 +     *
   10.11 +     * @param object object whose __proto__ has changed.
   10.12 +     * @param oldProto old __proto__
   10.13 +     * @param newProto new __proto__
   10.14 +     */
   10.15 +    public void protoChanged(ScriptObject object, ScriptObject oldProto, ScriptObject newProto);
   10.16  }
    11.1 --- a/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java	Mon Aug 19 19:37:29 2013 +0530
    11.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java	Fri Aug 23 16:44:02 2013 +0530
    11.3 @@ -140,6 +140,21 @@
    11.4          }
    11.5      }
    11.6  
    11.7 +    /**
    11.8 +     * This method can be called to notify __proto__ modification to this object's listeners.
    11.9 +     *
   11.10 +     * @param object The ScriptObject whose __proto__ was changed.
   11.11 +     * @param oldProto old __proto__
   11.12 +     * @param newProto new __proto__
   11.13 +     */
   11.14 +    protected synchronized final void notifyProtoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
   11.15 +        if (listeners != null) {
   11.16 +            for (PropertyListener listener : listeners.keySet()) {
   11.17 +                listener.protoChanged(object, oldProto, newProto);
   11.18 +            }
   11.19 +        }
   11.20 +    }
   11.21 +
   11.22      // PropertyListener methods
   11.23  
   11.24      @Override
   11.25 @@ -156,4 +171,9 @@
   11.26      public final void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
   11.27          notifyPropertyModified(object, oldProp, newProp);
   11.28      }
   11.29 +
   11.30 +    @Override
   11.31 +    public final void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
   11.32 +        notifyProtoChanged(object, oldProto, newProto);
   11.33 +    }
   11.34  }
    12.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java	Mon Aug 19 19:37:29 2013 +0530
    12.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java	Fri Aug 23 16:44:02 2013 +0530
    12.3 @@ -230,7 +230,7 @@
    12.4      }
    12.5  
    12.6      /**
    12.7 -     * Indicate that a prototype property hash changed.
    12.8 +     * Indicate that a prototype property has changed.
    12.9       *
   12.10       * @param property {@link Property} to invalidate.
   12.11       */
   12.12 @@ -251,6 +251,18 @@
   12.13      }
   12.14  
   12.15      /**
   12.16 +     * Indicate that proto itself has changed in hierachy somewhere.
   12.17 +     */
   12.18 +    private void invalidateAllProtoGetSwitchPoints() {
   12.19 +        assert !isShared() : "proto invalidation on a shared PropertyMap";
   12.20 +
   12.21 +        if (protoGetSwitches != null) {
   12.22 +            final Collection<SwitchPoint> sws = protoGetSwitches.values();
   12.23 +            SwitchPoint.invalidateAll(sws.toArray(new SwitchPoint[sws.size()]));
   12.24 +        }
   12.25 +    }
   12.26 +
   12.27 +    /**
   12.28       * Add a property to the map, re-binding its getters and setters,
   12.29       * if available, to a given receiver. This is typically the global scope. See
   12.30       * {@link ScriptObject#addBoundProperties(ScriptObject)}
   12.31 @@ -878,6 +890,15 @@
   12.32          invalidateProtoGetSwitchPoint(oldProp);
   12.33      }
   12.34  
   12.35 +    @Override
   12.36 +    public void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
   12.37 +        // We may walk and invalidate SwitchPoints for properties inherited
   12.38 +        // from 'object' or it's old proto chain. But, it may not be worth it.
   12.39 +        // For example, a new proto may have a user defined getter/setter for
   12.40 +        // a data property down the chain. So, invalidating all is better.
   12.41 +        invalidateAllProtoGetSwitchPoints();
   12.42 +    }
   12.43 +
   12.44      /*
   12.45       * Debugging and statistics.
   12.46       */
    13.1 --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Mon Aug 19 19:37:29 2013 +0530
    13.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Fri Aug 23 16:44:02 2013 +0530
    13.3 @@ -86,6 +86,9 @@
    13.4      /** Launch using as fx application */
    13.5      public final boolean _fx;
    13.6  
    13.7 +    /** Use single Global instance per jsr223 engine instance. */
    13.8 +    public final boolean _global_per_engine;
    13.9 +
   13.10      /**
   13.11       * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
   13.12       * (function declarations are source elements, but not statements).
   13.13 @@ -128,9 +131,6 @@
   13.14      /** Do not support typed arrays. */
   13.15      public final boolean _no_typed_arrays;
   13.16  
   13.17 -    /** Package to which generated class files are added */
   13.18 -    public final String  _package;
   13.19 -
   13.20      /** Only parse the source code, do not compile */
   13.21      public final boolean _parse_only;
   13.22  
   13.23 @@ -211,12 +211,12 @@
   13.24              _function_statement = FunctionStatementBehavior.ACCEPT;
   13.25          }
   13.26          _fx                   = options.getBoolean("fx");
   13.27 +        _global_per_engine    = options.getBoolean("global.per.engine");
   13.28          _lazy_compilation     = options.getBoolean("lazy.compilation");
   13.29          _loader_per_compile   = options.getBoolean("loader.per.compile");
   13.30          _no_java              = options.getBoolean("no.java");
   13.31          _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
   13.32          _no_typed_arrays      = options.getBoolean("no.typed.arrays");
   13.33 -        _package              = options.getString("package");
   13.34          _parse_only           = options.getBoolean("parse.only");
   13.35          _print_ast            = options.getBoolean("print.ast");
   13.36          _print_lower_ast      = options.getBoolean("print.lower.ast");
    14.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Aug 19 19:37:29 2013 +0530
    14.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Aug 23 16:44:02 2013 +0530
    14.3 @@ -1008,10 +1008,6 @@
    14.4          return getMap().findProperty(key);
    14.5      }
    14.6  
    14.7 -    static String convertKey(final Object key) {
    14.8 -        return (key instanceof String) ? (String)key : JSType.toString(key);
    14.9 -    }
   14.10 -
   14.11      /**
   14.12       * Overridden by {@link jdk.nashorn.internal.objects.NativeArguments} class (internal use.)
   14.13       * Used for argument access in a vararg function using parameter name.
   14.14 @@ -1129,6 +1125,9 @@
   14.15          proto = newProto;
   14.16  
   14.17          if (isPrototype()) {
   14.18 +            // tell listeners that my __proto__ has been changed
   14.19 +            notifyProtoChanged(this, oldProto, newProto);
   14.20 +
   14.21              if (oldProto != null) {
   14.22                  oldProto.removePropertyListener(this);
   14.23              }
   14.24 @@ -1144,7 +1143,19 @@
   14.25       * @param newProto Prototype to set.
   14.26       */
   14.27      public final void setProtoCheck(final Object newProto) {
   14.28 +        if (!isExtensible()) {
   14.29 +            throw typeError("__proto__.set.non.extensible", ScriptRuntime.safeToString(this));
   14.30 +        }
   14.31 +
   14.32          if (newProto == null || newProto instanceof ScriptObject) {
   14.33 +            // check for circularity
   14.34 +            ScriptObject proto = (ScriptObject)newProto;
   14.35 +            while (proto != null) {
   14.36 +                if (proto == this) {
   14.37 +                    throw typeError("circular.__proto__.set", ScriptRuntime.safeToString(this));
   14.38 +                }
   14.39 +                proto = proto.getProto();
   14.40 +            }
   14.41              setProto((ScriptObject)newProto);
   14.42          } else {
   14.43              final ScriptObject global = Context.getGlobalTrusted();
   14.44 @@ -2359,7 +2370,7 @@
   14.45              return array.getInt(index);
   14.46          }
   14.47  
   14.48 -        return getInt(index, convertKey(key));
   14.49 +        return getInt(index, JSType.toString(key));
   14.50      }
   14.51  
   14.52      @Override
   14.53 @@ -2371,7 +2382,7 @@
   14.54              return array.getInt(index);
   14.55          }
   14.56  
   14.57 -        return getInt(index, convertKey(key));
   14.58 +        return getInt(index, JSType.toString(key));
   14.59      }
   14.60  
   14.61      @Override
   14.62 @@ -2383,7 +2394,7 @@
   14.63              return array.getInt(index);
   14.64          }
   14.65  
   14.66 -        return getInt(index, convertKey(key));
   14.67 +        return getInt(index, JSType.toString(key));
   14.68      }
   14.69  
   14.70      @Override
   14.71 @@ -2394,7 +2405,7 @@
   14.72              return array.getInt(key);
   14.73          }
   14.74  
   14.75 -        return getInt(key, convertKey(key));
   14.76 +        return getInt(key, JSType.toString(key));
   14.77      }
   14.78  
   14.79      private long getLong(final int index, final String key) {
   14.80 @@ -2436,7 +2447,7 @@
   14.81              return array.getLong(index);
   14.82          }
   14.83  
   14.84 -        return getLong(index, convertKey(key));
   14.85 +        return getLong(index, JSType.toString(key));
   14.86      }
   14.87  
   14.88      @Override
   14.89 @@ -2448,7 +2459,7 @@
   14.90              return array.getLong(index);
   14.91          }
   14.92  
   14.93 -        return getLong(index, convertKey(key));
   14.94 +        return getLong(index, JSType.toString(key));
   14.95      }
   14.96  
   14.97      @Override
   14.98 @@ -2460,7 +2471,7 @@
   14.99              return array.getLong(index);
  14.100          }
  14.101  
  14.102 -        return getLong(index, convertKey(key));
  14.103 +        return getLong(index, JSType.toString(key));
  14.104      }
  14.105  
  14.106      @Override
  14.107 @@ -2471,7 +2482,7 @@
  14.108              return array.getLong(key);
  14.109          }
  14.110  
  14.111 -        return getLong(key, convertKey(key));
  14.112 +        return getLong(key, JSType.toString(key));
  14.113      }
  14.114  
  14.115      private double getDouble(final int index, final String key) {
  14.116 @@ -2513,7 +2524,7 @@
  14.117              return array.getDouble(index);
  14.118          }
  14.119  
  14.120 -        return getDouble(index, convertKey(key));
  14.121 +        return getDouble(index, JSType.toString(key));
  14.122      }
  14.123  
  14.124      @Override
  14.125 @@ -2525,7 +2536,7 @@
  14.126              return array.getDouble(index);
  14.127          }
  14.128  
  14.129 -        return getDouble(index, convertKey(key));
  14.130 +        return getDouble(index, JSType.toString(key));
  14.131      }
  14.132  
  14.133      @Override
  14.134 @@ -2537,7 +2548,7 @@
  14.135              return array.getDouble(index);
  14.136          }
  14.137  
  14.138 -        return getDouble(index, convertKey(key));
  14.139 +        return getDouble(index, JSType.toString(key));
  14.140      }
  14.141  
  14.142      @Override
  14.143 @@ -2548,7 +2559,7 @@
  14.144              return array.getDouble(key);
  14.145          }
  14.146  
  14.147 -        return getDouble(key, convertKey(key));
  14.148 +        return getDouble(key, JSType.toString(key));
  14.149      }
  14.150  
  14.151      private Object get(final int index, final String key) {
  14.152 @@ -2590,7 +2601,7 @@
  14.153              return array.getObject(index);
  14.154          }
  14.155  
  14.156 -        return get(index, convertKey(key));
  14.157 +        return get(index, JSType.toString(key));
  14.158      }
  14.159  
  14.160      @Override
  14.161 @@ -2602,7 +2613,7 @@
  14.162              return array.getObject(index);
  14.163          }
  14.164  
  14.165 -        return get(index, convertKey(key));
  14.166 +        return get(index, JSType.toString(key));
  14.167      }
  14.168  
  14.169      @Override
  14.170 @@ -2614,7 +2625,7 @@
  14.171              return array.getObject(index);
  14.172          }
  14.173  
  14.174 -        return get(index, convertKey(key));
  14.175 +        return get(index, JSType.toString(key));
  14.176      }
  14.177  
  14.178      @Override
  14.179 @@ -2625,7 +2636,7 @@
  14.180              return array.getObject(key);
  14.181          }
  14.182  
  14.183 -        return get(key, convertKey(key));
  14.184 +        return get(key, JSType.toString(key));
  14.185      }
  14.186  
  14.187      /**
  14.188 @@ -2640,7 +2651,7 @@
  14.189          final long longIndex = index & JSType.MAX_UINT;
  14.190  
  14.191          if (!getArray().has(index)) {
  14.192 -            final String key = convertKey(longIndex);
  14.193 +            final String key = JSType.toString(longIndex);
  14.194              final FindProperty find = findProperty(key, true);
  14.195  
  14.196              if (find != null) {
  14.197 @@ -2786,7 +2797,7 @@
  14.198              return;
  14.199          }
  14.200  
  14.201 -        final String       propName = convertKey(key);
  14.202 +        final String       propName = JSType.toString(key);
  14.203          final FindProperty find     = findProperty(propName, true);
  14.204  
  14.205          setObject(find, strict, propName, value);
  14.206 @@ -3008,7 +3019,7 @@
  14.207              }
  14.208          }
  14.209  
  14.210 -        final FindProperty find = findProperty(convertKey(key), true);
  14.211 +        final FindProperty find = findProperty(JSType.toString(key), true);
  14.212  
  14.213          return find != null;
  14.214      }
  14.215 @@ -3025,7 +3036,7 @@
  14.216              }
  14.217          }
  14.218  
  14.219 -        final FindProperty find = findProperty(convertKey(key), true);
  14.220 +        final FindProperty find = findProperty(JSType.toString(key), true);
  14.221  
  14.222          return find != null;
  14.223      }
  14.224 @@ -3042,7 +3053,7 @@
  14.225              }
  14.226          }
  14.227  
  14.228 -        final FindProperty find = findProperty(convertKey(key), true);
  14.229 +        final FindProperty find = findProperty(JSType.toString(key), true);
  14.230  
  14.231          return find != null;
  14.232      }
  14.233 @@ -3059,7 +3070,7 @@
  14.234              }
  14.235          }
  14.236  
  14.237 -        final FindProperty find = findProperty(convertKey(key), true);
  14.238 +        final FindProperty find = findProperty(JSType.toString(key), true);
  14.239  
  14.240          return find != null;
  14.241      }
  14.242 @@ -3072,7 +3083,7 @@
  14.243              return true;
  14.244          }
  14.245  
  14.246 -        final FindProperty find = findProperty(convertKey(key), false);
  14.247 +        final FindProperty find = findProperty(JSType.toString(key), false);
  14.248  
  14.249          return find != null;
  14.250      }
  14.251 @@ -3085,7 +3096,7 @@
  14.252              return true;
  14.253          }
  14.254  
  14.255 -        final FindProperty find = findProperty(convertKey(key), false);
  14.256 +        final FindProperty find = findProperty(JSType.toString(key), false);
  14.257  
  14.258          return find != null;
  14.259      }
  14.260 @@ -3098,7 +3109,7 @@
  14.261              return true;
  14.262          }
  14.263  
  14.264 -        final FindProperty find = findProperty(convertKey(key), false);
  14.265 +        final FindProperty find = findProperty(JSType.toString(key), false);
  14.266  
  14.267          return find != null;
  14.268      }
  14.269 @@ -3111,7 +3122,7 @@
  14.270              return true;
  14.271          }
  14.272  
  14.273 -        final FindProperty find = findProperty(convertKey(key), false);
  14.274 +        final FindProperty find = findProperty(JSType.toString(key), false);
  14.275  
  14.276          return find != null;
  14.277      }
  14.278 @@ -3181,7 +3192,7 @@
  14.279      }
  14.280  
  14.281      private boolean deleteObject(final Object key, final boolean strict) {
  14.282 -        final String propName = convertKey(key);
  14.283 +        final String propName = JSType.toString(key);
  14.284          final FindProperty find = findProperty(propName, false);
  14.285  
  14.286          if (find == null) {
    15.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Mon Aug 19 19:37:29 2013 +0530
    15.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Fri Aug 23 16:44:02 2013 +0530
    15.3 @@ -37,7 +37,9 @@
    15.4  import java.lang.reflect.Array;
    15.5  import java.util.Collections;
    15.6  import java.util.Iterator;
    15.7 +import java.util.List;
    15.8  import java.util.Locale;
    15.9 +import java.util.Map;
   15.10  import java.util.NoSuchElementException;
   15.11  import java.util.Objects;
   15.12  import jdk.internal.dynalink.beans.StaticClass;
   15.13 @@ -221,49 +223,71 @@
   15.14      }
   15.15  
   15.16      /**
   15.17 -     * Used to determine property iterator used in for in.
   15.18 -     * @param obj Object to iterate on.
   15.19 -     * @return Iterator.
   15.20 +     * Returns an iterator over property identifiers used in the {@code for...in} statement. Note that the ECMAScript
   15.21 +     * 5.1 specification, chapter 12.6.4. uses the terminology "property names", which seems to imply that the property
   15.22 +     * identifiers are expected to be strings, but this is not actually spelled out anywhere, and Nashorn will in some
   15.23 +     * cases deviate from this. Namely, we guarantee to always return an iterator over {@link String} values for any
   15.24 +     * built-in JavaScript object. We will however return an iterator over {@link Integer} objects for native Java
   15.25 +     * arrays and {@link List} objects, as well as arbitrary objects representing keys of a {@link Map}. Therefore, the
   15.26 +     * expression {@code typeof i} within a {@code for(i in obj)} statement can return something other than
   15.27 +     * {@code string} when iterating over native Java arrays, {@code List}, and {@code Map} objects.
   15.28 +     * @param obj object to iterate on.
   15.29 +     * @return iterator over the object's property names.
   15.30       */
   15.31 -    public static Iterator<String> toPropertyIterator(final Object obj) {
   15.32 +    public static Iterator<?> toPropertyIterator(final Object obj) {
   15.33          if (obj instanceof ScriptObject) {
   15.34              return ((ScriptObject)obj).propertyIterator();
   15.35          }
   15.36  
   15.37          if (obj != null && obj.getClass().isArray()) {
   15.38 -            final int length = Array.getLength(obj);
   15.39 -
   15.40 -            return new Iterator<String>() {
   15.41 -                private int index = 0;
   15.42 -
   15.43 -                @Override
   15.44 -                public boolean hasNext() {
   15.45 -                    return index < length;
   15.46 -                }
   15.47 -
   15.48 -                @Override
   15.49 -                public String next() {
   15.50 -                    return "" + index++; //TODO numeric property iterator?
   15.51 -                }
   15.52 -
   15.53 -                @Override
   15.54 -                public void remove() {
   15.55 -                    throw new UnsupportedOperationException();
   15.56 -                }
   15.57 -            };
   15.58 +            return new RangeIterator(Array.getLength(obj));
   15.59          }
   15.60  
   15.61          if (obj instanceof ScriptObjectMirror) {
   15.62              return ((ScriptObjectMirror)obj).keySet().iterator();
   15.63          }
   15.64  
   15.65 +        if (obj instanceof List) {
   15.66 +            return new RangeIterator(((List<?>)obj).size());
   15.67 +        }
   15.68 +
   15.69 +        if (obj instanceof Map) {
   15.70 +            return ((Map<?,?>)obj).keySet().iterator();
   15.71 +        }
   15.72 +
   15.73          return Collections.emptyIterator();
   15.74      }
   15.75  
   15.76 +    private static final class RangeIterator implements Iterator<Integer> {
   15.77 +        private final int length;
   15.78 +        private int index;
   15.79 +
   15.80 +        RangeIterator(int length) {
   15.81 +            this.length = length;
   15.82 +        }
   15.83 +
   15.84 +        @Override
   15.85 +        public boolean hasNext() {
   15.86 +            return index < length;
   15.87 +        }
   15.88 +
   15.89 +        @Override
   15.90 +        public Integer next() {
   15.91 +            return index++;
   15.92 +        }
   15.93 +
   15.94 +        @Override
   15.95 +        public void remove() {
   15.96 +            throw new UnsupportedOperationException();
   15.97 +        }
   15.98 +    }
   15.99 +
  15.100      /**
  15.101 -     * Used to determine property value iterator used in for each in.
  15.102 -     * @param obj Object to iterate on.
  15.103 -     * @return Iterator.
  15.104 +     * Returns an iterator over property values used in the {@code for each...in} statement. Aside from built-in JS
  15.105 +     * objects, it also operates on Java arrays, any {@link Iterable}, as well as on {@link Map} objects, iterating over
  15.106 +     * map values.
  15.107 +     * @param obj object to iterate on.
  15.108 +     * @return iterator over the object's property values.
  15.109       */
  15.110      public static Iterator<?> toValueIterator(final Object obj) {
  15.111          if (obj instanceof ScriptObject) {
  15.112 @@ -301,6 +325,10 @@
  15.113              return ((ScriptObjectMirror)obj).values().iterator();
  15.114          }
  15.115  
  15.116 +        if (obj instanceof Map) {
  15.117 +            return ((Map<?,?>)obj).values().iterator();
  15.118 +        }
  15.119 +
  15.120          if (obj instanceof Iterable) {
  15.121              return ((Iterable<?>)obj).iterator();
  15.122          }
    16.1 --- a/src/jdk/nashorn/internal/runtime/WithObject.java	Mon Aug 19 19:37:29 2013 +0530
    16.2 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java	Fri Aug 23 16:44:02 2013 +0530
    16.3 @@ -73,7 +73,7 @@
    16.4      public boolean delete(final Object key, final boolean strict) {
    16.5          if (expression instanceof ScriptObject) {
    16.6              final ScriptObject self = (ScriptObject)expression;
    16.7 -            final String propName = ScriptObject.convertKey(key);
    16.8 +            final String propName = JSType.toString(key);
    16.9  
   16.10              final FindProperty find = self.findProperty(propName, true);
   16.11  
    17.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Mon Aug 19 19:37:29 2013 +0530
    17.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Fri Aug 23 16:44:02 2013 +0530
    17.3 @@ -36,6 +36,7 @@
    17.4  import jdk.internal.dynalink.DynamicLinker;
    17.5  import jdk.internal.dynalink.DynamicLinkerFactory;
    17.6  import jdk.internal.dynalink.beans.BeansLinker;
    17.7 +import jdk.internal.dynalink.beans.StaticClass;
    17.8  import jdk.internal.dynalink.linker.GuardedInvocation;
    17.9  import jdk.internal.dynalink.linker.LinkerServices;
   17.10  import jdk.nashorn.api.scripting.ScriptObjectMirror;
   17.11 @@ -61,7 +62,7 @@
   17.12      static {
   17.13          final DynamicLinkerFactory factory = new DynamicLinkerFactory();
   17.14          factory.setPrioritizedLinkers(new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(),
   17.15 -                new BoundDynamicMethodLinker(), new JSObjectLinker(), new ReflectionCheckLinker());
   17.16 +                new BoundDynamicMethodLinker(), new JavaSuperAdapterLinker(), new JSObjectLinker(), new ReflectionCheckLinker());
   17.17          factory.setFallbackLinkers(new BeansLinker(), new NashornBottomLinker());
   17.18          factory.setSyncOnRelink(true);
   17.19          final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1);
   17.20 @@ -88,7 +89,8 @@
   17.21          return obj instanceof ScriptFunction ||
   17.22              ((obj instanceof ScriptObjectMirror) && ((ScriptObjectMirror)obj).isFunction()) ||
   17.23              isDynamicMethod(obj) ||
   17.24 -            isFunctionalInterfaceObject(obj);
   17.25 +            isFunctionalInterfaceObject(obj) ||
   17.26 +            obj instanceof StaticClass;
   17.27      }
   17.28  
   17.29      /**
   17.30 @@ -262,6 +264,16 @@
   17.31      }
   17.32  
   17.33      /**
   17.34 +     * Creates a super-adapter for an adapter, that is, an adapter to the adapter that allows invocation of superclass
   17.35 +     * methods on it.
   17.36 +     * @param adapter the original adapter
   17.37 +     * @return a new adapter that can be used to invoke super methods on the original adapter.
   17.38 +     */
   17.39 +    public static Object createSuperAdapter(final Object adapter) {
   17.40 +        return new JavaSuperAdapter(adapter);
   17.41 +    }
   17.42 +
   17.43 +    /**
   17.44       * If the given class is a reflection-specific class (anything in {@code java.lang.reflect} and
   17.45       * {@code java.lang.invoke} package, as well a {@link Class} and any subclass of {@link ClassLoader}) and there is
   17.46       * a security manager in the system, then it checks the {@code nashorn.JavaReflection} {@code RuntimePermission}.
    18.1 --- a/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java	Mon Aug 19 19:37:29 2013 +0530
    18.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java	Fri Aug 23 16:44:02 2013 +0530
    18.3 @@ -67,11 +67,12 @@
    18.4          // BeansLinker.
    18.5          final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
    18.6          final MethodType type = descriptor.getMethodType();
    18.7 +        final Class<?> dynamicMethodClass = dynamicMethod.getClass();
    18.8          final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(
    18.9 -                type.changeParameterType(0, dynamicMethod.getClass()).changeParameterType(1, boundThis.getClass()));
   18.10 +                type.changeParameterType(0, dynamicMethodClass).changeParameterType(1, boundThis.getClass()));
   18.11  
   18.12          // Delegate to BeansLinker
   18.13 -        final GuardedInvocation inv = BeansLinker.getLinkerForClass(dynamicMethod.getClass()).getGuardedInvocation(
   18.14 +        final GuardedInvocation inv = BeansLinker.getLinkerForClass(dynamicMethodClass).getGuardedInvocation(
   18.15                  linkRequest.replaceArguments(newDescriptor, args), linkerServices);
   18.16          if(inv == null) {
   18.17              return null;
    19.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Mon Aug 19 19:37:29 2013 +0530
    19.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Fri Aug 23 16:44:02 2013 +0530
    19.3 @@ -173,6 +173,9 @@
    19.4      private static final String CLASS_INIT = "<clinit>";
    19.5      private static final String STATIC_GLOBAL_FIELD_NAME = "staticGlobal";
    19.6  
    19.7 +    // Method name prefix for invoking super-methods
    19.8 +    static final String SUPER_PREFIX = "super$";
    19.9 +
   19.10      /**
   19.11       * Collection of methods we never override: Object.clone(), Object.finalize().
   19.12       */
   19.13 @@ -240,6 +243,7 @@
   19.14          }
   19.15          generateConstructors();
   19.16          generateMethods();
   19.17 +        generateSuperMethods();
   19.18          // }
   19.19          cw.visitEnd();
   19.20      }
   19.21 @@ -507,6 +511,10 @@
   19.22  
   19.23      private static void endInitMethod(final InstructionAdapter mv) {
   19.24          mv.visitInsn(RETURN);
   19.25 +        endMethod(mv);
   19.26 +    }
   19.27 +
   19.28 +    private static void endMethod(final InstructionAdapter mv) {
   19.29          mv.visitMaxs(0, 0);
   19.30          mv.visitEnd();
   19.31      }
   19.32 @@ -603,13 +611,8 @@
   19.33       */
   19.34      private void generateMethod(final MethodInfo mi) {
   19.35          final Method method = mi.method;
   19.36 -        final int mod = method.getModifiers();
   19.37 -        final int access = ACC_PUBLIC | (method.isVarArgs() ? ACC_VARARGS : 0);
   19.38          final Class<?>[] exceptions = method.getExceptionTypes();
   19.39 -        final String[] exceptionNames = new String[exceptions.length];
   19.40 -        for (int i = 0; i < exceptions.length; ++i) {
   19.41 -            exceptionNames[i] = Type.getInternalName(exceptions[i]);
   19.42 -        }
   19.43 +        final String[] exceptionNames = getExceptionNames(exceptions);
   19.44          final MethodType type = mi.type;
   19.45          final String methodDesc = type.toMethodDescriptorString();
   19.46          final String name = mi.getName();
   19.47 @@ -617,14 +620,8 @@
   19.48          final Type asmType = Type.getMethodType(methodDesc);
   19.49          final Type[] asmArgTypes = asmType.getArgumentTypes();
   19.50  
   19.51 -        // Determine the first index for a local variable
   19.52 -        int nextLocalVar = 1; // this
   19.53 -        for(final Type t: asmArgTypes) {
   19.54 -            nextLocalVar += t.getSize();
   19.55 -        }
   19.56 -
   19.57 -        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(access, name, methodDesc, null,
   19.58 -                exceptionNames));
   19.59 +        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method), name,
   19.60 +                methodDesc, null, exceptionNames));
   19.61          mv.visitCode();
   19.62  
   19.63          final Label instanceHandleDefined = new Label();
   19.64 @@ -646,7 +643,7 @@
   19.65          }
   19.66  
   19.67          // No handle is available, fall back to default behavior
   19.68 -        if(Modifier.isAbstract(mod)) {
   19.69 +        if(Modifier.isAbstract(method.getModifiers())) {
   19.70              // If the super method is abstract, throw an exception
   19.71              mv.anew(UNSUPPORTED_OPERATION_TYPE);
   19.72              mv.dup();
   19.73 @@ -654,14 +651,7 @@
   19.74              mv.athrow();
   19.75          } else {
   19.76              // If the super method is not abstract, delegate to it.
   19.77 -            mv.visitVarInsn(ALOAD, 0);
   19.78 -            int nextParam = 1;
   19.79 -            for(final Type t: asmArgTypes) {
   19.80 -                mv.load(nextParam, t);
   19.81 -                nextParam += t.getSize();
   19.82 -            }
   19.83 -            mv.invokespecial(superClassName, name, methodDesc);
   19.84 -            mv.areturn(asmReturnType);
   19.85 +            emitSuperCall(mv, name, methodDesc);
   19.86          }
   19.87  
   19.88          final Label setupGlobal = new Label();
   19.89 @@ -685,6 +675,12 @@
   19.90          // stack: [creatingGlobal, someHandle]
   19.91          mv.visitLabel(setupGlobal);
   19.92  
   19.93 +        // Determine the first index for a local variable
   19.94 +        int nextLocalVar = 1; // "this" is at 0
   19.95 +        for(final Type t: asmArgTypes) {
   19.96 +            nextLocalVar += t.getSize();
   19.97 +        }
   19.98 +        // Set our local variable indices
   19.99          final int currentGlobalVar  = nextLocalVar++;
  19.100          final int globalsDifferVar  = nextLocalVar++;
  19.101  
  19.102 @@ -775,8 +771,7 @@
  19.103              }
  19.104              mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, throwableHandler, THROWABLE_TYPE_NAME);
  19.105          }
  19.106 -        mv.visitMaxs(0, 0);
  19.107 -        mv.visitEnd();
  19.108 +        endMethod(mv);
  19.109      }
  19.110  
  19.111      /**
  19.112 @@ -817,6 +812,53 @@
  19.113          return false;
  19.114      }
  19.115  
  19.116 +    private void generateSuperMethods() {
  19.117 +        for(final MethodInfo mi: methodInfos) {
  19.118 +            if(!Modifier.isAbstract(mi.method.getModifiers())) {
  19.119 +                generateSuperMethod(mi);
  19.120 +            }
  19.121 +        }
  19.122 +    }
  19.123 +
  19.124 +    private void generateSuperMethod(MethodInfo mi) {
  19.125 +        final Method method = mi.method;
  19.126 +
  19.127 +        final String methodDesc = mi.type.toMethodDescriptorString();
  19.128 +        final String name = mi.getName();
  19.129 +
  19.130 +        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method),
  19.131 +                SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes())));
  19.132 +        mv.visitCode();
  19.133 +
  19.134 +        emitSuperCall(mv, name, methodDesc);
  19.135 +
  19.136 +        endMethod(mv);
  19.137 +    }
  19.138 +
  19.139 +    private void emitSuperCall(final InstructionAdapter mv, final String name, final String methodDesc) {
  19.140 +        mv.visitVarInsn(ALOAD, 0);
  19.141 +        int nextParam = 1;
  19.142 +        final Type methodType = Type.getMethodType(methodDesc);
  19.143 +        for(final Type t: methodType.getArgumentTypes()) {
  19.144 +            mv.load(nextParam, t);
  19.145 +            nextParam += t.getSize();
  19.146 +        }
  19.147 +        mv.invokespecial(superClassName, name, methodDesc);
  19.148 +        mv.areturn(methodType.getReturnType());
  19.149 +    }
  19.150 +
  19.151 +    private static String[] getExceptionNames(final Class<?>[] exceptions) {
  19.152 +        final String[] exceptionNames = new String[exceptions.length];
  19.153 +        for (int i = 0; i < exceptions.length; ++i) {
  19.154 +            exceptionNames[i] = Type.getInternalName(exceptions[i]);
  19.155 +        }
  19.156 +        return exceptionNames;
  19.157 +    }
  19.158 +
  19.159 +    private static int getAccessModifiers(final Method method) {
  19.160 +        return ACC_PUBLIC | (method.isVarArgs() ? ACC_VARARGS : 0);
  19.161 +    }
  19.162 +
  19.163      /**
  19.164       * Gathers methods that can be implemented or overridden from the specified type into this factory's
  19.165       * {@link #methodInfos} set. It will add all non-final, non-static methods that are either public or protected from
    20.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Mon Aug 19 19:37:29 2013 +0530
    20.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Fri Aug 23 16:44:02 2013 +0530
    20.3 @@ -34,7 +34,6 @@
    20.4  import java.security.PrivilegedAction;
    20.5  import java.security.ProtectionDomain;
    20.6  import java.security.SecureClassLoader;
    20.7 -
    20.8  import jdk.internal.dynalink.beans.StaticClass;
    20.9  
   20.10  /**
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java	Fri Aug 23 16:44:02 2013 +0530
    21.3 @@ -0,0 +1,44 @@
    21.4 +/*
    21.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 + *
    21.8 + * This code is free software; you can redistribute it and/or modify it
    21.9 + * under the terms of the GNU General Public License version 2 only, as
   21.10 + * published by the Free Software Foundation.  Oracle designates this
   21.11 + * particular file as subject to the "Classpath" exception as provided
   21.12 + * by Oracle in the LICENSE file that accompanied this code.
   21.13 + *
   21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.17 + * version 2 for more details (a copy is included in the LICENSE file that
   21.18 + * accompanied this code).
   21.19 + *
   21.20 + * You should have received a copy of the GNU General Public License version
   21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.23 + *
   21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   21.25 + * or visit www.oracle.com if you need additional information or have any
   21.26 + * questions.
   21.27 + */
   21.28 +
   21.29 +package jdk.nashorn.internal.runtime.linker;
   21.30 +
   21.31 +/**
   21.32 + * Represents a an adapter for invoking superclass methods on an adapter instance generated by
   21.33 + * {@link JavaAdapterBytecodeGenerator}. Note that objects of this class are just wrappers around the adapter instances,
   21.34 + * without any behavior. All the behavior is defined in the {@code JavaSuperAdapterLinker}.
   21.35 + */
   21.36 +class JavaSuperAdapter {
   21.37 +    private final Object adapter;
   21.38 +
   21.39 +    JavaSuperAdapter(final Object adapter) {
   21.40 +        adapter.getClass(); // NPE check
   21.41 +        this.adapter = adapter;
   21.42 +    }
   21.43 +
   21.44 +    public Object getAdapter() {
   21.45 +        return adapter;
   21.46 +    }
   21.47 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java	Fri Aug 23 16:44:02 2013 +0530
    22.3 @@ -0,0 +1,180 @@
    22.4 +/*
    22.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    22.7 + *
    22.8 + * This code is free software; you can redistribute it and/or modify it
    22.9 + * under the terms of the GNU General Public License version 2 only, as
   22.10 + * published by the Free Software Foundation.  Oracle designates this
   22.11 + * particular file as subject to the "Classpath" exception as provided
   22.12 + * by Oracle in the LICENSE file that accompanied this code.
   22.13 + *
   22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   22.17 + * version 2 for more details (a copy is included in the LICENSE file that
   22.18 + * accompanied this code).
   22.19 + *
   22.20 + * You should have received a copy of the GNU General Public License version
   22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   22.23 + *
   22.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22.25 + * or visit www.oracle.com if you need additional information or have any
   22.26 + * questions.
   22.27 + */
   22.28 +
   22.29 +package jdk.nashorn.internal.runtime.linker;
   22.30 +
   22.31 +import static jdk.nashorn.internal.lookup.Lookup.EMPTY_GETTER;
   22.32 +import static jdk.nashorn.internal.runtime.linker.JavaAdapterBytecodeGenerator.SUPER_PREFIX;
   22.33 +
   22.34 +import java.lang.invoke.MethodHandle;
   22.35 +import java.lang.invoke.MethodHandles;
   22.36 +import java.lang.invoke.MethodType;
   22.37 +import jdk.internal.dynalink.CallSiteDescriptor;
   22.38 +import jdk.internal.dynalink.beans.BeansLinker;
   22.39 +import jdk.internal.dynalink.linker.GuardedInvocation;
   22.40 +import jdk.internal.dynalink.linker.LinkRequest;
   22.41 +import jdk.internal.dynalink.linker.LinkerServices;
   22.42 +import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
   22.43 +import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
   22.44 +import jdk.internal.dynalink.support.Lookup;
   22.45 +import jdk.nashorn.internal.runtime.ScriptRuntime;
   22.46 +
   22.47 +/**
   22.48 + * A linker for instances of {@link JavaSuperAdapter}. Only links {@code getMethod} calls, by forwarding them to the
   22.49 + * bean linker for the adapter class and prepending {@code super$} to method names.
   22.50 + *
   22.51 + */
   22.52 +final class JavaSuperAdapterLinker implements TypeBasedGuardingDynamicLinker {
   22.53 +    private static final String GET_METHOD = "getMethod";
   22.54 +    private static final String DYN_GET_METHOD = "dyn:" + GET_METHOD;
   22.55 +    private static final String DYN_GET_METHOD_FIXED = DYN_GET_METHOD + ":" + SUPER_PREFIX;
   22.56 +
   22.57 +    private static final MethodHandle ADD_PREFIX_TO_METHOD_NAME;
   22.58 +    private static final MethodHandle BIND_DYNAMIC_METHOD;
   22.59 +    private static final MethodHandle GET_ADAPTER;
   22.60 +    private static final MethodHandle IS_ADAPTER_OF_CLASS;
   22.61 +
   22.62 +    static {
   22.63 +        final Lookup lookup = new Lookup(MethodHandles.lookup());
   22.64 +        ADD_PREFIX_TO_METHOD_NAME = lookup.findOwnStatic("addPrefixToMethodName", Object.class, Object.class);
   22.65 +        BIND_DYNAMIC_METHOD = lookup.findOwnStatic("bindDynamicMethod", Object.class, Object.class, Object.class);
   22.66 +        GET_ADAPTER = lookup.findVirtual(JavaSuperAdapter.class, "getAdapter", MethodType.methodType(Object.class));
   22.67 +        IS_ADAPTER_OF_CLASS = lookup.findOwnStatic("isAdapterOfClass", boolean.class, Class.class, Object.class);
   22.68 +    }
   22.69 +
   22.70 +    @Override
   22.71 +    public boolean canLinkType(final Class<?> type) {
   22.72 +        return type == JavaSuperAdapter.class;
   22.73 +    }
   22.74 +
   22.75 +    @Override
   22.76 +    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
   22.77 +            throws Exception {
   22.78 +        final Object objSuperAdapter = linkRequest.getReceiver();
   22.79 +        if(!(objSuperAdapter instanceof JavaSuperAdapter)) {
   22.80 +            return null;
   22.81 +        }
   22.82 +
   22.83 +        final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
   22.84 +        if(!CallSiteDescriptorFactory.tokenizeOperators(descriptor).contains(GET_METHOD)) {
   22.85 +            // We only handle getMethod
   22.86 +            return null;
   22.87 +        }
   22.88 +
   22.89 +        final Object adapter = ((JavaSuperAdapter)objSuperAdapter).getAdapter();
   22.90 +
   22.91 +        // Replace argument (javaSuperAdapter, ...) => (adapter, ...) when delegating to BeansLinker
   22.92 +        final Object[] args = linkRequest.getArguments();
   22.93 +        args[0] = adapter;
   22.94 +
   22.95 +        // Use R(T0, ...) => R(adapter.class, ...) call site type when delegating to BeansLinker.
   22.96 +        final MethodType type = descriptor.getMethodType();
   22.97 +        final Class<?> adapterClass = adapter.getClass();
   22.98 +        final boolean hasFixedName = descriptor.getNameTokenCount() > 2;
   22.99 +        final String opName = hasFixedName ? (DYN_GET_METHOD_FIXED + descriptor.getNameToken(
  22.100 +                CallSiteDescriptor.NAME_OPERAND)) : DYN_GET_METHOD;
  22.101 +
  22.102 +        final CallSiteDescriptor newDescriptor = NashornCallSiteDescriptor.get(descriptor.getLookup(), opName,
  22.103 +                type.changeParameterType(0, adapterClass), 0);
  22.104 +
  22.105 +        // Delegate to BeansLinker
  22.106 +        final GuardedInvocation guardedInv = BeansLinker.getLinkerForClass(adapterClass).getGuardedInvocation(
  22.107 +                linkRequest.replaceArguments(newDescriptor, args), linkerServices);
  22.108 +
  22.109 +        final MethodHandle guard = IS_ADAPTER_OF_CLASS.bindTo(adapterClass);
  22.110 +        if(guardedInv == null) {
  22.111 +            // Short circuit the lookup here for non-existent methods by linking an empty getter. If we just returned
  22.112 +            // null instead, BeansLinker would find final methods on the JavaSuperAdapter instead: getClass() and
  22.113 +            // wait().
  22.114 +            return new GuardedInvocation(MethodHandles.dropArguments(EMPTY_GETTER, 1,type.parameterList().subList(1,
  22.115 +                    type.parameterCount())), guard).asType(descriptor);
  22.116 +        }
  22.117 +
  22.118 +        final MethodHandle invocation = guardedInv.getInvocation();
  22.119 +        final MethodType invType = invocation.type();
  22.120 +        // For invocation typed R(T0, ...) create a dynamic method binder of type R(R, T0)
  22.121 +        final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(invType.returnType(),
  22.122 +                invType.returnType(), invType.parameterType(0)));
  22.123 +        // For invocation typed R(T0, T1, ...) create a dynamic method binder of type R(R, T0, T1, ...)
  22.124 +        final MethodHandle droppingBinder = MethodHandles.dropArguments(typedBinder, 2,
  22.125 +                invType.parameterList().subList(1, invType.parameterCount()));
  22.126 +        // Finally, fold the invocation into the binder to produce a method handle that will bind every returned
  22.127 +        // DynamicMethod object from dyn:getMethod calls to the actual receiver
  22.128 +        // R(R(T0, T1, ...), T0, T1, ...)
  22.129 +        final MethodHandle bindingInvocation = MethodHandles.foldArguments(droppingBinder, invocation);
  22.130 +
  22.131 +        final MethodHandle typedGetAdapter = asFilterType(GET_ADAPTER, 0, invType, type);
  22.132 +        final MethodHandle adaptedInvocation;
  22.133 +        if(hasFixedName) {
  22.134 +            adaptedInvocation = MethodHandles.filterArguments(bindingInvocation, 0, typedGetAdapter);
  22.135 +        } else {
  22.136 +            // Add a filter that'll prepend "super$" to each name passed to the variable-name "dyn:getMethod".
  22.137 +            final MethodHandle typedAddPrefix = asFilterType(ADD_PREFIX_TO_METHOD_NAME, 1, invType, type);
  22.138 +            adaptedInvocation = MethodHandles.filterArguments(bindingInvocation, 0, typedGetAdapter, typedAddPrefix);
  22.139 +        }
  22.140 +
  22.141 +        return guardedInv.replaceMethods(adaptedInvocation, guard).asType(descriptor);
  22.142 +    }
  22.143 +
  22.144 +    /**
  22.145 +     * Adapts the type of a method handle used as a filter in a position from a source method type to a target method type.
  22.146 +     * @param filter the filter method handle
  22.147 +     * @param pos the position in the argument list that it's filtering
  22.148 +     * @param targetType the target method type for filtering
  22.149 +     * @param sourceType the source method type for filtering
  22.150 +     * @return a type adapted filter
  22.151 +     */
  22.152 +    private static MethodHandle asFilterType(final MethodHandle filter, int pos, MethodType targetType, MethodType sourceType) {
  22.153 +        return filter.asType(MethodType.methodType(targetType.parameterType(pos), sourceType.parameterType(pos)));
  22.154 +    }
  22.155 +
  22.156 +    @SuppressWarnings("unused")
  22.157 +    private static Object addPrefixToMethodName(final Object name) {
  22.158 +        return SUPER_PREFIX.concat(String.valueOf(name));
  22.159 +    }
  22.160 +
  22.161 +    /**
  22.162 +     * Used to transform the return value of getMethod; transform a {@code DynamicMethod} into a
  22.163 +     * {@code BoundDynamicMethod} while also accounting for the possibility of a non-existent method.
  22.164 +     * @param dynamicMethod the dynamic method to bind
  22.165 +     * @param boundThis the adapter underlying a super adapter, to which the dynamic method is bound.
  22.166 +     * @return a dynamic method bound to the adapter instance.
  22.167 +     */
  22.168 +    @SuppressWarnings("unused")
  22.169 +    private static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) {
  22.170 +        return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindDynamicMethod(dynamicMethod, boundThis);
  22.171 +    }
  22.172 +
  22.173 +    /**
  22.174 +     * Used as the guard of linkages, as the receiver is not guaranteed to be a JavaSuperAdapter.
  22.175 +     * @param clazz the class the receiver's adapter is tested against.
  22.176 +     * @param obj receiver
  22.177 +     * @return true if the receiver is a super adapter, and its underlying adapter is of the specified class
  22.178 +     */
  22.179 +    @SuppressWarnings("unused")
  22.180 +    private static boolean isAdapterOfClass(Class<?> clazz, Object obj) {
  22.181 +        return obj instanceof JavaSuperAdapter && clazz == (((JavaSuperAdapter)obj).getAdapter()).getClass();
  22.182 +    }
  22.183 +}
    23.1 --- a/src/jdk/nashorn/internal/runtime/regexp/RegExp.java	Mon Aug 19 19:37:29 2013 +0530
    23.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExp.java	Fri Aug 23 16:44:02 2013 +0530
    23.3 @@ -60,7 +60,7 @@
    23.4       * @param flags the flags string
    23.5       */
    23.6      protected RegExp(final String source, final String flags) {
    23.7 -        this.source = source;
    23.8 +        this.source = source.length() == 0 ? "(?:)" : source;
    23.9          for (int i = 0; i < flags.length(); i++) {
   23.10              final char ch = flags.charAt(i);
   23.11              switch (ch) {
    24.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Mon Aug 19 19:37:29 2013 +0530
    24.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Fri Aug 23 16:44:02 2013 +0530
    24.3 @@ -94,6 +94,8 @@
    24.4  type.error.cant.redefine.property=Cannot redefine property "{0}" of {1}
    24.5  type.error.property.not.writable="{0}" is not a writable property of {1}
    24.6  type.error.object.non.extensible=Cannot add new property "{0}" to non-extensible {1}
    24.7 +type.error.__proto__.set.non.extensible=Cannot set __proto__ of non-extensible {0}
    24.8 +type.error.circular.__proto__.set=Cannot create__proto__ cycle for {0}
    24.9  
   24.10  # miscellaneous
   24.11  type.error.regex.cant.supply.flags=Cannot supply flags when constructing one RegExp from another
    25.1 --- a/src/jdk/nashorn/internal/runtime/resources/Options.properties	Mon Aug 19 19:37:29 2013 +0530
    25.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties	Fri Aug 23 16:44:02 2013 +0530
    25.3 @@ -157,6 +157,14 @@
    25.4      default=false                               \
    25.5  }
    25.6  
    25.7 +nashorn.option.global.per.engine = {            \
    25.8 +    name="--global-per-engine",                 \
    25.9 +    desc="Use single Global instance per script engine instance.", \
   25.10 +    is_undocumented=true,                                          \
   25.11 +    type=Boolean,                               \
   25.12 +    default=false                               \
   25.13 +}
   25.14 +
   25.15  nashorn.option.log = {                                                       \
   25.16      name="--log",                                                            \
   25.17      is_undocumented=true,                                                    \
   25.18 @@ -216,15 +224,6 @@
   25.19      default=false                                  \
   25.20  }
   25.21  
   25.22 -nashorn.option.package = {                                     \
   25.23 -    name="--package",                                          \
   25.24 -    is_undocumented=true,                                      \
   25.25 -    desc="Package to which generated .class files are added.", \
   25.26 -    params="<package>",                                        \
   25.27 -    type=String,                                               \
   25.28 -    default=""                                                 \
   25.29 -}
   25.30 -
   25.31  nashorn.option.parse.only = {       \
   25.32      name="--parse-only",            \
   25.33      is_undocumented=true,           \
    26.1 --- a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Mon Aug 19 19:37:29 2013 +0530
    26.2 +++ b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Fri Aug 23 16:44:02 2013 +0530
    26.3 @@ -144,7 +144,7 @@
    26.4          return Object.getPrototypeOf(this);
    26.5      },
    26.6      set: function(x) {
    26.7 -        throw new TypeError("__proto__ set not supported");
    26.8 +        Object.setPrototypeOf(this, x);
    26.9      }
   26.10  });
   26.11  
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/test/script/basic/JDK-8022903.js	Fri Aug 23 16:44:02 2013 +0530
    27.3 @@ -0,0 +1,55 @@
    27.4 +/*
    27.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    27.7 + * 
    27.8 + * This code is free software; you can redistribute it and/or modify it
    27.9 + * under the terms of the GNU General Public License version 2 only, as
   27.10 + * published by the Free Software Foundation.
   27.11 + * 
   27.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   27.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   27.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   27.15 + * version 2 for more details (a copy is included in the LICENSE file that
   27.16 + * accompanied this code).
   27.17 + * 
   27.18 + * You should have received a copy of the GNU General Public License version
   27.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   27.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   27.21 + * 
   27.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   27.23 + * or visit www.oracle.com if you need additional information or have any
   27.24 + * questions.
   27.25 + */
   27.26 +
   27.27 +/**
   27.28 + * JDK-8022903: Enhance for-in and for-each for Lists and Maps
   27.29 + *
   27.30 + * @test
   27.31 + * @run
   27.32 + */
   27.33 +
   27.34 +var colors = new java.util.ArrayList()
   27.35 +colors.add("red")
   27.36 +colors.add("purple")
   27.37 +colors.add("pink")
   27.38 +
   27.39 +for(var index in colors) {
   27.40 +    print("colors[" + index + "]=" + colors[index])
   27.41 +}
   27.42 +
   27.43 +for each(var color in colors) {
   27.44 +    print(color)
   27.45 +}
   27.46 +
   27.47 +var capitals = new java.util.LinkedHashMap()
   27.48 +capitals.Sweden = "Stockholm"
   27.49 +capitals.Hungary = "Budapet"
   27.50 +capitals.Croatia = "Zagreb"
   27.51 +
   27.52 +for(var key in capitals) {
   27.53 +    print("capital of " + key + " is " + capitals[key])
   27.54 +}
   27.55 +
   27.56 +for each(var capital in capitals) {
   27.57 +    print(capital)
   27.58 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/test/script/basic/JDK-8022903.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    28.3 @@ -0,0 +1,12 @@
    28.4 +colors[0]=red
    28.5 +colors[1]=purple
    28.6 +colors[2]=pink
    28.7 +red
    28.8 +purple
    28.9 +pink
   28.10 +capital of Sweden is Stockholm
   28.11 +capital of Hungary is Budapet
   28.12 +capital of Croatia is Zagreb
   28.13 +Stockholm
   28.14 +Budapet
   28.15 +Zagreb
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/test/script/basic/JDK-8023368.js	Fri Aug 23 16:44:02 2013 +0530
    29.3 @@ -0,0 +1,73 @@
    29.4 +/*
    29.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.7 + *
    29.8 + * This code is free software; you can redistribute it and/or modify it
    29.9 + * under the terms of the GNU General Public License version 2 only, as
   29.10 + * published by the Free Software Foundation.
   29.11 + *
   29.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   29.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   29.15 + * version 2 for more details (a copy is included in the LICENSE file that
   29.16 + * accompanied this code).
   29.17 + *
   29.18 + * You should have received a copy of the GNU General Public License version
   29.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   29.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   29.21 + *
   29.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   29.23 + * or visit www.oracle.com if you need additional information or have any
   29.24 + * questions.
   29.25 + */
   29.26 +
   29.27 +/**
   29.28 + * JDK-8023368: Instance __proto__ property should exist and be writable.
   29.29 + *
   29.30 + * @test
   29.31 + * @run
   29.32 + */
   29.33 +
   29.34 +load("nashorn:mozilla_compat.js");
   29.35 +
   29.36 +// function to force same callsites
   29.37 +function check(obj) {
   29.38 +    print(obj.func());
   29.39 +    print(obj.x);
   29.40 +    print(obj.toString());
   29.41 +}
   29.42 +
   29.43 +function Func() {
   29.44 +}
   29.45 +
   29.46 +Func.prototype.func = function() {
   29.47 +    return "Func.prototype.func";
   29.48 +}
   29.49 +
   29.50 +Func.prototype.x = "hello";
   29.51 +
   29.52 +var obj = new Func();
   29.53 +var obj2 = Object.create(obj);
   29.54 +
   29.55 +// check direct and indirect __proto__ change
   29.56 +check(obj);
   29.57 +check(obj2);
   29.58 +obj.__proto__ = {
   29.59 +   func: function() {
   29.60 +        return "obj.__proto__.func @ " + __LINE__;
   29.61 +   },
   29.62 +   x: 344
   29.63 +};
   29.64 +
   29.65 +check(obj);
   29.66 +check(obj2);
   29.67 +
   29.68 +// check indirect (1 and 2 levels) __proto__ function change
   29.69 +obj.__proto__.__proto__ = {
   29.70 +    toString: function() {
   29.71 +        return "new object.toString";
   29.72 +    }
   29.73 +};
   29.74 +
   29.75 +check(obj);
   29.76 +check(obj2);
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/test/script/basic/JDK-8023368.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    30.3 @@ -0,0 +1,18 @@
    30.4 +Func.prototype.func
    30.5 +hello
    30.6 +[object Object]
    30.7 +Func.prototype.func
    30.8 +hello
    30.9 +[object Object]
   30.10 +obj.__proto__.func @ 57
   30.11 +344
   30.12 +[object Object]
   30.13 +obj.__proto__.func @ 57
   30.14 +344
   30.15 +[object Object]
   30.16 +obj.__proto__.func @ 57
   30.17 +344
   30.18 +new object.toString
   30.19 +obj.__proto__.func @ 57
   30.20 +344
   30.21 +new object.toString
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/test/script/basic/JDK-8023368_2.js	Fri Aug 23 16:44:02 2013 +0530
    31.3 @@ -0,0 +1,73 @@
    31.4 +/*
    31.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    31.7 + *
    31.8 + * This code is free software; you can redistribute it and/or modify it
    31.9 + * under the terms of the GNU General Public License version 2 only, as
   31.10 + * published by the Free Software Foundation.
   31.11 + *
   31.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   31.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   31.15 + * version 2 for more details (a copy is included in the LICENSE file that
   31.16 + * accompanied this code).
   31.17 + *
   31.18 + * You should have received a copy of the GNU General Public License version
   31.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   31.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   31.21 + *
   31.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   31.23 + * or visit www.oracle.com if you need additional information or have any
   31.24 + * questions.
   31.25 + */
   31.26 +
   31.27 +/**
   31.28 + * JDK-8023368: Instance __proto__ property should exist and be writable.
   31.29 + *
   31.30 + * @test
   31.31 + * @run
   31.32 + */
   31.33 +
   31.34 +// check Object.setPrototypeOf extension rather than using __proto__
   31.35 +
   31.36 +// function to force same callsites
   31.37 +function check(obj) {
   31.38 +    print(obj.func());
   31.39 +    print(obj.x);
   31.40 +    print(obj.toString());
   31.41 +}
   31.42 +
   31.43 +function Func() {
   31.44 +}
   31.45 +
   31.46 +Func.prototype.func = function() {
   31.47 +    return "Func.prototype.func";
   31.48 +}
   31.49 +
   31.50 +Func.prototype.x = "hello";
   31.51 +
   31.52 +var obj = new Func();
   31.53 +var obj2 = Object.create(obj);
   31.54 +
   31.55 +// check direct and indirect __proto__ change
   31.56 +check(obj);
   31.57 +check(obj2);
   31.58 +Object.setPrototypeOf(obj, {
   31.59 +   func: function() {
   31.60 +        return "obj.__proto__.func @ " + __LINE__;
   31.61 +   },
   31.62 +   x: 344
   31.63 +});
   31.64 +
   31.65 +check(obj);
   31.66 +check(obj2);
   31.67 +
   31.68 +// check indirect (1 and 2 levels) __proto__ function change
   31.69 +Object.setPrototypeOf(Object.getPrototypeOf(obj), {
   31.70 +    toString: function() {
   31.71 +        return "new object.toString";
   31.72 +    }
   31.73 +});
   31.74 +
   31.75 +check(obj);
   31.76 +check(obj2);
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/test/script/basic/JDK-8023368_2.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    32.3 @@ -0,0 +1,18 @@
    32.4 +Func.prototype.func
    32.5 +hello
    32.6 +[object Object]
    32.7 +Func.prototype.func
    32.8 +hello
    32.9 +[object Object]
   32.10 +obj.__proto__.func @ 57
   32.11 +344
   32.12 +[object Object]
   32.13 +obj.__proto__.func @ 57
   32.14 +344
   32.15 +[object Object]
   32.16 +obj.__proto__.func @ 57
   32.17 +344
   32.18 +new object.toString
   32.19 +obj.__proto__.func @ 57
   32.20 +344
   32.21 +new object.toString
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/test/script/basic/JDK-8023373.js	Fri Aug 23 16:44:02 2013 +0530
    33.3 @@ -0,0 +1,84 @@
    33.4 +/*
    33.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 + * 
    33.8 + * This code is free software; you can redistribute it and/or modify it
    33.9 + * under the terms of the GNU General Public License version 2 only, as
   33.10 + * published by the Free Software Foundation.
   33.11 + * 
   33.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   33.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   33.15 + * version 2 for more details (a copy is included in the LICENSE file that
   33.16 + * accompanied this code).
   33.17 + * 
   33.18 + * You should have received a copy of the GNU General Public License version
   33.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   33.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.21 + * 
   33.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   33.23 + * or visit www.oracle.com if you need additional information or have any
   33.24 + * questions.
   33.25 + */
   33.26 +
   33.27 +/**
   33.28 + * JDK-8023373: allow super invocation for adapters
   33.29 + *
   33.30 + * @test
   33.31 + * @run
   33.32 + */
   33.33 +
   33.34 +var CharArray = Java.type("char[]")
   33.35 +var jString = Java.type("java.lang.String")
   33.36 +var Character = Java.type("java.lang.Character")
   33.37 +
   33.38 +function capitalize(s) {
   33.39 +    if(s instanceof CharArray) {
   33.40 +        return new jString(s).toUpperCase()
   33.41 +    }
   33.42 +    if(s instanceof jString) {
   33.43 +        return s.toUpperCase()
   33.44 +    }
   33.45 +    return Character.toUpperCase(s) // must be int
   33.46 +}
   33.47 +
   33.48 +var sw = new (Java.type("java.io.StringWriter"))
   33.49 +
   33.50 +var FilterWriterAdapter = Java.extend(Java.type("java.io.FilterWriter"))
   33.51 +
   33.52 +var cw = new FilterWriterAdapter(sw) {
   33.53 +    write: function(s, off, len) {
   33.54 +        s = capitalize(s)
   33.55 +        // Must handle overloads by arity
   33.56 +        if(off === undefined) {	
   33.57 +            cw.super$write(s, 0, s.length())
   33.58 +        } else if (typeof s === "string") {
   33.59 +            cw.super$write(s, off, len)
   33.60 +        }
   33.61 +    }
   33.62 +}
   33.63 +
   33.64 +cw.write("abcd")
   33.65 +cw.write("e".charAt(0))
   33.66 +cw.write("fgh".toCharArray())
   33.67 +cw.write("**ijk**", 2, 3)
   33.68 +cw.write("***lmno**".toCharArray(), 3, 4)
   33.69 +cw.flush()
   33.70 +print(sw)
   33.71 +
   33.72 +// Can invoke super for Object methods
   33.73 +print("cw has super hashCode(): " + (typeof cw.super$hashCode === "function"))
   33.74 +print("cw has super equals(): " + (typeof cw.super$equals === "function"))
   33.75 +// Can't invoke super for final methods
   33.76 +print("cw has no super getClass(): " + (typeof cw.super$getClass === "undefined"))
   33.77 +print("cw has no super wait(): " + (typeof cw.super$wait === "undefined"))
   33.78 +
   33.79 +var r = new (Java.type("java.lang.Runnable"))(function() {})
   33.80 +// Can't invoke super for abstract methods
   33.81 +print("r has no super run(): " + (typeof r.super$run === "undefined"))
   33.82 +// Interfaces can also invoke super Object methods
   33.83 +print("r has super hashCode(): " + (typeof r.super$hashCode === "function"))
   33.84 +print("r has super equals(): " + (typeof r.super$equals === "function"))
   33.85 +// But still can't invoke final methods
   33.86 +print("r has no super getClass(): " + (typeof r.super$getClass === "undefined"))
   33.87 +print("r has no super wait(): " + (typeof r.super$wait === "undefined"))
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/test/script/basic/JDK-8023373.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    34.3 @@ -0,0 +1,10 @@
    34.4 +ABCDEFGHIJKLMNO
    34.5 +cw has super hashCode(): true
    34.6 +cw has super equals(): true
    34.7 +cw has no super getClass(): true
    34.8 +cw has no super wait(): true
    34.9 +r has no super run(): true
   34.10 +r has super hashCode(): true
   34.11 +r has super equals(): true
   34.12 +r has no super getClass(): true
   34.13 +r has no super wait(): true
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/test/script/basic/JDK-8023531.js	Fri Aug 23 16:44:02 2013 +0530
    35.3 @@ -0,0 +1,106 @@
    35.4 +/*
    35.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + * 
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.
   35.11 + * 
   35.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.15 + * version 2 for more details (a copy is included in the LICENSE file that
   35.16 + * accompanied this code).
   35.17 + * 
   35.18 + * You should have received a copy of the GNU General Public License version
   35.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.21 + * 
   35.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   35.23 + * or visit www.oracle.com if you need additional information or have any
   35.24 + * questions.
   35.25 + */
   35.26 +
   35.27 +/**
   35.28 + * JDK-8023531: new RegExp('').toString() should return '/(?:)/'
   35.29 + *
   35.30 + * @test
   35.31 + * @run
   35.32 + */
   35.33 +
   35.34 +if (new RegExp("").toString() !== "/(?:)/") {
   35.35 +    throw new Error();
   35.36 +} else if (!(new RegExp("").test(""))) {
   35.37 +    throw new Error();
   35.38 +}
   35.39 +
   35.40 +if (new RegExp("", "g").toString() !== "/(?:)/g") {
   35.41 +    throw new Error();
   35.42 +} else if (!(new RegExp("", "g").test(""))) {
   35.43 +    throw new Error();
   35.44 +}
   35.45 +
   35.46 +if (new RegExp("", "i").toString() !== "/(?:)/i") {
   35.47 +    throw new Error();
   35.48 +} else if (!(new RegExp("", "i").test(""))) {
   35.49 +    throw new Error();
   35.50 +}
   35.51 +
   35.52 +if (new RegExp("", "m").toString() !== "/(?:)/m") {
   35.53 +    throw new Error();
   35.54 +} else if (!(new RegExp("", "m").test(""))) {
   35.55 +    throw new Error();
   35.56 +}
   35.57 +
   35.58 +if (RegExp("").toString() !== "/(?:)/") {
   35.59 +    throw new Error();
   35.60 +} else if (!RegExp("").test("")) {
   35.61 +    throw new Error();
   35.62 +}
   35.63 +
   35.64 +if (RegExp("", "g").toString() !== "/(?:)/g") {
   35.65 +    throw new Error();
   35.66 +} else if (!RegExp("", "g").test("")) {
   35.67 +    throw new Error();
   35.68 +}
   35.69 +
   35.70 +if (RegExp("", "i").toString() !== "/(?:)/i") {
   35.71 +    throw new Error();
   35.72 +} else if (!RegExp("", "i").test("")) {
   35.73 +    throw new Error();
   35.74 +}
   35.75 +
   35.76 +if (RegExp("", "m").toString() !== "/(?:)/m") {
   35.77 +    throw new Error();
   35.78 +} else if (!RegExp("", "m").test("")) {
   35.79 +    throw new Error();
   35.80 +}
   35.81 +
   35.82 +var re = /abc/;
   35.83 +re.compile("");
   35.84 +if (re.toString() !== "/(?:)/") {
   35.85 +    throw new Error();
   35.86 +} else if (!re.test("")) {
   35.87 +    throw new Error();
   35.88 +}
   35.89 +
   35.90 +re.compile("", "g");
   35.91 +if (re.toString() !== "/(?:)/g") {
   35.92 +    throw new Error();
   35.93 +} else if (!re.test("")) {
   35.94 +    throw new Error();
   35.95 +}
   35.96 +
   35.97 +re.compile("", "i");
   35.98 +if (re.toString() !== "/(?:)/i") {
   35.99 +    throw new Error();
  35.100 +} else if (!re.test("")) {
  35.101 +    throw new Error();
  35.102 +}
  35.103 +
  35.104 +re.compile("", "m");
  35.105 +if (re.toString() !== "/(?:)/m") {
  35.106 +    throw new Error();
  35.107 +} else if (!re.test("")) {
  35.108 +    throw new Error();
  35.109 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/test/script/basic/JDK-8023551.js	Fri Aug 23 16:44:02 2013 +0530
    36.3 @@ -0,0 +1,42 @@
    36.4 +/*
    36.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    36.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    36.7 + * 
    36.8 + * This code is free software; you can redistribute it and/or modify it
    36.9 + * under the terms of the GNU General Public License version 2 only, as
   36.10 + * published by the Free Software Foundation.
   36.11 + * 
   36.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   36.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   36.15 + * version 2 for more details (a copy is included in the LICENSE file that
   36.16 + * accompanied this code).
   36.17 + * 
   36.18 + * You should have received a copy of the GNU General Public License version
   36.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   36.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   36.21 + * 
   36.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   36.23 + * or visit www.oracle.com if you need additional information or have any
   36.24 + * questions.
   36.25 + */
   36.26 +
   36.27 +/**
   36.28 + * JDK-8023551: Mirror functions can not be invoked using invokeMethod, invokeFunction
   36.29 + *
   36.30 + * @test
   36.31 + * @run
   36.32 + */
   36.33 +
   36.34 +var m = new javax.script.ScriptEngineManager();
   36.35 +var e = m.getEngineByName("nashorn");
   36.36 +
   36.37 +function func(x) {
   36.38 +   print("func: " + x);
   36.39 +}
   36.40 +
   36.41 +e.put("func", func);
   36.42 +e.invokeFunction("func", "hello");
   36.43 +
   36.44 +var obj = e.eval("({ foo: func })");
   36.45 +e.invokeMethod(obj, "foo", "world");
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/test/script/basic/JDK-8023551.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    37.3 @@ -0,0 +1,2 @@
    37.4 +func: hello
    37.5 +func: world
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/test/script/basic/JDK-8023630.js	Fri Aug 23 16:44:02 2013 +0530
    38.3 @@ -0,0 +1,94 @@
    38.4 +/*
    38.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    38.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    38.7 + * 
    38.8 + * This code is free software; you can redistribute it and/or modify it
    38.9 + * under the terms of the GNU General Public License version 2 only, as
   38.10 + * published by the Free Software Foundation.
   38.11 + * 
   38.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   38.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   38.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   38.15 + * version 2 for more details (a copy is included in the LICENSE file that
   38.16 + * accompanied this code).
   38.17 + * 
   38.18 + * You should have received a copy of the GNU General Public License version
   38.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   38.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   38.21 + * 
   38.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   38.23 + * or visit www.oracle.com if you need additional information or have any
   38.24 + * questions.
   38.25 + */
   38.26 +
   38.27 +/**
   38.28 + * JDK-8023630: Implement Java.super() as the preferred way to call super methods
   38.29 + *
   38.30 + * @test
   38.31 + * @run
   38.32 + */
   38.33 +
   38.34 +var CharArray = Java.type("char[]")
   38.35 +var jString = Java.type("java.lang.String")
   38.36 +var Character = Java.type("java.lang.Character")
   38.37 +
   38.38 +function capitalize(s) {
   38.39 +    if(s instanceof CharArray) {
   38.40 +        return new jString(s).toUpperCase()
   38.41 +    }
   38.42 +    if(s instanceof jString) {
   38.43 +        return s.toUpperCase()
   38.44 +    }
   38.45 +    return Character.toUpperCase(s) // must be int
   38.46 +}
   38.47 +
   38.48 +var sw = new (Java.type("java.io.StringWriter"))
   38.49 +
   38.50 +var FilterWriterAdapter = Java.extend(Java.type("java.io.FilterWriter"))
   38.51 +
   38.52 +var cw = new FilterWriterAdapter(sw) {
   38.53 +    write: function(s, off, len) {
   38.54 +        s = capitalize(s)
   38.55 +        // Must handle overloads by arity
   38.56 +        if(off === undefined) {	
   38.57 +            cw_super.write(s, 0, s.length())
   38.58 +        } else if (typeof s === "string") {
   38.59 +            cw_super.write(s, off, len)
   38.60 +        }
   38.61 +    }
   38.62 +}
   38.63 +var cw_super = Java.super(cw)
   38.64 +
   38.65 +cw.write("abcd")
   38.66 +cw.write("e".charAt(0))
   38.67 +cw.write("fgh".toCharArray())
   38.68 +cw.write("**ijk**", 2, 3)
   38.69 +cw.write("***lmno**".toCharArray(), 3, 4)
   38.70 +cw.flush()
   38.71 +print(sw)
   38.72 +
   38.73 +// Can invoke super for Object methods
   38.74 +print("cw_super has hashCode(): " + (typeof cw_super.hashCode === "function"))
   38.75 +print("cw_super has super equals(): " + (typeof cw_super.equals === "function"))
   38.76 +// Can't invoke super for final methods
   38.77 +print("cw_super has no getClass(): " + (typeof cw_super.getClass === "undefined"))
   38.78 +print("cw_super has no wait(): " + (typeof cw_super.wait === "undefined"))
   38.79 +
   38.80 +var r = new (Java.type("java.lang.Runnable"))(function() {})
   38.81 +var r_super = Java.super(r)
   38.82 +
   38.83 +// Can't invoke super for abstract methods
   38.84 +print("r_super has no run(): " + (typeof r_super.run === "undefined"))
   38.85 +// Interfaces can also invoke super Object methods
   38.86 +print("r_super has hashCode(): " + (typeof r_super.hashCode === "function"))
   38.87 +print("r_super has equals(): " + (typeof r_super.equals === "function"))
   38.88 +// But still can't invoke final methods
   38.89 +print("r_super has no getClass(): " + (typeof r_super.getClass === "undefined"))
   38.90 +print("r_super has no wait(): " + (typeof r_super.wait === "undefined"))
   38.91 +
   38.92 +var name = "write"
   38.93 +print("cw_super can access write through [] getter: " + (typeof cw_super[name] === "function"))
   38.94 +var name = "hashCode"
   38.95 +print("cw_super can access hashCode through [] getter: " + (typeof cw_super[name] === "function"))
   38.96 +var name = "getClass"
   38.97 +print("cw_super can not access getClass through [] getter: " + (typeof cw_super[name] === "undefined"))
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/test/script/basic/JDK-8023630.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    39.3 @@ -0,0 +1,13 @@
    39.4 +ABCDEFGHIJKLMNO
    39.5 +cw_super has hashCode(): true
    39.6 +cw_super has super equals(): true
    39.7 +cw_super has no getClass(): true
    39.8 +cw_super has no wait(): true
    39.9 +r_super has no run(): true
   39.10 +r_super has hashCode(): true
   39.11 +r_super has equals(): true
   39.12 +r_super has no getClass(): true
   39.13 +r_super has no wait(): true
   39.14 +cw_super can access write through [] getter: true
   39.15 +cw_super can access hashCode through [] getter: true
   39.16 +cw_super can not access getClass through [] getter: true
    40.1 --- a/test/script/basic/NASHORN-397.js	Mon Aug 19 19:37:29 2013 +0530
    40.2 +++ b/test/script/basic/NASHORN-397.js	Fri Aug 23 16:44:02 2013 +0530
    40.3 @@ -35,7 +35,10 @@
    40.4      fail("typeof(5).x is not 'number'");
    40.5  }
    40.6  
    40.7 -if (typeof (java.lang.System.out) != 'object') {
    40.8 +// It is function because PrintStream implements Closeable, which is
    40.9 +// marked with @FunctionalInterface. Yes, this means calling a stream
   40.10 +// like "stream()" closes it.
   40.11 +if (typeof (java.lang.System.out) != 'function') {
   40.12      fail("typeof java.lang.System.out is not 'object'");
   40.13  }
   40.14  
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/test/script/basic/circular_proto.js	Fri Aug 23 16:44:02 2013 +0530
    41.3 @@ -0,0 +1,46 @@
    41.4 +/*
    41.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    41.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    41.7 + *
    41.8 + * This code is free software; you can redistribute it and/or modify it
    41.9 + * under the terms of the GNU General Public License version 2 only, as
   41.10 + * published by the Free Software Foundation.
   41.11 + *
   41.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   41.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   41.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   41.15 + * version 2 for more details (a copy is included in the LICENSE file that
   41.16 + * accompanied this code).
   41.17 + *
   41.18 + * You should have received a copy of the GNU General Public License version
   41.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   41.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   41.21 + *
   41.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   41.23 + * or visit www.oracle.com if you need additional information or have any
   41.24 + * questions.
   41.25 + */
   41.26 +
   41.27 +/**
   41.28 + * JDK-8023368: Instance __proto__ property should exist and be writable.
   41.29 + *
   41.30 + * @test
   41.31 + * @run
   41.32 + */
   41.33 +
   41.34 +// check that we cannot create __proto__ cycle
   41.35 +load("nashorn:mozilla_compat.js");
   41.36 +
   41.37 +var obj = {};
   41.38 +var obj2 = Object.create(obj);
   41.39 +
   41.40 +// attempt to create __proto__ cycle
   41.41 +try {
   41.42 +    obj.__proto__ = obj2;
   41.43 +    fail("Should have thrown TypeError");
   41.44 +} catch (e) {
   41.45 +    if (! (e instanceof TypeError)) {
   41.46 +        fail("Expected TypeError, got " + e);
   41.47 +    }
   41.48 +    print(e);
   41.49 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/test/script/basic/circular_proto.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    42.3 @@ -0,0 +1,1 @@
    42.4 +TypeError: Cannot create__proto__ cycle for [object Object]
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/test/script/basic/mirror_proto_assign.js	Fri Aug 23 16:44:02 2013 +0530
    43.3 @@ -0,0 +1,52 @@
    43.4 +/*
    43.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    43.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    43.7 + *
    43.8 + * This code is free software; you can redistribute it and/or modify it
    43.9 + * under the terms of the GNU General Public License version 2 only, as
   43.10 + * published by the Free Software Foundation.
   43.11 + *
   43.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   43.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   43.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   43.15 + * version 2 for more details (a copy is included in the LICENSE file that
   43.16 + * accompanied this code).
   43.17 + *
   43.18 + * You should have received a copy of the GNU General Public License version
   43.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   43.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   43.21 + *
   43.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   43.23 + * or visit www.oracle.com if you need additional information or have any
   43.24 + * questions.
   43.25 + */
   43.26 +
   43.27 +/**
   43.28 + * JDK-8023368: Instance __proto__ property should exist and be writable.
   43.29 + *
   43.30 + * @test
   43.31 + * @run
   43.32 + */
   43.33 +
   43.34 +// check that Object.setPrototypeOf works for mirror objects as well.
   43.35 +
   43.36 +var global = loadWithNewGlobal({
   43.37 +    name: "test",
   43.38 +    script: "var obj = {}; this"
   43.39 +});
   43.40 +
   43.41 +var proto = global.eval("({ foo: 323 })");
   43.42 +
   43.43 +Object.setPrototypeOf(global.obj, proto);
   43.44 +
   43.45 +function func(obj) {
   43.46 +    // check proto inherited value
   43.47 +    print("obj.foo = " + obj.foo);
   43.48 +}
   43.49 +
   43.50 +func(global.obj);
   43.51 +
   43.52 +var newProto = global.eval("({ foo: 'hello' })");
   43.53 +Object.setPrototypeOf(global.obj, newProto);
   43.54 +
   43.55 +func(global.obj);
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/test/script/basic/mirror_proto_assign.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    44.3 @@ -0,0 +1,2 @@
    44.4 +obj.foo = 323
    44.5 +obj.foo = hello
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/test/script/basic/nonextensible_proto_assign.js	Fri Aug 23 16:44:02 2013 +0530
    45.3 @@ -0,0 +1,44 @@
    45.4 +/*
    45.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    45.7 + *
    45.8 + * This code is free software; you can redistribute it and/or modify it
    45.9 + * under the terms of the GNU General Public License version 2 only, as
   45.10 + * published by the Free Software Foundation.
   45.11 + *
   45.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   45.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   45.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   45.15 + * version 2 for more details (a copy is included in the LICENSE file that
   45.16 + * accompanied this code).
   45.17 + *
   45.18 + * You should have received a copy of the GNU General Public License version
   45.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   45.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   45.21 + *
   45.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   45.23 + * or visit www.oracle.com if you need additional information or have any
   45.24 + * questions.
   45.25 + */
   45.26 +
   45.27 +/**
   45.28 + * JDK-8023368: Instance __proto__ property should exist and be writable.
   45.29 + *
   45.30 + * @test
   45.31 + * @run
   45.32 + */
   45.33 +
   45.34 +load("nashorn:mozilla_compat.js")
   45.35 +
   45.36 +// check that we cannot assign to __proto__ of a non-extensible object
   45.37 +try {
   45.38 +    var obj = {}
   45.39 +    Object.preventExtensions(obj);
   45.40 +    obj.__proto__ = { };
   45.41 +    fail("Should have thrown TypeError");
   45.42 +} catch (e) {
   45.43 +    if (! (e instanceof TypeError)) {
   45.44 +        fail("Expected TypeError, got " + e);
   45.45 +    }
   45.46 +    print(e);
   45.47 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/test/script/basic/nonextensible_proto_assign.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
    46.3 @@ -0,0 +1,1 @@
    46.4 +TypeError: Cannot set __proto__ of non-extensible [object Object]
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/test/src/jdk/nashorn/api/scripting/InvocableTest.java	Fri Aug 23 16:44:02 2013 +0530
    47.3 @@ -0,0 +1,525 @@
    47.4 +/*
    47.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    47.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    47.7 + *
    47.8 + * This code is free software; you can redistribute it and/or modify it
    47.9 + * under the terms of the GNU General Public License version 2 only, as
   47.10 + * published by the Free Software Foundation.  Oracle designates this
   47.11 + * particular file as subject to the "Classpath" exception as provided
   47.12 + * by Oracle in the LICENSE file that accompanied this code.
   47.13 + *
   47.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   47.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   47.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   47.17 + * version 2 for more details (a copy is included in the LICENSE file that
   47.18 + * accompanied this code).
   47.19 + *
   47.20 + * You should have received a copy of the GNU General Public License version
   47.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   47.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   47.23 + *
   47.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   47.25 + * or visit www.oracle.com if you need additional information or have any
   47.26 + * questions.
   47.27 + */
   47.28 +
   47.29 +package jdk.nashorn.api.scripting;
   47.30 +
   47.31 +import java.util.Objects;
   47.32 +import javax.script.Invocable;
   47.33 +import javax.script.ScriptContext;
   47.34 +import javax.script.ScriptEngine;
   47.35 +import javax.script.ScriptEngineManager;
   47.36 +import javax.script.ScriptException;
   47.37 +import javax.script.SimpleScriptContext;
   47.38 +import org.testng.Assert;
   47.39 +import static org.testng.Assert.assertEquals;
   47.40 +import static org.testng.Assert.fail;
   47.41 +import org.testng.annotations.Test;
   47.42 +
   47.43 +/**
   47.44 + * Tests for javax.script.Invocable implementation of nashorn.
   47.45 + */
   47.46 +public class InvocableTest {
   47.47 +
   47.48 +    private void log(String msg) {
   47.49 +        org.testng.Reporter.log(msg, true);
   47.50 +    }
   47.51 +
   47.52 +    @Test
   47.53 +    public void invokeMethodTest() {
   47.54 +        final ScriptEngineManager m = new ScriptEngineManager();
   47.55 +        final ScriptEngine e = m.getEngineByName("nashorn");
   47.56 +
   47.57 +        try {
   47.58 +            e.eval("var Example = function() { this.hello = function() { return 'Hello World!'; };}; myExample = new Example();");
   47.59 +            final Object obj = e.get("myExample");
   47.60 +            final Object res = ((Invocable) e).invokeMethod(obj, "hello");
   47.61 +            assertEquals(res, "Hello World!");
   47.62 +        } catch (final Exception exp) {
   47.63 +            exp.printStackTrace();
   47.64 +            fail(exp.getMessage());
   47.65 +        }
   47.66 +    }
   47.67 +
   47.68 +    @Test
   47.69 +    /**
   47.70 +     * Check that we can call invokeMethod on an object that we got by
   47.71 +     * evaluating script with different Context set.
   47.72 +     */
   47.73 +    public void invokeMethodDifferentContextTest() {
   47.74 +        ScriptEngineManager m = new ScriptEngineManager();
   47.75 +        ScriptEngine e = m.getEngineByName("nashorn");
   47.76 +
   47.77 +        try {
   47.78 +            // define an object with method on it
   47.79 +            Object obj = e.eval("({ hello: function() { return 'Hello World!'; } })");
   47.80 +
   47.81 +            final ScriptContext ctxt = new SimpleScriptContext();
   47.82 +            ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
   47.83 +            e.setContext(ctxt);
   47.84 +
   47.85 +            // invoke 'func' on obj - but with current script context changed
   47.86 +            final Object res = ((Invocable) e).invokeMethod(obj, "hello");
   47.87 +            assertEquals(res, "Hello World!");
   47.88 +        } catch (final Exception exp) {
   47.89 +            exp.printStackTrace();
   47.90 +            fail(exp.getMessage());
   47.91 +        }
   47.92 +    }
   47.93 +
   47.94 +    @Test
   47.95 +    /**
   47.96 +     * Check that invokeMethod throws NPE on null method name.
   47.97 +     */
   47.98 +    public void invokeMethodNullNameTest() {
   47.99 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.100 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.101 +
  47.102 +        try {
  47.103 +            final Object obj = e.eval("({})");
  47.104 +            final Object res = ((Invocable) e).invokeMethod(obj, null);
  47.105 +            fail("should have thrown NPE");
  47.106 +        } catch (final Exception exp) {
  47.107 +            if (!(exp instanceof NullPointerException)) {
  47.108 +                exp.printStackTrace();
  47.109 +                fail(exp.getMessage());
  47.110 +            }
  47.111 +        }
  47.112 +    }
  47.113 +
  47.114 +    @Test
  47.115 +    /**
  47.116 +     * Check that invokeMethod throws NoSuchMethodException on missing method.
  47.117 +     */
  47.118 +    public void invokeMethodMissingTest() {
  47.119 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.120 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.121 +
  47.122 +        try {
  47.123 +            final Object obj = e.eval("({})");
  47.124 +            final Object res = ((Invocable) e).invokeMethod(obj, "nonExistentMethod");
  47.125 +            fail("should have thrown NoSuchMethodException");
  47.126 +        } catch (final Exception exp) {
  47.127 +            if (!(exp instanceof NoSuchMethodException)) {
  47.128 +                exp.printStackTrace();
  47.129 +                fail(exp.getMessage());
  47.130 +            }
  47.131 +        }
  47.132 +    }
  47.133 +
  47.134 +    @Test
  47.135 +    /**
  47.136 +     * Check that calling method on non-script object 'thiz' results in
  47.137 +     * IllegalArgumentException.
  47.138 +     */
  47.139 +    public void invokeMethodNonScriptObjectThizTest() {
  47.140 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.141 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.142 +
  47.143 +        try {
  47.144 +            ((Invocable) e).invokeMethod(new Object(), "toString");
  47.145 +            fail("should have thrown IllegalArgumentException");
  47.146 +        } catch (final Exception exp) {
  47.147 +            if (!(exp instanceof IllegalArgumentException)) {
  47.148 +                exp.printStackTrace();
  47.149 +                fail(exp.getMessage());
  47.150 +            }
  47.151 +        }
  47.152 +    }
  47.153 +
  47.154 +    @Test
  47.155 +    /**
  47.156 +     * Check that calling method on null 'thiz' results in
  47.157 +     * IllegalArgumentException.
  47.158 +     */
  47.159 +    public void invokeMethodNullThizTest() {
  47.160 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.161 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.162 +
  47.163 +        try {
  47.164 +            ((Invocable) e).invokeMethod(null, "toString");
  47.165 +            fail("should have thrown IllegalArgumentException");
  47.166 +        } catch (final Exception exp) {
  47.167 +            if (!(exp instanceof IllegalArgumentException)) {
  47.168 +                exp.printStackTrace();
  47.169 +                fail(exp.getMessage());
  47.170 +            }
  47.171 +        }
  47.172 +    }
  47.173 +
  47.174 +    @Test
  47.175 +    /**
  47.176 +     * Check that calling method on mirror created by another engine results in
  47.177 +     * IllegalArgumentException.
  47.178 +     */
  47.179 +    public void invokeMethodMixEnginesTest() {
  47.180 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.181 +        final ScriptEngine engine1 = m.getEngineByName("nashorn");
  47.182 +        final ScriptEngine engine2 = m.getEngineByName("nashorn");
  47.183 +
  47.184 +        try {
  47.185 +            Object obj = engine1.eval("({ run: function() {} })");
  47.186 +            // pass object from engine1 to engine2 as 'thiz' for invokeMethod
  47.187 +            ((Invocable) engine2).invokeMethod(obj, "run");
  47.188 +            fail("should have thrown IllegalArgumentException");
  47.189 +        } catch (final Exception exp) {
  47.190 +            if (!(exp instanceof IllegalArgumentException)) {
  47.191 +                exp.printStackTrace();
  47.192 +                fail(exp.getMessage());
  47.193 +            }
  47.194 +        }
  47.195 +    }
  47.196 +
  47.197 +    @Test
  47.198 +    public void getInterfaceTest() {
  47.199 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.200 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.201 +        final Invocable inv = (Invocable) e;
  47.202 +
  47.203 +        // try to get interface from global functions
  47.204 +        try {
  47.205 +            e.eval("function run() { print('run'); };");
  47.206 +            final Runnable runnable = inv.getInterface(Runnable.class);
  47.207 +            runnable.run();
  47.208 +        } catch (final Exception exp) {
  47.209 +            exp.printStackTrace();
  47.210 +            fail(exp.getMessage());
  47.211 +        }
  47.212 +
  47.213 +        // try interface on specific script object
  47.214 +        try {
  47.215 +            e.eval("var obj = { run: function() { print('run from obj'); } };");
  47.216 +            Object obj = e.get("obj");
  47.217 +            final Runnable runnable = inv.getInterface(obj, Runnable.class);
  47.218 +            runnable.run();
  47.219 +        } catch (final Exception exp) {
  47.220 +            exp.printStackTrace();
  47.221 +            fail(exp.getMessage());
  47.222 +        }
  47.223 +    }
  47.224 +
  47.225 +    public interface Foo {
  47.226 +
  47.227 +        public void bar();
  47.228 +    }
  47.229 +
  47.230 +    public interface Foo2 extends Foo {
  47.231 +
  47.232 +        public void bar2();
  47.233 +    }
  47.234 +
  47.235 +    @Test
  47.236 +    public void getInterfaceMissingTest() {
  47.237 +        final ScriptEngineManager manager = new ScriptEngineManager();
  47.238 +        final ScriptEngine engine = manager.getEngineByName("nashorn");
  47.239 +
  47.240 +        // don't define any function.
  47.241 +        try {
  47.242 +            engine.eval("");
  47.243 +        } catch (final Exception exp) {
  47.244 +            exp.printStackTrace();
  47.245 +            fail(exp.getMessage());
  47.246 +        }
  47.247 +
  47.248 +        Runnable runnable = ((Invocable) engine).getInterface(Runnable.class);
  47.249 +        if (runnable != null) {
  47.250 +            fail("runnable is not null!");
  47.251 +        }
  47.252 +
  47.253 +        // now define "run"
  47.254 +        try {
  47.255 +            engine.eval("function run() { print('this is run function'); }");
  47.256 +        } catch (final Exception exp) {
  47.257 +            exp.printStackTrace();
  47.258 +            fail(exp.getMessage());
  47.259 +        }
  47.260 +        runnable = ((Invocable) engine).getInterface(Runnable.class);
  47.261 +        // should not return null now!
  47.262 +        runnable.run();
  47.263 +
  47.264 +        // define only one method of "Foo2"
  47.265 +        try {
  47.266 +            engine.eval("function bar() { print('bar function'); }");
  47.267 +        } catch (final Exception exp) {
  47.268 +            exp.printStackTrace();
  47.269 +            fail(exp.getMessage());
  47.270 +        }
  47.271 +
  47.272 +        Foo2 foo2 = ((Invocable) engine).getInterface(Foo2.class);
  47.273 +        if (foo2 != null) {
  47.274 +            throw new RuntimeException("foo2 is not null!");
  47.275 +        }
  47.276 +
  47.277 +        // now define other method of "Foo2"
  47.278 +        try {
  47.279 +            engine.eval("function bar2() { print('bar2 function'); }");
  47.280 +        } catch (final Exception exp) {
  47.281 +            exp.printStackTrace();
  47.282 +            fail(exp.getMessage());
  47.283 +        }
  47.284 +        foo2 = ((Invocable) engine).getInterface(Foo2.class);
  47.285 +        foo2.bar();
  47.286 +        foo2.bar2();
  47.287 +    }
  47.288 +
  47.289 +    @Test
  47.290 +    /**
  47.291 +     * Try passing non-interface Class object for interface implementation.
  47.292 +     */
  47.293 +    public void getNonInterfaceGetInterfaceTest() {
  47.294 +        final ScriptEngineManager manager = new ScriptEngineManager();
  47.295 +        final ScriptEngine engine = manager.getEngineByName("nashorn");
  47.296 +        try {
  47.297 +            log(Objects.toString(((Invocable) engine).getInterface(Object.class)));
  47.298 +            fail("Should have thrown IllegalArgumentException");
  47.299 +        } catch (final Exception exp) {
  47.300 +            if (!(exp instanceof IllegalArgumentException)) {
  47.301 +                fail("IllegalArgumentException expected, got " + exp);
  47.302 +            }
  47.303 +        }
  47.304 +    }
  47.305 +
  47.306 +    @Test
  47.307 +    /**
  47.308 +     * Check that we can get interface out of a script object even after
  47.309 +     * switching to use different ScriptContext.
  47.310 +     */
  47.311 +    public void getInterfaceDifferentContext() {
  47.312 +        ScriptEngineManager m = new ScriptEngineManager();
  47.313 +        ScriptEngine e = m.getEngineByName("nashorn");
  47.314 +        try {
  47.315 +            Object obj = e.eval("({ run: function() { } })");
  47.316 +
  47.317 +            // change script context
  47.318 +            ScriptContext ctxt = new SimpleScriptContext();
  47.319 +            ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
  47.320 +            e.setContext(ctxt);
  47.321 +
  47.322 +            Runnable r = ((Invocable) e).getInterface(obj, Runnable.class);
  47.323 +            r.run();
  47.324 +        } catch (final Exception exp) {
  47.325 +            exp.printStackTrace();
  47.326 +            fail(exp.getMessage());
  47.327 +        }
  47.328 +    }
  47.329 +
  47.330 +    @Test
  47.331 +    /**
  47.332 +     * Check that getInterface on non-script object 'thiz' results in
  47.333 +     * IllegalArgumentException.
  47.334 +     */
  47.335 +    public void getInterfaceNonScriptObjectThizTest() {
  47.336 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.337 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.338 +
  47.339 +        try {
  47.340 +            ((Invocable) e).getInterface(new Object(), Runnable.class);
  47.341 +            fail("should have thrown IllegalArgumentException");
  47.342 +        } catch (final Exception exp) {
  47.343 +            if (!(exp instanceof IllegalArgumentException)) {
  47.344 +                exp.printStackTrace();
  47.345 +                fail(exp.getMessage());
  47.346 +            }
  47.347 +        }
  47.348 +    }
  47.349 +
  47.350 +    @Test
  47.351 +    /**
  47.352 +     * Check that getInterface on null 'thiz' results in
  47.353 +     * IllegalArgumentException.
  47.354 +     */
  47.355 +    public void getInterfaceNullThizTest() {
  47.356 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.357 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.358 +
  47.359 +        try {
  47.360 +            ((Invocable) e).getInterface(null, Runnable.class);
  47.361 +            fail("should have thrown IllegalArgumentException");
  47.362 +        } catch (final Exception exp) {
  47.363 +            if (!(exp instanceof IllegalArgumentException)) {
  47.364 +                exp.printStackTrace();
  47.365 +                fail(exp.getMessage());
  47.366 +            }
  47.367 +        }
  47.368 +    }
  47.369 +
  47.370 +    @Test
  47.371 +    /**
  47.372 +     * Check that calling getInterface on mirror created by another engine
  47.373 +     * results in IllegalArgumentException.
  47.374 +     */
  47.375 +    public void getInterfaceMixEnginesTest() {
  47.376 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.377 +        final ScriptEngine engine1 = m.getEngineByName("nashorn");
  47.378 +        final ScriptEngine engine2 = m.getEngineByName("nashorn");
  47.379 +
  47.380 +        try {
  47.381 +            Object obj = engine1.eval("({ run: function() {} })");
  47.382 +            // pass object from engine1 to engine2 as 'thiz' for getInterface
  47.383 +            ((Invocable) engine2).getInterface(obj, Runnable.class);
  47.384 +            fail("should have thrown IllegalArgumentException");
  47.385 +        } catch (final Exception exp) {
  47.386 +            if (!(exp instanceof IllegalArgumentException)) {
  47.387 +                exp.printStackTrace();
  47.388 +                fail(exp.getMessage());
  47.389 +            }
  47.390 +        }
  47.391 +    }
  47.392 +
  47.393 +    @Test
  47.394 +    /**
  47.395 +     * check that null function name results in NPE.
  47.396 +     */
  47.397 +    public void invokeFunctionNullNameTest() {
  47.398 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.399 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.400 +
  47.401 +        try {
  47.402 +            final Object res = ((Invocable) e).invokeFunction(null);
  47.403 +            fail("should have thrown NPE");
  47.404 +        } catch (final Exception exp) {
  47.405 +            if (!(exp instanceof NullPointerException)) {
  47.406 +                exp.printStackTrace();
  47.407 +                fail(exp.getMessage());
  47.408 +            }
  47.409 +        }
  47.410 +    }
  47.411 +
  47.412 +    @Test
  47.413 +    /**
  47.414 +     * Check that attempt to call missing function results in
  47.415 +     * NoSuchMethodException.
  47.416 +     */
  47.417 +    public void invokeFunctionMissingTest() {
  47.418 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.419 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.420 +
  47.421 +        try {
  47.422 +            final Object res = ((Invocable) e).invokeFunction("NonExistentFunc");
  47.423 +            fail("should have thrown NoSuchMethodException");
  47.424 +        } catch (final Exception exp) {
  47.425 +            if (!(exp instanceof NoSuchMethodException)) {
  47.426 +                exp.printStackTrace();
  47.427 +                fail(exp.getMessage());
  47.428 +            }
  47.429 +        }
  47.430 +    }
  47.431 +
  47.432 +    @Test
  47.433 +    /**
  47.434 +     * Check that invokeFunction calls functions only from current context's
  47.435 +     * Bindings.
  47.436 +     */
  47.437 +    public void invokeFunctionDifferentContextTest() {
  47.438 +        ScriptEngineManager m = new ScriptEngineManager();
  47.439 +        ScriptEngine e = m.getEngineByName("nashorn");
  47.440 +
  47.441 +        try {
  47.442 +            // define an object with method on it
  47.443 +            Object obj = e.eval("function hello() { return 'Hello World!'; }");
  47.444 +            final ScriptContext ctxt = new SimpleScriptContext();
  47.445 +            ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
  47.446 +            // change engine's current context
  47.447 +            e.setContext(ctxt);
  47.448 +
  47.449 +            ((Invocable) e).invokeFunction("hello"); // no 'hello' in new context!
  47.450 +            fail("should have thrown NoSuchMethodException");
  47.451 +        } catch (final Exception exp) {
  47.452 +            if (!(exp instanceof NoSuchMethodException)) {
  47.453 +                exp.printStackTrace();
  47.454 +                fail(exp.getMessage());
  47.455 +            }
  47.456 +        }
  47.457 +    }
  47.458 +
  47.459 +    @Test
  47.460 +    public void invokeFunctionExceptionTest() {
  47.461 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.462 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.463 +        try {
  47.464 +            e.eval("function func() { throw new TypeError(); }");
  47.465 +        } catch (final Throwable t) {
  47.466 +            t.printStackTrace();
  47.467 +            fail(t.getMessage());
  47.468 +        }
  47.469 +
  47.470 +        try {
  47.471 +            ((Invocable) e).invokeFunction("func");
  47.472 +            fail("should have thrown exception");
  47.473 +        } catch (final ScriptException se) {
  47.474 +            // ECMA TypeError property wrapped as a ScriptException
  47.475 +            log("got " + se + " as expected");
  47.476 +        } catch (final Throwable t) {
  47.477 +            t.printStackTrace();
  47.478 +            fail(t.getMessage());
  47.479 +        }
  47.480 +    }
  47.481 +
  47.482 +    @Test
  47.483 +    public void invokeMethodExceptionTest() {
  47.484 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.485 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.486 +        try {
  47.487 +            e.eval("var sobj = {}; sobj.foo = function func() { throw new TypeError(); }");
  47.488 +        } catch (final Throwable t) {
  47.489 +            t.printStackTrace();
  47.490 +            fail(t.getMessage());
  47.491 +        }
  47.492 +
  47.493 +        try {
  47.494 +            final Object sobj = e.get("sobj");
  47.495 +            ((Invocable) e).invokeMethod(sobj, "foo");
  47.496 +            fail("should have thrown exception");
  47.497 +        } catch (final ScriptException se) {
  47.498 +            // ECMA TypeError property wrapped as a ScriptException
  47.499 +            log("got " + se + " as expected");
  47.500 +        } catch (final Throwable t) {
  47.501 +            t.printStackTrace();
  47.502 +            fail(t.getMessage());
  47.503 +        }
  47.504 +    }
  47.505 +
  47.506 +    @Test
  47.507 +    /**
  47.508 +     * Tests whether invocation of a JavaScript method through a variable arity
  47.509 +     * Java method will pass the vararg array. Both non-vararg and vararg
  47.510 +     * JavaScript methods are tested.
  47.511 +     *
  47.512 +     * @throws ScriptException
  47.513 +     */
  47.514 +    public void variableArityInterfaceTest() throws ScriptException {
  47.515 +        final ScriptEngineManager m = new ScriptEngineManager();
  47.516 +        final ScriptEngine e = m.getEngineByName("nashorn");
  47.517 +        e.eval(
  47.518 +                "function test1(i, strings) {"
  47.519 +                + "    return 'i == ' + i + ', strings instanceof java.lang.String[] == ' + (strings instanceof Java.type('java.lang.String[]')) + ', strings == ' + java.util.Arrays.toString(strings)"
  47.520 +                + "}"
  47.521 +                + "function test2() {"
  47.522 +                + "    return 'arguments[0] == ' + arguments[0] + ', arguments[1] instanceof java.lang.String[] == ' + (arguments[1] instanceof Java.type('java.lang.String[]')) + ', arguments[1] == ' + java.util.Arrays.toString(arguments[1])"
  47.523 +                + "}");
  47.524 +        final VariableArityTestInterface itf = ((Invocable) e).getInterface(VariableArityTestInterface.class);
  47.525 +        Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
  47.526 +        Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
  47.527 +    }
  47.528 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Fri Aug 23 16:44:02 2013 +0530
    48.3 @@ -0,0 +1,248 @@
    48.4 +/*
    48.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    48.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    48.7 + *
    48.8 + * This code is free software; you can redistribute it and/or modify it
    48.9 + * under the terms of the GNU General Public License version 2 only, as
   48.10 + * published by the Free Software Foundation.  Oracle designates this
   48.11 + * particular file as subject to the "Classpath" exception as provided
   48.12 + * by Oracle in the LICENSE file that accompanied this code.
   48.13 + *
   48.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   48.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   48.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   48.17 + * version 2 for more details (a copy is included in the LICENSE file that
   48.18 + * accompanied this code).
   48.19 + *
   48.20 + * You should have received a copy of the GNU General Public License version
   48.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   48.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   48.23 + *
   48.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   48.25 + * or visit www.oracle.com if you need additional information or have any
   48.26 + * questions.
   48.27 + */
   48.28 +package jdk.nashorn.api.scripting;
   48.29 +
   48.30 +import javax.script.Bindings;
   48.31 +import javax.script.ScriptContext;
   48.32 +import javax.script.ScriptEngine;
   48.33 +import javax.script.ScriptEngineManager;
   48.34 +import javax.script.ScriptException;
   48.35 +import javax.script.SimpleBindings;
   48.36 +import javax.script.SimpleScriptContext;
   48.37 +import org.testng.Assert;
   48.38 +import static org.testng.Assert.assertEquals;
   48.39 +import static org.testng.Assert.assertNotNull;
   48.40 +import static org.testng.Assert.assertTrue;
   48.41 +import static org.testng.Assert.fail;
   48.42 +import org.testng.annotations.Test;
   48.43 +
   48.44 +/**
   48.45 + * Tests for jsr223 Bindings "scope" (engine, global scopes)
   48.46 + */
   48.47 +public class ScopeTest {
   48.48 +
   48.49 +    @Test
   48.50 +    public void createBindingsTest() {
   48.51 +        final ScriptEngineManager m = new ScriptEngineManager();
   48.52 +        final ScriptEngine e = m.getEngineByName("nashorn");
   48.53 +        Bindings b = e.createBindings();
   48.54 +        b.put("foo", 42.0);
   48.55 +        Object res = null;
   48.56 +        try {
   48.57 +            res = e.eval("foo == 42.0", b);
   48.58 +        } catch (final ScriptException | NullPointerException se) {
   48.59 +            se.printStackTrace();
   48.60 +            fail(se.getMessage());
   48.61 +        }
   48.62 +
   48.63 +        assertEquals(res, Boolean.TRUE);
   48.64 +    }
   48.65 +
   48.66 +    @Test
   48.67 +    public void engineScopeTest() {
   48.68 +        final ScriptEngineManager m = new ScriptEngineManager();
   48.69 +        final ScriptEngine e = m.getEngineByName("nashorn");
   48.70 +        Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
   48.71 +
   48.72 +        // check few ECMA standard built-in global properties
   48.73 +        assertNotNull(engineScope.get("Object"));
   48.74 +        assertNotNull(engineScope.get("TypeError"));
   48.75 +        assertNotNull(engineScope.get("eval"));
   48.76 +
   48.77 +        // can access via ScriptEngine.get as well
   48.78 +        assertNotNull(e.get("Object"));
   48.79 +        assertNotNull(e.get("TypeError"));
   48.80 +        assertNotNull(e.get("eval"));
   48.81 +
   48.82 +        // Access by either way should return same object
   48.83 +        assertEquals(engineScope.get("Array"), e.get("Array"));
   48.84 +        assertEquals(engineScope.get("EvalError"), e.get("EvalError"));
   48.85 +        assertEquals(engineScope.get("undefined"), e.get("undefined"));
   48.86 +
   48.87 +        // try exposing a new variable from scope
   48.88 +        engineScope.put("myVar", "foo");
   48.89 +        try {
   48.90 +            assertEquals(e.eval("myVar"), "foo");
   48.91 +        } catch (final ScriptException se) {
   48.92 +            se.printStackTrace();
   48.93 +            fail(se.getMessage());
   48.94 +        }
   48.95 +
   48.96 +        // update "myVar" in script an check the value from scope
   48.97 +        try {
   48.98 +            e.eval("myVar = 'nashorn';");
   48.99 +        } catch (final ScriptException se) {
  48.100 +            se.printStackTrace();
  48.101 +            fail(se.getMessage());
  48.102 +        }
  48.103 +
  48.104 +        // now check modified value from scope and engine
  48.105 +        assertEquals(engineScope.get("myVar"), "nashorn");
  48.106 +        assertEquals(e.get("myVar"), "nashorn");
  48.107 +    }
  48.108 +
  48.109 +    @Test
  48.110 +    public void multiGlobalTest() {
  48.111 +        final ScriptEngineManager m = new ScriptEngineManager();
  48.112 +        final ScriptEngine e = m.getEngineByName("nashorn");
  48.113 +        final Bindings b = e.createBindings();
  48.114 +        final ScriptContext newCtxt = new SimpleScriptContext();
  48.115 +        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
  48.116 +
  48.117 +        try {
  48.118 +            Object obj1 = e.eval("Object");
  48.119 +            Object obj2 = e.eval("Object", newCtxt);
  48.120 +            Assert.assertNotEquals(obj1, obj2);
  48.121 +            Assert.assertNotNull(obj1);
  48.122 +            Assert.assertNotNull(obj2);
  48.123 +            Assert.assertEquals(obj1.toString(), obj2.toString());
  48.124 +
  48.125 +            e.eval("x = 'hello'");
  48.126 +            e.eval("x = 'world'", newCtxt);
  48.127 +            Object x1 = e.getContext().getAttribute("x");
  48.128 +            Object x2 = newCtxt.getAttribute("x");
  48.129 +            Assert.assertNotEquals(x1, x2);
  48.130 +            Assert.assertEquals(x1, "hello");
  48.131 +            Assert.assertEquals(x2, "world");
  48.132 +
  48.133 +            x1 = e.eval("x");
  48.134 +            x2 = e.eval("x", newCtxt);
  48.135 +            Assert.assertNotEquals(x1, x2);
  48.136 +            Assert.assertEquals(x1, "hello");
  48.137 +            Assert.assertEquals(x2, "world");
  48.138 +
  48.139 +            final ScriptContext origCtxt = e.getContext();
  48.140 +            e.setContext(newCtxt);
  48.141 +            e.eval("y = new Object()");
  48.142 +            e.eval("y = new Object()", origCtxt);
  48.143 +
  48.144 +            Object y1 = origCtxt.getAttribute("y");
  48.145 +            Object y2 = newCtxt.getAttribute("y");
  48.146 +            Assert.assertNotEquals(y1, y2);
  48.147 +            Assert.assertNotEquals(e.eval("y"), e.eval("y", origCtxt));
  48.148 +            Assert.assertEquals("[object Object]", y1.toString());
  48.149 +            Assert.assertEquals("[object Object]", y2.toString());
  48.150 +        } catch (final ScriptException se) {
  48.151 +            se.printStackTrace();
  48.152 +            fail(se.getMessage());
  48.153 +        }
  48.154 +    }
  48.155 +
  48.156 +    @Test
  48.157 +    public void userEngineScopeBindingsTest() throws ScriptException {
  48.158 +        final ScriptEngineManager m = new ScriptEngineManager();
  48.159 +        final ScriptEngine e = m.getEngineByName("nashorn");
  48.160 +        e.eval("function func() {}");
  48.161 +
  48.162 +        final ScriptContext newContext = new SimpleScriptContext();
  48.163 +        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
  48.164 +        // we are using a new bindings - so it should have 'func' defined
  48.165 +        Object value = e.eval("typeof func", newContext);
  48.166 +        assertTrue(value.equals("undefined"));
  48.167 +    }
  48.168 +
  48.169 +    @Test
  48.170 +    public void userEngineScopeBindingsNoLeakTest() throws ScriptException {
  48.171 +        final ScriptEngineManager m = new ScriptEngineManager();
  48.172 +        final ScriptEngine e = m.getEngineByName("nashorn");
  48.173 +        final ScriptContext newContext = new SimpleScriptContext();
  48.174 +        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
  48.175 +        e.eval("function foo() {}", newContext);
  48.176 +
  48.177 +        // in the default context's ENGINE_SCOPE, 'foo' shouldn't exist
  48.178 +        assertTrue(e.eval("typeof foo").equals("undefined"));
  48.179 +    }
  48.180 +
  48.181 +    @Test
  48.182 +    public void userEngineScopeBindingsRetentionTest() throws ScriptException {
  48.183 +        final ScriptEngineManager m = new ScriptEngineManager();
  48.184 +        final ScriptEngine e = m.getEngineByName("nashorn");
  48.185 +        final ScriptContext newContext = new SimpleScriptContext();
  48.186 +        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
  48.187 +        e.eval("function foo() {}", newContext);
  48.188 +
  48.189 +        // definition retained with user's ENGINE_SCOPE Binding
  48.190 +        assertTrue(e.eval("typeof foo", newContext).equals("function"));
  48.191 +
  48.192 +        final Bindings oldBindings = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
  48.193 +        // but not in another ENGINE_SCOPE binding
  48.194 +        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
  48.195 +        assertTrue(e.eval("typeof foo", newContext).equals("undefined"));
  48.196 +
  48.197 +        // restore ENGINE_SCOPE and check again
  48.198 +        newContext.setBindings(oldBindings, ScriptContext.ENGINE_SCOPE);
  48.199 +        assertTrue(e.eval("typeof foo", newContext).equals("function"));
  48.200 +    }
  48.201 +
  48.202 +    @Test
  48.203 +    // check that engine.js definitions are visible in all new global instances
  48.204 +    public void checkBuiltinsInNewBindingsTest() throws ScriptException {
  48.205 +        final ScriptEngineManager m = new ScriptEngineManager();
  48.206 +        final ScriptEngine e = m.getEngineByName("nashorn");
  48.207 +
  48.208 +        // check default global instance has engine.js definitions
  48.209 +        final Bindings g = (Bindings) e.eval("this");
  48.210 +        Object value = g.get("__noSuchProperty__");
  48.211 +        assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
  48.212 +        value = g.get("print");
  48.213 +        assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
  48.214 +
  48.215 +        // check new global instance created has engine.js definitions
  48.216 +        Bindings b = e.createBindings();
  48.217 +        value = b.get("__noSuchProperty__");
  48.218 +        assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
  48.219 +        value = b.get("print");
  48.220 +        assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
  48.221 +
  48.222 +        // put a mapping into GLOBAL_SCOPE
  48.223 +        final Bindings globalScope = e.getContext().getBindings(ScriptContext.GLOBAL_SCOPE);
  48.224 +        globalScope.put("x", "hello");
  48.225 +
  48.226 +        // GLOBAL_SCOPE mapping should be visible from default ScriptContext eval
  48.227 +        assertTrue(e.eval("x").equals("hello"));
  48.228 +
  48.229 +        final ScriptContext ctx = new SimpleScriptContext();
  48.230 +        ctx.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
  48.231 +        ctx.setBindings(b, ScriptContext.ENGINE_SCOPE);
  48.232 +
  48.233 +        // GLOBAL_SCOPE mapping should be visible from non-default ScriptContext eval
  48.234 +        assertTrue(e.eval("x", ctx).equals("hello"));
  48.235 +
  48.236 +        // try some arbitray Bindings for ENGINE_SCOPE
  48.237 +        Bindings sb = new SimpleBindings();
  48.238 +        ctx.setBindings(sb, ScriptContext.ENGINE_SCOPE);
  48.239 +
  48.240 +        // GLOBAL_SCOPE mapping should be visible from non-default ScriptContext eval
  48.241 +        assertTrue(e.eval("x", ctx).equals("hello"));
  48.242 +
  48.243 +        // engine.js builtins are still defined even with arbitrary Bindings
  48.244 +        assertTrue(e.eval("typeof print", ctx).equals("function"));
  48.245 +        assertTrue(e.eval("typeof __noSuchProperty__", ctx).equals("function"));
  48.246 +
  48.247 +        // ENGINE_SCOPE definition should 'hide' GLOBAL_SCOPE definition
  48.248 +        sb.put("x", "newX");
  48.249 +        assertTrue(e.eval("x", ctx).equals("newX"));
  48.250 +    }
  48.251 +}
    49.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Mon Aug 19 19:37:29 2013 +0530
    49.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Fri Aug 23 16:44:02 2013 +0530
    49.3 @@ -26,7 +26,6 @@
    49.4  package jdk.nashorn.api.scripting;
    49.5  
    49.6  import static org.testng.Assert.assertEquals;
    49.7 -import static org.testng.Assert.assertFalse;
    49.8  import static org.testng.Assert.assertNotNull;
    49.9  import static org.testng.Assert.assertTrue;
   49.10  import static org.testng.Assert.fail;
   49.11 @@ -34,21 +33,13 @@
   49.12  import java.io.StringReader;
   49.13  import java.io.StringWriter;
   49.14  import java.lang.reflect.Method;
   49.15 -import java.util.HashMap;
   49.16 -import java.util.Map;
   49.17 -import java.util.Objects;
   49.18  import java.util.concurrent.Callable;
   49.19 -import javax.script.Bindings;
   49.20  import javax.script.Compilable;
   49.21  import javax.script.CompiledScript;
   49.22 -import javax.script.Invocable;
   49.23 -import javax.script.ScriptContext;
   49.24  import javax.script.ScriptEngine;
   49.25  import javax.script.ScriptEngineFactory;
   49.26  import javax.script.ScriptEngineManager;
   49.27  import javax.script.ScriptException;
   49.28 -import javax.script.SimpleScriptContext;
   49.29 -import org.testng.Assert;
   49.30  import org.testng.annotations.Test;
   49.31  
   49.32  /**
   49.33 @@ -239,214 +230,6 @@
   49.34      }
   49.35  
   49.36      @Test
   49.37 -    public void createBindingsTest() {
   49.38 -        final ScriptEngineManager m = new ScriptEngineManager();
   49.39 -        final ScriptEngine e = m.getEngineByName("nashorn");
   49.40 -        Bindings b = e.createBindings();
   49.41 -        b.put("foo", 42.0);
   49.42 -        Object res = null;
   49.43 -        try {
   49.44 -            res = e.eval("foo == 42.0", b);
   49.45 -        } catch (final ScriptException | NullPointerException se) {
   49.46 -            se.printStackTrace();
   49.47 -            fail(se.getMessage());
   49.48 -        }
   49.49 -
   49.50 -        assertEquals(res, Boolean.TRUE);
   49.51 -    }
   49.52 -
   49.53 -    @Test
   49.54 -    public void getInterfaceTest() {
   49.55 -        final ScriptEngineManager m = new ScriptEngineManager();
   49.56 -        final ScriptEngine e = m.getEngineByName("nashorn");
   49.57 -        final Invocable inv = (Invocable)e;
   49.58 -
   49.59 -        // try to get interface from global functions
   49.60 -        try {
   49.61 -            e.eval("function run() { print('run'); };");
   49.62 -            final Runnable runnable = inv.getInterface(Runnable.class);
   49.63 -            runnable.run();
   49.64 -        } catch (final Exception exp) {
   49.65 -            exp.printStackTrace();
   49.66 -            fail(exp.getMessage());
   49.67 -        }
   49.68 -
   49.69 -        // try interface on specific script object
   49.70 -        try {
   49.71 -            e.eval("var obj = { run: function() { print('run from obj'); } };");
   49.72 -            Object obj = e.get("obj");
   49.73 -            final Runnable runnable = inv.getInterface(obj, Runnable.class);
   49.74 -            runnable.run();
   49.75 -        } catch (final Exception exp) {
   49.76 -            exp.printStackTrace();
   49.77 -            fail(exp.getMessage());
   49.78 -        }
   49.79 -    }
   49.80 -
   49.81 -    public interface Foo {
   49.82 -        public void bar();
   49.83 -    }
   49.84 -
   49.85 -    public interface Foo2 extends Foo {
   49.86 -        public void bar2();
   49.87 -    }
   49.88 -
   49.89 -    @Test
   49.90 -    public void getInterfaceMissingTest() {
   49.91 -        final ScriptEngineManager manager = new ScriptEngineManager();
   49.92 -        final ScriptEngine engine = manager.getEngineByName("nashorn");
   49.93 -
   49.94 -        // don't define any function.
   49.95 -        try {
   49.96 -            engine.eval("");
   49.97 -        } catch (final Exception exp) {
   49.98 -            exp.printStackTrace();
   49.99 -            fail(exp.getMessage());
  49.100 -        }
  49.101 -
  49.102 -        Runnable runnable = ((Invocable)engine).getInterface(Runnable.class);
  49.103 -        if (runnable != null) {
  49.104 -            fail("runnable is not null!");
  49.105 -        }
  49.106 -
  49.107 -        // now define "run"
  49.108 -        try {
  49.109 -            engine.eval("function run() { print('this is run function'); }");
  49.110 -        } catch (final Exception exp) {
  49.111 -            exp.printStackTrace();
  49.112 -            fail(exp.getMessage());
  49.113 -        }
  49.114 -        runnable = ((Invocable)engine).getInterface(Runnable.class);
  49.115 -        // should not return null now!
  49.116 -        runnable.run();
  49.117 -
  49.118 -        // define only one method of "Foo2"
  49.119 -        try {
  49.120 -            engine.eval("function bar() { print('bar function'); }");
  49.121 -        } catch (final Exception exp) {
  49.122 -            exp.printStackTrace();
  49.123 -            fail(exp.getMessage());
  49.124 -        }
  49.125 -
  49.126 -        Foo2 foo2 = ((Invocable)engine).getInterface(Foo2.class);
  49.127 -        if (foo2 != null) {
  49.128 -            throw new RuntimeException("foo2 is not null!");
  49.129 -        }
  49.130 -
  49.131 -        // now define other method of "Foo2"
  49.132 -        try {
  49.133 -            engine.eval("function bar2() { print('bar2 function'); }");
  49.134 -        } catch (final Exception exp) {
  49.135 -            exp.printStackTrace();
  49.136 -            fail(exp.getMessage());
  49.137 -        }
  49.138 -        foo2 = ((Invocable)engine).getInterface(Foo2.class);
  49.139 -        foo2.bar();
  49.140 -        foo2.bar2();
  49.141 -    }
  49.142 -
  49.143 -    @Test
  49.144 -    /**
  49.145 -     * Try passing non-interface Class object for interface implementation.
  49.146 -     */
  49.147 -    public void getNonInterfaceGetInterfaceTest() {
  49.148 -        final ScriptEngineManager manager = new ScriptEngineManager();
  49.149 -        final ScriptEngine engine = manager.getEngineByName("nashorn");
  49.150 -        try {
  49.151 -            log(Objects.toString(((Invocable)engine).getInterface(Object.class)));
  49.152 -            fail("Should have thrown IllegalArgumentException");
  49.153 -        } catch (final Exception exp) {
  49.154 -            if (! (exp instanceof IllegalArgumentException)) {
  49.155 -                fail("IllegalArgumentException expected, got " + exp);
  49.156 -            }
  49.157 -        }
  49.158 -    }
  49.159 -
  49.160 -    @Test
  49.161 -    /**
  49.162 -     * Check that we can get interface out of a script object even after
  49.163 -     * switching to use different ScriptContext.
  49.164 -     */
  49.165 -    public void getInterfaceDifferentContext() {
  49.166 -       ScriptEngineManager m = new ScriptEngineManager();
  49.167 -       ScriptEngine e = m.getEngineByName("nashorn");
  49.168 -       try {
  49.169 -           Object obj = e.eval("({ run: function() { } })");
  49.170 -
  49.171 -           // change script context
  49.172 -           ScriptContext ctxt = new SimpleScriptContext();
  49.173 -           ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
  49.174 -           e.setContext(ctxt);
  49.175 -
  49.176 -           Runnable r = ((Invocable)e).getInterface(obj, Runnable.class);
  49.177 -           r.run();
  49.178 -       }catch (final Exception exp) {
  49.179 -            exp.printStackTrace();
  49.180 -            fail(exp.getMessage());
  49.181 -       }
  49.182 -    }
  49.183 -
  49.184 -    @Test
  49.185 -    /**
  49.186 -     * Check that getInterface on non-script object 'thiz' results in IllegalArgumentException.
  49.187 -     */
  49.188 -    public void getInterfaceNonScriptObjectThizTest() {
  49.189 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.190 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.191 -
  49.192 -        try {
  49.193 -            ((Invocable)e).getInterface(new Object(), Runnable.class);
  49.194 -            fail("should have thrown IllegalArgumentException");
  49.195 -        } catch (final Exception exp) {
  49.196 -            if (! (exp instanceof IllegalArgumentException)) {
  49.197 -                exp.printStackTrace();
  49.198 -                fail(exp.getMessage());
  49.199 -            }
  49.200 -        }
  49.201 -    }
  49.202 -
  49.203 -    @Test
  49.204 -    /**
  49.205 -     * Check that getInterface on null 'thiz' results in IllegalArgumentException.
  49.206 -     */
  49.207 -    public void getInterfaceNullThizTest() {
  49.208 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.209 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.210 -
  49.211 -        try {
  49.212 -            ((Invocable)e).getInterface(null, Runnable.class);
  49.213 -            fail("should have thrown IllegalArgumentException");
  49.214 -        } catch (final Exception exp) {
  49.215 -            if (! (exp instanceof IllegalArgumentException)) {
  49.216 -                exp.printStackTrace();
  49.217 -                fail(exp.getMessage());
  49.218 -            }
  49.219 -        }
  49.220 -    }
  49.221 -
  49.222 -    @Test
  49.223 -    /**
  49.224 -     * Check that calling getInterface on mirror created by another engine results in IllegalArgumentException.
  49.225 -     */
  49.226 -    public void getInterfaceMixEnginesTest() {
  49.227 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.228 -        final ScriptEngine engine1 = m.getEngineByName("nashorn");
  49.229 -        final ScriptEngine engine2 = m.getEngineByName("nashorn");
  49.230 -
  49.231 -        try {
  49.232 -            Object obj = engine1.eval("({ run: function() {} })");
  49.233 -            // pass object from engine1 to engine2 as 'thiz' for getInterface
  49.234 -            ((Invocable)engine2).getInterface(obj, Runnable.class);
  49.235 -            fail("should have thrown IllegalArgumentException");
  49.236 -        } catch (final Exception exp) {
  49.237 -            if (! (exp instanceof IllegalArgumentException)) {
  49.238 -                exp.printStackTrace();
  49.239 -                fail(exp.getMessage());
  49.240 -            }
  49.241 -        }
  49.242 -    }
  49.243 -
  49.244 -    @Test
  49.245      public void accessGlobalTest() {
  49.246          final ScriptEngineManager m = new ScriptEngineManager();
  49.247          final ScriptEngine e = m.getEngineByName("nashorn");
  49.248 @@ -621,88 +404,6 @@
  49.249          assertEquals(sw.toString().replaceAll("\r", ""), "hello world\n");
  49.250      }
  49.251  
  49.252 -    @SuppressWarnings("unchecked")
  49.253 -    @Test
  49.254 -    public void reflectionTest() throws ScriptException {
  49.255 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.256 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.257 -
  49.258 -        e.eval("var obj = { x: 344, y: 'nashorn' }");
  49.259 -
  49.260 -        int count = 0;
  49.261 -        Map<Object, Object> map = (Map<Object, Object>)e.get("obj");
  49.262 -        assertFalse(map.isEmpty());
  49.263 -        assertTrue(map.keySet().contains("x"));
  49.264 -        assertTrue(map.containsKey("x"));
  49.265 -        assertTrue(map.values().contains("nashorn"));
  49.266 -        assertTrue(map.containsValue("nashorn"));
  49.267 -        for (final Map.Entry<?, ?> ex : map.entrySet()) {
  49.268 -            final Object key = ex.getKey();
  49.269 -            if (key.equals("x")) {
  49.270 -                assertTrue(344 == ((Number)ex.getValue()).doubleValue());
  49.271 -                count++;
  49.272 -            } else if (key.equals("y")) {
  49.273 -                assertEquals(ex.getValue(), "nashorn");
  49.274 -                count++;
  49.275 -            }
  49.276 -        }
  49.277 -        assertEquals(2, count);
  49.278 -        assertEquals(2, map.size());
  49.279 -
  49.280 -        // add property
  49.281 -        map.put("z", "hello");
  49.282 -        assertEquals(e.eval("obj.z"), "hello");
  49.283 -        assertEquals(map.get("z"), "hello");
  49.284 -        assertTrue(map.keySet().contains("z"));
  49.285 -        assertTrue(map.containsKey("z"));
  49.286 -        assertTrue(map.values().contains("hello"));
  49.287 -        assertTrue(map.containsValue("hello"));
  49.288 -        assertEquals(map.size(), 3);
  49.289 -
  49.290 -        final Map<Object, Object> newMap = new HashMap<>();
  49.291 -        newMap.put("foo", 23.0);
  49.292 -        newMap.put("bar", true);
  49.293 -        map.putAll(newMap);
  49.294 -
  49.295 -        assertEquals(e.eval("obj.foo"), 23.0);
  49.296 -        assertEquals(e.eval("obj.bar"), true);
  49.297 -
  49.298 -        // remove using map method
  49.299 -        map.remove("foo");
  49.300 -        assertEquals(e.eval("typeof obj.foo"), "undefined");
  49.301 -
  49.302 -        count = 0;
  49.303 -        e.eval("var arr = [ true, 'hello' ]");
  49.304 -        map = (Map<Object, Object>)e.get("arr");
  49.305 -        assertFalse(map.isEmpty());
  49.306 -        assertTrue(map.containsKey("length"));
  49.307 -        assertTrue(map.containsValue("hello"));
  49.308 -        for (final Map.Entry<?, ?> ex : map.entrySet()) {
  49.309 -            final Object key = ex.getKey();
  49.310 -            if (key.equals("0")) {
  49.311 -                assertEquals(ex.getValue(), Boolean.TRUE);
  49.312 -                count++;
  49.313 -            } else if (key.equals("1")) {
  49.314 -                assertEquals(ex.getValue(), "hello");
  49.315 -                count++;
  49.316 -            }
  49.317 -        }
  49.318 -        assertEquals(count, 2);
  49.319 -        assertEquals(map.size(), 2);
  49.320 -
  49.321 -        // add element
  49.322 -        map.put("2", "world");
  49.323 -        assertEquals(map.get("2"), "world");
  49.324 -        assertEquals(map.size(), 3);
  49.325 -
  49.326 -        // remove all
  49.327 -        map.clear();
  49.328 -        assertTrue(map.isEmpty());
  49.329 -        assertEquals(e.eval("typeof arr[0]"), "undefined");
  49.330 -        assertEquals(e.eval("typeof arr[1]"), "undefined");
  49.331 -        assertEquals(e.eval("typeof arr[2]"), "undefined");
  49.332 -    }
  49.333 -
  49.334      @Test
  49.335      public void redefineEchoTest() {
  49.336          final ScriptEngineManager m = new ScriptEngineManager();
  49.337 @@ -715,150 +416,6 @@
  49.338              fail(exp.getMessage());
  49.339          }
  49.340      }
  49.341 -
  49.342 -    @Test
  49.343 -    public void invokeMethodTest() {
  49.344 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.345 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.346 -
  49.347 -        try {
  49.348 -            e.eval("var Example = function() { this.hello = function() { return 'Hello World!'; };}; myExample = new Example();");
  49.349 -            final Object obj = e.get("myExample");
  49.350 -            final Object res = ((Invocable)e).invokeMethod(obj, "hello");
  49.351 -            assertEquals(res, "Hello World!");
  49.352 -        } catch (final Exception exp) {
  49.353 -            exp.printStackTrace();
  49.354 -            fail(exp.getMessage());
  49.355 -        }
  49.356 -    }
  49.357 -
  49.358 -    @Test
  49.359 -    /**
  49.360 -     * Check that we can call invokeMethod on an object that we got by evaluating
  49.361 -     * script with different Context set.
  49.362 -     */
  49.363 -    public void invokeMethodDifferentContextTest() {
  49.364 -       ScriptEngineManager m = new ScriptEngineManager();
  49.365 -       ScriptEngine e = m.getEngineByName("nashorn");
  49.366 -
  49.367 -       try {
  49.368 -           // define an object with method on it
  49.369 -           Object obj = e.eval("({ hello: function() { return 'Hello World!'; } })");
  49.370 -
  49.371 -           final ScriptContext ctxt = new SimpleScriptContext();
  49.372 -           ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
  49.373 -           e.setContext(ctxt);
  49.374 -
  49.375 -           // invoke 'func' on obj - but with current script context changed
  49.376 -           final Object res = ((Invocable)e).invokeMethod(obj, "hello");
  49.377 -           assertEquals(res, "Hello World!");
  49.378 -       } catch (final Exception exp) {
  49.379 -           exp.printStackTrace();
  49.380 -           fail(exp.getMessage());
  49.381 -       }
  49.382 -    }
  49.383 -
  49.384 -    @Test
  49.385 -    /**
  49.386 -     * Check that invokeMethod throws NPE on null method name.
  49.387 -     */
  49.388 -    public void invokeMethodNullNameTest() {
  49.389 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.390 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.391 -
  49.392 -        try {
  49.393 -            final Object obj = e.eval("({})");
  49.394 -            final Object res = ((Invocable)e).invokeMethod(obj, null);
  49.395 -            fail("should have thrown NPE");
  49.396 -        } catch (final Exception exp) {
  49.397 -            if (! (exp instanceof NullPointerException)) {
  49.398 -                exp.printStackTrace();
  49.399 -                fail(exp.getMessage());
  49.400 -            }
  49.401 -        }
  49.402 -    }
  49.403 -
  49.404 -    @Test
  49.405 -    /**
  49.406 -     * Check that invokeMethod throws NoSuchMethodException on missing method.
  49.407 -     */
  49.408 -    public void invokeMethodMissingTest() {
  49.409 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.410 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.411 -
  49.412 -        try {
  49.413 -            final Object obj = e.eval("({})");
  49.414 -            final Object res = ((Invocable)e).invokeMethod(obj, "nonExistentMethod");
  49.415 -            fail("should have thrown NoSuchMethodException");
  49.416 -        } catch (final Exception exp) {
  49.417 -            if (! (exp instanceof NoSuchMethodException)) {
  49.418 -                exp.printStackTrace();
  49.419 -                fail(exp.getMessage());
  49.420 -            }
  49.421 -        }
  49.422 -    }
  49.423 -
  49.424 -    @Test
  49.425 -    /**
  49.426 -     * Check that calling method on non-script object 'thiz' results in IllegalArgumentException.
  49.427 -     */
  49.428 -    public void invokeMethodNonScriptObjectThizTest() {
  49.429 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.430 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.431 -
  49.432 -        try {
  49.433 -            ((Invocable)e).invokeMethod(new Object(), "toString");
  49.434 -            fail("should have thrown IllegalArgumentException");
  49.435 -        } catch (final Exception exp) {
  49.436 -            if (! (exp instanceof IllegalArgumentException)) {
  49.437 -                exp.printStackTrace();
  49.438 -                fail(exp.getMessage());
  49.439 -            }
  49.440 -        }
  49.441 -    }
  49.442 -
  49.443 -    @Test
  49.444 -    /**
  49.445 -     * Check that calling method on null 'thiz' results in IllegalArgumentException.
  49.446 -     */
  49.447 -    public void invokeMethodNullThizTest() {
  49.448 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.449 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.450 -
  49.451 -        try {
  49.452 -            ((Invocable)e).invokeMethod(null, "toString");
  49.453 -            fail("should have thrown IllegalArgumentException");
  49.454 -        } catch (final Exception exp) {
  49.455 -            if (! (exp instanceof IllegalArgumentException)) {
  49.456 -                exp.printStackTrace();
  49.457 -                fail(exp.getMessage());
  49.458 -            }
  49.459 -        }
  49.460 -    }
  49.461 -
  49.462 -
  49.463 -    @Test
  49.464 -    /**
  49.465 -     * Check that calling method on mirror created by another engine results in IllegalArgumentException.
  49.466 -     */
  49.467 -    public void invokeMethodMixEnginesTest() {
  49.468 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.469 -        final ScriptEngine engine1 = m.getEngineByName("nashorn");
  49.470 -        final ScriptEngine engine2 = m.getEngineByName("nashorn");
  49.471 -
  49.472 -        try {
  49.473 -            Object obj = engine1.eval("({ run: function() {} })");
  49.474 -            // pass object from engine1 to engine2 as 'thiz' for invokeMethod
  49.475 -            ((Invocable)engine2).invokeMethod(obj, "run");
  49.476 -            fail("should have thrown IllegalArgumentException");
  49.477 -        } catch (final Exception exp) {
  49.478 -            if (! (exp instanceof IllegalArgumentException)) {
  49.479 -                exp.printStackTrace();
  49.480 -                fail(exp.getMessage());
  49.481 -            }
  49.482 -        }
  49.483 -    }
  49.484 -
  49.485      @Test
  49.486      public void noEnumerablePropertiesTest() {
  49.487          final ScriptEngineManager m = new ScriptEngineManager();
  49.488 @@ -920,308 +477,6 @@
  49.489      }
  49.490  
  49.491      @Test
  49.492 -    public void jsobjectTest() {
  49.493 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.494 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.495 -        try {
  49.496 -            e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }");
  49.497 -            JSObject obj = (JSObject) e.get("obj");
  49.498 -
  49.499 -            // try basic get on existing properties
  49.500 -            if (! obj.getMember("bar").equals("hello")) {
  49.501 -                fail("obj.bar != 'hello'");
  49.502 -            }
  49.503 -
  49.504 -            if (! obj.getSlot(1).equals("world")) {
  49.505 -                fail("obj[1] != 'world'");
  49.506 -            }
  49.507 -
  49.508 -            if (! obj.call("func", new Object[0]).equals("hello")) {
  49.509 -                fail("obj.call('func') != 'hello'");
  49.510 -            }
  49.511 -
  49.512 -            // try setting properties
  49.513 -            obj.setMember("bar", "new-bar");
  49.514 -            obj.setSlot(1, "new-element-1");
  49.515 -            if (! obj.getMember("bar").equals("new-bar")) {
  49.516 -                fail("obj.bar != 'new-bar'");
  49.517 -            }
  49.518 -
  49.519 -            if (! obj.getSlot(1).equals("new-element-1")) {
  49.520 -                fail("obj[1] != 'new-element-1'");
  49.521 -            }
  49.522 -
  49.523 -            // try adding properties
  49.524 -            obj.setMember("prop", "prop-value");
  49.525 -            obj.setSlot(12, "element-12");
  49.526 -            if (! obj.getMember("prop").equals("prop-value")) {
  49.527 -                fail("obj.prop != 'prop-value'");
  49.528 -            }
  49.529 -
  49.530 -            if (! obj.getSlot(12).equals("element-12")) {
  49.531 -                fail("obj[12] != 'element-12'");
  49.532 -            }
  49.533 -
  49.534 -            // delete properties
  49.535 -            obj.removeMember("prop");
  49.536 -            if ("prop-value".equals(obj.getMember("prop"))) {
  49.537 -                fail("obj.prop is not deleted!");
  49.538 -            }
  49.539 -
  49.540 -            // Simple eval tests
  49.541 -            assertEquals(obj.eval("typeof Object"), "function");
  49.542 -            assertEquals(obj.eval("'nashorn'.substring(3)"), "horn");
  49.543 -        } catch (final Exception exp) {
  49.544 -            exp.printStackTrace();
  49.545 -            fail(exp.getMessage());
  49.546 -        }
  49.547 -    }
  49.548 -
  49.549 -    @Test
  49.550 -    /**
  49.551 -     * check that null function name results in NPE.
  49.552 -     */
  49.553 -    public void invokeFunctionNullNameTest() {
  49.554 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.555 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.556 -
  49.557 -        try {
  49.558 -            final Object res = ((Invocable)e).invokeFunction(null);
  49.559 -            fail("should have thrown NPE");
  49.560 -        } catch (final Exception exp) {
  49.561 -            if (! (exp instanceof NullPointerException)) {
  49.562 -                exp.printStackTrace();
  49.563 -                fail(exp.getMessage());
  49.564 -            }
  49.565 -        }
  49.566 -    }
  49.567 -
  49.568 -    @Test
  49.569 -    /**
  49.570 -     * Check that attempt to call missing function results in NoSuchMethodException.
  49.571 -     */
  49.572 -    public void invokeFunctionMissingTest() {
  49.573 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.574 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.575 -
  49.576 -        try {
  49.577 -            final Object res = ((Invocable)e).invokeFunction("NonExistentFunc");
  49.578 -            fail("should have thrown NoSuchMethodException");
  49.579 -        } catch (final Exception exp) {
  49.580 -            if (! (exp instanceof NoSuchMethodException)) {
  49.581 -                exp.printStackTrace();
  49.582 -                fail(exp.getMessage());
  49.583 -            }
  49.584 -        }
  49.585 -    }
  49.586 -
  49.587 -    @Test
  49.588 -    /**
  49.589 -     * Check that invokeFunction calls functions only from current context's Bindings.
  49.590 -     */
  49.591 -    public void invokeFunctionDifferentContextTest() {
  49.592 -        ScriptEngineManager m = new ScriptEngineManager();
  49.593 -        ScriptEngine e = m.getEngineByName("nashorn");
  49.594 -
  49.595 -        try {
  49.596 -            // define an object with method on it
  49.597 -            Object obj = e.eval("function hello() { return 'Hello World!'; }");
  49.598 -            final ScriptContext ctxt = new SimpleScriptContext();
  49.599 -            ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
  49.600 -            // change engine's current context
  49.601 -            e.setContext(ctxt);
  49.602 -
  49.603 -            ((Invocable)e).invokeFunction("hello"); // no 'hello' in new context!
  49.604 -            fail("should have thrown NoSuchMethodException");
  49.605 -        } catch (final Exception exp) {
  49.606 -            if (! (exp instanceof NoSuchMethodException)) {
  49.607 -                exp.printStackTrace();
  49.608 -                fail(exp.getMessage());
  49.609 -            }
  49.610 -        }
  49.611 -    }
  49.612 -
  49.613 -    @Test
  49.614 -    public void invokeFunctionExceptionTest() {
  49.615 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.616 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.617 -        try {
  49.618 -            e.eval("function func() { throw new TypeError(); }");
  49.619 -        } catch (final Throwable t) {
  49.620 -            t.printStackTrace();
  49.621 -            fail(t.getMessage());
  49.622 -        }
  49.623 -
  49.624 -        try {
  49.625 -            ((Invocable)e).invokeFunction("func");
  49.626 -            fail("should have thrown exception");
  49.627 -        } catch (final ScriptException se) {
  49.628 -            // ECMA TypeError property wrapped as a ScriptException
  49.629 -            log("got " + se + " as expected");
  49.630 -        } catch (final Throwable t) {
  49.631 -            t.printStackTrace();
  49.632 -            fail(t.getMessage());
  49.633 -        }
  49.634 -    }
  49.635 -
  49.636 -    @Test
  49.637 -    public void invokeMethodExceptionTest() {
  49.638 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.639 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.640 -        try {
  49.641 -            e.eval("var sobj = {}; sobj.foo = function func() { throw new TypeError(); }");
  49.642 -        } catch (final Throwable t) {
  49.643 -            t.printStackTrace();
  49.644 -            fail(t.getMessage());
  49.645 -        }
  49.646 -
  49.647 -        try {
  49.648 -            final Object sobj = e.get("sobj");
  49.649 -            ((Invocable)e).invokeMethod(sobj, "foo");
  49.650 -            fail("should have thrown exception");
  49.651 -        } catch (final ScriptException se) {
  49.652 -            // ECMA TypeError property wrapped as a ScriptException
  49.653 -            log("got " + se + " as expected");
  49.654 -        } catch (final Throwable t) {
  49.655 -            t.printStackTrace();
  49.656 -            fail(t.getMessage());
  49.657 -        }
  49.658 -    }
  49.659 -
  49.660 -    @Test
  49.661 -    public void scriptObjectMirrorToStringTest() {
  49.662 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.663 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.664 -        try {
  49.665 -            Object obj = e.eval("new TypeError('wrong type')");
  49.666 -            assertEquals(obj.toString(), "TypeError: wrong type", "toString returns wrong value");
  49.667 -        } catch (final Throwable t) {
  49.668 -            t.printStackTrace();
  49.669 -            fail(t.getMessage());
  49.670 -        }
  49.671 -
  49.672 -        try {
  49.673 -            Object obj = e.eval("function func() { print('hello'); }");
  49.674 -            assertEquals(obj.toString(), "function func() { print('hello'); }", "toString returns wrong value");
  49.675 -        } catch (final Throwable t) {
  49.676 -            t.printStackTrace();
  49.677 -            fail(t.getMessage());
  49.678 -        }
  49.679 -    }
  49.680 -
  49.681 -    @Test
  49.682 -    public void engineScopeTest() {
  49.683 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.684 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.685 -        Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
  49.686 -
  49.687 -        // check few ECMA standard built-in global properties
  49.688 -        assertNotNull(engineScope.get("Object"));
  49.689 -        assertNotNull(engineScope.get("TypeError"));
  49.690 -        assertNotNull(engineScope.get("eval"));
  49.691 -
  49.692 -        // can access via ScriptEngine.get as well
  49.693 -        assertNotNull(e.get("Object"));
  49.694 -        assertNotNull(e.get("TypeError"));
  49.695 -        assertNotNull(e.get("eval"));
  49.696 -
  49.697 -        // Access by either way should return same object
  49.698 -        assertEquals(engineScope.get("Array"), e.get("Array"));
  49.699 -        assertEquals(engineScope.get("EvalError"), e.get("EvalError"));
  49.700 -        assertEquals(engineScope.get("undefined"), e.get("undefined"));
  49.701 -
  49.702 -        // try exposing a new variable from scope
  49.703 -        engineScope.put("myVar", "foo");
  49.704 -        try {
  49.705 -            assertEquals(e.eval("myVar"), "foo");
  49.706 -        } catch (final ScriptException se) {
  49.707 -            se.printStackTrace();
  49.708 -            fail(se.getMessage());
  49.709 -        }
  49.710 -
  49.711 -        // update "myVar" in script an check the value from scope
  49.712 -        try {
  49.713 -            e.eval("myVar = 'nashorn';");
  49.714 -        } catch (final ScriptException se) {
  49.715 -            se.printStackTrace();
  49.716 -            fail(se.getMessage());
  49.717 -        }
  49.718 -
  49.719 -        // now check modified value from scope and engine
  49.720 -        assertEquals(engineScope.get("myVar"), "nashorn");
  49.721 -        assertEquals(e.get("myVar"), "nashorn");
  49.722 -    }
  49.723 -
  49.724 -    @Test
  49.725 -    public void multiGlobalTest() {
  49.726 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.727 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.728 -        final Bindings b = e.createBindings();
  49.729 -        final ScriptContext newCtxt = new SimpleScriptContext();
  49.730 -        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
  49.731 -
  49.732 -        try {
  49.733 -            Object obj1 = e.eval("Object");
  49.734 -            Object obj2 = e.eval("Object", newCtxt);
  49.735 -            Assert.assertNotEquals(obj1, obj2);
  49.736 -            Assert.assertNotNull(obj1);
  49.737 -            Assert.assertNotNull(obj2);
  49.738 -            Assert.assertEquals(obj1.toString(), obj2.toString());
  49.739 -
  49.740 -            e.eval("x = 'hello'");
  49.741 -            e.eval("x = 'world'", newCtxt);
  49.742 -            Object x1 = e.getContext().getAttribute("x");
  49.743 -            Object x2 = newCtxt.getAttribute("x");
  49.744 -            Assert.assertNotEquals(x1, x2);
  49.745 -            Assert.assertEquals(x1, "hello");
  49.746 -            Assert.assertEquals(x2, "world");
  49.747 -
  49.748 -            x1 = e.eval("x");
  49.749 -            x2 = e.eval("x", newCtxt);
  49.750 -            Assert.assertNotEquals(x1, x2);
  49.751 -            Assert.assertEquals(x1, "hello");
  49.752 -            Assert.assertEquals(x2, "world");
  49.753 -
  49.754 -            final ScriptContext origCtxt = e.getContext();
  49.755 -            e.setContext(newCtxt);
  49.756 -            e.eval("y = new Object()");
  49.757 -            e.eval("y = new Object()", origCtxt);
  49.758 -
  49.759 -            Object y1 = origCtxt.getAttribute("y");
  49.760 -            Object y2 = newCtxt.getAttribute("y");
  49.761 -            Assert.assertNotEquals(y1, y2);
  49.762 -            Assert.assertNotEquals(e.eval("y"), e.eval("y", origCtxt));
  49.763 -            Assert.assertEquals("[object Object]", y1.toString());
  49.764 -            Assert.assertEquals("[object Object]", y2.toString());
  49.765 -        } catch (final ScriptException se) {
  49.766 -            se.printStackTrace();
  49.767 -            fail(se.getMessage());
  49.768 -        }
  49.769 -    }
  49.770 -
  49.771 -    @Test
  49.772 -    /**
  49.773 -     * Tests whether invocation of a JavaScript method through a variable arity Java method will pass the vararg array.
  49.774 -     * Both non-vararg and vararg JavaScript methods are tested.
  49.775 -     * @throws ScriptException
  49.776 -     */
  49.777 -    public void variableArityInterfaceTest() throws ScriptException {
  49.778 -        final ScriptEngineManager m = new ScriptEngineManager();
  49.779 -        final ScriptEngine e = m.getEngineByName("nashorn");
  49.780 -        e.eval(
  49.781 -            "function test1(i, strings) {" +
  49.782 -            "    return 'i == ' + i + ', strings instanceof java.lang.String[] == ' + (strings instanceof Java.type('java.lang.String[]')) + ', strings == ' + java.util.Arrays.toString(strings)" +
  49.783 -            "}" +
  49.784 -            "function test2() {" +
  49.785 -            "    return 'arguments[0] == ' + arguments[0] + ', arguments[1] instanceof java.lang.String[] == ' + (arguments[1] instanceof Java.type('java.lang.String[]')) + ', arguments[1] == ' + java.util.Arrays.toString(arguments[1])" +
  49.786 -            "}"
  49.787 -        );
  49.788 -        final VariableArityTestInterface itf = ((Invocable)e).getInterface(VariableArityTestInterface.class);
  49.789 -        Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
  49.790 -        Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
  49.791 -    }
  49.792 -
  49.793 -    @Test
  49.794      // check that print function prints arg followed by newline char
  49.795      public void printTest() {
  49.796          final ScriptEngineManager m = new ScriptEngineManager();
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java	Fri Aug 23 16:44:02 2013 +0530
    50.3 @@ -0,0 +1,230 @@
    50.4 +/*
    50.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    50.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    50.7 + *
    50.8 + * This code is free software; you can redistribute it and/or modify it
    50.9 + * under the terms of the GNU General Public License version 2 only, as
   50.10 + * published by the Free Software Foundation.  Oracle designates this
   50.11 + * particular file as subject to the "Classpath" exception as provided
   50.12 + * by Oracle in the LICENSE file that accompanied this code.
   50.13 + *
   50.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   50.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   50.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   50.17 + * version 2 for more details (a copy is included in the LICENSE file that
   50.18 + * accompanied this code).
   50.19 + *
   50.20 + * You should have received a copy of the GNU General Public License version
   50.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   50.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   50.23 + *
   50.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   50.25 + * or visit www.oracle.com if you need additional information or have any
   50.26 + * questions.
   50.27 + */
   50.28 +
   50.29 +package jdk.nashorn.api.scripting;
   50.30 +
   50.31 +import java.util.HashMap;
   50.32 +import java.util.Map;
   50.33 +import javax.script.ScriptEngine;
   50.34 +import javax.script.ScriptEngineManager;
   50.35 +import javax.script.ScriptException;
   50.36 +import static org.testng.Assert.assertEquals;
   50.37 +import static org.testng.Assert.assertFalse;
   50.38 +import static org.testng.Assert.assertTrue;
   50.39 +import static org.testng.Assert.fail;
   50.40 +import org.testng.annotations.Test;
   50.41 +
   50.42 +/**
   50.43 + * Tests to check jdk.nashorn.api.scripting.ScriptObjectMirror API.
   50.44 + */
   50.45 +public class ScriptObjectMirrorTest {
   50.46 +
   50.47 +    @SuppressWarnings("unchecked")
   50.48 +    @Test
   50.49 +    public void reflectionTest() throws ScriptException {
   50.50 +        final ScriptEngineManager m = new ScriptEngineManager();
   50.51 +        final ScriptEngine e = m.getEngineByName("nashorn");
   50.52 +
   50.53 +        e.eval("var obj = { x: 344, y: 'nashorn' }");
   50.54 +
   50.55 +        int count = 0;
   50.56 +        Map<Object, Object> map = (Map<Object, Object>) e.get("obj");
   50.57 +        assertFalse(map.isEmpty());
   50.58 +        assertTrue(map.keySet().contains("x"));
   50.59 +        assertTrue(map.containsKey("x"));
   50.60 +        assertTrue(map.values().contains("nashorn"));
   50.61 +        assertTrue(map.containsValue("nashorn"));
   50.62 +        for (final Map.Entry<?, ?> ex : map.entrySet()) {
   50.63 +            final Object key = ex.getKey();
   50.64 +            if (key.equals("x")) {
   50.65 +                assertTrue(344 == ((Number) ex.getValue()).doubleValue());
   50.66 +                count++;
   50.67 +            } else if (key.equals("y")) {
   50.68 +                assertEquals(ex.getValue(), "nashorn");
   50.69 +                count++;
   50.70 +            }
   50.71 +        }
   50.72 +        assertEquals(2, count);
   50.73 +        assertEquals(2, map.size());
   50.74 +
   50.75 +        // add property
   50.76 +        map.put("z", "hello");
   50.77 +        assertEquals(e.eval("obj.z"), "hello");
   50.78 +        assertEquals(map.get("z"), "hello");
   50.79 +        assertTrue(map.keySet().contains("z"));
   50.80 +        assertTrue(map.containsKey("z"));
   50.81 +        assertTrue(map.values().contains("hello"));
   50.82 +        assertTrue(map.containsValue("hello"));
   50.83 +        assertEquals(map.size(), 3);
   50.84 +
   50.85 +        final Map<Object, Object> newMap = new HashMap<>();
   50.86 +        newMap.put("foo", 23.0);
   50.87 +        newMap.put("bar", true);
   50.88 +        map.putAll(newMap);
   50.89 +
   50.90 +        assertEquals(e.eval("obj.foo"), 23.0);
   50.91 +        assertEquals(e.eval("obj.bar"), true);
   50.92 +
   50.93 +        // remove using map method
   50.94 +        map.remove("foo");
   50.95 +        assertEquals(e.eval("typeof obj.foo"), "undefined");
   50.96 +
   50.97 +        count = 0;
   50.98 +        e.eval("var arr = [ true, 'hello' ]");
   50.99 +        map = (Map<Object, Object>) e.get("arr");
  50.100 +        assertFalse(map.isEmpty());
  50.101 +        assertTrue(map.containsKey("length"));
  50.102 +        assertTrue(map.containsValue("hello"));
  50.103 +        for (final Map.Entry<?, ?> ex : map.entrySet()) {
  50.104 +            final Object key = ex.getKey();
  50.105 +            if (key.equals("0")) {
  50.106 +                assertEquals(ex.getValue(), Boolean.TRUE);
  50.107 +                count++;
  50.108 +            } else if (key.equals("1")) {
  50.109 +                assertEquals(ex.getValue(), "hello");
  50.110 +                count++;
  50.111 +            }
  50.112 +        }
  50.113 +        assertEquals(count, 2);
  50.114 +        assertEquals(map.size(), 2);
  50.115 +
  50.116 +        // add element
  50.117 +        map.put("2", "world");
  50.118 +        assertEquals(map.get("2"), "world");
  50.119 +        assertEquals(map.size(), 3);
  50.120 +
  50.121 +        // remove all
  50.122 +        map.clear();
  50.123 +        assertTrue(map.isEmpty());
  50.124 +        assertEquals(e.eval("typeof arr[0]"), "undefined");
  50.125 +        assertEquals(e.eval("typeof arr[1]"), "undefined");
  50.126 +        assertEquals(e.eval("typeof arr[2]"), "undefined");
  50.127 +    }
  50.128 +
  50.129 +    @Test
  50.130 +    public void jsobjectTest() {
  50.131 +        final ScriptEngineManager m = new ScriptEngineManager();
  50.132 +        final ScriptEngine e = m.getEngineByName("nashorn");
  50.133 +        try {
  50.134 +            e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }");
  50.135 +            JSObject obj = (JSObject) e.get("obj");
  50.136 +
  50.137 +            // try basic get on existing properties
  50.138 +            if (!obj.getMember("bar").equals("hello")) {
  50.139 +                fail("obj.bar != 'hello'");
  50.140 +            }
  50.141 +
  50.142 +            if (!obj.getSlot(1).equals("world")) {
  50.143 +                fail("obj[1] != 'world'");
  50.144 +            }
  50.145 +
  50.146 +            if (!obj.call("func", new Object[0]).equals("hello")) {
  50.147 +                fail("obj.call('func') != 'hello'");
  50.148 +            }
  50.149 +
  50.150 +            // try setting properties
  50.151 +            obj.setMember("bar", "new-bar");
  50.152 +            obj.setSlot(1, "new-element-1");
  50.153 +            if (!obj.getMember("bar").equals("new-bar")) {
  50.154 +                fail("obj.bar != 'new-bar'");
  50.155 +            }
  50.156 +
  50.157 +            if (!obj.getSlot(1).equals("new-element-1")) {
  50.158 +                fail("obj[1] != 'new-element-1'");
  50.159 +            }
  50.160 +
  50.161 +            // try adding properties
  50.162 +            obj.setMember("prop", "prop-value");
  50.163 +            obj.setSlot(12, "element-12");
  50.164 +            if (!obj.getMember("prop").equals("prop-value")) {
  50.165 +                fail("obj.prop != 'prop-value'");
  50.166 +            }
  50.167 +
  50.168 +            if (!obj.getSlot(12).equals("element-12")) {
  50.169 +                fail("obj[12] != 'element-12'");
  50.170 +            }
  50.171 +
  50.172 +            // delete properties
  50.173 +            obj.removeMember("prop");
  50.174 +            if ("prop-value".equals(obj.getMember("prop"))) {
  50.175 +                fail("obj.prop is not deleted!");
  50.176 +            }
  50.177 +
  50.178 +            // Simple eval tests
  50.179 +            assertEquals(obj.eval("typeof Object"), "function");
  50.180 +            assertEquals(obj.eval("'nashorn'.substring(3)"), "horn");
  50.181 +        } catch (final Exception exp) {
  50.182 +            exp.printStackTrace();
  50.183 +            fail(exp.getMessage());
  50.184 +        }
  50.185 +    }
  50.186 +
  50.187 +    @Test
  50.188 +    public void scriptObjectMirrorToStringTest() {
  50.189 +        final ScriptEngineManager m = new ScriptEngineManager();
  50.190 +        final ScriptEngine e = m.getEngineByName("nashorn");
  50.191 +        try {
  50.192 +            Object obj = e.eval("new TypeError('wrong type')");
  50.193 +            assertEquals(obj.toString(), "TypeError: wrong type", "toString returns wrong value");
  50.194 +        } catch (final Throwable t) {
  50.195 +            t.printStackTrace();
  50.196 +            fail(t.getMessage());
  50.197 +        }
  50.198 +
  50.199 +        try {
  50.200 +            Object obj = e.eval("function func() { print('hello'); }");
  50.201 +            assertEquals(obj.toString(), "function func() { print('hello'); }", "toString returns wrong value");
  50.202 +        } catch (final Throwable t) {
  50.203 +            t.printStackTrace();
  50.204 +            fail(t.getMessage());
  50.205 +        }
  50.206 +    }
  50.207 +
  50.208 +    @Test
  50.209 +    public void mirrorNewObjectGlobalFunctionTest() throws ScriptException {
  50.210 +        final ScriptEngineManager m = new ScriptEngineManager();
  50.211 +        final ScriptEngine e = m.getEngineByName("nashorn");
  50.212 +        final ScriptEngine e2 = m.getEngineByName("nashorn");
  50.213 +
  50.214 +        e.eval("function func() {}");
  50.215 +        e2.put("foo", e.get("func"));
  50.216 +        final Object e2global = e2.eval("this");
  50.217 +        final Object newObj = ((ScriptObjectMirror) e2global).newObject("foo");
  50.218 +        assertTrue(newObj instanceof ScriptObjectMirror);
  50.219 +    }
  50.220 +
  50.221 +    @Test
  50.222 +    public void mirrorNewObjectInstanceFunctionTest() throws ScriptException {
  50.223 +        final ScriptEngineManager m = new ScriptEngineManager();
  50.224 +        final ScriptEngine e = m.getEngineByName("nashorn");
  50.225 +        final ScriptEngine e2 = m.getEngineByName("nashorn");
  50.226 +
  50.227 +        e.eval("function func() {}");
  50.228 +        e2.put("func", e.get("func"));
  50.229 +        final Object e2obj = e2.eval("({ foo: func })");
  50.230 +        final Object newObj = ((ScriptObjectMirror) e2obj).newObject("foo");
  50.231 +        assertTrue(newObj instanceof ScriptObjectMirror);
  50.232 +    }
  50.233 +}
    51.1 --- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java	Mon Aug 19 19:37:29 2013 +0530
    51.2 +++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java	Fri Aug 23 16:44:02 2013 +0530
    51.3 @@ -32,7 +32,10 @@
    51.4  import javax.script.ScriptEngine;
    51.5  import javax.script.ScriptEngineFactory;
    51.6  import javax.script.ScriptEngineManager;
    51.7 +import javax.script.ScriptContext;
    51.8  import javax.script.ScriptException;
    51.9 +import javax.script.SimpleBindings;
   51.10 +import javax.script.SimpleScriptContext;
   51.11  import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
   51.12  import org.testng.annotations.Test;
   51.13  
   51.14 @@ -196,4 +199,25 @@
   51.15          }
   51.16          fail("Cannot find nashorn factory!");
   51.17      }
   51.18 +
   51.19 +    @Test
   51.20 +    public void globalPerEngineTest() throws ScriptException {
   51.21 +        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
   51.22 +        final String[] options = new String[] { "--global-per-engine" };
   51.23 +        final ScriptEngine e = fac.getScriptEngine(options);
   51.24 +
   51.25 +        e.eval("function foo() {}");
   51.26 +
   51.27 +        final ScriptContext newCtx = new SimpleScriptContext();
   51.28 +        newCtx.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
   51.29 +
   51.30 +        // all global definitions shared and so 'foo' should be
   51.31 +        // visible in new Bindings as well.
   51.32 +        assertTrue(e.eval("typeof foo", newCtx).equals("function"));
   51.33 +
   51.34 +        e.eval("function bar() {}", newCtx);
   51.35 +
   51.36 +        // bar should be visible in default context
   51.37 +        assertTrue(e.eval("typeof bar").equals("function"));
   51.38 +    }
   51.39  }

mercurial