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