diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 9286c0aaa6..33f447df17 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -269,7 +269,7 @@ Value WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_obj interpreter.vm().stop_unwind(); break; } else { - return js_undefined(); + return last_value; } } } @@ -293,7 +293,7 @@ Value DoWhileStatement::execute(Interpreter& interpreter, GlobalObject& global_o interpreter.vm().stop_unwind(); break; } else { - return js_undefined(); + return last_value; } } } while (m_test->execute(interpreter, global_object).to_boolean()); @@ -343,7 +343,7 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec interpreter.vm().stop_unwind(); break; } else { - return js_undefined(); + return last_value; } } if (m_update) { @@ -364,7 +364,7 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec interpreter.vm().stop_unwind(); break; } else { - return js_undefined(); + return last_value; } } if (m_update) { @@ -431,7 +431,7 @@ Value ForInStatement::execute(Interpreter& interpreter, GlobalObject& global_obj interpreter.vm().stop_unwind(); break; } else { - return js_undefined(); + return last_value; } } } @@ -480,8 +480,6 @@ Value ForOfStatement::execute(Interpreter& interpreter, GlobalObject& global_obj if (interpreter.exception()) return {}; - if (interpreter.vm().should_unwind()) - return js_undefined(); return last_value; } diff --git a/Libraries/LibJS/Runtime/VM.h b/Libraries/LibJS/Runtime/VM.h index c7f95da39c..01b8db1288 100644 --- a/Libraries/LibJS/Runtime/VM.h +++ b/Libraries/LibJS/Runtime/VM.h @@ -167,7 +167,7 @@ public: m_unwind_until_label = label; } void stop_unwind() { m_unwind_until = ScopeType::None; } - bool should_unwind_until(ScopeType type, FlyString label) const + bool should_unwind_until(ScopeType type, FlyString label = {}) const { if (m_unwind_until_label.is_null()) return m_unwind_until == type; diff --git a/Libraries/LibJS/Tests/return.js b/Libraries/LibJS/Tests/return.js index e69de29bb2..2c5b8683f6 100644 --- a/Libraries/LibJS/Tests/return.js +++ b/Libraries/LibJS/Tests/return.js @@ -0,0 +1,53 @@ +describe("returning from loops", () => { + test("returning from while loops", () => { + function foo() { + while (true) { + return 10; + } + } + + expect(foo()).toBe(10); + }); + + test("returning from do-while loops", () => { + function foo() { + do { + return 10; + } while (true); + } + + expect(foo()).toBe(10); + }); + + test("returning from for loops", () => { + function foo() { + for (let i = 0; i < 5; i++) { + return 10; + } + } + + expect(foo()).toBe(10); + }); + + test("returning from for-in loops", () => { + function foo() { + const o = { a: 1, b: 2 }; + for (let a in o) { + return 10; + } + } + + expect(foo()).toBe(10); + }); + + test("returning from for-of loops", () => { + function foo() { + const o = [1, 2, 3]; + for (let a of o) { + return 10; + } + } + + expect(foo()).toBe(10); + }); +});