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 java.nio.ByteBuffer;
29 import java.security.AccessControlContext;
30 import java.security.AccessController;
31 import java.security.Permissions;
32 import java.security.PrivilegedAction;
33 import java.security.ProtectionDomain;
34 import java.util.AbstractMap;
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.Iterator;
39 import java.util.LinkedHashSet;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Set;
43 import java.util.concurrent.Callable;
44 import javax.script.Bindings;
45 import jdk.nashorn.internal.objects.Global;
46 import jdk.nashorn.internal.runtime.ConsString;
47 import jdk.nashorn.internal.runtime.Context;
48 import jdk.nashorn.internal.runtime.JSType;
49 import jdk.nashorn.internal.runtime.ScriptFunction;
50 import jdk.nashorn.internal.runtime.ScriptObject;
51 import jdk.nashorn.internal.runtime.ScriptRuntime;
52 import jdk.nashorn.internal.runtime.arrays.ArrayData;
53 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
54
55 /**
56 * Mirror object that wraps a given Nashorn Script object.
57 *
58 * @since 1.8u40
59 */
60 @jdk.Exported
61 public final class ScriptObjectMirror extends AbstractJSObject implements Bindings {
163 public Object call() {
164 final Context context = AccessController.doPrivileged(
165 new PrivilegedAction<Context>() {
166 @Override
167 public Context run() {
168 return Context.getContext();
169 }
170 }, GET_CONTEXT_ACC_CTXT);
171 return wrap(context.eval(global, s, sobj, null, false), global);
172 }
173 });
174 }
175
176 /**
177 * Call member function
178 * @param functionName function name
179 * @param args arguments
180 * @return return value of function
181 */
182 public Object callMember(final String functionName, final Object... args) {
183 functionName.getClass(); // null check
184 final Global oldGlobal = Context.getGlobal();
185 final boolean globalChanged = (oldGlobal != global);
186
187 try {
188 if (globalChanged) {
189 Context.setGlobal(global);
190 }
191
192 final Object val = sobj.get(functionName);
193 if (val instanceof ScriptFunction) {
194 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
195 return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
196 } else if (val instanceof JSObject && ((JSObject)val).isFunction()) {
197 return ((JSObject)val).call(sobj, args);
198 }
199
200 throw new NoSuchMethodException("No such function " + functionName);
201 } catch (final NashornException ne) {
202 throw ne.initEcmaError(global);
203 } catch (final RuntimeException | Error e) {
204 throw e;
205 } catch (final Throwable t) {
206 throw new RuntimeException(t);
207 } finally {
208 if (globalChanged) {
209 Context.setGlobal(oldGlobal);
210 }
211 }
212 }
213
214 @Override
215 public Object getMember(final String name) {
216 name.getClass();
217 return inGlobal(new Callable<Object>() {
218 @Override public Object call() {
219 return wrap(sobj.get(name), global);
220 }
221 });
222 }
223
224 @Override
225 public Object getSlot(final int index) {
226 return inGlobal(new Callable<Object>() {
227 @Override public Object call() {
228 return wrap(sobj.get(index), global);
229 }
230 });
231 }
232
233 @Override
234 public boolean hasMember(final String name) {
235 name.getClass();
236 return inGlobal(new Callable<Boolean>() {
237 @Override public Boolean call() {
238 return sobj.has(name);
239 }
240 });
241 }
242
243 @Override
244 public boolean hasSlot(final int slot) {
245 return inGlobal(new Callable<Boolean>() {
246 @Override public Boolean call() {
247 return sobj.has(slot);
248 }
249 });
250 }
251
252 @Override
253 public void removeMember(final String name) {
254 name.getClass();
255 remove(name);
256 }
257
258 @Override
259 public void setMember(final String name, final Object value) {
260 name.getClass();
261 put(name, value);
262 }
263
264 @Override
265 public void setSlot(final int index, final Object value) {
266 inGlobal(new Callable<Void>() {
267 @Override public Void call() {
268 sobj.set(index, unwrap(value, global), getCallSiteFlags());
269 return null;
270 }
271 });
272 }
273
274 /**
275 * Nashorn extension: setIndexedPropertiesToExternalArrayData.
276 * set indexed properties be exposed from a given nio ByteBuffer.
277 *
278 * @param buf external buffer - should be a nio ByteBuffer
279 */
280 public void setIndexedPropertiesToExternalArrayData(final ByteBuffer buf) {
408 return Collections.unmodifiableSet(keySet);
409 }
410 });
411 }
412
413 @Override
414 public Object put(final String key, final Object value) {
415 checkKey(key);
416 final ScriptObject oldGlobal = Context.getGlobal();
417 final boolean globalChanged = (oldGlobal != global);
418 return inGlobal(new Callable<Object>() {
419 @Override public Object call() {
420 final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
421 return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global), strict), global));
422 }
423 });
424 }
425
426 @Override
427 public void putAll(final Map<? extends String, ? extends Object> map) {
428 if (map == null) {
429 throw new NullPointerException("map is null");
430 }
431 final ScriptObject oldGlobal = Context.getGlobal();
432 final boolean globalChanged = (oldGlobal != global);
433 inGlobal(new Callable<Object>() {
434 @Override public Object call() {
435 for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
436 final Object value = entry.getValue();
437 final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
438 final String key = entry.getKey();
439 checkKey(key);
440 sobj.set(key, unwrap(modValue, global), getCallSiteFlags());
441 }
442 return null;
443 }
444 });
445 }
446
447 @Override
448 public Object remove(final Object key) {
449 checkKey(key);
450 return inGlobal(new Callable<Object>() {
787 } catch (final RuntimeException e) {
788 throw e;
789 } catch (final Exception e) {
790 throw new AssertionError("Cannot happen", e);
791 } finally {
792 if (globalChanged) {
793 Context.setGlobal(oldGlobal);
794 }
795 }
796 }
797
798 /**
799 * Ensures the key is not null, empty string, or a non-String object. The contract of the {@link Bindings}
800 * interface requires that these are not accepted as keys.
801 * @param key the key to check
802 * @throws NullPointerException if key is null
803 * @throws ClassCastException if key is not a String
804 * @throws IllegalArgumentException if key is empty string
805 */
806 private static void checkKey(final Object key) {
807 if (key == null) {
808 throw new NullPointerException("key can not be null");
809 } else if (!(key instanceof String)) {
810 throw new ClassCastException("key should be a String. It is " + key.getClass().getName() + " instead.");
811 } else if (((String)key).length() == 0) {
812 throw new IllegalArgumentException("key can not be empty");
813 }
814 }
815
816 @Override
817 public double toNumber() {
818 return inGlobal(new Callable<Double>() {
819 @Override public Double call() {
820 return JSType.toNumber(sobj);
821 }
822 });
823 }
824 }
|
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 java.nio.ByteBuffer;
29 import java.security.AccessControlContext;
30 import java.security.AccessController;
31 import java.security.Permissions;
32 import java.security.PrivilegedAction;
33 import java.security.ProtectionDomain;
34 import java.util.AbstractMap;
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.Iterator;
39 import java.util.LinkedHashSet;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Objects;
43 import java.util.Set;
44 import java.util.concurrent.Callable;
45 import javax.script.Bindings;
46 import jdk.nashorn.internal.objects.Global;
47 import jdk.nashorn.internal.runtime.ConsString;
48 import jdk.nashorn.internal.runtime.Context;
49 import jdk.nashorn.internal.runtime.JSType;
50 import jdk.nashorn.internal.runtime.ScriptFunction;
51 import jdk.nashorn.internal.runtime.ScriptObject;
52 import jdk.nashorn.internal.runtime.ScriptRuntime;
53 import jdk.nashorn.internal.runtime.arrays.ArrayData;
54 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
55
56 /**
57 * Mirror object that wraps a given Nashorn Script object.
58 *
59 * @since 1.8u40
60 */
61 @jdk.Exported
62 public final class ScriptObjectMirror extends AbstractJSObject implements Bindings {
164 public Object call() {
165 final Context context = AccessController.doPrivileged(
166 new PrivilegedAction<Context>() {
167 @Override
168 public Context run() {
169 return Context.getContext();
170 }
171 }, GET_CONTEXT_ACC_CTXT);
172 return wrap(context.eval(global, s, sobj, null, false), global);
173 }
174 });
175 }
176
177 /**
178 * Call member function
179 * @param functionName function name
180 * @param args arguments
181 * @return return value of function
182 */
183 public Object callMember(final String functionName, final Object... args) {
184 Objects.requireNonNull(functionName);
185 final Global oldGlobal = Context.getGlobal();
186 final boolean globalChanged = (oldGlobal != global);
187
188 try {
189 if (globalChanged) {
190 Context.setGlobal(global);
191 }
192
193 final Object val = sobj.get(functionName);
194 if (val instanceof ScriptFunction) {
195 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
196 return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
197 } else if (val instanceof JSObject && ((JSObject)val).isFunction()) {
198 return ((JSObject)val).call(sobj, args);
199 }
200
201 throw new NoSuchMethodException("No such function " + functionName);
202 } catch (final NashornException ne) {
203 throw ne.initEcmaError(global);
204 } catch (final RuntimeException | Error e) {
205 throw e;
206 } catch (final Throwable t) {
207 throw new RuntimeException(t);
208 } finally {
209 if (globalChanged) {
210 Context.setGlobal(oldGlobal);
211 }
212 }
213 }
214
215 @Override
216 public Object getMember(final String name) {
217 Objects.requireNonNull(name);
218 return inGlobal(new Callable<Object>() {
219 @Override public Object call() {
220 return wrap(sobj.get(name), global);
221 }
222 });
223 }
224
225 @Override
226 public Object getSlot(final int index) {
227 return inGlobal(new Callable<Object>() {
228 @Override public Object call() {
229 return wrap(sobj.get(index), global);
230 }
231 });
232 }
233
234 @Override
235 public boolean hasMember(final String name) {
236 Objects.requireNonNull(name);
237 return inGlobal(new Callable<Boolean>() {
238 @Override public Boolean call() {
239 return sobj.has(name);
240 }
241 });
242 }
243
244 @Override
245 public boolean hasSlot(final int slot) {
246 return inGlobal(new Callable<Boolean>() {
247 @Override public Boolean call() {
248 return sobj.has(slot);
249 }
250 });
251 }
252
253 @Override
254 public void removeMember(final String name) {
255 Objects.requireNonNull(name);
256 remove(name);
257 }
258
259 @Override
260 public void setMember(final String name, final Object value) {
261 Objects.requireNonNull(name);
262 put(name, value);
263 }
264
265 @Override
266 public void setSlot(final int index, final Object value) {
267 inGlobal(new Callable<Void>() {
268 @Override public Void call() {
269 sobj.set(index, unwrap(value, global), getCallSiteFlags());
270 return null;
271 }
272 });
273 }
274
275 /**
276 * Nashorn extension: setIndexedPropertiesToExternalArrayData.
277 * set indexed properties be exposed from a given nio ByteBuffer.
278 *
279 * @param buf external buffer - should be a nio ByteBuffer
280 */
281 public void setIndexedPropertiesToExternalArrayData(final ByteBuffer buf) {
409 return Collections.unmodifiableSet(keySet);
410 }
411 });
412 }
413
414 @Override
415 public Object put(final String key, final Object value) {
416 checkKey(key);
417 final ScriptObject oldGlobal = Context.getGlobal();
418 final boolean globalChanged = (oldGlobal != global);
419 return inGlobal(new Callable<Object>() {
420 @Override public Object call() {
421 final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
422 return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global), strict), global));
423 }
424 });
425 }
426
427 @Override
428 public void putAll(final Map<? extends String, ? extends Object> map) {
429 Objects.requireNonNull(map, "map is null");
430 final ScriptObject oldGlobal = Context.getGlobal();
431 final boolean globalChanged = (oldGlobal != global);
432 inGlobal(new Callable<Object>() {
433 @Override public Object call() {
434 for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
435 final Object value = entry.getValue();
436 final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
437 final String key = entry.getKey();
438 checkKey(key);
439 sobj.set(key, unwrap(modValue, global), getCallSiteFlags());
440 }
441 return null;
442 }
443 });
444 }
445
446 @Override
447 public Object remove(final Object key) {
448 checkKey(key);
449 return inGlobal(new Callable<Object>() {
786 } catch (final RuntimeException e) {
787 throw e;
788 } catch (final Exception e) {
789 throw new AssertionError("Cannot happen", e);
790 } finally {
791 if (globalChanged) {
792 Context.setGlobal(oldGlobal);
793 }
794 }
795 }
796
797 /**
798 * Ensures the key is not null, empty string, or a non-String object. The contract of the {@link Bindings}
799 * interface requires that these are not accepted as keys.
800 * @param key the key to check
801 * @throws NullPointerException if key is null
802 * @throws ClassCastException if key is not a String
803 * @throws IllegalArgumentException if key is empty string
804 */
805 private static void checkKey(final Object key) {
806 Objects.requireNonNull(key, "key can not be null");
807
808 if (!(key instanceof String)) {
809 throw new ClassCastException("key should be a String. It is " + key.getClass().getName() + " instead.");
810 } else if (((String)key).length() == 0) {
811 throw new IllegalArgumentException("key can not be empty");
812 }
813 }
814
815 @Override
816 public double toNumber() {
817 return inGlobal(new Callable<Double>() {
818 @Override public Double call() {
819 return JSType.toNumber(sobj);
820 }
821 });
822 }
823 }
|