diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 216b7758b5..99087bc5f0 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -480,7 +480,7 @@ Value AssignmentExpression::execute(Interpreter& interpreter) const commit = [&](Value value) { auto object = static_cast(*m_lhs).object().execute(interpreter).to_object(interpreter.heap()); ASSERT(object.is_object()); - auto property_name = static_cast(static_cast(*m_lhs).property()).string(); + auto property_name = static_cast(*m_lhs).computed_property_name(interpreter); object.as_object()->put(property_name, value); }; } else { @@ -638,24 +638,26 @@ Value ObjectExpression::execute(Interpreter& interpreter) const void MemberExpression::dump(int indent) const { - ASTNode::dump(indent); + print_indent(indent); + printf("%s (computed=%s)\n", class_name(), is_computed() ? "true" : "false"); m_object->dump(indent + 1); m_property->dump(indent + 1); } +String MemberExpression::computed_property_name(Interpreter& interpreter) const +{ + if (!is_computed()) { + ASSERT(m_property->is_identifier()); + return static_cast(*m_property).string(); + } + return m_property->execute(interpreter).to_string(); +} + Value MemberExpression::execute(Interpreter& interpreter) const { auto object_result = m_object->execute(interpreter).to_object(interpreter.heap()); ASSERT(object_result.is_object()); - - String property_name; - if (m_property->is_identifier()) { - property_name = static_cast(*m_property).string(); - } else { - ASSERT_NOT_REACHED(); - } - - return object_result.as_object()->get(property_name); + return object_result.as_object()->get(computed_property_name(interpreter)); } Value StringLiteral::execute(Interpreter& interpreter) const diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index eb5847a59f..b4943caa59 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -601,24 +601,29 @@ private: class MemberExpression final : public Expression { public: - MemberExpression(NonnullRefPtr object, NonnullRefPtr property) + MemberExpression(NonnullRefPtr object, NonnullRefPtr property, bool computed = false) : m_object(move(object)) , m_property(move(property)) + , m_computed(computed) { } virtual Value execute(Interpreter&) const override; virtual void dump(int indent) const override; + bool is_computed() const { return m_computed; } const Expression& object() const { return *m_object; } const Expression& property() const { return *m_property; } + String computed_property_name(Interpreter&) const; + private: virtual bool is_member_expression() const override { return true; } virtual const char* class_name() const override { return "MemberExpression"; } NonnullRefPtr m_object; NonnullRefPtr m_property; + bool m_computed { false }; }; } diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index 6e3a3935b0..bd02564ad8 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -369,6 +369,12 @@ NonnullRefPtr Parser::parse_secondary_expression(NonnullRefPtr(move(lhs), parse_expression(min_precedence, associativity)); + case TokenType::BracketOpen: { + consume(TokenType::BracketOpen); + auto expression = create_ast_node(move(lhs), parse_expression(min_precedence, associativity), true); + consume(TokenType::BracketClose); + return expression; + } case TokenType::PlusPlus: consume(); return create_ast_node(UpdateOp::Increment, move(lhs)); @@ -587,6 +593,7 @@ bool Parser::match_secondary_expression() const || type == TokenType::LessThanEquals || type == TokenType::ParenOpen || type == TokenType::Period + || type == TokenType::BracketOpen || type == TokenType::PlusPlus || type == TokenType::MinusMinus; }