jdk.nashorn.internal.runtime.Source Java Examples

The following examples show how to use jdk.nashorn.internal.runtime.Source. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Compiler.java    From hottub with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Creates a compiler for an on-demand compilation job.
 *
 * @param installer                code installer
 * @param source                   source to compile
 * @param isStrict                 is this a strict compilation
 * @param compiledFunction         compiled function, if any
 * @param types                    parameter and return value type information, if any is known
 * @param invalidatedProgramPoints invalidated program points for recompilation
 * @param typeInformationFile      descriptor of the location where type information is persisted
 * @param continuationEntryPoints  continuation entry points for restof method
 * @param runtimeScope             runtime scope for recompilation type lookup in {@code TypeEvaluator}
 * @return a new compiler
 */
public static Compiler forOnDemandCompilation(
        final CodeInstaller installer,
        final Source source,
        final boolean isStrict,
        final RecompilableScriptFunctionData compiledFunction,
        final TypeMap types,
        final Map<Integer, Type> invalidatedProgramPoints,
        final Object typeInformationFile,
        final int[] continuationEntryPoints,
        final ScriptObject runtimeScope) {
    final Context context = installer.getContext();
    return new Compiler(context, installer, source, context.getErrorManager(), isStrict, true,
            compiledFunction, types, invalidatedProgramPoints, typeInformationFile,
            continuationEntryPoints, runtimeScope);
}
 
Example #2
Source File: NashornScriptEngine.java    From openjdk-8 with GNU General Public License v2.0 6 votes vote down vote up
@SuppressWarnings("resource")
private static char[] loadEngineJSSource() {
    final String script = "resources/engine.js";
    try {
        final InputStream is = AccessController.doPrivileged(
                new PrivilegedExceptionAction<InputStream>() {
                    @Override
                    public InputStream run() throws Exception {
                        final URL url = NashornScriptEngine.class.getResource(script);
                        return url.openStream();
                    }
                });
        return Source.readFully(new InputStreamReader(is));
    } catch (final PrivilegedActionException | IOException e) {
        if (Context.DEBUG) {
            e.printStackTrace();
        }
        throw new RuntimeException(e);
    }
}
 
Example #3
Source File: Token.java    From jdk8u_nashorn with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Return a string representation of a token.
 * @param source  Token source.
 * @param token   Token descriptor.
 * @param verbose True to include details.
 * @return String representation.
 */
public static String toString(final Source source, final long token, final boolean verbose) {
    final TokenType type = Token.descType(token);
    String result;

    if (source != null && type.getKind() == LITERAL) {
        result = source.getString(token);
    } else {
        result = type.getNameOrType();
    }

    if (verbose) {
        final int position = Token.descPosition(token);
        final int length = Token.descLength(token);
        result += " (" + position + ", " + length + ")";
    }

    return result;
}
 
Example #4
Source File: Parser.java    From openjdk-jdk8u with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Construct a parser.
 *
 * @param env     script environment
 * @param source  source to parse
 * @param errors  error manager
 * @param strict  parser created with strict mode enabled.
 * @param lineOffset line offset to start counting lines from
 * @param log debug logger if one is needed
 */
public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
    super(source, errors, strict, lineOffset);
    this.env = env;
    this.namespace = new Namespace(env.getNamespace());
    this.scripting = env._scripting;
    if (this.scripting) {
        this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
            @Override
            public void lineInfo(final int receiverLine, final int receiverLinePosition) {
                // update the parser maintained line information
                Parser.this.line = receiverLine;
                Parser.this.linePosition = receiverLinePosition;
            }
        };
    } else {
        // non-scripting mode script can't have multi-line literals
        this.lineInfoReceiver = null;
    }

    this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
}
 
