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

Print this page
rev 737 : 8029364: NashornException to expose thrown object
Reviewed-by: lagergren, jlaskey
rev 752 : 8011964: need indexed access to externally-managed ByteBuffer
Reviewed-by: lagergren, hannesw
rev 760 : 8037400: Remove getInitialMap getters and GlobalObject interface
Reviewed-by: lagergren, jlaskey, attila


   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 java.security.AccessControlContext;
  29 import java.security.AccessController;
  30 import java.security.Permissions;
  31 import java.security.PrivilegedAction;
  32 import java.security.ProtectionDomain;
  33 import java.util.AbstractMap;
  34 import java.util.ArrayList;
  35 import java.util.Collection;
  36 import java.util.Collections;
  37 import java.util.Iterator;
  38 import java.util.LinkedHashSet;
  39 import java.util.List;
  40 import java.util.Map;
  41 import java.util.Set;
  42 import java.util.concurrent.Callable;
  43 import javax.script.Bindings;


  44 import jdk.nashorn.internal.runtime.ConsString;
  45 import jdk.nashorn.internal.runtime.Context;
  46 import jdk.nashorn.internal.runtime.GlobalObject;
  47 import jdk.nashorn.internal.runtime.JSType;
  48 import jdk.nashorn.internal.runtime.ScriptFunction;
  49 import jdk.nashorn.internal.runtime.ScriptObject;
  50 import jdk.nashorn.internal.runtime.ScriptRuntime;
  51 
  52 /**
  53  * Mirror object that wraps a given Nashorn Script object.
  54  */
  55 public final class ScriptObjectMirror extends AbstractJSObject implements Bindings {
  56     private static AccessControlContext getContextAccCtxt() {
  57         final Permissions perms = new Permissions();
  58         perms.add(new RuntimePermission(Context.NASHORN_GET_CONTEXT));
  59         return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
  60     }
  61 
  62     private static final AccessControlContext GET_CONTEXT_ACC_CTXT = getContextAccCtxt();
  63 
  64     private final ScriptObject sobj;
  65     private final ScriptObject global;
  66     private final boolean strict;
  67 
  68     @Override
  69     public boolean equals(final Object other) {
  70         if (other instanceof ScriptObjectMirror) {
  71             return sobj.equals(((ScriptObjectMirror)other).sobj);
  72         }
  73 
  74         return false;
  75     }
  76 
  77     @Override
  78     public int hashCode() {
  79         return sobj.hashCode();
  80     }
  81 
  82     @Override
  83     public String toString() {
  84         return inGlobal(new Callable<String>() {
  85             @Override
  86             public String call() {
  87                 return ScriptRuntime.safeToString(sobj);
  88             }
  89         });
  90     }
  91 
  92     // JSObject methods
  93 
  94     @Override
  95     public Object call(final Object thiz, final Object... args) {
  96         final ScriptObject oldGlobal = Context.getGlobal();
  97         final boolean globalChanged = (oldGlobal != global);
  98 
  99         try {
 100             if (globalChanged) {
 101                 Context.setGlobal(global);
 102             }
 103 
 104             if (sobj instanceof ScriptFunction) {
 105                 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
 106                 final Object self = globalChanged? wrap(thiz, oldGlobal) : thiz;
 107                 return wrap(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)), global);
 108             }
 109 
 110             throw new RuntimeException("not a function: " + toString());


 111         } catch (final RuntimeException | Error e) {
 112             throw e;
 113         } catch (final Throwable t) {
 114             throw new RuntimeException(t);
 115         } finally {
 116             if (globalChanged) {
 117                 Context.setGlobal(oldGlobal);
 118             }
 119         }
 120     }
 121 
 122     @Override
 123     public Object newObject(final Object... args) {
 124         final ScriptObject oldGlobal = Context.getGlobal();
 125         final boolean globalChanged = (oldGlobal != global);
 126 
 127         try {
 128             if (globalChanged) {
 129                 Context.setGlobal(global);
 130             }
 131 
 132             if (sobj instanceof ScriptFunction) {
 133                 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
 134                 return wrap(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)), global);
 135             }
 136 
 137             throw new RuntimeException("not a constructor: " + toString());


 138         } catch (final RuntimeException | Error e) {
 139             throw e;
 140         } catch (final Throwable t) {
 141             throw new RuntimeException(t);
 142         } finally {
 143             if (globalChanged) {
 144                 Context.setGlobal(oldGlobal);
 145             }
 146         }
 147     }
 148 
 149     @Override
 150     public Object eval(final String s) {
 151         return inGlobal(new Callable<Object>() {
 152             @Override
 153             public Object call() {
 154                 final Context context = AccessController.doPrivileged(
 155                         new PrivilegedAction<Context>() {
 156                             @Override
 157                             public Context run() {
 158                                 return Context.getContext();
 159                             }
 160                         }, GET_CONTEXT_ACC_CTXT);
 161                 return wrap(context.eval(global, s, null, null, false), global);
 162             }
 163         });
 164     }
 165 
 166     public Object callMember(final String functionName, final Object... args) {
 167         functionName.getClass(); // null check
 168         final ScriptObject oldGlobal = Context.getGlobal();
 169         final boolean globalChanged = (oldGlobal != global);
 170 
 171         try {
 172             if (globalChanged) {
 173                 Context.setGlobal(global);
 174             }
 175 
 176             final Object val = sobj.get(functionName);
 177             if (val instanceof ScriptFunction) {
 178                 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
 179                 return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
 180             } else if (val instanceof JSObject && ((JSObject)val).isFunction()) {
 181                 return ((JSObject)val).call(sobj, args);
 182             }
 183 
 184             throw new NoSuchMethodException("No such function " + functionName);


 185         } catch (final RuntimeException | Error e) {
 186             throw e;
 187         } catch (final Throwable t) {
 188             throw new RuntimeException(t);
 189         } finally {
 190             if (globalChanged) {
 191                 Context.setGlobal(oldGlobal);
 192             }
 193         }
 194     }
 195 
 196     @Override
 197     public Object getMember(final String name) {
 198         name.getClass();
 199         return inGlobal(new Callable<Object>() {
 200             @Override public Object call() {
 201                 return wrap(sobj.get(name), global);
 202             }
 203         });
 204     }


 236         name.getClass();
 237         remove(name);
 238     }
 239 
 240     @Override
 241     public void setMember(final String name, final Object value) {
 242         name.getClass();
 243         put(name, value);
 244     }
 245 
 246     @Override
 247     public void setSlot(final int index, final Object value) {
 248         inGlobal(new Callable<Void>() {
 249             @Override public Void call() {
 250                 sobj.set(index, unwrap(value, global), strict);
 251                 return null;
 252             }
 253         });
 254     }
 255 
















 256     @Override
 257     public boolean isInstance(final Object obj) {
 258         if (! (obj instanceof ScriptObjectMirror)) {
 259             return false;
 260         }
 261 
 262         final ScriptObjectMirror instance = (ScriptObjectMirror)obj;
 263         // if not belongs to my global scope, return false
 264         if (global != instance.global) {
 265             return false;
 266         }
 267 
 268         return inGlobal(new Callable<Boolean>() {
 269             @Override public Boolean call() {
 270                 return sobj.isInstance(instance.sobj);
 271             }
 272         });
 273     }
 274 
 275     @Override


 601      * @return converted object
 602      */
 603     public <T> T to(final Class<T> type) {
 604         return inGlobal(new Callable<T>() {
 605             @Override
 606             public T call() {
 607                 return type.cast(ScriptUtils.convert(sobj, type));
 608             }
 609         });
 610     }
 611 
 612     /**
 613      * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings.
 614      *
 615      * @param obj object to be wrapped/converted
 616      * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
 617      * @return wrapped/converted object
 618      */
 619     public static Object wrap(final Object obj, final Object homeGlobal) {
 620         if(obj instanceof ScriptObject) {
 621             return homeGlobal instanceof ScriptObject ? new ScriptObjectMirror((ScriptObject)obj, (ScriptObject)homeGlobal) : obj;
 622         }
 623         if(obj instanceof ConsString) {
 624             return obj.toString();
 625         }
 626         return obj;
 627     }
 628 
 629     /**
 630      * Unwrap a script object mirror if needed.
 631      *
 632      * @param obj object to be unwrapped
 633      * @param homeGlobal global to which this object belongs
 634      * @return unwrapped object
 635      */
 636     public static Object unwrap(final Object obj, final Object homeGlobal) {
 637         if (obj instanceof ScriptObjectMirror) {
 638             final ScriptObjectMirror mirror = (ScriptObjectMirror)obj;
 639             return (mirror.global == homeGlobal)? mirror.sobj : obj;
 640         }
 641 


 669      * @param args array to be unwrapped
 670      * @param homeGlobal global to which this object belongs
 671      * @return unwrapped array
 672      */
 673     public static Object[] unwrapArray(final Object[] args, final Object homeGlobal) {
 674         if (args == null || args.length == 0) {
 675             return args;
 676         }
 677 
 678         final Object[] newArgs = new Object[args.length];
 679         int index = 0;
 680         for (final Object obj : args) {
 681             newArgs[index] = unwrap(obj, homeGlobal);
 682             index++;
 683         }
 684         return newArgs;
 685     }
 686 
 687     // package-privates below this.
 688 
 689     ScriptObjectMirror(final ScriptObject sobj, final ScriptObject global) {
 690         assert sobj != null : "ScriptObjectMirror on null!";
 691         assert global instanceof GlobalObject : "global is not a GlobalObject";
 692 
 693         this.sobj = sobj;
 694         this.global = global;
 695         this.strict = ((GlobalObject)global).isStrictContext();
 696     }
 697 
 698     // accessors for script engine
 699     ScriptObject getScriptObject() {
 700         return sobj;
 701     }
 702 
 703     ScriptObject getHomeGlobal() {
 704         return global;
 705     }
 706 
 707     static Object translateUndefined(Object obj) {
 708         return (obj == ScriptRuntime.UNDEFINED)? null : obj;
 709     }
 710 
 711     // internals only below this.
 712     private <V> V inGlobal(final Callable<V> callable) {
 713         final ScriptObject oldGlobal = Context.getGlobal();
 714         final boolean globalChanged = (oldGlobal != global);
 715         if (globalChanged) {
 716             Context.setGlobal(global);
 717         }
 718         try {
 719             return callable.call();


 720         } catch (final RuntimeException e) {
 721             throw e;
 722         } catch (final Exception e) {
 723             throw new AssertionError("Cannot happen", e);
 724         } finally {
 725             if (globalChanged) {
 726                 Context.setGlobal(oldGlobal);
 727             }
 728         }
 729     }
 730 
 731     @Override
 732     public double toNumber() {
 733         return inGlobal(new Callable<Double>() {
 734             @Override public Double call() {
 735                 return JSType.toNumber(sobj);
 736             }
 737         });
 738     }
 739 }


   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 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.arrays.ArrayData;
  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 
  54 /**
  55  * Mirror object that wraps a given Nashorn Script object.
  56  */
  57 public final class ScriptObjectMirror extends AbstractJSObject implements Bindings {
  58     private static AccessControlContext getContextAccCtxt() {
  59         final Permissions perms = new Permissions();
  60         perms.add(new RuntimePermission(Context.NASHORN_GET_CONTEXT));
  61         return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
  62     }
  63 
  64     private static final AccessControlContext GET_CONTEXT_ACC_CTXT = getContextAccCtxt();
  65 
  66     private final ScriptObject sobj;
  67     private final Global  global;
  68     private final boolean strict;
  69 
  70     @Override
  71     public boolean equals(final Object other) {
  72         if (other instanceof ScriptObjectMirror) {
  73             return sobj.equals(((ScriptObjectMirror)other).sobj);
  74         }
  75 
  76         return false;
  77     }
  78 
  79     @Override
  80     public int hashCode() {
  81         return sobj.hashCode();
  82     }
  83 
  84     @Override
  85     public String toString() {
  86         return inGlobal(new Callable<String>() {
  87             @Override
  88             public String call() {
  89                 return ScriptRuntime.safeToString(sobj);
  90             }
  91         });
  92     }
  93 
  94     // JSObject methods
  95 
  96     @Override
  97     public Object call(final Object thiz, final Object... args) {
  98         final Global oldGlobal = Context.getGlobal();
  99         final boolean globalChanged = (oldGlobal != global);
 100 
 101         try {
 102             if (globalChanged) {
 103                 Context.setGlobal(global);
 104             }
 105 
 106             if (sobj instanceof ScriptFunction) {
 107                 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
 108                 final Object self = globalChanged? wrap(thiz, oldGlobal) : thiz;
 109                 return wrap(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)), global);
 110             }
 111 
 112             throw new RuntimeException("not a function: " + toString());
 113         } catch (final NashornException ne) {
 114             throw ne.initEcmaError(global);
 115         } catch (final RuntimeException | Error e) {
 116             throw e;
 117         } catch (final Throwable t) {
 118             throw new RuntimeException(t);
 119         } finally {
 120             if (globalChanged) {
 121                 Context.setGlobal(oldGlobal);
 122             }
 123         }
 124     }
 125 
 126     @Override
 127     public Object newObject(final Object... args) {
 128         final Global oldGlobal = Context.getGlobal();
 129         final boolean globalChanged = (oldGlobal != global);
 130 
 131         try {
 132             if (globalChanged) {
 133                 Context.setGlobal(global);
 134             }
 135 
 136             if (sobj instanceof ScriptFunction) {
 137                 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
 138                 return wrap(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)), global);
 139             }
 140 
 141             throw new RuntimeException("not a constructor: " + toString());
 142         } catch (final NashornException ne) {
 143             throw ne.initEcmaError(global);
 144         } catch (final RuntimeException | Error e) {
 145             throw e;
 146         } catch (final Throwable t) {
 147             throw new RuntimeException(t);
 148         } finally {
 149             if (globalChanged) {
 150                 Context.setGlobal(oldGlobal);
 151             }
 152         }
 153     }
 154 
 155     @Override
 156     public Object eval(final String s) {
 157         return inGlobal(new Callable<Object>() {
 158             @Override
 159             public Object call() {
 160                 final Context context = AccessController.doPrivileged(
 161                         new PrivilegedAction<Context>() {
 162                             @Override
 163                             public Context run() {
 164                                 return Context.getContext();
 165                             }
 166                         }, GET_CONTEXT_ACC_CTXT);
 167                 return wrap(context.eval(global, s, null, null, false), global);
 168             }
 169         });
 170     }
 171 
 172     public Object callMember(final String functionName, final Object... args) {
 173         functionName.getClass(); // null check
 174         final Global oldGlobal = Context.getGlobal();
 175         final boolean globalChanged = (oldGlobal != global);
 176 
 177         try {
 178             if (globalChanged) {
 179                 Context.setGlobal(global);
 180             }
 181 
 182             final Object val = sobj.get(functionName);
 183             if (val instanceof ScriptFunction) {
 184                 final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
 185                 return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
 186             } else if (val instanceof JSObject && ((JSObject)val).isFunction()) {
 187                 return ((JSObject)val).call(sobj, args);
 188             }
 189 
 190             throw new NoSuchMethodException("No such function " + functionName);
 191         } catch (final NashornException ne) {
 192             throw ne.initEcmaError(global);
 193         } catch (final RuntimeException | Error e) {
 194             throw e;
 195         } catch (final Throwable t) {
 196             throw new RuntimeException(t);
 197         } finally {
 198             if (globalChanged) {
 199                 Context.setGlobal(oldGlobal);
 200             }
 201         }
 202     }
 203 
 204     @Override
 205     public Object getMember(final String name) {
 206         name.getClass();
 207         return inGlobal(new Callable<Object>() {
 208             @Override public Object call() {
 209                 return wrap(sobj.get(name), global);
 210             }
 211         });
 212     }


 244         name.getClass();
 245         remove(name);
 246     }
 247 
 248     @Override
 249     public void setMember(final String name, final Object value) {
 250         name.getClass();
 251         put(name, value);
 252     }
 253 
 254     @Override
 255     public void setSlot(final int index, final Object value) {
 256         inGlobal(new Callable<Void>() {
 257             @Override public Void call() {
 258                 sobj.set(index, unwrap(value, global), strict);
 259                 return null;
 260             }
 261         });
 262     }
 263 
 264     /**
 265      * Nashorn extension: setIndexedPropertiesToExternalArrayData.
 266      * set indexed properties be exposed from a given nio ByteBuffer.
 267      *
 268      * @param buf external buffer - should be a nio ByteBuffer
 269      */
 270     public void setIndexedPropertiesToExternalArrayData(final ByteBuffer buf) {
 271         inGlobal(new Callable<Void>() {
 272             @Override public Void call() {
 273                 sobj.setArray(ArrayData.allocate(buf));
 274                 return null;
 275             }
 276         });
 277     }
 278 
 279 
 280     @Override
 281     public boolean isInstance(final Object obj) {
 282         if (! (obj instanceof ScriptObjectMirror)) {
 283             return false;
 284         }
 285 
 286         final ScriptObjectMirror instance = (ScriptObjectMirror)obj;
 287         // if not belongs to my global scope, return false
 288         if (global != instance.global) {
 289             return false;
 290         }
 291 
 292         return inGlobal(new Callable<Boolean>() {
 293             @Override public Boolean call() {
 294                 return sobj.isInstance(instance.sobj);
 295             }
 296         });
 297     }
 298 
 299     @Override


 625      * @return converted object
 626      */
 627     public <T> T to(final Class<T> type) {
 628         return inGlobal(new Callable<T>() {
 629             @Override
 630             public T call() {
 631                 return type.cast(ScriptUtils.convert(sobj, type));
 632             }
 633         });
 634     }
 635 
 636     /**
 637      * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings.
 638      *
 639      * @param obj object to be wrapped/converted
 640      * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
 641      * @return wrapped/converted object
 642      */
 643     public static Object wrap(final Object obj, final Object homeGlobal) {
 644         if(obj instanceof ScriptObject) {
 645             return homeGlobal instanceof Global ? new ScriptObjectMirror((ScriptObject)obj, (Global)homeGlobal) : obj;
 646         }
 647         if(obj instanceof ConsString) {
 648             return obj.toString();
 649         }
 650         return obj;
 651     }
 652 
 653     /**
 654      * Unwrap a script object mirror if needed.
 655      *
 656      * @param obj object to be unwrapped
 657      * @param homeGlobal global to which this object belongs
 658      * @return unwrapped object
 659      */
 660     public static Object unwrap(final Object obj, final Object homeGlobal) {
 661         if (obj instanceof ScriptObjectMirror) {
 662             final ScriptObjectMirror mirror = (ScriptObjectMirror)obj;
 663             return (mirror.global == homeGlobal)? mirror.sobj : obj;
 664         }
 665 


 693      * @param args array to be unwrapped
 694      * @param homeGlobal global to which this object belongs
 695      * @return unwrapped array
 696      */
 697     public static Object[] unwrapArray(final Object[] args, final Object homeGlobal) {
 698         if (args == null || args.length == 0) {
 699             return args;
 700         }
 701 
 702         final Object[] newArgs = new Object[args.length];
 703         int index = 0;
 704         for (final Object obj : args) {
 705             newArgs[index] = unwrap(obj, homeGlobal);
 706             index++;
 707         }
 708         return newArgs;
 709     }
 710 
 711     // package-privates below this.
 712 
 713     ScriptObjectMirror(final ScriptObject sobj, final Global global) {
 714         assert sobj != null : "ScriptObjectMirror on null!";
 715         assert global != null : "home Global is null";
 716 
 717         this.sobj = sobj;
 718         this.global = global;
 719         this.strict = global.isStrictContext();
 720     }
 721 
 722     // accessors for script engine
 723     ScriptObject getScriptObject() {
 724         return sobj;
 725     }
 726 
 727     Global getHomeGlobal() {
 728         return global;
 729     }
 730 
 731     static Object translateUndefined(Object obj) {
 732         return (obj == ScriptRuntime.UNDEFINED)? null : obj;
 733     }
 734 
 735     // internals only below this.
 736     private <V> V inGlobal(final Callable<V> callable) {
 737         final Global oldGlobal = Context.getGlobal();
 738         final boolean globalChanged = (oldGlobal != global);
 739         if (globalChanged) {
 740             Context.setGlobal(global);
 741         }
 742         try {
 743             return callable.call();
 744         } catch (final NashornException ne) {
 745             throw ne.initEcmaError(global);
 746         } catch (final RuntimeException e) {
 747             throw e;
 748         } catch (final Exception e) {
 749             throw new AssertionError("Cannot happen", e);
 750         } finally {
 751             if (globalChanged) {
 752                 Context.setGlobal(oldGlobal);
 753             }
 754         }
 755     }
 756 
 757     @Override
 758     public double toNumber() {
 759         return inGlobal(new Callable<Double>() {
 760             @Override public Double call() {
 761                 return JSType.toNumber(sobj);
 762             }
 763         });
 764     }
 765 }