diff options
author | Hendiadyoin1 <leon.a@serenityos.org> | 2022-10-01 01:36:06 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-10-17 01:36:41 +0200 |
commit | 490c097bc4b7356127d603f99566039ca453a6a6 (patch) | |
tree | 95e3843989107d07464e4fe49f6a64b1c04bf2c0 /Userland/Libraries/LibJS/Bytecode | |
parent | a2ccf31a629ee0bbc51710612b427463aaf44f05 (diff) | |
download | serenity-490c097bc4b7356127d603f99566039ca453a6a6.zip |
LibJS: Forward a string aproximation of the CallExpression to Call Ops
This gives us better debug output when analysing calls to `undefined`
and also fixes multiple test-js cases expecting an
`(evaluated from $Expression)` in the error message.
This also refactors out the generation of that string, to avoid code
duplication with the AST interpreter.
Diffstat (limited to 'Userland/Libraries/LibJS/Bytecode')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.cpp | 19 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.h | 6 |
3 files changed, 26 insertions, 6 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 3cc90852d2..8f022cf20f 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -1548,7 +1548,12 @@ Bytecode::CodeGenerationErrorOr<void> CallExpression::generate_bytecode(Bytecode call_type = Bytecode::Op::Call::CallType::Call; } - generator.emit<Bytecode::Op::Call>(call_type, callee_reg, this_reg); + Optional<Bytecode::StringTableIndex> expression_string_index; + if (auto expression_string = this->expression_string(); expression_string.has_value()) + expression_string_index = generator.intern_string(expression_string.release_value()); + + generator.emit<Bytecode::Op::Call>(call_type, callee_reg, this_reg, expression_string_index); + return {}; } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 07adf1fe6c..7efde7e84c 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -584,6 +584,15 @@ static MarkedVector<Value> argument_list_evaluation(Bytecode::Interpreter& inter return argument_values; } +Completion Call::throw_type_error_for_callee(Bytecode::Interpreter& interpreter, StringView callee_type) const +{ + auto callee = interpreter.reg(m_callee); + if (m_expression_string.has_value()) + return interpreter.vm().throw_completion<TypeError>(ErrorType::IsNotAEvaluatedFrom, callee.to_string_without_side_effects(), callee_type, interpreter.current_executable().get_string(m_expression_string->value())); + + return interpreter.vm().throw_completion<TypeError>(ErrorType::IsNotA, callee.to_string_without_side_effects(), callee_type); +} + ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) const { auto& vm = interpreter.vm(); @@ -591,10 +600,9 @@ ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) c auto callee = interpreter.reg(m_callee); if (m_type == CallType::Call && !callee.is_function()) - return vm.throw_completion<TypeError>(ErrorType::IsNotA, callee.to_string_without_side_effects(), "function"sv); - + return throw_type_error_for_callee(interpreter, "function"sv); if (m_type == CallType::Construct && !callee.is_constructor()) - return vm.throw_completion<TypeError>(ErrorType::IsNotA, callee.to_string_without_side_effects(), "constructor"sv); + return throw_type_error_for_callee(interpreter, "constructor"sv); auto& function = callee.as_function(); @@ -1138,8 +1146,11 @@ String JumpUndefined::to_string_impl(Bytecode::Executable const&) const return String::formatted("JumpUndefined undefined:{} not undefined:{}", true_string, false_string); } -String Call::to_string_impl(Bytecode::Executable const&) const +String Call::to_string_impl(Bytecode::Executable const& executable) const { + if (m_expression_string.has_value()) + return String::formatted("Call callee:{}, this:{}, arguments:[...acc] ({})", m_callee, m_this_value, executable.get_string(m_expression_string.value())); + return String::formatted("Call callee:{}, this:{}, arguments:[...acc]", m_callee, m_this_value); } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index db951a337e..b4cf413e8a 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -604,11 +604,12 @@ public: Construct, }; - Call(CallType type, Register callee, Register this_value) + Call(CallType type, Register callee, Register this_value, Optional<StringTableIndex> expression_string = {}) : Instruction(Type::Call) , m_callee(callee) , m_this_value(this_value) , m_type(type) + , m_expression_string(expression_string) { } @@ -616,10 +617,13 @@ public: String to_string_impl(Bytecode::Executable const&) const; void replace_references_impl(BasicBlock const&, BasicBlock const&) { } + Completion throw_type_error_for_callee(Bytecode::Interpreter&, StringView callee_type) const; + private: Register m_callee; Register m_this_value; CallType m_type; + Optional<StringTableIndex> m_expression_string; }; // NOTE: This instruction is variable-width depending on the number of arguments! |