Explorar o código

LibJS/Bytecode: Support `in` binary operator for private fields

11 new passes on test262. :^)
Andreas Kling %!s(int64=2) %!d(string=hai) anos
pai
achega
e87d84f883

+ 7 - 0
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -66,6 +66,13 @@ Bytecode::CodeGenerationErrorOr<void> ExpressionStatement::generate_bytecode(Byt
 
 Bytecode::CodeGenerationErrorOr<void> BinaryExpression::generate_bytecode(Bytecode::Generator& generator) const
 {
+    if (m_op == BinaryOp::In && is<PrivateIdentifier>(*m_lhs)) {
+        auto const& private_identifier = static_cast<PrivateIdentifier const&>(*m_lhs).string();
+        TRY(m_rhs->generate_bytecode(generator));
+        generator.emit<Bytecode::Op::HasPrivateId>(generator.intern_identifier(private_identifier));
+        return {};
+    }
+
     TRY(m_lhs->generate_bytecode(generator));
     auto lhs_reg = generator.allocate_register();
     generator.emit<Bytecode::Op::Store>(lhs_reg);

+ 1 - 0
Userland/Libraries/LibJS/Bytecode/Instruction.h

@@ -43,6 +43,7 @@
     O(GetVariable)                   \
     O(GreaterThan)                   \
     O(GreaterThanEquals)             \
+    O(HasPrivateId)                  \
     O(ImportCall)                    \
     O(In)                            \
     O(Increment)                     \

+ 19 - 0
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -544,6 +544,20 @@ ThrowCompletionOr<void> GetPrivateById::execute_impl(Bytecode::Interpreter& inte
     return {};
 }
 
+ThrowCompletionOr<void> HasPrivateId::execute_impl(Bytecode::Interpreter& interpreter) const
+{
+    auto& vm = interpreter.vm();
+
+    if (!interpreter.accumulator().is_object())
+        return vm.throw_completion<TypeError>(ErrorType::InOperatorWithObject);
+
+    auto private_environment = vm.running_execution_context().private_environment;
+    VERIFY(private_environment);
+    auto private_name = private_environment->resolve_private_identifier(interpreter.current_executable().get_identifier(m_property));
+    interpreter.accumulator() = Value(interpreter.accumulator().as_object().private_element_find(private_name) != nullptr);
+    return {};
+}
+
 ThrowCompletionOr<void> PutById::execute_impl(Bytecode::Interpreter& interpreter) const
 {
     auto& vm = interpreter.vm();
@@ -1383,6 +1397,11 @@ DeprecatedString GetPrivateById::to_deprecated_string_impl(Bytecode::Executable
     return DeprecatedString::formatted("GetPrivateById {} ({})", m_property, executable.identifier_table->get(m_property));
 }
 
+DeprecatedString HasPrivateId::to_deprecated_string_impl(Bytecode::Executable const& executable) const
+{
+    return DeprecatedString::formatted("HasPrivateId {} ({})", m_property, executable.identifier_table->get(m_property));
+}
+
 DeprecatedString DeleteById::to_deprecated_string_impl(Bytecode::Executable const& executable) const
 {
     return DeprecatedString::formatted("DeleteById {} ({})", m_property, executable.identifier_table->get(m_property));

+ 17 - 0
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -558,6 +558,23 @@ private:
     IdentifierTableIndex m_property;
 };
 
+class HasPrivateId final : public Instruction {
+public:
+    explicit HasPrivateId(IdentifierTableIndex property)
+        : Instruction(Type::HasPrivateId)
+        , m_property(property)
+    {
+    }
+
+    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
+    DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
+    void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
+    void replace_references_impl(Register, Register) { }
+
+private:
+    IdentifierTableIndex m_property;
+};
+
 enum class PropertyKind {
     Getter,
     Setter,