mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:37:34 +00:00
LibJS: Fix return statements not working properly in loops
Previously, when a loop detected an unwind of type ScopeType::Function (which means a return statement was executed inside of the loop), it would just return undefined. This set the VM's last_value to undefined, when it should have been the returned value. This patch makes all loop statements return the appropriate value in the above case.
This commit is contained in:
parent
d980073122
commit
6e05685ad4
3 changed files with 59 additions and 8 deletions
|
@ -269,7 +269,7 @@ Value WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_obj
|
||||||
interpreter.vm().stop_unwind();
|
interpreter.vm().stop_unwind();
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return js_undefined();
|
return last_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ Value DoWhileStatement::execute(Interpreter& interpreter, GlobalObject& global_o
|
||||||
interpreter.vm().stop_unwind();
|
interpreter.vm().stop_unwind();
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return js_undefined();
|
return last_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (m_test->execute(interpreter, global_object).to_boolean());
|
} 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();
|
interpreter.vm().stop_unwind();
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return js_undefined();
|
return last_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_update) {
|
if (m_update) {
|
||||||
|
@ -364,7 +364,7 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec
|
||||||
interpreter.vm().stop_unwind();
|
interpreter.vm().stop_unwind();
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return js_undefined();
|
return last_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_update) {
|
if (m_update) {
|
||||||
|
@ -431,7 +431,7 @@ Value ForInStatement::execute(Interpreter& interpreter, GlobalObject& global_obj
|
||||||
interpreter.vm().stop_unwind();
|
interpreter.vm().stop_unwind();
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return js_undefined();
|
return last_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -480,8 +480,6 @@ Value ForOfStatement::execute(Interpreter& interpreter, GlobalObject& global_obj
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (interpreter.vm().should_unwind())
|
|
||||||
return js_undefined();
|
|
||||||
return last_value;
|
return last_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ public:
|
||||||
m_unwind_until_label = label;
|
m_unwind_until_label = label;
|
||||||
}
|
}
|
||||||
void stop_unwind() { m_unwind_until = ScopeType::None; }
|
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())
|
if (m_unwind_until_label.is_null())
|
||||||
return m_unwind_until == type;
|
return m_unwind_until == type;
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue