Browse Source

LibJS: Keep track of current AST node inside the call stack

Jean-Baptiste Boric 4 years ago
parent
commit
6172cb3599

+ 1 - 0
Userland/Libraries/LibJS/AST.cpp

@@ -225,6 +225,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj
         }
     }
 
+    vm.call_frame().current_node = vm.node_stack().last();
     Object* new_object = nullptr;
     Value result;
     if (is<NewExpression>(*this)) {

+ 2 - 0
Userland/Libraries/LibJS/Interpreter.cpp

@@ -62,6 +62,7 @@ Value Interpreter::run(GlobalObject& global_object, const Program& program)
     VM::InterpreterExecutionScope scope(*this);
 
     CallFrame global_call_frame;
+    global_call_frame.current_node = &program;
     global_call_frame.this_value = &global_object;
     static FlyString global_execution_context_name = "(global execution context)";
     global_call_frame.function_name = global_execution_context_name;
@@ -140,6 +141,7 @@ void Interpreter::exit_scope(const ScopeNode& scope_node)
 
 void Interpreter::enter_node(const ASTNode& node)
 {
+    vm().call_frame().current_node = &node;
     vm().push_ast_node(node);
 }
 

+ 2 - 0
Userland/Libraries/LibJS/Runtime/Object.cpp

@@ -900,6 +900,7 @@ Value Object::call_native_property_getter(NativeProperty& property, Value this_v
 {
     auto& vm = this->vm();
     CallFrame call_frame;
+    call_frame.current_node = property.vm().node_stack().last();
     call_frame.is_strict_mode = vm.in_strict_mode();
     call_frame.this_value = this_value;
     vm.push_call_frame(call_frame, global_object());
@@ -914,6 +915,7 @@ void Object::call_native_property_setter(NativeProperty& property, Value this_va
 {
     auto& vm = this->vm();
     CallFrame call_frame;
+    call_frame.current_node = property.vm().node_stack().last();
     call_frame.is_strict_mode = vm.in_strict_mode();
     call_frame.this_value = this_value;
     vm.push_call_frame(call_frame, global_object());

+ 4 - 1
Userland/Libraries/LibJS/Runtime/VM.cpp

@@ -211,6 +211,7 @@ Reference VM::get_reference(const FlyString& name)
 Value VM::construct(Function& function, Function& new_target, Optional<MarkedValueList> arguments, GlobalObject& global_object)
 {
     CallFrame call_frame;
+    call_frame.current_node = function.vm().node_stack().last();
     call_frame.is_strict_mode = function.is_strict_mode();
 
     push_call_frame(call_frame, function.global_object());
@@ -285,10 +286,11 @@ void VM::throw_exception(Exception* exception)
         dbgln("Throwing JavaScript Error: {}, {}", error.name(), error.message());
 
         for (ssize_t i = m_call_stack.size() - 1; i >= 0; --i) {
+            const auto& source_range = m_call_stack[i]->current_node->source_range();
             auto function_name = m_call_stack[i]->function_name;
             if (function_name.is_empty())
                 function_name = "<anonymous>";
-            dbgln("  {}", function_name);
+            dbgln("  {} at {}:{}:{}", function_name, source_range.filename, source_range.start.line, source_range.start.column);
         }
     }
 
@@ -333,6 +335,7 @@ Value VM::call_internal(Function& function, Value this_value, Optional<MarkedVal
     VERIFY(!exception());
 
     CallFrame call_frame;
+    call_frame.current_node = function.vm().node_stack().last();
     call_frame.is_strict_mode = function.is_strict_mode();
     call_frame.function_name = function.name();
     call_frame.this_value = function.bound_this().value_or(this_value);

+ 1 - 0
Userland/Libraries/LibJS/Runtime/VM.h

@@ -56,6 +56,7 @@ struct ScopeFrame {
 };
 
 struct CallFrame {
+    const ASTNode* current_node;
     FlyString function_name;
     Value this_value;
     Vector<Value> arguments;