Example #5
Source File: NashornScriptEngine.java    From nashorn with GNU General Public License v2.0 6 votes vote down vote up
@SuppressWarnings("resource")
private static char[] loadEngineJSSource() {
    final String script = "resources/engine.js";
    try {
        final InputStream is = AccessController.doPrivileged(
                new PrivilegedExceptionAction<InputStream>() {
                    @Override
                    public InputStream run() throws Exception {
                        final URL url = NashornScriptEngine.class.getResource(script);
                        return url.openStream();
                    }
                });
        return Source.readFully(new InputStreamReader(is));
    } catch (final PrivilegedActionException | IOException e) {
        if (Context.DEBUG) {
            e.printStackTrace();
        }
        throw new RuntimeException(e);
    }
}
 
Example #6
Source File: NashornScriptEngine.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 6 votes vote down vote up
private ScriptFunction compileImpl(final Source source, final Global newGlobal) throws ScriptException {
    final Global oldGlobal = Context.getGlobal();
    final boolean globalChanged = (oldGlobal != newGlobal);
    try {
        if (globalChanged) {
            Context.setGlobal(newGlobal);
        }

        return nashornContext.compileScript(source, newGlobal);
    } catch (final Exception e) {
        throwAsScriptException(e, newGlobal);
        throw new AssertionError("should not reach here");
    } finally {
        if (globalChanged) {
            Context.setGlobal(oldGlobal);
        }
    }
}
 
Example #7
Source File: FunctionNode.java    From jdk8u_nashorn with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
 * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
 * a deserialized function node.
 * @param source the source for the function.
 * @param namespace the namespace for the function
 * @return a new function node with the set source and namespace
 * @throws IllegalArgumentException if the specified source or namespace is null
 * @throws IllegalStateException if the function already has either a source or namespace set.
 */
public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) {
    if (source == null || namespace == null) {
        throw new IllegalArgumentException();
    } else if (this.source == source && this.namespace == namespace) {
        return this;
    } else if (this.source != null || this.namespace != null) {
        throw new IllegalStateException();
    }
    return new FunctionNode(
        this,
        lastToken,
        endParserState,
        flags,
        name,
        returnType,
        compileUnit,
        body,
        parameters,
        thisProperties,
        rootClass, source, namespace);
}
 
Example #8
Source File: Compiler.java    From TencentKona-8 with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Creates a compiler for an on-demand compilation job.
 *
 * @param installer                code installer
 * @param source                   source to compile
 * @param isStrict                 is this a strict compilation
 * @param compiledFunction         compiled function, if any
 * @param types                    parameter and return value type information, if any is known
 * @param invalidatedProgramPoints invalidated program points for recompilation
 * @param typeInformationFile      descriptor of the location where type information is persisted
 * @param continuationEntryPoints  continuation entry points for restof method
 * @param runtimeScope             runtime scope for recompilation type lookup in {@code TypeEvaluator}
 * @return a new compiler
 */
public static Compiler forOnDemandCompilation(
        final CodeInstaller installer,
        final Source source,
        final boolean isStrict,
        final RecompilableScriptFunctionData compiledFunction,
        final TypeMap types,
        final Map<Integer, Type> invalidatedProgramPoints,
        final Object typeInformationFile,
        final int[] continuationEntryPoints,
        final ScriptObject runtimeScope) {
    final Context context = installer.getContext();
    return new Compiler(context, installer, source, context.getErrorManager(), isStrict, true,
            compiledFunction, types, invalidatedProgramPoints, typeInformationFile,
            continuationEntryPoints, runtimeScope);
}
 
Example #9
Source File: NashornScriptEngine.java    From openjdk-8 with GNU General Public License v2.0 6 votes vote down vote up
private ScriptFunction compileImpl(final Source source, final ScriptObject newGlobal) throws ScriptException {
    final ScriptObject oldGlobal = Context.getGlobal();
    final boolean globalChanged = (oldGlobal != newGlobal);
    try {
        if (globalChanged) {
            Context.setGlobal(newGlobal);
        }

        return nashornContext.compileScript(source, newGlobal);
    } catch (final Exception e) {
        throwAsScriptException(e);
        throw new AssertionError("should not reach here");
    } finally {
        if (globalChanged) {
            Context.setGlobal(oldGlobal);
        }
    }
}
 
