summaryrefslogtreecommitdiff
path: root/Libraries/LibJS
diff options
context:
space:
mode:
authorMatthew Olsson <matthewcolsson@gmail.com>2020-10-08 13:12:31 -0700
committerAndreas Kling <kling@serenityos.org>2020-10-08 23:23:55 +0200
commitd980073122bbb17a805acee3ac34c4f788f87f4b (patch)
tree12d1dfbcaeba0bb92eafe04c758caebab9f96ab5 /Libraries/LibJS
parent397e5766ffb6c0c1633d228975c73292939ad92e (diff)
downloadserenity-d980073122bbb17a805acee3ac34c4f788f87f4b.zip
LibJS: Handle unwinding in while and do-while statements
For some reason, this was never added. So something like "while (true) { return }" would loop infinitely.
Diffstat (limited to 'Libraries/LibJS')
-rw-r--r--Libraries/LibJS/AST.cpp20
-rw-r--r--Libraries/LibJS/Tests/return.js0
2 files changed, 20 insertions, 0 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp
index 60de3d9383..9286c0aaa6 100644
--- a/Libraries/LibJS/AST.cpp
+++ b/Libraries/LibJS/AST.cpp
@@ -262,6 +262,16 @@ Value WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_obj
last_value = interpreter.execute_statement(global_object, *m_body);
if (interpreter.exception())
return {};
+ if (interpreter.vm().should_unwind()) {
+ if (interpreter.vm().should_unwind_until(ScopeType::Continuable, m_label)) {
+ interpreter.vm().stop_unwind();
+ } else if (interpreter.vm().should_unwind_until(ScopeType::Breakable, m_label)) {
+ interpreter.vm().stop_unwind();
+ break;
+ } else {
+ return js_undefined();
+ }
+ }
}
return last_value;
@@ -276,6 +286,16 @@ Value DoWhileStatement::execute(Interpreter& interpreter, GlobalObject& global_o
last_value = interpreter.execute_statement(global_object, *m_body);
if (interpreter.exception())
return {};
+ if (interpreter.vm().should_unwind()) {
+ if (interpreter.vm().should_unwind_until(ScopeType::Continuable, m_label)) {
+ interpreter.vm().stop_unwind();
+ } else if (interpreter.vm().should_unwind_until(ScopeType::Breakable, m_label)) {
+ interpreter.vm().stop_unwind();
+ break;
+ } else {
+ return js_undefined();
+ }
+ }
} while (m_test->execute(interpreter, global_object).to_boolean());
return last_value;
diff --git a/Libraries/LibJS/Tests/return.js b/Libraries/LibJS/Tests/return.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/Libraries/LibJS/Tests/return.js