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.assertFalse;
  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.Method;
  37 import java.util.HashMap;
  38 import java.util.Map;
  39 import java.util.concurrent.Callable;
  40 import javax.script.Bindings;
  41 import javax.script.Compilable;
  42 import javax.script.CompiledScript;
  43 import javax.script.Invocable;
  44 import javax.script.ScriptContext;
  45 import javax.script.ScriptEngine;
  46 import javax.script.ScriptEngineFactory;
  47 import javax.script.ScriptEngineManager;
  48 import javax.script.ScriptException;
  49 import javax.script.SimpleScriptContext;
  50 import jdk.nashorn.internal.runtime.Version;
  51 import netscape.javascript.JSObject;
  52 import org.testng.Assert;
  53 import org.testng.TestNG;
  54 import org.testng.annotations.Test;
  55 
  56 /**
  57  * Tests for JSR-223 script engine for Nashorn.
  58  */
  59 public class ScriptEngineTest {
  60 
  61     public static void main(final String[] args) {
  62         TestNG.main(args);
  63     }
  64 
  65     private void log(String msg) {
  66         org.testng.Reporter.log(msg, true);
  67     }
  68 
  69     @Test
  70     public void argumentsTest() {
  71         final ScriptEngineManager m = new ScriptEngineManager();
  72         final ScriptEngine e = m.getEngineByName("nashorn");
  73 
  74         String[] args = new String[] { "hello", "world" };
  75         try {
  76             e.put("arguments", args);
  77             Object arg0 = e.eval("arguments[0]");
  78             Object arg1 = e.eval("arguments[1]");
  79             assertEquals(args[0], arg0);
  80             assertEquals(args[1], arg1);
  81         } catch (final Exception exp) {
  82             exp.printStackTrace();
  83             fail(exp.getMessage());
  84         }
  85     }
  86 
  87     @Test
  88     public void argumentsWithTest() {
  89         final ScriptEngineManager m = new ScriptEngineManager();
  90         final ScriptEngine e = m.getEngineByName("nashorn");
  91 
  92         String[] args = new String[] { "hello", "world" };
  93         try {
  94             e.put("arguments", args);
  95             Object arg0 = e.eval("var imports = new JavaImporter(java.io); " +
  96                     " with(imports) { arguments[0] }");
  97             Object arg1 = e.eval("var imports = new JavaImporter(java.util, java.io); " +
  98                     " with(imports) { arguments[1] }");
  99             assertEquals(args[0], arg0);
 100             assertEquals(args[1], arg1);
 101         } catch (final Exception exp) {
 102             exp.printStackTrace();
 103             fail(exp.getMessage());
 104         }
 105     }
 106 
 107     @Test
 108     public void argumentsEmptyTest() {
 109         final ScriptEngineManager m = new ScriptEngineManager();
 110         final ScriptEngine e = m.getEngineByName("nashorn");
 111 
 112         try {
 113             assertEquals(e.eval("arguments instanceof Array"), true);
 114             assertEquals(e.eval("arguments.length == 0"), true);
 115         } catch (final Exception exp) {
 116             exp.printStackTrace();
 117             fail(exp.getMessage());
 118         }
 119     }
 120 
 121     @Test
 122     public void factoryTests() {
 123         final ScriptEngineManager m = new ScriptEngineManager();
 124         final ScriptEngine e = m.getEngineByName("nashorn");
 125         assertNotNull(e);
 126 
 127         final ScriptEngineFactory fac = e.getFactory();
 128 
 129         assertEquals(fac.getLanguageName(), "ECMAScript");
 130         assertEquals(fac.getParameter(ScriptEngine.NAME), "javascript");
 131         assertEquals(fac.getLanguageVersion(), "ECMA - 262 Edition 5.1");
 132         assertEquals(fac.getEngineName(), "Oracle Nashorn");
 133         assertEquals(fac.getEngineVersion(), Version.version());
 134         assertEquals(fac.getOutputStatement("context"), "print(context)");
 135         assertEquals(fac.getParameter(ScriptEngine.NAME), "javascript");
 136 
 137         boolean seenJS = false;
 138         for (String ext : fac.getExtensions()) {
 139             if (ext.equals("js")) {
 140                 seenJS = true;
 141             }
 142         }
 143 
 144         assertEquals(seenJS, true);
 145         String str = fac.getMethodCallSyntax("obj", "foo", "x");
 146         assertEquals(str, "obj.foo(x)");
 147 
 148         boolean seenNashorn = false, seenJavaScript = false, seenECMAScript = false;
 149         for (String name : fac.getNames()) {
 150             switch (name) {
 151                 case "nashorn": seenNashorn = true; break;
 152                 case "javascript": seenJavaScript = true; break;
 153                 case "ECMAScript": seenECMAScript = true; break;
 154             }
 155         }
 156 
 157         assertTrue(seenNashorn);
 158         assertTrue(seenJavaScript);
 159         assertTrue(seenECMAScript);
 160 
 161         boolean seenAppJS = false, seenAppECMA = false, seenTextJS = false, seenTextECMA = false;
 162         for (String mime : fac.getMimeTypes()) {
 163             switch (mime) {
 164                 case "application/javascript": seenAppJS = true; break;
 165                 case "application/ecmascript": seenAppECMA = true; break;
 166                 case "text/javascript": seenTextJS = true; break;
 167                 case "text/ecmascript": seenTextECMA = true; break;
 168             }
 169         }
 170 
 171         assertTrue(seenAppJS);
 172         assertTrue(seenAppECMA);
 173         assertTrue(seenTextJS);
 174         assertTrue(seenTextECMA);
 175     }
 176 
 177     @Test
 178     public void evalTests() {
 179         final ScriptEngineManager m = new ScriptEngineManager();
 180         final ScriptEngine e = m.getEngineByName("nashorn");
 181         e.put(ScriptEngine.FILENAME, "myfile.js");
 182 
 183         try {
 184             e.eval("print('hello')");
 185         } catch (final ScriptException se) {
 186             fail(se.getMessage());
 187         }
 188         try {
 189             e.eval("print('hello)");
 190             fail("script exception expected");
 191         } catch (final ScriptException se) {
 192             assertEquals(se.getLineNumber(), 1);
 193             assertEquals(se.getColumnNumber(), 13);
 194             assertEquals(se.getFileName(), "myfile.js");
 195             // se.printStackTrace();
 196         }
 197 
 198         try {
 199             Object obj = e.eval("34 + 41");
 200             assertTrue(34.0 + 41.0 == ((Number)obj).doubleValue());
 201             obj = e.eval("x = 5");
 202             assertTrue(5.0 == ((Number)obj).doubleValue());
 203         } catch (final ScriptException se) {
 204             se.printStackTrace();
 205             fail(se.getMessage());
 206         }
 207     }
 208 
 209     @Test
 210     public void compileTests() {
 211         final ScriptEngineManager m = new ScriptEngineManager();
 212         final ScriptEngine e = m.getEngineByName("nashorn");
 213         CompiledScript script = null;
 214 
 215         try {
 216             script = ((Compilable)e).compile("print('hello')");
 217         } catch (final ScriptException se) {
 218             fail(se.getMessage());
 219         }
 220 
 221         try {
 222             script.eval();
 223         } catch (final ScriptException | NullPointerException se) {
 224             se.printStackTrace();
 225             fail(se.getMessage());
 226         }
 227 
 228         // try to compile from a Reader
 229         try {
 230             script = ((Compilable)e).compile(new StringReader("print('world')"));
 231         } catch (final ScriptException se) {
 232             fail(se.getMessage());
 233         }
 234 
 235         try {
 236             script.eval();
 237         } catch (final ScriptException | NullPointerException se) {
 238             se.printStackTrace();
 239             fail(se.getMessage());
 240         }
 241     }
 242 
 243     @Test
 244     public void createBindingsTest() {
 245         final ScriptEngineManager m = new ScriptEngineManager();
 246         final ScriptEngine e = m.getEngineByName("nashorn");
 247         Bindings b = e.createBindings();
 248         b.put("foo", 42.0);
 249         Object res = null;
 250         try {
 251             res = e.eval("foo == 42.0", b);
 252         } catch (final ScriptException | NullPointerException se) {
 253             se.printStackTrace();
 254             fail(se.getMessage());
 255         }
 256 
 257         assertEquals(res, Boolean.TRUE);
 258     }
 259 
 260     @Test
 261     public void getInterfaceTest() {
 262         final ScriptEngineManager m = new ScriptEngineManager();
 263         final ScriptEngine e = m.getEngineByName("nashorn");
 264         final Invocable inv = (Invocable)e;
 265 
 266         // try to get interface from global functions
 267         try {
 268             e.eval("function run() { print('run'); };");
 269             final Runnable runnable = inv.getInterface(Runnable.class);
 270             runnable.run();
 271         } catch (final Exception exp) {
 272             exp.printStackTrace();
 273             fail(exp.getMessage());
 274         }
 275 
 276         // try interface on specific script object
 277         try {
 278             e.eval("var obj = { run: function() { print('run from obj'); } };");
 279             Object obj = e.get("obj");
 280             final Runnable runnable = inv.getInterface(obj, Runnable.class);
 281             runnable.run();
 282         } catch (final Exception exp) {
 283             exp.printStackTrace();
 284             fail(exp.getMessage());
 285         }
 286     }
 287 
 288     @Test
 289     public void accessGlobalTest() {
 290         final ScriptEngineManager m = new ScriptEngineManager();
 291         final ScriptEngine e = m.getEngineByName("nashorn");
 292 
 293         try {
 294             e.eval("var x = 'hello'");
 295             assertEquals(e.get("x"), "hello");
 296         } catch (final ScriptException exp) {
 297             exp.printStackTrace();
 298             fail(exp.getMessage());
 299         }
 300     }
 301 
 302     @Test
 303     public void exposeGlobalTest() {
 304         final ScriptEngineManager m = new ScriptEngineManager();
 305         final ScriptEngine e = m.getEngineByName("nashorn");
 306 
 307         try {
 308             e.put("y", "foo");
 309             e.eval("print(y)");
 310         } catch (final ScriptException exp) {
 311             exp.printStackTrace();
 312             fail(exp.getMessage());
 313         }
 314     }
 315 
 316     public static void alert(final Object msg) {
 317         System.out.println(msg);
 318     }
 319 
 320     @Test
 321     public void exposeMethodTest() {
 322         final ScriptEngineManager m = new ScriptEngineManager();
 323         final ScriptEngine e = m.getEngineByName("nashorn");
 324 
 325         try {
 326             final Method alert = ScriptEngineTest.class.getMethod("alert", Object.class);
 327             // expose a Method object as global var.
 328             e.put("alert", alert);
 329             // call the global var.
 330             e.eval("alert.invoke(null, 'alert! alert!!')");
 331         } catch (final NoSuchMethodException | SecurityException | ScriptException exp) {
 332             exp.printStackTrace();
 333             fail(exp.getMessage());
 334         }
 335     }
 336 
 337     @Test
 338     public void putGlobalFunctionTest() {
 339         final ScriptEngineManager m = new ScriptEngineManager();
 340         final ScriptEngine e = m.getEngineByName("nashorn");
 341 
 342         e.put("callable", new Callable<String>() {
 343             @Override
 344             public String call() throws Exception {
 345                 return "callable was called";
 346             }
 347         });
 348 
 349         try {
 350             e.eval("print(callable.call())");
 351         } catch (final ScriptException exp) {
 352             exp.printStackTrace();
 353             fail(exp.getMessage());
 354         }
 355     }
 356 
 357     @Test
 358     public void windowAlertTest() {
 359         final ScriptEngineManager m = new ScriptEngineManager();
 360         final ScriptEngine e = m.getEngineByName("nashorn");
 361         final Window window = new Window();
 362 
 363         try {
 364             e.put("window", window);
 365             e.eval("print(window.alert)");
 366             e.eval("window.alert('calling window.alert...')");
 367         } catch (final Exception exp) {
 368             exp.printStackTrace();
 369             fail(exp.getMessage());
 370         }
 371     }
 372 
 373     @Test
 374     public void windowLocationTest() {
 375         final ScriptEngineManager m = new ScriptEngineManager();
 376         final ScriptEngine e = m.getEngineByName("nashorn");
 377         final Window window = new Window();
 378 
 379         try {
 380             e.put("window", window);
 381             e.eval("print(window.location)");
 382             final Object locationValue = e.eval("window.getLocation()");
 383             assertEquals(locationValue, "http://localhost:8080/window");
 384         } catch (final Exception exp) {
 385             exp.printStackTrace();
 386             fail(exp.getMessage());
 387         }
 388     }
 389 
 390     @Test
 391     public void windowItemTest() {
 392         final ScriptEngineManager m = new ScriptEngineManager();
 393         final ScriptEngine e = m.getEngineByName("nashorn");
 394         final Window window = new Window();
 395 
 396         try {
 397             e.put("window", window);
 398             final String item1 = (String)e.eval("window.item(65535)");
 399             assertEquals(item1, "ffff");
 400             final String item2 = (String)e.eval("window.item(255)");
 401             assertEquals(item2, "ff");
 402         } catch (final Exception exp) {
 403             exp.printStackTrace();
 404             fail(exp.getMessage());
 405         }
 406     }
 407 
 408     @Test
 409     public void windowEventTest() {
 410         final ScriptEngineManager m = new ScriptEngineManager();
 411         final ScriptEngine e = m.getEngineByName("nashorn");
 412         final Window window = new Window();
 413 
 414         try {
 415             e.put("window", window);
 416             e.eval("window.onload = function() { print('window load event fired'); return true }");
 417             assertTrue((Boolean)e.eval("window.onload.loaded()"));
 418             final WindowEventHandler handler = window.getOnload();
 419             assertNotNull(handler);
 420             assertTrue(handler.loaded());
 421         } catch (final Exception exp) {
 422             exp.printStackTrace();
 423             fail(exp.getMessage());
 424         }
 425     }
 426 
 427     @Test
 428     public void throwTest() {
 429         final ScriptEngineManager m = new ScriptEngineManager();
 430         final ScriptEngine e = m.getEngineByName("nashorn");
 431         e.put(ScriptEngine.FILENAME, "throwtest.js");
 432 
 433         try {
 434             e.eval("throw 'foo'");
 435         } catch (final ScriptException exp) {
 436             log(exp.getMessage());
 437             assertEquals(exp.getMessage(), "foo in throwtest.js at line number 1 at column number 0");
 438             assertEquals(exp.getFileName(), "throwtest.js");
 439             assertEquals(exp.getLineNumber(), 1);
 440         }
 441     }
 442 
 443     @Test
 444     public void setTimeoutTest() {
 445         final ScriptEngineManager m = new ScriptEngineManager();
 446         final ScriptEngine e = m.getEngineByName("nashorn");
 447         final Window window = new Window();
 448 
 449         try {
 450             final Class<?> setTimeoutParamTypes[] = { Window.class, String.class, int.class };
 451             final Method setTimeout = Window.class.getDeclaredMethod("setTimeout", setTimeoutParamTypes);
 452             assertNotNull(setTimeout);
 453             e.put("window", window);
 454             e.eval("window.setTimeout('foo()', 100)");
 455 
 456             // try to make setTimeout global
 457             e.put("setTimeout", setTimeout);
 458             // TODO: java.lang.ClassCastException: required class
 459             // java.lang.Integer but encountered class java.lang.Double
 460             // e.eval("setTimeout('foo2()', 200)");
 461         } catch (final Exception exp) {
 462             exp.printStackTrace();
 463             fail(exp.getMessage());
 464         }
 465     }
 466 
 467     @Test
 468     public void setWriterTest() {
 469         final ScriptEngineManager m = new ScriptEngineManager();
 470         final ScriptEngine e = m.getEngineByName("nashorn");
 471         final StringWriter sw = new StringWriter();
 472         e.getContext().setWriter(sw);
 473 
 474         try {
 475             e.eval("print('hello world')");
 476         } catch (final Exception exp) {
 477             exp.printStackTrace();
 478             fail(exp.getMessage());
 479         }
 480         // dos2unix - fix line endings if running on windows
 481         assertEquals(sw.toString().replaceAll("\r", ""), "hello world\n");
 482     }
 483 
 484     @SuppressWarnings("unchecked")
 485     @Test
 486     public void reflectionTest() throws ScriptException {
 487         final ScriptEngineManager m = new ScriptEngineManager();
 488         final ScriptEngine e = m.getEngineByName("nashorn");
 489 
 490         e.eval("var obj = { x: 344, y: 'nashorn' }");
 491 
 492         int count = 0;
 493         Map<Object, Object> map = (Map<Object, Object>)e.get("obj");
 494         assertFalse(map.isEmpty());
 495         assertTrue(map.keySet().contains("x"));
 496         assertTrue(map.containsKey("x"));
 497         assertTrue(map.values().contains("nashorn"));
 498         assertTrue(map.containsValue("nashorn"));
 499         for (final Map.Entry<?, ?> ex : map.entrySet()) {
 500             final Object key = ex.getKey();
 501             if (key.equals("x")) {
 502                 assertTrue(344 == ((Number)ex.getValue()).doubleValue());
 503                 count++;
 504             } else if (key.equals("y")) {
 505                 assertEquals(ex.getValue(), "nashorn");
 506                 count++;
 507             }
 508         }
 509         assertEquals(2, count);
 510         assertEquals(2, map.size());
 511 
 512         // add property
 513         map.put("z", "hello");
 514         assertEquals(e.eval("obj.z"), "hello");
 515         assertEquals(map.get("z"), "hello");
 516         assertTrue(map.keySet().contains("z"));
 517         assertTrue(map.containsKey("z"));
 518         assertTrue(map.values().contains("hello"));
 519         assertTrue(map.containsValue("hello"));
 520         assertEquals(map.size(), 3);
 521 
 522         final Map<Object, Object> newMap = new HashMap<>();
 523         newMap.put("foo", 23.0);
 524         newMap.put("bar", true);
 525         map.putAll(newMap);
 526 
 527         assertEquals(e.eval("obj.foo"), 23.0);
 528         assertEquals(e.eval("obj.bar"), true);
 529 
 530         // remove using map method
 531         map.remove("foo");
 532         assertEquals(e.eval("typeof obj.foo"), "undefined");
 533 
 534         count = 0;
 535         e.eval("var arr = [ true, 'hello' ]");
 536         map = (Map<Object, Object>)e.get("arr");
 537         assertFalse(map.isEmpty());
 538         assertTrue(map.containsKey("length"));
 539         assertTrue(map.containsValue("hello"));
 540         for (final Map.Entry<?, ?> ex : map.entrySet()) {
 541             final Object key = ex.getKey();
 542             if (key.equals("0")) {
 543                 assertEquals(ex.getValue(), Boolean.TRUE);
 544                 count++;
 545             } else if (key.equals("1")) {
 546                 assertEquals(ex.getValue(), "hello");
 547                 count++;
 548             }
 549         }
 550         assertEquals(count, 2);
 551         assertEquals(map.size(), 2);
 552 
 553         // add element
 554         map.put("2", "world");
 555         assertEquals(map.get("2"), "world");
 556         assertEquals(map.size(), 3);
 557 
 558         // remove all
 559         map.clear();
 560         assertTrue(map.isEmpty());
 561         assertEquals(e.eval("typeof arr[0]"), "undefined");
 562         assertEquals(e.eval("typeof arr[1]"), "undefined");
 563         assertEquals(e.eval("typeof arr[2]"), "undefined");
 564     }
 565 
 566     @Test
 567     public void redefineEchoTest() {
 568         final ScriptEngineManager m = new ScriptEngineManager();
 569         final ScriptEngine e = m.getEngineByName("nashorn");
 570 
 571         try {
 572             e.eval("var echo = {}; if (typeof echo !== 'object') { throw 'echo is a '+typeof echo; }");
 573         } catch (final Exception exp) {
 574             exp.printStackTrace();
 575             fail(exp.getMessage());
 576         }
 577     }
 578 
 579     @Test
 580     public void invokeMethodTest() {
 581         final ScriptEngineManager m = new ScriptEngineManager();
 582         final ScriptEngine e = m.getEngineByName("nashorn");
 583 
 584         try {
 585             e.eval("var Example = function() { this.hello = function() { return 'Hello World!'; };}; myExample = new Example();");
 586             final Object obj = e.get("myExample");
 587             final Object res = ((Invocable)e).invokeMethod(obj, "hello");
 588             assertEquals(res, "Hello World!");
 589         } catch (final Exception exp) {
 590             exp.printStackTrace();
 591             fail(exp.getMessage());
 592         }
 593     }
 594 
 595     @Test
 596     public void versionTest() {
 597         final ScriptEngineManager m = new ScriptEngineManager();
 598         final ScriptEngine e = m.getEngineByName("nashorn");
 599         assertEquals(e.getFactory().getEngineVersion(), Version.version());
 600     }
 601 
 602     @Test
 603     public void noEnumerablePropertiesTest() {
 604         final ScriptEngineManager m = new ScriptEngineManager();
 605         final ScriptEngine e = m.getEngineByName("nashorn");
 606         try {
 607             e.eval("for (i in this) { throw 'found property: ' + i }");
 608         } catch (final Exception exp) {
 609             exp.printStackTrace();
 610             fail(exp.getMessage());
 611         }
 612     }
 613 
 614     @Test
 615     public void noRefErrorForGlobalThisAccessTest() {
 616         final ScriptEngineManager m = new ScriptEngineManager();
 617         final ScriptEngine e = m.getEngineByName("nashorn");
 618         try {
 619             e.eval("this.foo");
 620         } catch (final Exception exp) {
 621             exp.printStackTrace();
 622             fail(exp.getMessage());
 623         }
 624     }
 625 
 626     @Test
 627     public void refErrorForUndeclaredAccessTest() {
 628         final ScriptEngineManager m = new ScriptEngineManager();
 629         final ScriptEngine e = m.getEngineByName("nashorn");
 630         try {
 631             e.eval("try { print(foo); throw 'no ref error' } catch (e) { if (!(e instanceof ReferenceError)) throw e; }");
 632         } catch (final Exception exp) {
 633             exp.printStackTrace();
 634             fail(exp.getMessage());
 635         }
 636     }
 637 
 638     @Test
 639     public void typeErrorForGlobalThisCallTest() {
 640         final ScriptEngineManager m = new ScriptEngineManager();
 641         final ScriptEngine e = m.getEngineByName("nashorn");
 642         try {
 643             e.eval("try { this.foo() } catch(e) { if (! (e instanceof TypeError)) throw 'no type error' }");
 644         } catch (final Exception exp) {
 645             exp.printStackTrace();
 646             fail(exp.getMessage());
 647         }
 648     }
 649 
 650     @Test
 651     public void refErrorForUndeclaredCallTest() {
 652         final ScriptEngineManager m = new ScriptEngineManager();
 653         final ScriptEngine e = m.getEngineByName("nashorn");
 654         try {
 655             e.eval("try { foo() } catch(e) { if (! (e instanceof ReferenceError)) throw 'no ref error' }");
 656         } catch (final Exception exp) {
 657             exp.printStackTrace();
 658             fail(exp.getMessage());
 659         }
 660     }
 661 
 662     @Test
 663     public void securityPackagesTest() {
 664         if (System.getSecurityManager() == null) {
 665             // pass vacuously
 666         }
 667 
 668         final ScriptEngineManager m = new ScriptEngineManager();
 669         final ScriptEngine e = m.getEngineByName("nashorn");
 670         try {
 671             e.eval("var v = Packages.sun.misc.Unsafe;");
 672             fail("should have thrown SecurityException");
 673         } catch (final Exception exp) {
 674             if (exp instanceof SecurityException) {
 675                 log("got " + exp + " as expected");
 676             } else {
 677                 fail(exp.getMessage());
 678             }
 679         }
 680     }
 681 
 682     @Test
 683     public void securityJavaTypeTest() {
 684         if (System.getSecurityManager() == null) {
 685             // pass vacuously
 686         }
 687 
 688         final ScriptEngineManager m = new ScriptEngineManager();
 689         final ScriptEngine e = m.getEngineByName("nashorn");
 690         try {
 691             e.eval("var v = Java.type('sun.misc.Unsafe');");
 692             fail("should have thrown SecurityException");
 693         } catch (final Exception exp) {
 694             if (exp instanceof SecurityException) {
 695                 log("got " + exp + " as expected");
 696             } else {
 697                 fail(exp.getMessage());
 698             }
 699         }
 700     }
 701 
 702     @Test
 703     public void securityClassForNameTest() {
 704         if (System.getSecurityManager() == null) {
 705             // pass vacuously
 706         }
 707 
 708         final ScriptEngineManager m = new ScriptEngineManager();
 709         final ScriptEngine e = m.getEngineByName("nashorn");
 710         try {
 711             e.eval("var v = java.lang.Class.forName('sun.misc.Unsafe');");
 712             fail("should have thrown SecurityException");
 713         } catch (final Exception exp) {
 714             if (exp instanceof SecurityException) {
 715                 log("got " + exp + " as expected");
 716             } else {
 717                 fail(exp.getMessage());
 718             }
 719         }
 720     }
 721 
 722     @Test
 723     public void securitySystemExit() {
 724         if (System.getSecurityManager() == null) {
 725             // pass vacuously
 726         }
 727 
 728         final ScriptEngineManager m = new ScriptEngineManager();
 729         final ScriptEngine e = m.getEngineByName("nashorn");
 730         try {
 731             e.eval("java.lang.System.exit(0);");
 732             fail("should have thrown SecurityException");
 733         } catch (final Exception exp) {
 734             if (exp instanceof SecurityException) {
 735                 log("got " + exp + " as expected");
 736             } else {
 737                 fail(exp.getMessage());
 738             }
 739         }
 740     }
 741 
 742     @Test
 743     public void securitySystemLoadLibrary() {
 744         if (System.getSecurityManager() == null) {
 745             // pass vacuously
 746         }
 747 
 748         final ScriptEngineManager m = new ScriptEngineManager();
 749         final ScriptEngine e = m.getEngineByName("nashorn");
 750         try {
 751             e.eval("java.lang.System.loadLibrary('foo');");
 752             fail("should have thrown SecurityException");
 753         } catch (final Exception exp) {
 754             if (exp instanceof SecurityException) {
 755                 log("got " + exp + " as expected");
 756             } else {
 757                 fail(exp.getMessage());
 758             }
 759         }
 760     }
 761 
 762     @Test
 763     public void jsobjectTest() {
 764         final ScriptEngineManager m = new ScriptEngineManager();
 765         final ScriptEngine e = m.getEngineByName("nashorn");
 766         try {
 767             e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }");
 768             JSObject obj = (JSObject) e.get("obj");
 769 
 770             // try basic get on existing properties
 771             if (! obj.getMember("bar").equals("hello")) {
 772                 fail("obj.bar != 'hello'");
 773             }
 774 
 775             if (! obj.getSlot(1).equals("world")) {
 776                 fail("obj[1] != 'world'");
 777             }
 778 
 779             if (! obj.call("func", new Object[0]).equals("hello")) {
 780                 fail("obj.call('func') != 'hello'");
 781             }
 782 
 783             // try setting properties
 784             obj.setMember("bar", "new-bar");
 785             obj.setSlot(1, "new-element-1");
 786             if (! obj.getMember("bar").equals("new-bar")) {
 787                 fail("obj.bar != 'new-bar'");
 788             }
 789 
 790             if (! obj.getSlot(1).equals("new-element-1")) {
 791                 fail("obj[1] != 'new-element-1'");
 792             }
 793 
 794             // try adding properties
 795             obj.setMember("prop", "prop-value");
 796             obj.setSlot(12, "element-12");
 797             if (! obj.getMember("prop").equals("prop-value")) {
 798                 fail("obj.prop != 'prop-value'");
 799             }
 800 
 801             if (! obj.getSlot(12).equals("element-12")) {
 802                 fail("obj[12] != 'element-12'");
 803             }
 804 
 805             // delete properties
 806             obj.removeMember("prop");
 807             if ("prop-value".equals(obj.getMember("prop"))) {
 808                 fail("obj.prop is not deleted!");
 809             }
 810 
 811         } catch (final Exception exp) {
 812             exp.printStackTrace();
 813             fail(exp.getMessage());
 814         }
 815     }
 816 
 817     @Test
 818     public void invokeFunctionExceptionTest() {
 819         final ScriptEngineManager m = new ScriptEngineManager();
 820         final ScriptEngine e = m.getEngineByName("nashorn");
 821         try {
 822             e.eval("function func() { throw new TypeError(); }");
 823         } catch (final Throwable t) {
 824             t.printStackTrace();
 825             fail(t.getMessage());
 826         }
 827 
 828         try {
 829             ((Invocable)e).invokeFunction("func");
 830             fail("should have thrown exception");
 831         } catch (final ScriptException se) {
 832             // ECMA TypeError property wrapped as a ScriptException
 833             log("got " + se + " as expected");
 834         } catch (final Throwable t) {
 835             t.printStackTrace();
 836             fail(t.getMessage());
 837         }
 838     }
 839 
 840     @Test
 841     public void invokeMethodExceptionTest() {
 842         final ScriptEngineManager m = new ScriptEngineManager();
 843         final ScriptEngine e = m.getEngineByName("nashorn");
 844         try {
 845             e.eval("var sobj = {}; sobj.foo = function func() { throw new TypeError(); }");
 846         } catch (final Throwable t) {
 847             t.printStackTrace();
 848             fail(t.getMessage());
 849         }
 850 
 851         try {
 852             final Object sobj = e.get("sobj");
 853             ((Invocable)e).invokeMethod(sobj, "foo");
 854             fail("should have thrown exception");
 855         } catch (final ScriptException se) {
 856             // ECMA TypeError property wrapped as a ScriptException
 857             log("got " + se + " as expected");
 858         } catch (final Throwable t) {
 859             t.printStackTrace();
 860             fail(t.getMessage());
 861         }
 862     }
 863 
 864     @Test
 865     public void scriptObjectMirrorToStringTest() {
 866         final ScriptEngineManager m = new ScriptEngineManager();
 867         final ScriptEngine e = m.getEngineByName("nashorn");
 868         try {
 869             Object obj = e.eval("new TypeError('wrong type')");
 870             assertEquals(obj.toString(), "TypeError: wrong type", "toString returns wrong value");
 871         } catch (final Throwable t) {
 872             t.printStackTrace();
 873             fail(t.getMessage());
 874         }
 875 
 876         try {
 877             Object obj = e.eval("function func() { print('hello'); }");
 878             assertEquals(obj.toString(), "function func() { print('hello'); }", "toString returns wrong value");
 879         } catch (final Throwable t) {
 880             t.printStackTrace();
 881             fail(t.getMessage());
 882         }
 883     }
 884 
 885     @Test
 886     public void engineScopeTest() {
 887         final ScriptEngineManager m = new ScriptEngineManager();
 888         final ScriptEngine e = m.getEngineByName("nashorn");
 889         Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
 890 
 891         // check few ECMA standard built-in global properties
 892         assertNotNull(engineScope.get("Object"));
 893         assertNotNull(engineScope.get("TypeError"));
 894         assertNotNull(engineScope.get("eval"));
 895 
 896         // can access via ScriptEngine.get as well
 897         assertNotNull(e.get("Object"));
 898         assertNotNull(e.get("TypeError"));
 899         assertNotNull(e.get("eval"));
 900 
 901         // Access by either way should return same object
 902         assertEquals(engineScope.get("Array"), e.get("Array"));
 903         assertEquals(engineScope.get("EvalError"), e.get("EvalError"));
 904         assertEquals(engineScope.get("undefined"), e.get("undefined"));
 905 
 906         // try exposing a new variable from scope
 907         engineScope.put("myVar", "foo");
 908         try {
 909             assertEquals(e.eval("myVar"), "foo");
 910         } catch (final ScriptException se) {
 911             se.printStackTrace();
 912             fail(se.getMessage());
 913         }
 914 
 915         // update "myVar" in script an check the value from scope
 916         try {
 917             e.eval("myVar = 'nashorn';");
 918         } catch (final ScriptException se) {
 919             se.printStackTrace();
 920             fail(se.getMessage());
 921         }
 922 
 923         // now check modified value from scope and engine
 924         assertEquals(engineScope.get("myVar"), "nashorn");
 925         assertEquals(e.get("myVar"), "nashorn");
 926     }
 927 
 928     @Test
 929     public void multiGlobalTest() {
 930         final ScriptEngineManager m = new ScriptEngineManager();
 931         final ScriptEngine e = m.getEngineByName("nashorn");
 932         final Bindings b = e.createBindings();
 933         final ScriptContext newCtxt = new SimpleScriptContext();
 934         newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
 935 
 936         try {
 937             Object obj1 = e.eval("Object");
 938             Object obj2 = e.eval("Object", newCtxt);
 939             Assert.assertNotEquals(obj1, obj2);
 940             Assert.assertNotNull(obj1);
 941             Assert.assertNotNull(obj2);
 942             Assert.assertEquals(obj1.toString(), obj2.toString());
 943 
 944             e.eval("x = 'hello'");
 945             e.eval("x = 'world'", newCtxt);
 946             Object x1 = e.getContext().getAttribute("x");
 947             Object x2 = newCtxt.getAttribute("x");
 948             Assert.assertNotEquals(x1, x2);
 949             Assert.assertEquals(x1, "hello");
 950             Assert.assertEquals(x2, "world");
 951 
 952             x1 = e.eval("x");
 953             x2 = e.eval("x", newCtxt);
 954             Assert.assertNotEquals(x1, x2);
 955             Assert.assertEquals(x1, "hello");
 956             Assert.assertEquals(x2, "world");
 957 
 958             final ScriptContext origCtxt = e.getContext();
 959             e.setContext(newCtxt);
 960             e.eval("y = new Object()");
 961             e.eval("y = new Object()", origCtxt);
 962 
 963             Object y1 = origCtxt.getAttribute("y");
 964             Object y2 = newCtxt.getAttribute("y");
 965             Assert.assertNotEquals(y1, y2);
 966             Assert.assertNotEquals(e.eval("y"), e.eval("y", origCtxt));
 967             Assert.assertEquals("[object Object]", y1.toString());
 968             Assert.assertEquals("[object Object]", y2.toString());
 969         } catch (final ScriptException se) {
 970             se.printStackTrace();
 971             fail(se.getMessage());
 972         }
 973     }
 974 }