summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp')
-rw-r--r--Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp52
1 files changed, 51 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
index 2fdfb567f0..028683b934 100644
--- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
+++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
@@ -11,6 +11,8 @@
#include <LibJS/Bytecode/Instruction.h>
#include <LibJS/Bytecode/Op.h>
#include <LibJS/Bytecode/Register.h>
+#include <LibJS/Bytecode/StringTable.h>
+#include <LibJS/Runtime/ScopeObject.h>
namespace JS {
@@ -27,6 +29,41 @@ void ScopeNode::generate_bytecode(Bytecode::Generator& generator) const
generator.emit<Bytecode::Op::SetVariable>(generator.intern_string(function.name()));
}
+ HashMap<u32, Variable> scope_variables_with_declaration_kind;
+
+ bool is_program_node = is<Program>(*this);
+ for (auto& declaration : variables()) {
+ for (auto& declarator : declaration.declarations()) {
+ if (is_program_node && declaration.declaration_kind() == DeclarationKind::Var) {
+ declarator.target().visit(
+ [&](const NonnullRefPtr<Identifier>& id) {
+ generator.emit<Bytecode::Op::LoadImmediate>(js_undefined());
+ generator.emit<Bytecode::Op::PutById>(Bytecode::Register::global_object(), generator.intern_string(id->string()));
+ },
+ [&](const NonnullRefPtr<BindingPattern>& binding) {
+ binding->for_each_assigned_name([&](const auto& name) {
+ generator.emit<Bytecode::Op::LoadImmediate>(js_undefined());
+ generator.emit<Bytecode::Op::PutById>(Bytecode::Register::global_object(), generator.intern_string(name));
+ });
+ });
+ } else {
+ declarator.target().visit(
+ [&](const NonnullRefPtr<Identifier>& id) {
+ scope_variables_with_declaration_kind.set((size_t)generator.intern_string(id->string()).value(), { js_undefined(), declaration.declaration_kind() });
+ },
+ [&](const NonnullRefPtr<BindingPattern>& binding) {
+ binding->for_each_assigned_name([&](const auto& name) {
+ scope_variables_with_declaration_kind.set((size_t)generator.intern_string(name).value(), { js_undefined(), declaration.declaration_kind() });
+ });
+ });
+ }
+ }
+ }
+
+ if (!scope_variables_with_declaration_kind.is_empty()) {
+ generator.emit<Bytecode::Op::PushLexicalEnvironment>(move(scope_variables_with_declaration_kind));
+ }
+
for (auto& child : children()) {
child.generate_bytecode(generator);
if (generator.is_current_block_terminated())
@@ -560,8 +597,21 @@ void FunctionDeclaration::generate_bytecode(Bytecode::Generator&) const
{
}
-void VariableDeclaration::generate_bytecode(Bytecode::Generator&) const
+void VariableDeclaration::generate_bytecode(Bytecode::Generator& generator) const
{
+ for (auto& declarator : m_declarations) {
+ if (declarator.init())
+ declarator.init()->generate_bytecode(generator);
+ else
+ generator.emit<Bytecode::Op::LoadImmediate>(js_undefined());
+ declarator.target().visit(
+ [&](const NonnullRefPtr<Identifier>& id) {
+ generator.emit<Bytecode::Op::SetVariable>(generator.intern_string(id->string()));
+ },
+ [&](const NonnullRefPtr<BindingPattern>&) {
+ TODO();
+ });
+ }
}
void CallExpression::generate_bytecode(Bytecode::Generator& generator) const