diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index d3b34dc0278..f89b3b0f5a4 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -81,7 +81,7 @@ Value CallExpression::execute(Interpreter& interpreter) const Value ReturnStatement::execute(Interpreter& interpreter) const { auto value = argument() ? argument()->execute(interpreter) : js_undefined(); - interpreter.do_return(); + interpreter.unwind(ScopeType::Function); return value; } diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index ac80f688b07..f602336bc41 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -61,8 +61,13 @@ Value Interpreter::run(const Statement& statement, Vector arguments, S Value last_value = js_undefined(); for (auto& node : block.children()) { last_value = node.execute(*this); + if (m_unwind_until != ScopeType::None) + break; } + if (m_unwind_until == scope_type) + m_unwind_until = ScopeType::None; + exit_scope(block); return last_value; } @@ -80,11 +85,10 @@ void Interpreter::exit_scope(const ScopeNode& scope_node) { while (m_scope_stack.last().scope_node.ptr() != &scope_node) m_scope_stack.take_last(); -} -void Interpreter::do_return() -{ - dbg() << "FIXME: Implement Interpreter::do_return()"; + // If we unwind all the way, just reset m_unwind_until so that future "return" doesn't break. + if (m_scope_stack.is_empty()) + m_unwind_until = ScopeType::None; } void Interpreter::declare_variable(const FlyString& name, DeclarationType declaration_type) diff --git a/Libraries/LibJS/Interpreter.h b/Libraries/LibJS/Interpreter.h index 1aa7b87f05a..fab56397d11 100644 --- a/Libraries/LibJS/Interpreter.h +++ b/Libraries/LibJS/Interpreter.h @@ -37,6 +37,7 @@ namespace JS { enum class ScopeType { + None, Function, Block, }; @@ -74,7 +75,7 @@ public: Heap& heap() { return m_heap; } - void do_return(); + void unwind(ScopeType type) { m_unwind_until = type; } Value get_variable(const FlyString& name); void set_variable(const FlyString& name, Value, bool first_assignment = false); @@ -114,6 +115,8 @@ private: Object* m_string_prototype { nullptr }; Object* m_object_prototype { nullptr }; Object* m_array_prototype { nullptr }; + + ScopeType m_unwind_until { ScopeType::None }; }; }