diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index d3ebb2dca8..00a47ed90d 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -844,6 +844,7 @@ public: virtual Completion execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; + virtual Bytecode::CodeGenerationErrorOr generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_object; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index a952ded98f..b26e55cc58 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -1618,4 +1618,13 @@ Bytecode::CodeGenerationErrorOr AwaitExpression::generate_bytecode(Bytecod return {}; } +Bytecode::CodeGenerationErrorOr WithStatement::generate_bytecode(Bytecode::Generator& generator) const +{ + TRY(m_object->generate_bytecode(generator)); + generator.emit(); + TRY(m_body->generate_bytecode(generator)); + generator.emit(Bytecode::Op::EnvironmentMode::Lexical); + return {}; +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index 720ad67b21..e76529ee89 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -25,6 +25,7 @@ O(Decrement) \ O(Div) \ O(EnterUnwindContext) \ + O(EnterObjectEnvironment) \ O(Exp) \ O(FinishUnwind) \ O(GetById) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index da022f5b3a..8202bc1f8f 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -274,6 +275,15 @@ ThrowCompletionOr CreateEnvironment::execute_impl(Bytecode::Interpreter& i return {}; } +ThrowCompletionOr EnterObjectEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const +{ + auto& old_environment = interpreter.vm().running_execution_context().lexical_environment; + interpreter.saved_lexical_environment_stack().append(old_environment); + auto object = TRY(interpreter.accumulator().to_object(interpreter.global_object())); + interpreter.vm().running_execution_context().lexical_environment = new_object_environment(*object, true, old_environment); + return {}; +} + ThrowCompletionOr CreateVariable::execute_impl(Bytecode::Interpreter& interpreter) const { auto& vm = interpreter.vm(); @@ -695,6 +705,11 @@ String CreateVariable::to_string_impl(Bytecode::Executable const& executable) co return String::formatted("CreateVariable env:{} immutable:{} {} ({})", mode_string, m_is_immutable, m_identifier, executable.identifier_table->get(m_identifier)); } +String EnterObjectEnvironment::to_string_impl(const Executable&) const +{ + return String::formatted("EnterObjectEnvironment"); +} + String SetVariable::to_string_impl(Bytecode::Executable const& executable) const { auto initialization_mode_name = m_initialization_mode == InitializationMode ::Initialize ? "Initialize" diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 00b8b0ecc1..b286e925e0 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -303,6 +303,18 @@ private: EnvironmentMode m_mode { EnvironmentMode::Lexical }; }; +class EnterObjectEnvironment final : public Instruction { +public: + explicit EnterObjectEnvironment() + : Instruction(Type::EnterObjectEnvironment) + { + } + + ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; + String to_string_impl(Bytecode::Executable const&) const; + void replace_references_impl(BasicBlock const&, BasicBlock const&) { } +}; + class CreateVariable final : public Instruction { public: explicit CreateVariable(IdentifierTableIndex identifier, EnvironmentMode mode, bool is_immutable)