From 7e8724db71a838e910d935ea81808af3985e74fe Mon Sep 17 00:00:00 2001 From: davidot Date: Thu, 14 Oct 2021 02:05:24 +0200 Subject: [PATCH] LibJS: Add support for the '#privateName in obj' expression --- Userland/Libraries/LibJS/AST.cpp | 18 ++++++++++++++++++ Userland/Libraries/LibJS/Parser.cpp | 5 +++++ 2 files changed, 23 insertions(+) diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 88bb48434c..471eb4cee0 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -902,6 +902,24 @@ Value BinaryExpression::execute(Interpreter& interpreter, GlobalObject& global_o { InterpreterNodeScope node_scope { interpreter, *this }; + // Special case in which we cannot execute the lhs. RelationalExpression : PrivateIdentifier in ShiftExpression + // RelationalExpression : PrivateIdentifier in ShiftExpression, https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation + if (m_op == BinaryOp::In && is(*m_lhs)) { + auto& private_identifier = static_cast(*m_lhs).string(); + + auto rhs_result = m_rhs->execute(interpreter, global_object); + if (interpreter.exception()) + return {}; + if (!rhs_result.is_object()) { + interpreter.vm().throw_exception(global_object, ErrorType::InOperatorWithObject); + return {}; + } + auto* private_environment = interpreter.vm().running_execution_context().private_environment; + VERIFY(private_environment); + auto private_name = private_environment->resolve_private_identifier(private_identifier); + return Value(rhs_result.as_object().private_element_find(private_name) != nullptr); + } + auto lhs_result = m_lhs->execute(interpreter, global_object); if (interpreter.exception()) return {}; diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp index b00f119e6b..0bd4ca0698 100644 --- a/Userland/Libraries/LibJS/Parser.cpp +++ b/Userland/Libraries/LibJS/Parser.cpp @@ -1214,6 +1214,11 @@ Parser::PrimaryExpressionParseResult Parser::parse_primary_expression() if (!m_state.in_generator_function_context) goto read_as_identifier; return { parse_yield_expression(), false }; + case TokenType::PrivateIdentifier: + VERIFY(next_token().type() == TokenType::In); + if (!is_private_identifier_valid()) + syntax_error(String::formatted("Reference to undeclared private field or method '{}'", m_state.current_token.value())); + return { create_ast_node({ m_state.current_token.filename(), rule_start.position(), position() }, consume().value()) }; default: if (match_identifier_name()) goto read_as_identifier;