LibJS: Implement private identifiers in optional chains

This commit is contained in:
davidot 2021-10-18 23:32:47 +02:00 committed by Linus Groh
parent 4c8090a45d
commit 2d48529073
Notes: sideshowbarker 2024-07-18 02:07:45 +09:00
3 changed files with 35 additions and 2 deletions

View file

@ -2704,6 +2704,11 @@ void OptionalChain::dump(int indent) const
print_indent(indent + 1);
outln("MemberReference({})", ref.mode == Mode::Optional ? "Optional" : "Not Optional");
ref.identifier->dump(indent + 2);
},
[&](PrivateMemberReference const& ref) {
print_indent(indent + 1);
outln("PrivateMemberReference({})", ref.mode == Mode::Optional ? "Optional" : "Not Optional");
ref.private_identifier->dump(indent + 2);
});
}
}
@ -2738,6 +2743,12 @@ Optional<OptionalChain::ReferenceAndValue> OptionalChain::to_reference_and_value
create_ast_node<SyntheticReferenceExpression>(source_range(), *base_reference, base),
ref.identifier,
false);
},
[&](PrivateMemberReference const& ref) -> NonnullRefPtr<Expression> {
return create_ast_node<MemberExpression>(source_range(),
create_ast_node<SyntheticReferenceExpression>(source_range(), *base_reference, base),
ref.private_identifier,
false);
});
if (is<CallExpression>(*expression)) {
base_reference = JS::Reference {};

View file

@ -1590,8 +1590,12 @@ public:
NonnullRefPtr<Identifier> identifier;
Mode mode;
};
struct PrivateMemberReference {
NonnullRefPtr<PrivateIdentifier> private_identifier;
Mode mode;
};
using Reference = Variant<Call, ComputedReference, MemberReference>;
using Reference = Variant<Call, ComputedReference, MemberReference, PrivateMemberReference>;
OptionalChain(SourceRange source_range, NonnullRefPtr<Expression> base, Vector<Reference> references)
: Expression(source_range)

View file

@ -2696,6 +2696,17 @@ NonnullRefPtr<OptionalChain> Parser::parse_optional_chain(NonnullRefPtr<Expressi
chain.append(OptionalChain::ComputedReference { parse_expression(0), OptionalChain::Mode::Optional });
consume(TokenType::BracketClose);
break;
case TokenType::PrivateIdentifier: {
if (!is_private_identifier_valid())
syntax_error(String::formatted("Reference to undeclared private field or method '{}'", m_state.current_token.value()));
auto start = position();
auto private_identifier = consume();
chain.append(OptionalChain::PrivateMemberReference {
create_ast_node<PrivateIdentifier>({ m_state.current_token.filename(), start, position() }, private_identifier.value()),
OptionalChain::Mode::Optional });
break;
}
case TokenType::TemplateLiteralStart:
// 13.3.1.1 - Static Semantics: Early Errors
// OptionalChain :
@ -2721,7 +2732,14 @@ NonnullRefPtr<OptionalChain> Parser::parse_optional_chain(NonnullRefPtr<Expressi
chain.append(OptionalChain::Call { parse_arguments(), OptionalChain::Mode::NotOptional });
} else if (match(TokenType::Period)) {
consume();
if (match_identifier_name()) {
if (match(TokenType::PrivateIdentifier)) {
auto start = position();
auto private_identifier = consume();
chain.append(OptionalChain::PrivateMemberReference {
create_ast_node<PrivateIdentifier>({ m_state.current_token.filename(), start, position() }, private_identifier.value()),
OptionalChain::Mode::NotOptional,
});
} else if (match_identifier_name()) {
auto start = position();
auto identifier = consume();
chain.append(OptionalChain::MemberReference {