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 package jdk.nashorn.api.scripting; 26 27 import javax.script.Bindings; 28 import javax.script.ScriptContext; 29 import javax.script.ScriptEngine; 30 import javax.script.ScriptEngineManager; 31 import javax.script.ScriptException; 32 import javax.script.SimpleBindings; 33 import javax.script.SimpleScriptContext; 34 import org.testng.Assert; 35 import static org.testng.Assert.assertEquals; 36 import static org.testng.Assert.assertNotNull; 37 import static org.testng.Assert.assertTrue; 38 import static org.testng.Assert.fail; 39 import org.testng.annotations.Test; 40 41 /** 42 * Tests for jsr223 Bindings "scope" (engine, global scopes) 43 */ 44 public class ScopeTest { 45 46 @Test 47 public void createBindingsTest() { 48 final ScriptEngineManager m = new ScriptEngineManager(); 49 final ScriptEngine e = m.getEngineByName("nashorn"); 50 Bindings b = e.createBindings(); 51 b.put("foo", 42.0); 52 Object res = null; 53 try { 54 res = e.eval("foo == 42.0", b); 55 } catch (final ScriptException | NullPointerException se) { 56 se.printStackTrace(); 57 fail(se.getMessage()); 58 } 59 60 assertEquals(res, Boolean.TRUE); 61 } 62 63 @Test 64 public void engineScopeTest() { 65 final ScriptEngineManager m = new ScriptEngineManager(); 66 final ScriptEngine e = m.getEngineByName("nashorn"); 67 Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE); 68 69 // check few ECMA standard built-in global properties 70 assertNotNull(engineScope.get("Object")); 71 assertNotNull(engineScope.get("TypeError")); 72 assertNotNull(engineScope.get("eval")); 73 74 // can access via ScriptEngine.get as well 75 assertNotNull(e.get("Object")); 76 assertNotNull(e.get("TypeError")); 77 assertNotNull(e.get("eval")); 78 79 // Access by either way should return same object 80 assertEquals(engineScope.get("Array"), e.get("Array")); 81 assertEquals(engineScope.get("EvalError"), e.get("EvalError")); 82 assertEquals(engineScope.get("undefined"), e.get("undefined")); 83 84 // try exposing a new variable from scope 85 engineScope.put("myVar", "foo"); 86 try { 87 assertEquals(e.eval("myVar"), "foo"); 88 } catch (final ScriptException se) { 89 se.printStackTrace(); 90 fail(se.getMessage()); 91 } 92 93 // update "myVar" in script an check the value from scope 94 try { 95 e.eval("myVar = 'nashorn';"); 96 } catch (final ScriptException se) { 97 se.printStackTrace(); 98 fail(se.getMessage()); 99 } 100 101 // now check modified value from scope and engine 102 assertEquals(engineScope.get("myVar"), "nashorn"); 103 assertEquals(e.get("myVar"), "nashorn"); 104 } 105 106 @Test 107 public void multiGlobalTest() { 108 final ScriptEngineManager m = new ScriptEngineManager(); 109 final ScriptEngine e = m.getEngineByName("nashorn"); 110 final Bindings b = e.createBindings(); 111 final ScriptContext newCtxt = new SimpleScriptContext(); 112 newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); 113 114 try { 115 Object obj1 = e.eval("Object"); 116 Object obj2 = e.eval("Object", newCtxt); 117 Assert.assertNotEquals(obj1, obj2); 118 Assert.assertNotNull(obj1); 119 Assert.assertNotNull(obj2); 120 Assert.assertEquals(obj1.toString(), obj2.toString()); 121 122 e.eval("x = 'hello'"); 123 e.eval("x = 'world'", newCtxt); 124 Object x1 = e.getContext().getAttribute("x"); 125 Object x2 = newCtxt.getAttribute("x"); 126 Assert.assertNotEquals(x1, x2); 127 Assert.assertEquals(x1, "hello"); 128 Assert.assertEquals(x2, "world"); 129 130 x1 = e.eval("x"); 131 x2 = e.eval("x", newCtxt); 132 Assert.assertNotEquals(x1, x2); 133 Assert.assertEquals(x1, "hello"); 134 Assert.assertEquals(x2, "world"); 135 136 final ScriptContext origCtxt = e.getContext(); 137 e.setContext(newCtxt); 138 e.eval("y = new Object()"); 139 e.eval("y = new Object()", origCtxt); 140 141 Object y1 = origCtxt.getAttribute("y"); 142 Object y2 = newCtxt.getAttribute("y"); 143 Assert.assertNotEquals(y1, y2); 144 Assert.assertNotEquals(e.eval("y"), e.eval("y", origCtxt)); 145 Assert.assertEquals("[object Object]", y1.toString()); 146 Assert.assertEquals("[object Object]", y2.toString()); 147 } catch (final ScriptException se) { 148 se.printStackTrace(); 149 fail(se.getMessage()); 150 } 151 } 152 153 @Test 154 public void userEngineScopeBindingsTest() throws ScriptException { 155 final ScriptEngineManager m = new ScriptEngineManager(); 156 final ScriptEngine e = m.getEngineByName("nashorn"); 157 e.eval("function func() {}"); 158 159 final ScriptContext newContext = new SimpleScriptContext(); 160 newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE); 161 // we are using a new bindings - so it should have 'func' defined 162 Object value = e.eval("typeof func", newContext); 163 assertTrue(value.equals("undefined")); 164 } 165 166 @Test 167 public void userEngineScopeBindingsNoLeakTest() throws ScriptException { 168 final ScriptEngineManager m = new ScriptEngineManager(); 169 final ScriptEngine e = m.getEngineByName("nashorn"); 170 final ScriptContext newContext = new SimpleScriptContext(); 171 newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE); 172 e.eval("function foo() {}", newContext); 173 174 // in the default context's ENGINE_SCOPE, 'foo' shouldn't exist 175 assertTrue(e.eval("typeof foo").equals("undefined")); 176 } 177 178 @Test 179 public void userEngineScopeBindingsRetentionTest() throws ScriptException { 180 final ScriptEngineManager m = new ScriptEngineManager(); 181 final ScriptEngine e = m.getEngineByName("nashorn"); 182 final ScriptContext newContext = new SimpleScriptContext(); 183 newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE); 184 e.eval("function foo() {}", newContext); 185 186 // definition retained with user's ENGINE_SCOPE Binding 187 assertTrue(e.eval("typeof foo", newContext).equals("function")); 188 189 final Bindings oldBindings = newContext.getBindings(ScriptContext.ENGINE_SCOPE); 190 // but not in another ENGINE_SCOPE binding 191 newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE); 192 assertTrue(e.eval("typeof foo", newContext).equals("undefined")); 193 194 // restore ENGINE_SCOPE and check again 195 newContext.setBindings(oldBindings, ScriptContext.ENGINE_SCOPE); 196 assertTrue(e.eval("typeof foo", newContext).equals("function")); 197 } 198 199 @Test 200 // check that engine.js definitions are visible in all new global instances 201 public void checkBuiltinsInNewBindingsTest() throws ScriptException { 202 final ScriptEngineManager m = new ScriptEngineManager(); 203 final ScriptEngine e = m.getEngineByName("nashorn"); 204 205 // check default global instance has engine.js definitions 206 final Bindings g = (Bindings) e.eval("this"); 207 Object value = g.get("__noSuchProperty__"); 208 assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction()); 209 value = g.get("print"); 210 assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction()); 211 212 // check new global instance created has engine.js definitions 213 Bindings b = e.createBindings(); 214 value = b.get("__noSuchProperty__"); 215 assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction()); 216 value = b.get("print"); 217 assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction()); 218 219 // put a mapping into GLOBAL_SCOPE 220 final Bindings globalScope = e.getContext().getBindings(ScriptContext.GLOBAL_SCOPE); 221 globalScope.put("x", "hello"); 222 223 // GLOBAL_SCOPE mapping should be visible from default ScriptContext eval 224 assertTrue(e.eval("x").equals("hello")); 225 226 final ScriptContext ctx = new SimpleScriptContext(); 227 ctx.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE); 228 ctx.setBindings(b, ScriptContext.ENGINE_SCOPE); 229 230 // GLOBAL_SCOPE mapping should be visible from non-default ScriptContext eval 231 assertTrue(e.eval("x", ctx).equals("hello")); 232 233 // try some arbitray Bindings for ENGINE_SCOPE 234 Bindings sb = new SimpleBindings(); 235 ctx.setBindings(sb, ScriptContext.ENGINE_SCOPE); 236 237 // GLOBAL_SCOPE mapping should be visible from non-default ScriptContext eval 238 assertTrue(e.eval("x", ctx).equals("hello")); 239 240 // engine.js builtins are still defined even with arbitrary Bindings 241 assertTrue(e.eval("typeof print", ctx).equals("function")); 242 assertTrue(e.eval("typeof __noSuchProperty__", ctx).equals("function")); 243 244 // ENGINE_SCOPE definition should 'hide' GLOBAL_SCOPE definition 245 sb.put("x", "newX"); 246 assertTrue(e.eval("x", ctx).equals("newX")); 247 } 248 } --- EOF ---