mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 09:51:57 -05:00
LibJS: Actually leave the current function scope on "return"
We now unwind until the nearest function-level scope on the scope stack when executing a return statement.
This commit is contained in:
parent
df524203b2
commit
494df52961
3 changed files with 13 additions and 6 deletions
|
@ -81,7 +81,7 @@ Value CallExpression::execute(Interpreter& interpreter) const
|
||||||
Value ReturnStatement::execute(Interpreter& interpreter) const
|
Value ReturnStatement::execute(Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
auto value = argument() ? argument()->execute(interpreter) : js_undefined();
|
auto value = argument() ? argument()->execute(interpreter) : js_undefined();
|
||||||
interpreter.do_return();
|
interpreter.unwind(ScopeType::Function);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,13 @@ Value Interpreter::run(const Statement& statement, Vector<Argument> arguments, S
|
||||||
Value last_value = js_undefined();
|
Value last_value = js_undefined();
|
||||||
for (auto& node : block.children()) {
|
for (auto& node : block.children()) {
|
||||||
last_value = node.execute(*this);
|
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);
|
exit_scope(block);
|
||||||
return last_value;
|
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)
|
while (m_scope_stack.last().scope_node.ptr() != &scope_node)
|
||||||
m_scope_stack.take_last();
|
m_scope_stack.take_last();
|
||||||
}
|
|
||||||
|
|
||||||
void 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())
|
||||||
dbg() << "FIXME: Implement Interpreter::do_return()";
|
m_unwind_until = ScopeType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::declare_variable(const FlyString& name, DeclarationType declaration_type)
|
void Interpreter::declare_variable(const FlyString& name, DeclarationType declaration_type)
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
enum class ScopeType {
|
enum class ScopeType {
|
||||||
|
None,
|
||||||
Function,
|
Function,
|
||||||
Block,
|
Block,
|
||||||
};
|
};
|
||||||
|
@ -74,7 +75,7 @@ public:
|
||||||
|
|
||||||
Heap& heap() { return m_heap; }
|
Heap& heap() { return m_heap; }
|
||||||
|
|
||||||
void do_return();
|
void unwind(ScopeType type) { m_unwind_until = type; }
|
||||||
|
|
||||||
Value get_variable(const FlyString& name);
|
Value get_variable(const FlyString& name);
|
||||||
void set_variable(const FlyString& name, Value, bool first_assignment = false);
|
void set_variable(const FlyString& name, Value, bool first_assignment = false);
|
||||||
|
@ -114,6 +115,8 @@ private:
|
||||||
Object* m_string_prototype { nullptr };
|
Object* m_string_prototype { nullptr };
|
||||||
Object* m_object_prototype { nullptr };
|
Object* m_object_prototype { nullptr };
|
||||||
Object* m_array_prototype { nullptr };
|
Object* m_array_prototype { nullptr };
|
||||||
|
|
||||||
|
ScopeType m_unwind_until { ScopeType::None };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue