mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibJS: Implement 'in' operator
This commit is contained in:
parent
396ecfa2d7
commit
11728b7db5
Notes:
sideshowbarker
2024-07-19 07:21:32 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/11728b7db5e Pull-request: https://github.com/SerenityOS/serenity/pull/1931 Reviewed-by: https://github.com/awesomekling
6 changed files with 54 additions and 0 deletions
|
@ -331,6 +331,8 @@ Value BinaryExpression::execute(Interpreter& interpreter) const
|
|||
return right_shift(interpreter, lhs_result, rhs_result);
|
||||
case BinaryOp::UnsignedRightShift:
|
||||
return unsigned_right_shift(interpreter, lhs_result, rhs_result);
|
||||
case BinaryOp::In:
|
||||
return in(interpreter, lhs_result, rhs_result);
|
||||
case BinaryOp::InstanceOf:
|
||||
return instance_of(interpreter, lhs_result, rhs_result);
|
||||
}
|
||||
|
@ -512,6 +514,9 @@ void BinaryExpression::dump(int indent) const
|
|||
case BinaryOp::UnsignedRightShift:
|
||||
op_string = ">>>";
|
||||
break;
|
||||
case BinaryOp::In:
|
||||
op_string = "in";
|
||||
break;
|
||||
case BinaryOp::InstanceOf:
|
||||
op_string = "instanceof";
|
||||
break;
|
||||
|
|
|
@ -343,6 +343,7 @@ enum class BinaryOp {
|
|||
LeftShift,
|
||||
RightShift,
|
||||
UnsignedRightShift,
|
||||
In,
|
||||
InstanceOf,
|
||||
};
|
||||
|
||||
|
|
|
@ -566,6 +566,9 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
|
|||
case TokenType::ExclamationMarkEquals:
|
||||
consume();
|
||||
return create_ast_node<BinaryExpression>(BinaryOp::AbstractInequals, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::In:
|
||||
consume();
|
||||
return create_ast_node<BinaryExpression>(BinaryOp::In, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::Instanceof:
|
||||
consume();
|
||||
return create_ast_node<BinaryExpression>(BinaryOp::InstanceOf, move(lhs), parse_expression(min_precedence, associativity));
|
||||
|
@ -1076,6 +1079,7 @@ bool Parser::match_secondary_expression() const
|
|||
|| type == TokenType::BracketOpen
|
||||
|| type == TokenType::PlusPlus
|
||||
|| type == TokenType::MinusMinus
|
||||
|| type == TokenType::In
|
||||
|| type == TokenType::Instanceof
|
||||
|| type == TokenType::QuestionMark
|
||||
|| type == TokenType::Ampersand
|
||||
|
|
|
@ -382,6 +382,14 @@ Value eq(Interpreter& interpreter, Value lhs, Value rhs)
|
|||
return Value(false);
|
||||
}
|
||||
|
||||
Value in(Interpreter& interpreter, Value lhs, Value rhs)
|
||||
{
|
||||
if (!rhs.is_object())
|
||||
return interpreter.throw_exception<TypeError>("'in' operator must be used on object");
|
||||
|
||||
return Value(rhs.as_object().get(lhs.to_string()).has_value());
|
||||
}
|
||||
|
||||
Value instance_of(Interpreter&, Value lhs, Value rhs)
|
||||
{
|
||||
if (!lhs.is_object() || !rhs.is_object())
|
||||
|
|
|
@ -222,6 +222,7 @@ Value mod(Interpreter&, Value lhs, Value rhs);
|
|||
Value exp(Interpreter&, Value lhs, Value rhs);
|
||||
Value eq(Interpreter&, Value lhs, Value rhs);
|
||||
Value typed_eq(Interpreter&, Value lhs, Value rhs);
|
||||
Value in(Interpreter&, Value lhs, Value rhs);
|
||||
Value instance_of(Interpreter&, Value lhs, Value rhs);
|
||||
|
||||
const LogStream& operator<<(const LogStream&, const Value&);
|
||||
|
|
35
Libraries/LibJS/Tests/in-operator-basic.js
Normal file
35
Libraries/LibJS/Tests/in-operator-basic.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
load("test-common.js");
|
||||
|
||||
try {
|
||||
["foo", 123, null, undefined].forEach(value => {
|
||||
assertThrowsError(() => {
|
||||
"prop" in value;
|
||||
}, {
|
||||
error: TypeError,
|
||||
message: "'in' operator must be used on object"
|
||||
});
|
||||
});
|
||||
|
||||
var o = {foo: "bar", bar: undefined};
|
||||
assert("" in o === false);
|
||||
assert("foo" in o === true);
|
||||
assert("bar" in o === true);
|
||||
assert("baz" in o === false);
|
||||
assert("toString" in o === true);
|
||||
|
||||
var a = ["hello", "friends"];
|
||||
assert(0 in a === true);
|
||||
assert(1 in a === true);
|
||||
assert(2 in a === false);
|
||||
assert("0" in a === true);
|
||||
assert("hello" in a === false);
|
||||
assert("friends" in a === false);
|
||||
assert("length" in a === true);
|
||||
|
||||
var s = new String("foo");
|
||||
assert("length" in s);
|
||||
|
||||
console.log("PASS");
|
||||
} catch (e) {
|
||||
console.log("FAIL: " + e);
|
||||
}
|
Loading…
Reference in a new issue