mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibJS: Evaluate for statements in their own scope if necessary
We now evaluate for loops in their own scope if their init statement is a lexical declaration. Evaluating for loops in their own scope allow us to obtain expected behaviour, which means for example, that the block-scoped variables declared in a for statement will be limited to the scope of the for loop's body and statement and not to that of the current scope (i.e the one where the for statement was made)
This commit is contained in:
parent
0659d07241
commit
644b4f4201
Notes:
sideshowbarker
2024-07-19 08:18:43 +09:00
Author: https://github.com/0xtechnobabble Commit: https://github.com/SerenityOS/serenity/commit/644b4f42013 Pull-request: https://github.com/SerenityOS/serenity/pull/1445 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/deoxxa
4 changed files with 17 additions and 3 deletions
|
@ -95,6 +95,13 @@ Value WhileStatement::execute(Interpreter& interpreter) const
|
|||
|
||||
Value ForStatement::execute(Interpreter& interpreter) const
|
||||
{
|
||||
OwnPtr<BlockStatement> wrapper;
|
||||
|
||||
if (m_init->is_variable_declaration() && static_cast<const VariableDeclaration*>(m_init.ptr())->declaration_type() != DeclarationType::Var) {
|
||||
wrapper = make<BlockStatement>();
|
||||
interpreter.enter_scope(*wrapper, {}, ScopeType::Block);
|
||||
}
|
||||
|
||||
Value last_value = js_undefined();
|
||||
|
||||
if (m_init)
|
||||
|
@ -114,6 +121,9 @@ Value ForStatement::execute(Interpreter& interpreter) const
|
|||
}
|
||||
}
|
||||
|
||||
if (wrapper)
|
||||
interpreter.exit_scope(*wrapper);
|
||||
|
||||
return last_value;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,8 @@ private:
|
|||
};
|
||||
|
||||
class Statement : public ASTNode {
|
||||
public:
|
||||
virtual bool is_variable_declaration() const { return false; }
|
||||
};
|
||||
|
||||
class ErrorStatement final : public Statement {
|
||||
|
@ -480,7 +482,9 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual bool is_variable_declaration() const override { return true; }
|
||||
const Identifier& name() const { return *m_name; }
|
||||
DeclarationType declaration_type() const { return m_declaration_type; }
|
||||
|
||||
virtual Value execute(Interpreter&) const override;
|
||||
virtual void dump(int indent) const override;
|
||||
|
|
|
@ -68,8 +68,8 @@ void Interpreter::enter_scope(const ScopeNode& scope_node, Vector<Argument> argu
|
|||
|
||||
void Interpreter::exit_scope(const ScopeNode& scope_node)
|
||||
{
|
||||
ASSERT(&m_scope_stack.last().scope_node == &scope_node);
|
||||
m_scope_stack.take_last();
|
||||
while (&m_scope_stack.last().scope_node != &scope_node)
|
||||
m_scope_stack.take_last();
|
||||
}
|
||||
|
||||
void Interpreter::do_return()
|
||||
|
|
|
@ -76,10 +76,10 @@ public:
|
|||
|
||||
void collect_roots(Badge<Heap>, HashTable<Cell*>&);
|
||||
|
||||
private:
|
||||
void enter_scope(const ScopeNode&, Vector<Argument>, ScopeType);
|
||||
void exit_scope(const ScopeNode&);
|
||||
|
||||
private:
|
||||
Heap m_heap;
|
||||
|
||||
Vector<ScopeFrame> m_scope_stack;
|
||||
|
|
Loading…
Add table
Reference in a new issue