1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.api.scripting;
  27 
  28 import static org.testng.Assert.assertEquals;
  29 import static org.testng.Assert.assertNotNull;
  30 import static org.testng.Assert.assertNull;
  31 import static org.testng.Assert.assertTrue;
  32 import static org.testng.Assert.fail;
  33 
  34 import java.io.StringReader;
  35 import java.io.StringWriter;
  36 import java.lang.reflect.InvocationHandler;
  37 import java.lang.reflect.Method;
  38 import java.lang.reflect.Proxy;
  39 import java.util.Collections;
  40 import java.util.concurrent.Callable;
  41 import java.util.concurrent.atomic.AtomicBoolean;
  42 import java.util.function.Consumer;
  43 import java.util.function.Function;
  44 import javax.script.Bindings;
  45 import javax.script.Compilable;
  46 import javax.script.CompiledScript;
  47 import javax.script.Invocable;
  48 import javax.script.ScriptContext;
  49 import javax.script.ScriptEngine;
  50 import javax.script.ScriptEngineFactory;
  51 import javax.script.ScriptEngineManager;
  52 import javax.script.ScriptException;
  53 import javax.script.SimpleScriptContext;
  54 import org.testng.annotations.Test;
  55 
  56 /**
  57  * Tests for JSR-223 script engine for Nashorn.
  58  *
  59  * @test
  60  * @build jdk.nashorn.api.scripting.Window jdk.nashorn.api.scripting.WindowEventHandler jdk.nashorn.api.scripting.VariableArityTestInterface jdk.nashorn.api.scripting.ScriptEngineTest
  61  * @run testng/othervm jdk.nashorn.api.scripting.ScriptEngineTest
  62  */
  63 @SuppressWarnings("javadoc")
  64 public class ScriptEngineTest {
  65 
  66     private static void log(final String msg) {
  67         org.testng.Reporter.log(msg, true);
  68     }
  69 
  70     @Test
  71     public void argumentsTest() {
  72         final ScriptEngineManager m = new ScriptEngineManager();
  73         final ScriptEngine e = m.getEngineByName("nashorn");
  74 
  75         final String[] args = new String[] { "hello", "world" };
  76         try {
  77             e.put("arguments", args);
  78             final Object arg0 = e.eval("arguments[0]");
  79             final Object arg1 = e.eval("arguments[1]");
  80             assertEquals(args[0], arg0);
  81             assertEquals(args[1], arg1);
  82         } catch (final Exception exp) {
  83             exp.printStackTrace();
  84             fail(exp.getMessage());
  85         }
  86     }
  87 
  88     @Test
  89     public void argumentsWithTest() {
  90         final ScriptEngineManager m = new ScriptEngineManager();
  91         final ScriptEngine e = m.getEngineByName("nashorn");
  92 
  93         final String[] args = new String[] { "hello", "world" };
  94         try {
  95             e.put("arguments", args);
  96             final Object arg0 = e.eval("var imports = new JavaImporter(java.io); " +
  97                     " with(imports) { arguments[0] }");
  98             final Object arg1 = e.eval("var imports = new JavaImporter(java.util, java.io); " +
  99                     " with(imports) { arguments[1] }");
 100             assertEquals(args[0], arg0);
 101             assertEquals(args[1], arg1);
 102         } catch (final Exception exp) {
 103             exp.printStackTrace();
 104             fail(exp.getMessage());
 105         }
 106     }
 107 
 108     @Test
 109     public void argumentsEmptyTest() {
 110         final ScriptEngineManager m = new ScriptEngineManager();
 111         final ScriptEngine e = m.getEngineByName("nashorn");
 112 
 113         try {
 114             assertEquals(e.eval("arguments instanceof Array"), true);
 115             assertEquals(e.eval("arguments.length == 0"), true);
 116         } catch (final Exception exp) {
 117             exp.printStackTrace();
 118             fail(exp.getMessage());
 119         }
 120     }
 121 
 122     @Test
 123     public void factoryTests() {
 124         final ScriptEngineManager m = new ScriptEngineManager();
 125         final ScriptEngine e = m.getEngineByName("nashorn");
 126         assertNotNull(e);
 127 
 128         final ScriptEngineFactory fac = e.getFactory();
 129 
 130         assertEquals(fac.getLanguageName(), "ECMAScript");
 131         assertEquals(fac.getParameter(ScriptEngine.NAME), "javascript");
 132         assertEquals(fac.getLanguageVersion(), "ECMA - 262 Edition 5.1");
 133         assertEquals(fac.getEngineName(), "Oracle Nashorn");
 134         assertEquals(fac.getOutputStatement("context"), "print(context)");
 135         assertEquals(fac.getProgram("print('hello')", "print('world')"), "print('hello');print('world');");
 136         assertEquals(fac.getParameter(ScriptEngine.NAME), "javascript");
 137 
 138         boolean seenJS = false;
 139         for (final String ext : fac.getExtensions()) {
 140             if (ext.equals("js")) {
 141                 seenJS = true;
 142             }
 143         }
 144 
 145         assertEquals(seenJS, true);
 146         final String str = fac.getMethodCallSyntax("obj", "foo", "x");
 147         assertEquals(str, "obj.foo(x)");
 148 
 149         boolean seenNashorn = false, seenJavaScript = false, seenECMAScript = false;
 150         for (final String name : fac.getNames()) {
 151             switch (name) {
 152                 case "nashorn": seenNashorn = true; break;
 153                 case "javascript": seenJavaScript = true; break;
 154                 case "ECMAScript": seenECMAScript = true; break;
 155             default:
 156                 break;
 157             }
 158         }
 159 
 160         assertTrue(seenNashorn);
 161         assertTrue(seenJavaScript);
 162         assertTrue(seenECMAScript);
 163 
 164         boolean seenAppJS = false, seenAppECMA = false, seenTextJS = false, seenTextECMA = false;
 165         for (final String mime : fac.getMimeTypes()) {
 166             switch (mime) {
 167                 case "application/javascript": seenAppJS = true; break;
 168                 case "application/ecmascript": seenAppECMA = true; break;
 169                 case "text/javascript": seenTextJS = true; break;
 170                 case "text/ecmascript": seenTextECMA = true; break;
 171             default:
 172                 break;
 173             }
 174         }
 175 
 176         assertTrue(seenAppJS);
 177         assertTrue(seenAppECMA);
 178         assertTrue(seenTextJS);
 179         assertTrue(seenTextECMA);
 180     }
 181 
 182     @Test
 183     public void evalTests() {
 184         final ScriptEngineManager m = new ScriptEngineManager();
 185         final ScriptEngine e = m.getEngineByName("nashorn");
 186         e.put(ScriptEngine.FILENAME, "myfile.js");
 187 
 188         try {
 189             e.eval("print('hello')");
 190         } catch (final ScriptException se) {
 191             fail(se.getMessage());
 192         }
 193         try {
 194             e.eval("print('hello)");
 195             fail("script exception expected");
 196         } catch (final ScriptException se) {
 197             assertEquals(se.getLineNumber(), 1);
 198             assertEquals(se.getColumnNumber(), 13);
 199             assertEquals(se.getFileName(), "myfile.js");
 200             // se.printStackTrace();
 201         }
 202 
 203         try {
 204             Object obj = e.eval("34 + 41");
 205             assertTrue(34.0 + 41.0 == ((Number)obj).doubleValue());
 206             obj = e.eval("x = 5");
 207             assertTrue(5.0 == ((Number)obj).doubleValue());
 208         } catch (final ScriptException se) {
 209             se.printStackTrace();
 210             fail(se.getMessage());
 211         }
 212     }
 213 
 214     @Test
 215     public void compileTests() {
 216         final ScriptEngineManager m = new ScriptEngineManager();
 217         final ScriptEngine e = m.getEngineByName("nashorn");
 218         CompiledScript script = null;
 219 
 220         try {
 221             script = ((Compilable)e).compile("print('hello')");
 222         } catch (final ScriptException se) {
 223             fail(se.getMessage());
 224         }
 225 
 226         try {
 227             script.eval();
 228         } catch (final ScriptException | NullPointerException se) {
 229             se.printStackTrace();
 230             fail(se.getMessage());
 231         }
 232 
 233         // try to compile from a Reader
 234         try {
 235             script = ((Compilable)e).compile(new StringReader("print('world')"));
 236         } catch (final ScriptException se) {
 237             fail(se.getMessage());
 238         }
 239 
 240         try {
 241             script.eval();
 242         } catch (final ScriptException | NullPointerException se) {
 243             se.printStackTrace();
 244             fail(se.getMessage());
 245         }
 246     }
 247 
 248     @Test
 249     public void compileAndEvalInDiffContextTest() throws ScriptException {
 250         final ScriptEngineManager m = new ScriptEngineManager();
 251         final ScriptEngine engine = m.getEngineByName("js");
 252         final Compilable compilable = (Compilable) engine;
 253         final CompiledScript compiledScript = compilable.compile("foo");
 254         final ScriptContext ctxt = new SimpleScriptContext();
 255         ctxt.setAttribute("foo", "hello", ScriptContext.ENGINE_SCOPE);
 256         assertEquals(compiledScript.eval(ctxt), "hello");
 257     }
 258 
 259     @Test
 260     public void accessGlobalTest() {
 261         final ScriptEngineManager m = new ScriptEngineManager();
 262         final ScriptEngine e = m.getEngineByName("nashorn");
 263 
 264         try {
 265             e.eval("var x = 'hello'");
 266             assertEquals(e.get("x"), "hello");
 267         } catch (final ScriptException exp) {
 268             exp.printStackTrace();
 269             fail(exp.getMessage());
 270         }
 271     }
 272 
 273     @Test
 274     public void exposeGlobalTest() {
 275         final ScriptEngineManager m = new ScriptEngineManager();
 276         final ScriptEngine e = m.getEngineByName("nashorn");
 277 
 278         try {
 279             e.put("y", "foo");
 280             e.eval("print(y)");
 281         } catch (final ScriptException exp) {
 282             exp.printStackTrace();
 283             fail(exp.getMessage());
 284         }
 285     }
 286 
 287     @Test
 288     public void putGlobalFunctionTest() {
 289         final ScriptEngineManager m = new ScriptEngineManager();
 290         final ScriptEngine e = m.getEngineByName("nashorn");
 291 
 292         e.put("callable", new Callable<String>() {
 293             @Override
 294             public String call() throws Exception {
 295                 return "callable was called";
 296             }
 297         });
 298 
 299         try {
 300             e.eval("print(callable.call())");
 301         } catch (final ScriptException exp) {
 302             exp.printStackTrace();
 303             fail(exp.getMessage());
 304         }
 305     }
 306 
 307     @Test
 308     public void windowAlertTest() {
 309         final ScriptEngineManager m = new ScriptEngineManager();
 310         final ScriptEngine e = m.getEngineByName("nashorn");
 311         final Window window = new Window();
 312 
 313         try {
 314             e.put("window", window);
 315             e.eval("print(window.alert)");
 316             e.eval("window.alert('calling window.alert...')");
 317         } catch (final Exception exp) {
 318             exp.printStackTrace();
 319             fail(exp.getMessage());
 320         }
 321     }
 322 
 323     @Test
 324     public void windowLocationTest() {
 325         final ScriptEngineManager m = new ScriptEngineManager();
 326         final ScriptEngine e = m.getEngineByName("nashorn");
 327         final Window window = new Window();
 328 
 329         try {
 330             e.put("window", window);
 331             e.eval("print(window.location)");
 332             final Object locationValue = e.eval("window.getLocation()");
 333             assertEquals(locationValue, "http://localhost:8080/window");
 334         } catch (final Exception exp) {
 335             exp.printStackTrace();
 336             fail(exp.getMessage());
 337         }
 338     }
 339 
 340     @Test
 341     public void windowItemTest() {
 342         final ScriptEngineManager m = new ScriptEngineManager();
 343         final ScriptEngine e = m.getEngineByName("nashorn");
 344         final Window window = new Window();
 345 
 346         try {
 347             e.put("window", window);
 348             final String item1 = (String)e.eval("window.item(65535)");
 349             assertEquals(item1, "ffff");
 350             final String item2 = (String)e.eval("window.item(255)");
 351             assertEquals(item2, "ff");
 352         } catch (final Exception exp) {
 353             exp.printStackTrace();
 354             fail(exp.getMessage());
 355         }
 356     }
 357 
 358     @Test
 359     public void windowEventTest() {
 360         final ScriptEngineManager m = new ScriptEngineManager();
 361         final ScriptEngine e = m.getEngineByName("nashorn");
 362         final Window window = new Window();
 363 
 364         try {
 365             e.put("window", window);
 366             e.eval("window.onload = function() { print('window load event fired'); return true }");
 367             assertTrue((Boolean)e.eval("window.onload.loaded()"));
 368             final WindowEventHandler handler = window.getOnload();
 369             assertNotNull(handler);
 370             assertTrue(handler.loaded());
 371         } catch (final Exception exp) {
 372             exp.printStackTrace();
 373             fail(exp.getMessage());
 374         }
 375     }
 376 
 377     @Test
 378     public void throwTest() {
 379         final ScriptEngineManager m = new ScriptEngineManager();
 380         final ScriptEngine e = m.getEngineByName("nashorn");
 381         e.put(ScriptEngine.FILENAME, "throwtest.js");
 382 
 383         try {
 384             e.eval("throw 'foo'");
 385         } catch (final ScriptException exp) {
 386             log(exp.getMessage());
 387             assertEquals(exp.getMessage(), "foo in throwtest.js at line number 1 at column number 0");
 388             assertEquals(exp.getFileName(), "throwtest.js");
 389             assertEquals(exp.getLineNumber(), 1);
 390         }
 391     }
 392 
 393     @Test
 394     public void setTimeoutTest() {
 395         final ScriptEngineManager m = new ScriptEngineManager();
 396         final ScriptEngine e = m.getEngineByName("nashorn");
 397         final Window window = new Window();
 398 
 399         try {
 400             final Class<?> setTimeoutParamTypes[] = { Window.class, String.class, int.class };
 401             final Method setTimeout = Window.class.getDeclaredMethod("setTimeout", setTimeoutParamTypes);
 402             assertNotNull(setTimeout);
 403             e.put("window", window);
 404             e.eval("window.setTimeout('foo()', 100)");
 405 
 406             // try to make setTimeout global
 407             e.put("setTimeout", setTimeout);
 408             // TODO: java.lang.ClassCastException: required class
 409             // java.lang.Integer but encountered class java.lang.Double
 410             // e.eval("setTimeout('foo2()', 200)");
 411         } catch (final Exception exp) {
 412             exp.printStackTrace();
 413             fail(exp.getMessage());
 414         }
 415     }
 416 
 417     @Test
 418     public void setWriterTest() {
 419         final ScriptEngineManager m = new ScriptEngineManager();
 420         final ScriptEngine e = m.getEngineByName("nashorn");
 421         final StringWriter sw = new StringWriter();
 422         e.getContext().setWriter(sw);
 423 
 424         try {
 425             e.eval("print('hello world')");
 426         } catch (final Exception exp) {
 427             exp.printStackTrace();
 428             fail(exp.getMessage());
 429         }
 430         assertEquals(sw.toString(), println("hello world"));
 431     }
 432 
 433     @Test
 434     public void redefineEchoTest() {
 435         final ScriptEngineManager m = new ScriptEngineManager();
 436         final ScriptEngine e = m.getEngineByName("nashorn");
 437 
 438         try {
 439             e.eval("var echo = {}; if (typeof echo !== 'object') { throw 'echo is a '+typeof echo; }");
 440         } catch (final Exception exp) {
 441             exp.printStackTrace();
 442             fail(exp.getMessage());
 443         }
 444     }
 445     @Test
 446     public void noEnumerablePropertiesTest() {
 447         final ScriptEngineManager m = new ScriptEngineManager();
 448         final ScriptEngine e = m.getEngineByName("nashorn");
 449         try {
 450             e.eval("for (i in this) { throw 'found property: ' + i }");
 451         } catch (final Exception exp) {
 452             exp.printStackTrace();
 453             fail(exp.getMessage());
 454         }
 455     }
 456 
 457     @Test
 458     public void noRefErrorForGlobalThisAccessTest() {
 459         final ScriptEngineManager m = new ScriptEngineManager();
 460         final ScriptEngine e = m.getEngineByName("nashorn");
 461         try {
 462             e.eval("this.foo");
 463         } catch (final Exception exp) {
 464             exp.printStackTrace();
 465             fail(exp.getMessage());
 466         }
 467     }
 468 
 469     @Test
 470     public void refErrorForUndeclaredAccessTest() {
 471         final ScriptEngineManager m = new ScriptEngineManager();
 472         final ScriptEngine e = m.getEngineByName("nashorn");
 473         try {
 474             e.eval("try { print(foo); throw 'no ref error' } catch (e) { if (!(e instanceof ReferenceError)) throw e; }");
 475         } catch (final Exception exp) {
 476             exp.printStackTrace();
 477             fail(exp.getMessage());
 478         }
 479     }
 480 
 481     @Test
 482     public void typeErrorForGlobalThisCallTest() {
 483         final ScriptEngineManager m = new ScriptEngineManager();
 484         final ScriptEngine e = m.getEngineByName("nashorn");
 485         try {
 486             e.eval("try { this.foo() } catch(e) { if (! (e instanceof TypeError)) throw 'no type error' }");
 487         } catch (final Exception exp) {
 488             exp.printStackTrace();
 489             fail(exp.getMessage());
 490         }
 491     }
 492 
 493     @Test
 494     public void refErrorForUndeclaredCallTest() {
 495         final ScriptEngineManager m = new ScriptEngineManager();
 496         final ScriptEngine e = m.getEngineByName("nashorn");
 497         try {
 498             e.eval("try { foo() } catch(e) { if (! (e instanceof ReferenceError)) throw 'no ref error' }");
 499         } catch (final Exception exp) {
 500             exp.printStackTrace();
 501             fail(exp.getMessage());
 502         }
 503     }
 504 
 505     @Test
 506     // check that print function prints arg followed by newline char
 507     public void printTest() {
 508         final ScriptEngineManager m = new ScriptEngineManager();
 509         final ScriptEngine e = m.getEngineByName("nashorn");
 510         final StringWriter sw = new StringWriter();
 511         e.getContext().setWriter(sw);
 512         try {
 513             e.eval("print('hello')");
 514         } catch (final Throwable t) {
 515             t.printStackTrace();
 516             fail(t.getMessage());
 517         }
 518 
 519         assertEquals(sw.toString(), println("hello"));
 520     }
 521 
 522     @Test
 523     // check that print prints all arguments (more than one)
 524     public void printManyTest() {
 525         final ScriptEngineManager m = new ScriptEngineManager();
 526         final ScriptEngine e = m.getEngineByName("nashorn");
 527         final StringWriter sw = new StringWriter();
 528         e.getContext().setWriter(sw);
 529         try {
 530             e.eval("print(34, true, 'hello')");
 531         } catch (final Throwable t) {
 532             t.printStackTrace();
 533             fail(t.getMessage());
 534         }
 535 
 536         assertEquals(sw.toString(), println("34 true hello"));
 537     }
 538 
 539     @Test
 540     public void scriptObjectAutoConversionTest() throws ScriptException {
 541         final ScriptEngineManager m = new ScriptEngineManager();
 542         final ScriptEngine e = m.getEngineByName("nashorn");
 543         e.eval("obj = { foo: 'hello' }");
 544         e.put("Window", e.eval("Packages.jdk.nashorn.api.scripting.Window"));
 545         assertEquals(e.eval("Window.funcJSObject(obj)"), "hello");
 546         assertEquals(e.eval("Window.funcScriptObjectMirror(obj)"), "hello");
 547         assertEquals(e.eval("Window.funcMap(obj)"), "hello");
 548         assertEquals(e.eval("Window.funcJSObject(obj)"), "hello");
 549     }
 550 
 551     // @bug 8032948: Nashorn linkages awry
 552     @Test
 553     public void checkProxyAccess() throws ScriptException {
 554         final ScriptEngineManager m = new ScriptEngineManager();
 555         final ScriptEngine e = m.getEngineByName("nashorn");
 556         final boolean[] reached = new boolean[1];
 557         final Runnable r = (Runnable)Proxy.newProxyInstance(
 558             ScriptEngineTest.class.getClassLoader(),
 559             new Class[] { Runnable.class },
 560             new InvocationHandler() {
 561                 @Override
 562                 public Object invoke(final Object p, final Method mtd, final Object[] a) {
 563                     reached[0] = true;
 564                     return null;
 565                 }
 566             });
 567 
 568         e.put("r", r);
 569         e.eval("r.run()");
 570 
 571         assertTrue(reached[0]);
 572     }
 573 
 574     // properties that can be read by any code
 575     private static String[] propNames = {
 576         "java.version",
 577         "java.vendor",
 578         "java.vendor.url",
 579         "java.class.version",
 580         "os.name",
 581         "os.version",
 582         "os.arch",
 583         "file.separator",
 584         "path.separator",
 585         "line.separator",
 586         "java.specification.version",
 587         "java.specification.vendor",
 588         "java.specification.name",
 589         "java.vm.specification.version",
 590         "java.vm.specification.vendor",
 591         "java.vm.specification.name",
 592         "java.vm.version",
 593         "java.vm.vendor",
 594         "java.vm.name"
 595     };
 596 
 597     // @bug 8033924: Default permissions are not given for eval code
 598     @Test
 599     public void checkPropertyReadPermissions() throws ScriptException {
 600         final ScriptEngineManager m = new ScriptEngineManager();
 601         final ScriptEngine e = m.getEngineByName("nashorn");
 602 
 603         for (final String name : propNames) {
 604             checkProperty(e, name);
 605         }
 606     }
 607 
 608     // @bug 8046013: TypeError: Cannot apply "with" to non script object
 609     @Test
 610     public void withOnMirrorTest() throws ScriptException {
 611         final ScriptEngineManager m = new ScriptEngineManager();
 612         final ScriptEngine e = m.getEngineByName("nashorn");
 613 
 614         final Object obj = e.eval("({ foo: 'hello'})");
 615         final Object[] arr = new Object[1];
 616         arr[0] = obj;
 617         e.put("arr", arr);
 618         final Object res = e.eval("var res; with(arr[0]) { res = foo; }; res");
 619         assertEquals(res, "hello");
 620     }
 621 
 622     // @bug 8054223: Nashorn: AssertionError when use __DIR__ and ScriptEngine.eval()
 623     @Test
 624     public void check__DIR__Test() throws ScriptException {
 625         final ScriptEngineManager m = new ScriptEngineManager();
 626         final ScriptEngine e = m.getEngineByName("nashorn");
 627         e.eval("__DIR__");
 628     }
 629 
 630     // @bug 8050432:javax.script.filename variable should not be enumerable
 631     // with nashorn engine's ENGINE_SCOPE bindings
 632     @Test
 633     public void enumerableGlobalsTest() throws ScriptException {
 634         final ScriptEngineManager m = new ScriptEngineManager();
 635         final ScriptEngine e = m.getEngineByName("nashorn");
 636 
 637         e.put(ScriptEngine.FILENAME, "test");
 638         final Object enumerable = e.eval(
 639             "Object.getOwnPropertyDescriptor(this, " +
 640             " 'javax.script.filename').enumerable");
 641         assertEquals(enumerable, Boolean.FALSE);
 642     }
 643 
 644     public static class Context {
 645         private Object myobj;
 646 
 647         public void set(final Object o) {
 648             myobj = o;
 649         }
 650 
 651         public Object get() {
 652             return myobj;
 653         }
 654     }
 655 
 656     // @bug 8050977: Java8 Javascript Nashorn exception:
 657     // no current Global instance for nashorn
 658     @Test
 659     public void currentGlobalMissingTest() throws Exception {
 660         final ScriptEngineManager manager = new ScriptEngineManager();
 661         final ScriptEngine e = manager.getEngineByName("nashorn");
 662 
 663         final Context ctx = new Context();
 664         e.put("ctx", ctx);
 665         e.eval("var obj = { foo: function(str) { return str.toUpperCase() } }");
 666         e.eval("ctx.set(obj)");
 667         final Invocable inv = (Invocable)e;
 668         assertEquals("HELLO", inv.invokeMethod(ctx.get(), "foo", "hello"));
 669         // try object literal
 670         e.eval("ctx.set({ bar: function(str) { return str.toLowerCase() } })");
 671         assertEquals("hello", inv.invokeMethod(ctx.get(), "bar", "HELLO"));
 672         // try array literal
 673         e.eval("var arr = [ 'hello', 'world' ]");
 674         e.eval("ctx.set(arr)");
 675         assertEquals("helloworld", inv.invokeMethod(ctx.get(), "join", ""));
 676     }
 677 
 678     // @bug 8068524: NashornScriptEngineFactory.getParameter() throws IAE
 679     // for an unknown key, doesn't conform to the general spec
 680     @Test
 681     public void getParameterInvalidKeyTest() throws Exception {
 682         final ScriptEngineManager manager = new ScriptEngineManager();
 683         final ScriptEngine e = manager.getEngineByName("nashorn");
 684         // no exception expected here!
 685         Object value = e.getFactory().getParameter("no value assigned to this key");
 686         assertNull(value);
 687     }
 688 
 689     // @bug JDK-8068889: ConsString arguments to a functional interface wasn't converted to string.
 690     @Test
 691     public void functionalInterfaceStringTest() throws Exception {
 692         final ScriptEngineManager manager = new ScriptEngineManager();
 693         final ScriptEngine e = manager.getEngineByName("nashorn");
 694         final AtomicBoolean invoked = new AtomicBoolean(false);
 695         e.put("f", new Function<String, String>() {
 696             @Override
 697             public String apply(String t) {
 698                 invoked.set(true);
 699                 return t;
 700             }
 701         });
 702         assertEquals(e.eval("var x = 'a'; x += 'b'; f(x)"), "ab");
 703         assertTrue(invoked.get());
 704     }
 705 
 706     // @bug JDK-8068889: ScriptObject arguments to a functional interface wasn't converted to a mirror.
 707     @Test
 708     public void functionalInterfaceObjectTest() throws Exception {
 709         final ScriptEngineManager manager = new ScriptEngineManager();
 710         final ScriptEngine e = manager.getEngineByName("nashorn");
 711         final AtomicBoolean invoked = new AtomicBoolean(false);
 712         e.put("c", new Consumer<Object>() {
 713             @Override
 714             public void accept(Object t) {
 715                 assertTrue(t instanceof ScriptObjectMirror);
 716                 assertEquals(((ScriptObjectMirror)t).get("a"), "xyz");
 717                 invoked.set(true);
 718             }
 719         });
 720         e.eval("var x = 'xy'; x += 'z';c({a:x})");
 721         assertTrue(invoked.get());
 722     }
 723 
 724     // @bug JDK-8068603: NashornScriptEngine.put/get() impls don't conform to NPE, IAE spec assertions
 725     @Test
 726     public void illegalBindingsValuesTest() throws Exception {
 727         final ScriptEngineManager manager = new ScriptEngineManager();
 728         final ScriptEngine e = manager.getEngineByName("nashorn");
 729 
 730         try {
 731             e.put(null, "null-value");
 732             fail();
 733         } catch (NullPointerException x) {
 734             // expected
 735         }
 736 
 737         try {
 738             e.put("", "empty-value");
 739             fail();
 740         } catch (IllegalArgumentException x) {
 741             // expected
 742         }
 743 
 744         final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
 745         assertTrue(b instanceof ScriptObjectMirror);
 746 
 747         try {
 748             b.put(null, "null-value");
 749             fail();
 750         } catch (NullPointerException x) {
 751             // expected
 752         }
 753 
 754         try {
 755             b.put("", "empty-value");
 756             fail();
 757         } catch (IllegalArgumentException x) {
 758             // expected
 759         }
 760 
 761         try {
 762             b.get(null);
 763             fail();
 764         } catch (NullPointerException x) {
 765             // expected
 766         }
 767 
 768         try {
 769             b.get("");
 770             fail();
 771         } catch (IllegalArgumentException x) {
 772             // expected
 773         }
 774 
 775         try {
 776             b.get(1);
 777             fail();
 778         } catch (ClassCastException x) {
 779             // expected
 780         }
 781 
 782         try {
 783             b.remove(null);
 784             fail();
 785         } catch (NullPointerException x) {
 786             // expected
 787         }
 788 
 789         try {
 790             b.remove("");
 791             fail();
 792         } catch (IllegalArgumentException x) {
 793             // expected
 794         }
 795 
 796         try {
 797             b.remove(1);
 798             fail();
 799         } catch (ClassCastException x) {
 800             // expected
 801         }
 802 
 803         try {
 804             b.containsKey(null);
 805             fail();
 806         } catch (NullPointerException x) {
 807             // expected
 808         }
 809 
 810         try {
 811             b.containsKey("");
 812             fail();
 813         } catch (IllegalArgumentException x) {
 814             // expected
 815         }
 816 
 817         try {
 818             b.containsKey(1);
 819             fail();
 820         } catch (ClassCastException x) {
 821             // expected
 822         }
 823 
 824         try {
 825             b.putAll(null);
 826             fail();
 827         } catch (NullPointerException x) {
 828             // expected
 829         }
 830 
 831         try {
 832             b.putAll(Collections.singletonMap((String)null, "null-value"));
 833             fail();
 834         } catch (NullPointerException x) {
 835             // expected
 836         }
 837 
 838         try {
 839             b.putAll(Collections.singletonMap("", "empty-value"));
 840             fail();
 841         } catch (IllegalArgumentException x) {
 842             // expected
 843         }
 844     }
 845 
 846     private static void checkProperty(final ScriptEngine e, final String name)
 847         throws ScriptException {
 848         final String value = System.getProperty(name);
 849         e.put("name", name);
 850         assertEquals(value, e.eval("java.lang.System.getProperty(name)"));
 851     }
 852 
 853     private static final String LINE_SEPARATOR = System.getProperty("line.separator");
 854 
 855     // Returns String that would be the result of calling PrintWriter.println
 856     // of the given String. (This is to handle platform specific newline).
 857     private static String println(final String str) {
 858         return str + LINE_SEPARATOR;
 859     }
 860 }