mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 20:28:11 +00:00
LibJS: Implement async functions as generator functions in BC mode
This applies a simple transformation, and adds a simple wrapper that translates the generator interface to the async function interface.
This commit is contained in:
parent
c604e95993
commit
3b0bf05fa5
14 changed files with 192 additions and 43 deletions
|
@ -13,21 +13,21 @@
|
|||
|
||||
namespace JS {
|
||||
|
||||
ThrowCompletionOr<GeneratorObject*> GeneratorObject::create(GlobalObject& global_object, Value initial_value, ECMAScriptFunctionObject* generating_function, Environment* generating_scope, Bytecode::RegisterWindow frame)
|
||||
ThrowCompletionOr<GeneratorObject*> GeneratorObject::create(GlobalObject& global_object, Value initial_value, ECMAScriptFunctionObject* generating_function, ExecutionContext execution_context, Bytecode::RegisterWindow frame)
|
||||
{
|
||||
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
|
||||
auto generating_function_prototype = TRY(generating_function->get(global_object.vm().names.prototype));
|
||||
auto* generating_function_prototype_object = TRY(generating_function_prototype.to_object(global_object));
|
||||
auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object, *generating_function_prototype_object);
|
||||
auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object, *generating_function_prototype_object, move(execution_context));
|
||||
object->m_generating_function = generating_function;
|
||||
object->m_environment = generating_scope;
|
||||
object->m_frame = move(frame);
|
||||
object->m_previous_value = initial_value;
|
||||
return object;
|
||||
}
|
||||
|
||||
GeneratorObject::GeneratorObject(GlobalObject&, Object& prototype)
|
||||
GeneratorObject::GeneratorObject(GlobalObject&, Object& prototype, ExecutionContext context)
|
||||
: Object(prototype)
|
||||
, m_execution_context(move(context))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -42,12 +42,11 @@ GeneratorObject::~GeneratorObject()
|
|||
void GeneratorObject::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_environment);
|
||||
visitor.visit(m_generating_function);
|
||||
visitor.visit(m_previous_value);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<Value> GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<Value> value_to_throw)
|
||||
ThrowCompletionOr<Value> GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<Value> next_argument, Optional<Value> value_to_throw)
|
||||
{
|
||||
auto bytecode_interpreter = Bytecode::Interpreter::current();
|
||||
VERIFY(bytecode_interpreter);
|
||||
|
@ -92,20 +91,25 @@ ThrowCompletionOr<Value> GeneratorObject::next_impl(VM& vm, GlobalObject& global
|
|||
// Restore the snapshot registers
|
||||
bytecode_interpreter->enter_frame(m_frame);
|
||||
|
||||
// Temporarily switch to the captured execution context
|
||||
vm.push_execution_context(m_execution_context, global_object);
|
||||
|
||||
// Pretend that 'yield' returned the passed value, or threw
|
||||
if (value_to_throw.has_value()) {
|
||||
vm.throw_exception(global_object, value_to_throw.release_value());
|
||||
bytecode_interpreter->accumulator() = js_undefined();
|
||||
} else {
|
||||
bytecode_interpreter->accumulator() = vm.argument(0);
|
||||
bytecode_interpreter->accumulator() = next_argument.value_or(js_undefined());
|
||||
}
|
||||
|
||||
// Temporarily switch to the captured environment record
|
||||
TemporaryChange change { vm.running_execution_context().lexical_environment, m_environment };
|
||||
// Temporarily switch to the captured execution context
|
||||
vm.push_execution_context(m_execution_context, global_object);
|
||||
|
||||
m_previous_value = bytecode_interpreter->run(*m_generating_function->bytecode_executable(), next_block);
|
||||
|
||||
bytecode_interpreter->leave_frame();
|
||||
m_frame = move(*bytecode_interpreter->pop_frame());
|
||||
|
||||
vm.pop_execution_context();
|
||||
|
||||
m_done = TRY(generated_continuation(m_previous_value)) == nullptr;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue