src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java

Print this page




  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 }