mirror of
https://github.com/RGBCube/serenity
synced 2025-05-20 14:35:07 +00:00
LibJS: Implement nullish coalescing operator (??)
This commit is contained in:
parent
1806592d58
commit
d14ddb6461
4 changed files with 60 additions and 12 deletions
|
@ -338,20 +338,25 @@ Value LogicalExpression::execute(Interpreter& interpreter) const
|
|||
auto rhs_result = m_rhs->execute(interpreter);
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
|
||||
return Value(rhs_result);
|
||||
return rhs_result;
|
||||
}
|
||||
|
||||
return Value(lhs_result);
|
||||
case LogicalOp::Or:
|
||||
return lhs_result;
|
||||
case LogicalOp::Or: {
|
||||
if (lhs_result.to_boolean())
|
||||
return Value(lhs_result);
|
||||
|
||||
return lhs_result;
|
||||
auto rhs_result = m_rhs->execute(interpreter);
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
|
||||
return Value(rhs_result);
|
||||
return rhs_result;
|
||||
}
|
||||
case LogicalOp::NullishCoalescing:
|
||||
if (lhs_result.is_null() || lhs_result.is_undefined()) {
|
||||
auto rhs_result = m_rhs->execute(interpreter);
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
return rhs_result;
|
||||
}
|
||||
return lhs_result;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
|
@ -515,6 +520,9 @@ void LogicalExpression::dump(int indent) const
|
|||
case LogicalOp::Or:
|
||||
op_string = "||";
|
||||
break;
|
||||
case LogicalOp::NullishCoalescing:
|
||||
op_string = "??";
|
||||
break;
|
||||
}
|
||||
|
||||
print_indent(indent);
|
||||
|
|
|
@ -367,6 +367,7 @@ private:
|
|||
enum class LogicalOp {
|
||||
And,
|
||||
Or,
|
||||
NullishCoalescing,
|
||||
};
|
||||
|
||||
class LogicalExpression : public Expression {
|
||||
|
|
|
@ -601,6 +601,9 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
|
|||
case TokenType::DoublePipe:
|
||||
consume();
|
||||
return create_ast_node<LogicalExpression>(LogicalOp::Or, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::DoubleQuestionMark:
|
||||
consume();
|
||||
return create_ast_node<LogicalExpression>(LogicalOp::NullishCoalescing, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::QuestionMark:
|
||||
return parse_conditional_expression(move(lhs));
|
||||
default:
|
||||
|
@ -1039,7 +1042,8 @@ bool Parser::match_secondary_expression() const
|
|||
|| type == TokenType::Pipe
|
||||
|| type == TokenType::Caret
|
||||
|| type == TokenType::DoubleAmpersand
|
||||
|| type == TokenType::DoublePipe;
|
||||
|| type == TokenType::DoublePipe
|
||||
|| type == TokenType::DoubleQuestionMark;
|
||||
}
|
||||
|
||||
bool Parser::match_statement() const
|
||||
|
|
|
@ -17,7 +17,6 @@ try {
|
|||
assert(("foo" && true) === true);
|
||||
assert((false && "bar") === false);
|
||||
assert((true && "bar") === "bar");
|
||||
assert((null && true) === null);
|
||||
assert((0 && false) === 0);
|
||||
assert((0 && true) === 0);
|
||||
assert((42 && false) === false);
|
||||
|
@ -55,7 +54,6 @@ try {
|
|||
assert(("foo" || true) === "foo");
|
||||
assert((false || "bar") === "bar");
|
||||
assert((true || "bar") === true);
|
||||
assert((null || true) === true);
|
||||
assert((0 || false) === false);
|
||||
assert((0 || true) === true);
|
||||
assert((42 || false) === 42);
|
||||
|
@ -77,6 +75,43 @@ try {
|
|||
assert((false || undefined) === undefined);
|
||||
assert((true || undefined) === true);
|
||||
|
||||
assert((true ?? true) === true);
|
||||
assert((false ?? false) === false);
|
||||
assert((true ?? false) === true);
|
||||
assert((false ?? true) === false);
|
||||
assert((false ?? (1 === 2)) === false);
|
||||
assert((true ?? (1 === 2)) === true);
|
||||
assert(("" ?? "") === "");
|
||||
assert(("" ?? false) === "");
|
||||
assert(("" ?? true) === "");
|
||||
assert((false ?? "") === false);
|
||||
assert((true ?? "") === true);
|
||||
assert(("foo" ?? "bar") === "foo");
|
||||
assert(("foo" ?? false) === "foo");
|
||||
assert(("foo" ?? true) === "foo");
|
||||
assert((false ?? "bar") === false);
|
||||
assert((true ?? "bar") === true);
|
||||
assert((0 ?? false) === 0);
|
||||
assert((0 ?? true) === 0);
|
||||
assert((42 ?? false) === 42);
|
||||
assert((42 ?? true) === 42);
|
||||
assert((false ?? 0) === false);
|
||||
assert((true ?? 0) === true);
|
||||
assert((false ?? 42) === false);
|
||||
assert((true ?? 42) === true);
|
||||
assert(([] ?? false).length === 0);
|
||||
assert(([] ?? true).length === 0);
|
||||
assert((false ?? []) === false);
|
||||
assert((true ?? []) === true);
|
||||
assert((null ?? false) === false);
|
||||
assert((null ?? true) === true);
|
||||
assert((false ?? null) === false);
|
||||
assert((true ?? null) === true);
|
||||
assert((undefined ?? false) === false);
|
||||
assert((undefined ?? true) === true);
|
||||
assert((false ?? undefined) === false);
|
||||
assert((true ?? undefined) === true);
|
||||
|
||||
console.log("PASS");
|
||||
} catch (e) {
|
||||
console.log("FAIL: " + e);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue