LibJS: Correct behaviour of direct vs. indirect eval

eval only has direct access to the local scope when accessed through
the name eval. This includes locals named eval, because of course it
does.
This commit is contained in:
Anonymous 2021-06-19 20:13:53 -07:00 committed by Linus Groh
commit 2822da8c8f
Notes: sideshowbarker 2024-07-18 11:38:05 +09:00
10 changed files with 121 additions and 20 deletions

View file

@ -7,12 +7,16 @@
#include <AK/Function.h>
#include <AK/Result.h>
#include <AK/TemporaryChange.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Parser.h>
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/BoundFunction.h>
#include <LibJS/Runtime/DeclarativeEnvironmentRecord.h>
#include <LibJS/Runtime/ErrorTypes.h>
#include <LibJS/Runtime/Function.h>
#include <LibJS/Runtime/FunctionEnvironmentRecord.h>
#include <LibJS/Runtime/GlobalEnvironmentRecord.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/ObjectEnvironmentRecord.h>
@ -198,4 +202,30 @@ Object* get_super_constructor(VM& vm)
return super_constructor;
}
// 19.2.1.1 PerformEval ( x, callerRealm, strictCaller, direct ), https://tc39.es/ecma262/#sec-performeval
Value perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller, EvalMode direct)
{
VERIFY(direct == EvalMode::Direct || strict_caller == CallerMode::NonStrict);
if (!x.is_string())
return x;
auto& vm = caller_realm.vm();
auto& code_string = x.as_string();
Parser parser { Lexer { code_string.string() } };
auto program = parser.parse_program(strict_caller == CallerMode::Strict);
if (parser.has_errors()) {
auto& error = parser.errors()[0];
vm.throw_exception<SyntaxError>(caller_realm, error.to_string());
return {};
}
auto& interpreter = vm.interpreter();
if (direct == EvalMode::Direct)
return interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
TemporaryChange scope_change(vm.call_frame().lexical_environment, static_cast<EnvironmentRecord*>(&caller_realm.environment_record()));
return interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
}
}