diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 022f11ea87..f3a022ebc0 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -639,6 +639,65 @@ void FunctionExpression::generate_bytecode(Bytecode::Generator& generator) const generator.emit(*this); } +static void generate_binding_pattern_bytecode(Bytecode::Generator& generator, BindingPattern const& pattern, Bytecode::Register const& value, bool object_pattern) +{ + for (auto& [name, alias, initializer, is_rest] : pattern.entries) { + if (is_rest) + TODO(); + + if (object_pattern) { + Bytecode::StringTableIndex name_index; + + if (name.has>()) { + auto identifier = name.get>()->string(); + name_index = generator.intern_string(identifier); + generator.emit(value); + generator.emit(name_index); + } else { + auto expression = name.get>(); + expression->generate_bytecode(generator); + generator.emit(value); + } + + if (initializer) { + auto& if_undefined_block = generator.make_block(); + auto& if_not_undefined_block = generator.make_block(); + + generator.emit().set_targets( + Bytecode::Label { if_undefined_block }, + Bytecode::Label { if_not_undefined_block }); + + generator.switch_to_basic_block(if_undefined_block); + initializer->generate_bytecode(generator); + generator.emit().set_targets( + Bytecode::Label { if_not_undefined_block }, + {}); + + generator.switch_to_basic_block(if_not_undefined_block); + } + + if (alias.has>()) { + auto& binding_pattern = *alias.get>(); + auto nested_value_reg = generator.allocate_register(); + generator.emit(nested_value_reg); + generate_binding_pattern_bytecode(generator, binding_pattern, nested_value_reg, binding_pattern.kind == BindingPattern::Kind::Object); + } else if (alias.has()) { + if (name.has>()) { + // This needs some sort of SetVariableByValue opcode, as it's a runtime binding + TODO(); + } + + generator.emit(name_index); + } else { + auto& identifier = alias.get>()->string(); + generator.emit(generator.intern_string(identifier)); + } + } else { + TODO(); + } + } +}; + void VariableDeclaration::generate_bytecode(Bytecode::Generator& generator) const { for (auto& declarator : m_declarations) { @@ -647,11 +706,13 @@ void VariableDeclaration::generate_bytecode(Bytecode::Generator& generator) cons else generator.emit(js_undefined()); declarator.target().visit( - [&](const NonnullRefPtr& id) { + [&](NonnullRefPtr const& id) { generator.emit(generator.intern_string(id->string())); }, - [&](const NonnullRefPtr&) { - TODO(); + [&](NonnullRefPtr const& pattern) { + auto value_register = generator.allocate_register(); + generator.emit(value_register); + generate_binding_pattern_bytecode(generator, pattern, value_register, pattern->kind == BindingPattern::Kind::Object); }); } }