/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.interpreter; import static com.github.anba.es6draft.interpreter.DeclarationBindingInstantiation.EvalDeclarationInstantiation; import static com.github.anba.es6draft.interpreter.DeclarationBindingInstantiation.GlobalDeclarationInstantiation; import static com.github.anba.es6draft.runtime.ExecutionContext.newEvalExecutionContext; import static com.github.anba.es6draft.runtime.ExecutionContext.newScriptExecutionContext; import static com.github.anba.es6draft.runtime.LexicalEnvironment.newDeclarativeEnvironment; import com.github.anba.es6draft.Script; import com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord; import com.github.anba.es6draft.runtime.ExecutionContext; import com.github.anba.es6draft.runtime.GlobalEnvironmentRecord; import com.github.anba.es6draft.runtime.LexicalEnvironment; import com.github.anba.es6draft.runtime.Realm; import com.github.anba.es6draft.runtime.internal.DebugInfo; import com.github.anba.es6draft.runtime.internal.RuntimeInfo; import com.github.anba.es6draft.runtime.internal.Source; /** * */ final class InterpretedScriptBody implements RuntimeInfo.ScriptBody { private final com.github.anba.es6draft.ast.Script parsedScript; InterpretedScriptBody(com.github.anba.es6draft.ast.Script parsedScript) { this.parsedScript = parsedScript; } @Override public Source toSource() { return new Source(parsedScript.getSource().getFile(), parsedScript.getSource().getName(), 1); } @Override public Object evaluate(ExecutionContext cx, Script script) { assert script.getScriptBody() == this; if (parsedScript.isScripting()) { return scriptingEvaluation(cx); } if (parsedScript.isEvalScript()) { return evalScriptEvaluation(cx, script); } return scriptEvaluation(cx, script); } /** * 15.1.7 Runtime Semantics: ScriptEvaluation * * @param cx * the execution context * @param script * the script object * @return the script evaluation result */ private Object scriptEvaluation(ExecutionContext cx, Script script) { Realm realm = cx.getRealm(); /* step 1 (not applicable) */ /* step 2 */ LexicalEnvironment<GlobalEnvironmentRecord> globalEnv = realm.getGlobalEnv(); /* steps 3-7 */ ExecutionContext scriptCxt = newScriptExecutionContext(realm, script); /* steps 8-9 */ ExecutionContext oldScriptContext = realm.getScriptContext(); try { realm.setScriptContext(scriptCxt); /* step 10 */ GlobalDeclarationInstantiation(scriptCxt, parsedScript, globalEnv); /* steps 11-12 */ Object result = parsedScript.accept(new Interpreter(parsedScript), scriptCxt); /* step 16 */ return result; } finally { /* steps 13-15 */ realm.setScriptContext(oldScriptContext); } } /** * 18.2.1.1 Runtime Semantics: PerformEval( x, evalRealm, strictCaller, direct) * * @param cx * the execution context * @param script * the script object * @return the script evaluation result */ private Object evalScriptEvaluation(ExecutionContext cx, Script script) { // TODO: Skip allocating lex-env if not needed /* steps 1-5 (not applicable) */ /* steps 6-7 */ boolean strictEval = parsedScript.isStrict(); /* step 8 (omitted) */ /* steps 9-10 */ LexicalEnvironment<DeclarativeEnvironmentRecord> lexEnv; LexicalEnvironment<?> varEnv; if (parsedScript.isDirectEval()) { /* step 9 */ lexEnv = newDeclarativeEnvironment(cx.getLexicalEnvironment()); varEnv = cx.getVariableEnvironment(); } else { Realm evalRealm = cx.getRealm(); /* step 10 */ lexEnv = newDeclarativeEnvironment(evalRealm.getGlobalEnv()); varEnv = evalRealm.getGlobalEnv(); } /* step 11 */ if (strictEval) { varEnv = lexEnv; } /* steps 12-17 */ ExecutionContext evalCxt = newEvalExecutionContext(cx, script, varEnv, lexEnv); /* step 18 */ EvalDeclarationInstantiation(evalCxt, parsedScript, varEnv, lexEnv); /* steps 19-23 */ return parsedScript.accept(new Interpreter(parsedScript), evalCxt); } private Object scriptingEvaluation(ExecutionContext cx) { // NB: Don't need to create a new execution context here, cf. ScriptEngineImpl. // TODO: Skip allocating lex-env if not needed LexicalEnvironment<?> varEnv = cx.getVariableEnvironment(); LexicalEnvironment<DeclarativeEnvironmentRecord> lexEnv = newDeclarativeEnvironment(cx .getLexicalEnvironment()); cx.setLexicalEnvironment(lexEnv); EvalDeclarationInstantiation(cx, parsedScript, varEnv, lexEnv); return parsedScript.accept(new Interpreter(parsedScript), cx); } @Override public DebugInfo debugInfo() { return null; } }