diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 36ebb8b8c8..6dc50d51ae 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -980,8 +980,13 @@ Value SwitchStatement::execute(Interpreter& interpreter) const statement.execute(interpreter); if (interpreter.exception()) return {}; - if (interpreter.should_unwind()) + if (interpreter.should_unwind()) { + if (interpreter.should_unwind_until(ScopeType::Breakable)) { + interpreter.stop_unwind(); + return {}; + } return {}; + } } } diff --git a/Libraries/LibJS/Interpreter.h b/Libraries/LibJS/Interpreter.h index 757df0109c..428d63253c 100644 --- a/Libraries/LibJS/Interpreter.h +++ b/Libraries/LibJS/Interpreter.h @@ -86,6 +86,8 @@ public: Heap& heap() { return m_heap; } void unwind(ScopeType type) { m_unwind_until = type; } + void stop_unwind() { m_unwind_until = ScopeType::None; } + bool should_unwind_until(ScopeType type) const { return m_unwind_until == type; } bool should_unwind() const { return m_unwind_until != ScopeType::None; } Optional get_variable(const FlyString& name); diff --git a/Libraries/LibJS/Tests/switch-break.js b/Libraries/LibJS/Tests/switch-break.js new file mode 100644 index 0000000000..976e102092 --- /dev/null +++ b/Libraries/LibJS/Tests/switch-break.js @@ -0,0 +1,25 @@ +function assert(x) { if (!x) throw 1; } + +try { + var i = 0; + var three; + var five; + + for (; i < 9; ) { + switch (i) { + case 3: + three = i; + break; + case 5: + five = i; + break; + } + ++i; + } + assert(three === 3); + assert(five === 5); + + console.log("PASS"); +} catch { +} +