Example #10
Source File: OptimisticTypesPersistence.java    From jdk8u_nashorn with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed
 * to {@link #load(Object)} and {@link #store(Object, Map)} methods.
 * @param source the source where the function comes from
 * @param functionId the unique ID number of the function within the source
 * @param paramTypes the types of the function parameters (as persistence is per parameter type
 * specialization).
 * @return an opaque descriptor for the persistence location. Can be null if persistence is disabled.
 */
public static Object getLocationDescriptor(final Source source, final int functionId, final Type[] paramTypes) {
    if(cacheDir == null) {
        return null;
    }
    final StringBuilder b = new StringBuilder(48);
    // Base64-encode the digest of the source, and append the function id.
    b.append(source.getDigest()).append('-').append(functionId);
    // Finally, if this is a parameter-type specialized version of the function, add the parameter types
    // to the file name.
    if(paramTypes != null && paramTypes.length > 0) {
        b.append('-');
        for(final Type t: paramTypes) {
            b.append(Type.getShortSignatureDescriptor(t));
        }
    }
    return new LocationDescriptor(new File(cacheDir, b.toString()));
}
 
Example #11
Source File: LexicalContext.java    From openjdk-8-source with GNU General Public License v2.0 6 votes vote down vote up
@Override
public String toString() {
    final StringBuffer sb = new StringBuffer();
    sb.append("[ ");
    for (int i = 0; i < sp; i++) {
        final Object node = stack[i];
        sb.append(node.getClass().getSimpleName());
        sb.append('@');
        sb.append(Debug.id(node));
        sb.append(':');
        if (node instanceof FunctionNode) {
            final FunctionNode fn = (FunctionNode)node;
            final Source source = fn.getSource();
            String src = source.toString();
            if (src.contains(File.pathSeparator)) {
                src = src.substring(src.lastIndexOf(File.pathSeparator));
            }
            src += ' ';
            src += fn.getLineNumber();
            sb.append(src);
        }
        sb.append(' ');
    }
    sb.append(" ==> ]");
    return sb.toString();
}
 
Example #12
Source File: OptimisticTypesPersistence.java    From hottub with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed
 * to {@link #load(Object)} and {@link #store(Object, Map)} methods.
 * @param source the source where the function comes from
 * @param functionId the unique ID number of the function within the source
 * @param paramTypes the types of the function parameters (as persistence is per parameter type
 * specialization).
 * @return an opaque descriptor for the persistence location. Can be null if persistence is disabled.
 */
public static Object getLocationDescriptor(final Source source, final int functionId, final Type[] paramTypes) {
    if(cacheDir == null) {
        return null;
    }
    final StringBuilder b = new StringBuilder(48);
    // Base64-encode the digest of the source, and append the function id.
    b.append(source.getDigest()).append('-').append(functionId);
    // Finally, if this is a parameter-type specialized version of the function, add the parameter types
    // to the file name.
    if(paramTypes != null && paramTypes.length > 0) {
        b.append('-');
        for(final Type t: paramTypes) {
            b.append(Type.getShortSignatureDescriptor(t));
        }
    }
    return new LocationDescriptor(new File(cacheDir, b.toString()));
}
 
Example #13
Source File: ClassEmitter.java    From openjdk-8 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Define the static fields common in all scripts.
 * @param strictMode Should we generate this method in strict mode
 */
private void defineCommonStatics(final boolean strictMode) {
    // source - used to store the source data (text) for this script.  Shared across
    // compile units.  Set externally by the compiler.
    field(EnumSet.of(Flag.PRIVATE, Flag.STATIC), SOURCE.symbolName(), Source.class);

    // constants - used to the constants array for this script.  Shared across
    // compile units.  Set externally by the compiler.
    field(EnumSet.of(Flag.PRIVATE, Flag.STATIC), CONSTANTS.symbolName(), Object[].class);

    // strictMode - was this script compiled in strict mode.  Set externally by the compiler.
    field(EnumSet.of(Flag.PUBLIC, Flag.STATIC, Flag.FINAL), STRICT_MODE.symbolName(), boolean.class, strictMode);
}
 
Example #14
Source File: AssignSymbols.java    From hottub with GNU General Public License v2.0 5 votes vote down vote up
private void throwParserException(final String message, final Node origin) {
    if (origin == null) {
        throw new ParserException(message);
    }
    final Source source = compiler.getSource();
    final long token = origin.getToken();
    final int line = source.getLine(origin.getStart());
    final int column = source.getColumn(origin.getStart());
    final String formatted = ErrorManager.format(message, source, line, column, token);
    throw new ParserException(JSErrorType.SYNTAX_ERROR, formatted, source, line, column, token);
}
 
Example #15
Source File: Lower.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Calculate a synthetic eval location for a node for the stacktrace, for example src#17<eval>
 * @param node a node
 * @return eval location
 */
private String evalLocation(final IdentNode node) {
    final Source source = lc.getCurrentFunction().getSource();
    final int pos = node.position();
    return new StringBuilder().
        append(source.getName()).
        append('#').
        append(source.getLine(pos)).
        append(':').
        append(source.getColumn(pos)).
        append("<eval>").
        toString();
}
 
Example #16
Source File: JSONWriter.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
private void location(final Node node) {
    if (includeLocation) {
        objectStart("loc");

        // source name
        final Source src = lc.getCurrentFunction().getSource();
        property("source", src.getName());
        comma();

        // start position
        objectStart("start");
        final int start = node.getStart();
        property("line", src.getLine(start));
        comma();
        property("column", src.getColumn(start));
        objectEnd();
        comma();

        // end position
        objectStart("end");
        final int end = node.getFinish();
        property("line", src.getLine(end));
        comma();
        property("column", src.getColumn(end));
        objectEnd();

        // end 'loc'
        objectEnd();

        comma();
    }
}
 
Example #17
Source File: Lower.java    From nashorn with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Calculate a synthetic eval location for a node for the stacktrace, for example src#17<eval>
 * @param node a node
 * @return eval location
 */
private String evalLocation(final IdentNode node) {
    final Source source = lc.getCurrentFunction().getSource();
    return new StringBuilder().
        append(source.getName()).
        append('#').
        append(source.getLine(node.position())).
        append("<eval>").
        toString();
}
 
Example #18
Source File: FunctionNode.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Constructor
 *
 * @param source     the source
 * @param lineNumber line number
 * @param token      token
 * @param finish     finish
 * @param firstToken first token of the function node (including the function declaration)
 * @param lastToken  lastToken
 * @param namespace  the namespace
 * @param ident      the identifier
 * @param name       the name of the function
 * @param parameters parameter list
 * @param paramExprs the ES6 function parameter expressions
 * @param kind       kind of function as in {@link FunctionNode.Kind}
 * @param flags      initial flags
 * @param body       body of the function
 * @param endParserState The parser state at the end of the parsing.
 * @param module     the module
 * @param debugFlags the debug flags
 */
public FunctionNode(
    final Source source,
    final int lineNumber,
    final long token,
    final int finish,
    final long firstToken,
    final long lastToken,
    final Namespace namespace,
    final IdentNode ident,
    final String name,
    final List<IdentNode> parameters,
    final Map<IdentNode, Expression> paramExprs,
    final FunctionNode.Kind kind,
    final int flags,
    final Block body,
    final Object endParserState,
    final Module module,
    final int debugFlags) {
    super(token, finish);

    this.source           = source;
    this.lineNumber       = lineNumber;
    this.ident            = ident;
    this.name             = name;
    this.kind             = kind;
    this.parameters       = parameters;
    this.parameterExpressions = paramExprs;
    this.firstToken       = firstToken;
    this.lastToken        = lastToken;
    this.namespace        = namespace;
    this.flags            = flags;
    this.compileUnit      = null;
    this.body             = body;
    this.thisProperties   = 0;
    this.rootClass        = null;
    this.endParserState   = endParserState;
    this.module           = module;
    this.debugFlags       = debugFlags;
}
 
Example #19
Source File: JSONParser.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
ParserException error(final String message, final int start, final int length) throws ParserException {
    final long token     = Token.toDesc(STRING, start, length);
    final int  pos       = Token.descPosition(token);
    final Source src     = Source.sourceFor("<json>", source);
    final int  lineNum   = src.getLine(pos);
    final int  columnNum = src.getColumn(pos);
    final String formatted = ErrorManager.format(message, src, lineNum, columnNum, token);
    return new ParserException(JSErrorType.SYNTAX_ERROR, formatted, src, lineNum, columnNum, token);
}
 
Example #20
Source File: Lower.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Calculate a synthetic eval location for a node for the stacktrace, for example src#17<eval>
 * @param node a node
 * @return eval location
 */
private String evalLocation(final IdentNode node) {
    final Source source = lc.getCurrentFunction().getSource();
    final int pos = node.position();
    return new StringBuilder().
        append(source.getName()).
        append('#').
        append(source.getLine(pos)).
        append(':').
        append(source.getColumn(pos)).
        append("<eval>").
        toString();
}
 
Example #21
Source File: ClassEmitter.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Define the static fields common in all scripts.
 *
 * @param strictMode Should we generate this method in strict mode
 */
private void defineCommonStatics(final boolean strictMode) {
    // source - used to store the source data (text) for this script.  Shared across
    // compile units.  Set externally by the compiler.
    field(EnumSet.of(Flag.PRIVATE, Flag.STATIC), SOURCE.symbolName(), Source.class);

    // constants - used to the constants array for this script.  Shared across
    // compile units.  Set externally by the compiler.
    field(EnumSet.of(Flag.PRIVATE, Flag.STATIC), CONSTANTS.symbolName(), Object[].class);

    // strictMode - was this script compiled in strict mode.  Set externally by the compiler.
    field(EnumSet.of(Flag.PUBLIC, Flag.STATIC, Flag.FINAL), STRICT_MODE.symbolName(), boolean.class, strictMode);
}
 
Example #22
Source File: ParserImpl.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
@Override
public CompilationUnitTree parse(final ScriptObjectMirror scriptObj, final DiagnosticListener listener) throws NashornException {
    if (moduleMode) {
        return parseModule(scriptObj, listener);
    }
    final Map<?, ?> map = Objects.requireNonNull(scriptObj);
    if (map.containsKey("script") && map.containsKey("name")) {
        final String script = JSType.toString(map.get("script"));
        final String name = JSType.toString(map.get("name"));
        final Source src = Source.sourceFor(name, script);
        return translate(makeParser(src, listener).parse());
    } else {
        throw new IllegalArgumentException("can't find 'script' and 'name' properties");
    }
}
 
Example #23
Source File: JSONParser.java    From hottub with GNU General Public License v2.0 5 votes vote down vote up
ParserException error(final String message, final int start, final int length) throws ParserException {
    final long token     = Token.toDesc(STRING, start, length);
    final int  pos       = Token.descPosition(token);
    final Source src     = Source.sourceFor("<json>", source);
    final int  lineNum   = src.getLine(pos);
    final int  columnNum = src.getColumn(pos);
    final String formatted = ErrorManager.format(message, src, lineNum, columnNum, token);
    return new ParserException(JSErrorType.SYNTAX_ERROR, formatted, src, lineNum, columnNum, token);
}
 
Example #24
Source File: AssignSymbols.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
private void throwParserException(final String message, final Node origin) {
    if (origin == null) {
        throw new ParserException(message);
    }
    final Source source = compiler.getSource();
    final long token = origin.getToken();
    final int line = source.getLine(origin.getStart());
    final int column = source.getColumn(origin.getStart());
    final String formatted = ErrorManager.format(message, source, line, column, token);
    throw new ParserException(JSErrorType.SYNTAX_ERROR, formatted, source, line, column, token);
}
 
Example #25
Source File: Lower.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Calculate a synthetic eval location for a node for the stacktrace, for example src#17<eval>
 * @param node a node
 * @return eval location
 */
private String evalLocation(final IdentNode node) {
    final Source source = lc.getCurrentFunction().getSource();
    final int pos = node.position();
    return new StringBuilder().
        append(source.getName()).
        append('#').
        append(source.getLine(pos)).
        append(':').
        append(source.getColumn(pos)).
        append("<eval>").
        toString();
}
 
Example #26
Source File: NashornScriptEngine.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException {
    try {
        return sourceFor(getScriptName(ctxt), reader);
    } catch (final IOException e) {
        throw new ScriptException(e);
    }
}
 
Example #27
Source File: Lexer.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Constructor
 *
 * @param source    the source
 * @param start     start position in source from which to start lexing
 * @param len       length of source segment to lex
 * @param stream    token stream to lex
 * @param scripting are we in scripting mode
 * @param pauseOnFunctionBody if true, lexer will return from {@link #lexify()} when it encounters a
 * function body. This is used with the feature where the parser is skipping nested function bodies to
 * avoid reading ahead unnecessarily when we skip the function bodies.
 */

public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean pauseOnFunctionBody) {
    super(source.getContent(), 1, start, len);
    this.source      = source;
    this.stream      = stream;
    this.scripting   = scripting;
    this.nested      = false;
    this.pendingLine = 1;
    this.last        = EOL;

    this.pauseOnFunctionBody = pauseOnFunctionBody;
}
 
Example #28
Source File: ParserImpl.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
@Override
public CompilationUnitTree parse(final String name, final Reader reader, final DiagnosticListener listener) throws IOException, NashornException {
    if (moduleMode) {
        return parseModule(name, reader, listener);
    }
    final Source src = Source.sourceFor(Objects.requireNonNull(name), Objects.requireNonNull(reader));
    return translate(makeParser(src, listener).parse());
}
 
Example #29
Source File: SourceTest.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
private static void testSources(final Source source1, final Source source2) {
    final char[] chars1 = source1.getContent();
    final char[] chars2 = source2.getContent();
    final String str1 = source1.getString();
    final String str2 = source2.getString();
    assertTrue(Arrays.equals(chars1, chars2));
    assertEquals(str1, str2);
    assertEquals(source1.hashCode(), source2.hashCode());
    assertTrue(source1.equals(source2));
    assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray()));
    assertTrue(Arrays.equals(source1.getContent(), chars1));
    assertTrue(Arrays.equals(source1.getContent(), source2.getContent()));
}
 
