diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index a0b3c2206f..eac272b03a 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -989,6 +989,8 @@ Bytecode::CodeGenerationErrorOr FunctionExpression::generate_bytecode(Byte static Bytecode::CodeGenerationErrorOr generate_object_binding_pattern_bytecode(Bytecode::Generator& generator, BindingPattern const& pattern, Bytecode::Op::SetVariable::InitializationMode initialization_mode, Bytecode::Register const& value_reg, bool create_variables) { + generator.emit(); + Vector excluded_property_names; auto has_rest = false; if (pattern.entries.size() > 0) diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index 36c98cb71e..dff8d1dd71 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -92,6 +92,7 @@ O(SuperCall) \ O(Throw) \ O(ThrowIfNotObject) \ + O(ThrowIfNullish) \ O(ToNumeric) \ O(Typeof) \ O(TypeofVariable) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 4f954fb525..1595bd2e42 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -844,6 +844,15 @@ ThrowCompletionOr ThrowIfNotObject::execute_impl(Bytecode::Interpreter& in return {}; } +ThrowCompletionOr ThrowIfNullish::execute_impl(Bytecode::Interpreter& interpreter) const +{ + auto& vm = interpreter.vm(); + auto value = interpreter.accumulator(); + if (value.is_nullish()) + return vm.throw_completion(ErrorType::NotObjectCoercible, TRY_OR_THROW_OOM(vm, value.to_string_without_side_effects())); + return {}; +} + ThrowCompletionOr EnterUnwindContext::execute_impl(Bytecode::Interpreter& interpreter) const { interpreter.enter_unwind_context(m_handler_target, m_finalizer_target); @@ -1432,6 +1441,11 @@ DeprecatedString ThrowIfNotObject::to_deprecated_string_impl(Bytecode::Executabl return "ThrowIfNotObject"; } +DeprecatedString ThrowIfNullish::to_deprecated_string_impl(Bytecode::Executable const&) const +{ + return "ThrowIfNullish"; +} + DeprecatedString EnterUnwindContext::to_deprecated_string_impl(Bytecode::Executable const&) const { auto handler_string = m_handler_target.has_value() ? DeprecatedString::formatted("{}", *m_handler_target) : ""; diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 34c1730e31..7c4b5245a4 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -958,6 +958,19 @@ public: void replace_references_impl(Register, Register) { } }; +class ThrowIfNullish final : public Instruction { +public: + ThrowIfNullish() + : Instruction(Type::ThrowIfNullish) + { + } + + ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; + DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const; + void replace_references_impl(BasicBlock const&, BasicBlock const&) { } + void replace_references_impl(Register, Register) { } +}; + class EnterUnwindContext final : public Instruction { public: constexpr static bool IsTerminator = true;