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

Print this page




 459 
 460     // scripts should see "context" and "engine" as variables in the given global object
 461     private void setContextVariables(final ScriptObject ctxtGlobal, final ScriptContext ctxt) {
 462         // set "context" global variable via contextProperty - because this
 463         // property is non-writable
 464         contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
 465         Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal);
 466         if (args == null || args == UNDEFINED) {
 467             args = ScriptRuntime.EMPTY_ARRAY;
 468         }
 469         // if no arguments passed, expose it
 470         if (! (args instanceof ScriptObject)) {
 471             args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
 472             ctxtGlobal.set("arguments", args, false);
 473         }
 474     }
 475 
 476     private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
 477         name.getClass(); // null check
 478 

 479         ScriptObjectMirror selfMirror = null;
 480         if (selfObject instanceof ScriptObjectMirror) {
 481             selfMirror = (ScriptObjectMirror)selfObject;
 482             if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) {
 483                 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
 484             }

 485         } else if (selfObject instanceof ScriptObject) {
 486             // invokeMethod called from script code - in which case we may get 'naked' ScriptObject
 487             // Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
 488             final ScriptObject oldGlobal = Context.getGlobal();

 489             if (oldGlobal == null) {
 490                 throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
 491             }
 492 
 493             if (! isOfContext(oldGlobal, nashornContext)) {
 494                 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
 495             }
 496 
 497             selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
 498         } else if (selfObject == null) {
 499             // selfObject is null => global function call
 500             final ScriptObject ctxtGlobal = getNashornGlobalFrom(context);

 501             selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(ctxtGlobal, ctxtGlobal);
 502         }
 503 
 504         if (selfMirror != null) {
 505             try {
 506                 return ScriptObjectMirror.translateUndefined(selfMirror.callMember(name, args));
 507             } catch (final Exception e) {
 508                 final Throwable cause = e.getCause();
 509                 if (cause instanceof NoSuchMethodException) {
 510                     throw (NoSuchMethodException)cause;
 511                 }
 512                 throwAsScriptException(e);
 513                 throw new AssertionError("should not reach here");
 514             }
 515         }
 516 
 517         // Non-script object passed as selfObject
 518         throw new IllegalArgumentException(getMessage("interface.on.non.script.object"));
 519     }
 520 
 521     private Object evalImpl(final Source src, final ScriptContext ctxt) throws ScriptException {
 522         return evalImpl(compileImpl(src, ctxt), ctxt);
 523     }
 524 
 525     private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt) throws ScriptException {
 526         return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
 527     }
 528 
 529     private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final ScriptObject ctxtGlobal) throws ScriptException {
 530         if (script == null) {
 531             return null;
 532         }
 533         final ScriptObject oldGlobal = Context.getGlobal();
 534         final boolean globalChanged = (oldGlobal != ctxtGlobal);
 535         try {
 536             if (globalChanged) {
 537                 Context.setGlobal(ctxtGlobal);
 538             }
 539 
 540             // set ScriptContext variables if ctxt is non-null
 541             if (ctxt != null) {
 542                 setContextVariables(ctxtGlobal, ctxt);
 543             }
 544             return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
 545         } catch (final Exception e) {
 546             throwAsScriptException(e);
 547             throw new AssertionError("should not reach here");
 548         } finally {
 549             if (globalChanged) {
 550                 Context.setGlobal(oldGlobal);
 551             }
 552         }
 553     }
 554 
 555     private static void throwAsScriptException(final Exception e) throws ScriptException {
 556         if (e instanceof ScriptException) {
 557             throw (ScriptException)e;
 558         } else if (e instanceof NashornException) {
 559             final NashornException ne = (NashornException)e;
 560             final ScriptException se = new ScriptException(
 561                 ne.getMessage(), ne.getFileName(),
 562                 ne.getLineNumber(), ne.getColumnNumber());

 563             se.initCause(e);
 564             throw se;
 565         } else if (e instanceof RuntimeException) {
 566             throw (RuntimeException)e;
 567         } else {
 568             // wrap any other exception as ScriptException
 569             throw new ScriptException(e);
 570         }
 571     }
 572 
 573     private CompiledScript asCompiledScript(final Source source) throws ScriptException {
 574         final ScriptFunction func = compileImpl(source, context);
 575         return new CompiledScript() {
 576             @Override
 577             public Object eval(final ScriptContext ctxt) throws ScriptException {
 578                 final ScriptObject globalObject = getNashornGlobalFrom(ctxt);
 579                 // Are we running the script in the correct global?
 580                 if (func.getScope() == globalObject) {
 581                     return evalImpl(func, ctxt, globalObject);
 582                 }


 588             public ScriptEngine getEngine() {
 589                 return NashornScriptEngine.this;
 590             }
 591         };
 592     }
 593 
 594     private ScriptFunction compileImpl(final Source source, final ScriptContext ctxt) throws ScriptException {
 595         return compileImpl(source, getNashornGlobalFrom(ctxt));
 596     }
 597 
 598     private ScriptFunction compileImpl(final Source source, final ScriptObject newGlobal) throws ScriptException {
 599         final ScriptObject oldGlobal = Context.getGlobal();
 600         final boolean globalChanged = (oldGlobal != newGlobal);
 601         try {
 602             if (globalChanged) {
 603                 Context.setGlobal(newGlobal);
 604             }
 605 
 606             return nashornContext.compileScript(source, newGlobal);
 607         } catch (final Exception e) {
 608             throwAsScriptException(e);
 609             throw new AssertionError("should not reach here");
 610         } finally {
 611             if (globalChanged) {
 612                 Context.setGlobal(oldGlobal);
 613             }
 614         }
 615     }
 616 
 617     private static boolean isInterfaceImplemented(final Class<?> iface, final ScriptObject sobj) {
 618         for (final Method method : iface.getMethods()) {
 619             // ignore methods of java.lang.Object class
 620             if (method.getDeclaringClass() == Object.class) {
 621                 continue;
 622             }
 623 
 624             Object obj = sobj.get(method.getName());
 625             if (! (obj instanceof ScriptFunction)) {
 626                 return false;
 627             }
 628         }


 459 
 460     // scripts should see "context" and "engine" as variables in the given global object
 461     private void setContextVariables(final ScriptObject ctxtGlobal, final ScriptContext ctxt) {
 462         // set "context" global variable via contextProperty - because this
 463         // property is non-writable
 464         contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
 465         Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal);
 466         if (args == null || args == UNDEFINED) {
 467             args = ScriptRuntime.EMPTY_ARRAY;
 468         }
 469         // if no arguments passed, expose it
 470         if (! (args instanceof ScriptObject)) {
 471             args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
 472             ctxtGlobal.set("arguments", args, false);
 473         }
 474     }
 475 
 476     private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
 477         name.getClass(); // null check
 478 
 479         ScriptObject invokeGlobal = null;
 480         ScriptObjectMirror selfMirror = null;
 481         if (selfObject instanceof ScriptObjectMirror) {
 482             selfMirror = (ScriptObjectMirror)selfObject;
 483             if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) {
 484                 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
 485             }
 486             invokeGlobal = selfMirror.getHomeGlobal();
 487         } else if (selfObject instanceof ScriptObject) {
 488             // invokeMethod called from script code - in which case we may get 'naked' ScriptObject
 489             // Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
 490             final ScriptObject oldGlobal = Context.getGlobal();
 491             invokeGlobal = oldGlobal;
 492             if (oldGlobal == null) {
 493                 throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
 494             }
 495 
 496             if (! isOfContext(oldGlobal, nashornContext)) {
 497                 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
 498             }
 499 
 500             selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
 501         } else if (selfObject == null) {
 502             // selfObject is null => global function call
 503             final ScriptObject ctxtGlobal = getNashornGlobalFrom(context);
 504             invokeGlobal = ctxtGlobal;
 505             selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(ctxtGlobal, ctxtGlobal);
 506         }
 507 
 508         if (selfMirror != null) {
 509             try {
 510                 return ScriptObjectMirror.translateUndefined(selfMirror.callMember(name, args));
 511             } catch (final Exception e) {
 512                 final Throwable cause = e.getCause();
 513                 if (cause instanceof NoSuchMethodException) {
 514                     throw (NoSuchMethodException)cause;
 515                 }
 516                 throwAsScriptException(e, invokeGlobal);
 517                 throw new AssertionError("should not reach here");
 518             }
 519         }
 520 
 521         // Non-script object passed as selfObject
 522         throw new IllegalArgumentException(getMessage("interface.on.non.script.object"));
 523     }
 524 
 525     private Object evalImpl(final Source src, final ScriptContext ctxt) throws ScriptException {
 526         return evalImpl(compileImpl(src, ctxt), ctxt);
 527     }
 528 
 529     private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt) throws ScriptException {
 530         return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
 531     }
 532 
 533     private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final ScriptObject ctxtGlobal) throws ScriptException {
 534         if (script == null) {
 535             return null;
 536         }
 537         final ScriptObject oldGlobal = Context.getGlobal();
 538         final boolean globalChanged = (oldGlobal != ctxtGlobal);
 539         try {
 540             if (globalChanged) {
 541                 Context.setGlobal(ctxtGlobal);
 542             }
 543 
 544             // set ScriptContext variables if ctxt is non-null
 545             if (ctxt != null) {
 546                 setContextVariables(ctxtGlobal, ctxt);
 547             }
 548             return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
 549         } catch (final Exception e) {
 550             throwAsScriptException(e, ctxtGlobal);
 551             throw new AssertionError("should not reach here");
 552         } finally {
 553             if (globalChanged) {
 554                 Context.setGlobal(oldGlobal);
 555             }
 556         }
 557     }
 558 
 559     private static void throwAsScriptException(final Exception e, final ScriptObject global) throws ScriptException {
 560         if (e instanceof ScriptException) {
 561             throw (ScriptException)e;
 562         } else if (e instanceof NashornException) {
 563             final NashornException ne = (NashornException)e;
 564             final ScriptException se = new ScriptException(
 565                 ne.getMessage(), ne.getFileName(),
 566                 ne.getLineNumber(), ne.getColumnNumber());
 567             ne.initEcmaError(global);
 568             se.initCause(e);
 569             throw se;
 570         } else if (e instanceof RuntimeException) {
 571             throw (RuntimeException)e;
 572         } else {
 573             // wrap any other exception as ScriptException
 574             throw new ScriptException(e);
 575         }
 576     }
 577 
 578     private CompiledScript asCompiledScript(final Source source) throws ScriptException {
 579         final ScriptFunction func = compileImpl(source, context);
 580         return new CompiledScript() {
 581             @Override
 582             public Object eval(final ScriptContext ctxt) throws ScriptException {
 583                 final ScriptObject globalObject = getNashornGlobalFrom(ctxt);
 584                 // Are we running the script in the correct global?
 585                 if (func.getScope() == globalObject) {
 586                     return evalImpl(func, ctxt, globalObject);
 587                 }


 593             public ScriptEngine getEngine() {
 594                 return NashornScriptEngine.this;
 595             }
 596         };
 597     }
 598 
 599     private ScriptFunction compileImpl(final Source source, final ScriptContext ctxt) throws ScriptException {
 600         return compileImpl(source, getNashornGlobalFrom(ctxt));
 601     }
 602 
 603     private ScriptFunction compileImpl(final Source source, final ScriptObject newGlobal) throws ScriptException {
 604         final ScriptObject oldGlobal = Context.getGlobal();
 605         final boolean globalChanged = (oldGlobal != newGlobal);
 606         try {
 607             if (globalChanged) {
 608                 Context.setGlobal(newGlobal);
 609             }
 610 
 611             return nashornContext.compileScript(source, newGlobal);
 612         } catch (final Exception e) {
 613             throwAsScriptException(e, newGlobal);
 614             throw new AssertionError("should not reach here");
 615         } finally {
 616             if (globalChanged) {
 617                 Context.setGlobal(oldGlobal);
 618             }
 619         }
 620     }
 621 
 622     private static boolean isInterfaceImplemented(final Class<?> iface, final ScriptObject sobj) {
 623         for (final Method method : iface.getMethods()) {
 624             // ignore methods of java.lang.Object class
 625             if (method.getDeclaringClass() == Object.class) {
 626                 continue;
 627             }
 628 
 629             Object obj = sobj.get(method.getName());
 630             if (! (obj instanceof ScriptFunction)) {
 631                 return false;
 632             }
 633         }