diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 84981ae6e8..ca05c7a76d 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -1379,6 +1379,8 @@ Bytecode::CodeGenerationErrorOr CallExpression::generate_bytecode(Bytecode Bytecode::Op::Call::CallType call_type; if (is(*this)) { call_type = Bytecode::Op::Call::CallType::Construct; + } else if (m_callee->is_identifier() && static_cast(*m_callee).string() == "eval"sv) { + call_type = Bytecode::Op::Call::CallType::DirectEval; } else { call_type = Bytecode::Op::Call::CallType::Call; } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 61d64727da..f7f912811d 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -661,7 +661,12 @@ ThrowCompletionOr Call::execute_impl(Bytecode::Interpreter& interpreter) c auto argument_values = argument_list_evaluation(interpreter); Value return_value; - if (m_type == CallType::Call) + if (m_type == CallType::DirectEval) { + if (callee == interpreter.realm().intrinsics().eval_function()) + return_value = TRY(perform_eval(vm, argument_values[0].value_or(JS::js_undefined()), vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct)); + else + return_value = TRY(call(vm, function, this_value, move(argument_values))); + } else if (m_type == CallType::Call) return_value = TRY(call(vm, function, this_value, move(argument_values))); else return_value = TRY(construct(vm, function, move(argument_values))); @@ -1239,10 +1244,23 @@ DeprecatedString JumpUndefined::to_deprecated_string_impl(Bytecode::Executable c DeprecatedString Call::to_deprecated_string_impl(Bytecode::Executable const& executable) const { - if (m_expression_string.has_value()) - return DeprecatedString::formatted("Call callee:{}, this:{}, arguments:[...acc] ({})", m_callee, m_this_value, executable.get_string(m_expression_string.value())); + StringView type; + switch (m_type) { + case Call::CallType::Call: + type = ""sv; + break; + case Call::CallType::Construct: + type = " (Construct)"sv; + break; + case Call::CallType::DirectEval: + type = " (DirectEval)"sv; + break; + } - return DeprecatedString::formatted("Call callee:{}, this:{}, arguments:[...acc]", m_callee, m_this_value); + if (m_expression_string.has_value()) + return DeprecatedString::formatted("Call{} callee:{}, this:{}, arguments:[...acc] ({})", type, m_callee, m_this_value, executable.get_string(m_expression_string.value())); + + return DeprecatedString::formatted("Call{} callee:{}, this:{}, arguments:[...acc]", type, m_callee, m_this_value); } DeprecatedString SuperCall::to_deprecated_string_impl(Bytecode::Executable const&) const diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index c48beba20a..5d1cace67e 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -714,6 +714,7 @@ public: enum class CallType { Call, Construct, + DirectEval, }; Call(CallType type, Register callee, Register this_value, Optional expression_string = {})