Example #30
Source File: NashornScriptEngine.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
private CompiledScript asCompiledScript(final Source source) throws ScriptException {
    final Context.MultiGlobalCompiledScript mgcs;
    final ScriptFunction func;
    final Global oldGlobal = Context.getGlobal();
    final Global newGlobal = getNashornGlobalFrom(context);
    final boolean globalChanged = (oldGlobal != newGlobal);
    try {
        if (globalChanged) {
            Context.setGlobal(newGlobal);
        }

        mgcs = nashornContext.compileScript(source);
        func = mgcs.getFunction(newGlobal);
    } catch (final Exception e) {
        throwAsScriptException(e, newGlobal);
        throw new AssertionError("should not reach here");
    } finally {
        if (globalChanged) {
            Context.setGlobal(oldGlobal);
        }
    }

    return new CompiledScript() {
        @Override
        public Object eval(final ScriptContext ctxt) throws ScriptException {
            final Global globalObject = getNashornGlobalFrom(ctxt);
            // Are we running the script in the same global in which it was compiled?
            if (func.getScope() == globalObject) {
                return evalImpl(func, ctxt, globalObject);
            }

            // different global
            return evalImpl(mgcs, ctxt, globalObject);
        }
        @Override
        public ScriptEngine getEngine() {
            return NashornScriptEngine.this;
        }
    };
}