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 }
--- EOF ---