Bladeren bron

LibJS/Bytecode: Add support for direct eval()

This is implemented as a special mode of the Call opcode that invokes
the PerformEval AO (instead of the Call or Construct AO).
Andreas Kling 2 jaren geleden
bovenliggende
commit
2ac8a4bbb7

+ 2 - 0
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -1379,6 +1379,8 @@ Bytecode::CodeGenerationErrorOr<void> CallExpression::generate_bytecode(Bytecode
     Bytecode::Op::Call::CallType call_type;
     Bytecode::Op::Call::CallType call_type;
     if (is<NewExpression>(*this)) {
     if (is<NewExpression>(*this)) {
         call_type = Bytecode::Op::Call::CallType::Construct;
         call_type = Bytecode::Op::Call::CallType::Construct;
+    } else if (m_callee->is_identifier() && static_cast<Identifier const&>(*m_callee).string() == "eval"sv) {
+        call_type = Bytecode::Op::Call::CallType::DirectEval;
     } else {
     } else {
         call_type = Bytecode::Op::Call::CallType::Call;
         call_type = Bytecode::Op::Call::CallType::Call;
     }
     }

+ 21 - 3
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -661,7 +661,12 @@ ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) c
     auto argument_values = argument_list_evaluation(interpreter);
     auto argument_values = argument_list_evaluation(interpreter);
 
 
     Value return_value;
     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)));
         return_value = TRY(call(vm, function, this_value, move(argument_values)));
     else
     else
         return_value = TRY(construct(vm, function, move(argument_values)));
         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
 DeprecatedString Call::to_deprecated_string_impl(Bytecode::Executable const& executable) const
 {
 {
+    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;
+    }
+
     if (m_expression_string.has_value())
     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()));
+        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]", m_callee, m_this_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
 DeprecatedString SuperCall::to_deprecated_string_impl(Bytecode::Executable const&) const

+ 1 - 0
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -714,6 +714,7 @@ public:
     enum class CallType {
     enum class CallType {
         Call,
         Call,
         Construct,
         Construct,
+        DirectEval,
     };
     };
 
 
     Call(CallType type, Register callee, Register this_value, Optional<StringTableIndex> expression_string = {})
     Call(CallType type, Register callee, Register this_value, Optional<StringTableIndex> expression_string = {})