diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index 6cb9a90197..91e65fb49a 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -786,11 +786,25 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body() { auto& vm = this->vm(); auto& realm = *vm.current_realm(); - auto* bytecode_interpreter = Bytecode::Interpreter::current(); if (m_kind == FunctionKind::AsyncGenerator) return vm.throw_completion(ErrorType::NotImplemented, "Async Generator function execution"); + auto* bytecode_interpreter = Bytecode::Interpreter::current(); + + // The bytecode interpreter can execute generator functions while the AST interpreter cannot. + // This simply makes it create a new bytecode interpreter when one doesn't exist when executing a generator function. + // Doing so makes it automatically switch to the bytecode interpreter to execute any future code until it exits the generator. See below. + // This allows us to keep all of the existing functionality that works in AST while adding generator support on top of it. + // However, this does cause an awkward situation with features not supported in bytecode, where features that work outside of generators with AST + // suddenly stop working inside of generators. + // This is a stop gap until bytecode mode becomes the default. + OwnPtr temp_bc_interpreter; + if (m_kind == FunctionKind::Generator && !bytecode_interpreter) { + temp_bc_interpreter = make(realm); + bytecode_interpreter = temp_bc_interpreter.ptr(); + } + if (bytecode_interpreter) { if (!m_bytecode_executable) { auto compile = [&](auto& node, auto kind, auto name) -> ThrowCompletionOr> { diff --git a/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp b/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp index 6e60ff8efd..e17b333616 100644 --- a/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp @@ -103,11 +103,16 @@ ThrowCompletionOr GeneratorObject::execute(VM& vm, Completion const& comp completion_object->define_direct_property(vm.names.value, completion.value().value(), default_attributes); auto* bytecode_interpreter = Bytecode::Interpreter::current(); + + // If we're coming from a context which has no bytecode interpreter, e.g. from AST mode calling Generate.prototype.next, + // we need to make one to be able to continue, as generators are only supported in bytecode mode. + // See also ECMAScriptFunctionObject::ordinary_call_evaluate_body where this is done as well. OwnPtr temp_bc_interpreter; if (!bytecode_interpreter) { temp_bc_interpreter = make(realm); bytecode_interpreter = temp_bc_interpreter.ptr(); } + VERIFY(bytecode_interpreter); auto const* next_block = generated_continuation(m_previous_value);