mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 07:32:44 +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
	
	 Linus Groh
						Linus Groh