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 }
|