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); +}