From 520311eb8bd705ae793d82522f461f981bcd8922 Mon Sep 17 00:00:00 2001 From: Stephan Unverwerth Date: Fri, 3 Apr 2020 19:11:31 +0200 Subject: [PATCH] LibJS: Add short circuit logical evaluation When evaluating logical binop expressions, the rhs must not be evaluated if the lhs leads to the whole expression not being truthy. --- Libraries/LibJS/AST.cpp | 17 +++++++++++++---- .../Tests/logical-expressions-short-circuit.js | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 Libraries/LibJS/Tests/logical-expressions-short-circuit.js diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 763c799170..f96b798c43 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -282,17 +282,26 @@ Value LogicalExpression::execute(Interpreter& interpreter) const auto lhs_result = m_lhs->execute(interpreter); if (interpreter.exception()) return {}; - auto rhs_result = m_rhs->execute(interpreter); - if (interpreter.exception()) - return {}; + switch (m_op) { case LogicalOp::And: - if (lhs_result.to_boolean()) + if (lhs_result.to_boolean()) { + auto rhs_result = m_rhs->execute(interpreter); + if (interpreter.exception()) + return {}; + return Value(rhs_result); + } + return Value(lhs_result); case LogicalOp::Or: if (lhs_result.to_boolean()) return Value(lhs_result); + + auto rhs_result = m_rhs->execute(interpreter); + if (interpreter.exception()) + return {}; + return Value(rhs_result); } diff --git a/Libraries/LibJS/Tests/logical-expressions-short-circuit.js b/Libraries/LibJS/Tests/logical-expressions-short-circuit.js new file mode 100644 index 0000000000..105281f62f --- /dev/null +++ b/Libraries/LibJS/Tests/logical-expressions-short-circuit.js @@ -0,0 +1,15 @@ +function assert(x) { if (!x) throw 1; } + +try { + let foo = 1; + false && (foo = 2); + assert(foo === 1); + + foo = 1; + true || (foo = 2); + assert(foo === 1); + + console.log("PASS"); +} catch (e) { + console.log("FAIL: " + e); +}