summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime/VM.cpp
diff options
context:
space:
mode:
authordavidot <david.tuin@gmail.com>2021-09-18 01:11:32 +0200
committerLinus Groh <mail@linusgroh.de>2021-09-30 08:16:32 +0100
commitbfc1b4ba6185726f8b567f188a407e821892d5b1 (patch)
tree09c786930c9e41dc4b3a4e369c685886c0c48028 /Userland/Libraries/LibJS/Runtime/VM.cpp
parent9cb570039891b88a8d75c3fae761f617c340e2b7 (diff)
downloadserenity-bfc1b4ba6185726f8b567f188a407e821892d5b1.zip
LibJS: Allow member expressions in binding patterns
Also allows literal string and numbers as property names in object binding patterns.
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime/VM.cpp')
-rw-r--r--Userland/Libraries/LibJS/Runtime/VM.cpp52
1 files changed, 50 insertions, 2 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp
index b98969b86c..ec114f2a47 100644
--- a/Userland/Libraries/LibJS/Runtime/VM.cpp
+++ b/Userland/Libraries/LibJS/Runtime/VM.cpp
@@ -197,6 +197,20 @@ void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, Global
auto& entry = binding.entries[i];
+ Optional<Reference> assignment_target;
+ entry.alias.visit(
+ [&](Empty) {},
+ [&](NonnullRefPtr<Identifier> const&) {
+ // FIXME: We need to get the reference but bindings are broken so this doesn't work yet.
+ },
+ [&](NonnullRefPtr<BindingPattern> const&) {},
+ [&](NonnullRefPtr<MemberExpression> const& member_expression) {
+ assignment_target = member_expression->to_reference(interpreter(), global_object);
+ });
+
+ if (exception())
+ return;
+
if (entry.is_rest) {
VERIFY(i == binding.entries.size() - 1);
@@ -254,8 +268,15 @@ void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, Global
},
[&](NonnullRefPtr<BindingPattern> const& pattern) {
assign(pattern, value, global_object, first_assignment, specific_scope);
+ },
+ [&](NonnullRefPtr<MemberExpression> const&) {
+ VERIFY(assignment_target.has_value());
+ assignment_target->put_value(global_object, value);
});
+ if (exception())
+ return;
+
if (entry.is_rest)
break;
}
@@ -269,10 +290,21 @@ void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, Global
VERIFY(!property.is_elision());
PropertyName assignment_name;
+ Optional<Reference> assignment_target;
+
JS::Value value_to_assign;
if (property.is_rest) {
- VERIFY(property.name.has<NonnullRefPtr<Identifier>>());
- assignment_name = property.name.get<NonnullRefPtr<Identifier>>()->string();
+ if (auto identifier_ptr = property.name.get_pointer<NonnullRefPtr<Identifier>>())
+ assignment_name = (*identifier_ptr)->string();
+ property.alias.visit(
+ [&](Empty) {},
+ [&](NonnullRefPtr<Identifier> const&) {
+ // FIXME: We need to get the reference but bindings are broken so this doesn't work yet.
+ },
+ [&](NonnullRefPtr<BindingPattern> const&) {},
+ [&](NonnullRefPtr<MemberExpression> const& member_expression) {
+ assignment_target = member_expression->to_reference(interpreter(), global_object);
+ });
auto* rest_object = Object::create(global_object, global_object.object_prototype());
for (auto& object_property : object->shape().property_table()) {
@@ -298,6 +330,15 @@ void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, Global
return;
assignment_name = result.to_property_key(global_object);
});
+ property.alias.visit(
+ [&](Empty) {},
+ [&](NonnullRefPtr<Identifier> const&) {
+ // FIXME: We need to get the reference but bindings are broken so this doesn't work yet.
+ },
+ [&](NonnullRefPtr<BindingPattern> const&) {},
+ [&](NonnullRefPtr<MemberExpression> const& member_expression) {
+ assignment_target = member_expression->to_reference(interpreter(), global_object);
+ });
if (exception())
break;
@@ -327,8 +368,15 @@ void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, Global
[&](NonnullRefPtr<BindingPattern> const& pattern) {
VERIFY(!property.is_rest);
assign(pattern, value_to_assign, global_object, first_assignment, specific_scope);
+ },
+ [&](NonnullRefPtr<MemberExpression> const&) {
+ VERIFY(assignment_target.has_value());
+ assignment_target->put_value(global_object, value_to_assign);
});
+ if (exception())
+ return;
+
if (property.is_rest)
break;
}