mirror of
https://github.com/RGBCube/serenity
synced 2025-06-01 08: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
|
@ -911,7 +911,7 @@ void ReturnStatement::generate_bytecode(Bytecode::Generator& generator) const
|
|||
if (m_argument)
|
||||
m_argument->generate_bytecode(generator);
|
||||
|
||||
if (generator.is_in_generator_function())
|
||||
if (generator.is_in_generator_or_async_function())
|
||||
generator.emit<Bytecode::Op::Yield>(nullptr);
|
||||
else
|
||||
generator.emit<Bytecode::Op::Return>();
|
||||
|
@ -1269,4 +1269,16 @@ void ThisExpression::generate_bytecode(Bytecode::Generator& generator) const
|
|||
generator.emit<Bytecode::Op::ResolveThisBinding>();
|
||||
}
|
||||
|
||||
void AwaitExpression::generate_bytecode(Bytecode::Generator& generator) const
|
||||
{
|
||||
VERIFY(generator.is_in_async_function());
|
||||
|
||||
// Transform `await expr` to `yield expr`
|
||||
m_argument->generate_bytecode(generator);
|
||||
|
||||
auto& continuation_block = generator.make_block();
|
||||
generator.emit<Bytecode::Op::Yield>(Bytecode::Label { continuation_block });
|
||||
generator.switch_to_basic_block(continuation_block);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,19 +23,19 @@ Generator::~Generator()
|
|||
{
|
||||
}
|
||||
|
||||
Executable Generator::generate(ASTNode const& node, bool is_in_generator_function)
|
||||
Executable Generator::generate(ASTNode const& node, FunctionKind enclosing_function_kind)
|
||||
{
|
||||
Generator generator;
|
||||
generator.switch_to_basic_block(generator.make_block());
|
||||
if (is_in_generator_function) {
|
||||
generator.enter_generator_context();
|
||||
generator.m_enclosing_function_kind = enclosing_function_kind;
|
||||
if (generator.is_in_generator_or_async_function()) {
|
||||
// Immediately yield with no value.
|
||||
auto& start_block = generator.make_block();
|
||||
generator.emit<Bytecode::Op::Yield>(Label { start_block });
|
||||
generator.switch_to_basic_block(start_block);
|
||||
}
|
||||
node.generate_bytecode(generator);
|
||||
if (is_in_generator_function) {
|
||||
if (generator.is_in_generator_or_async_function()) {
|
||||
// Terminate all unterminated blocks with yield return
|
||||
for (auto& block : generator.m_root_basic_blocks) {
|
||||
if (block.is_terminated())
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
#include <LibJS/Bytecode/Register.h>
|
||||
#include <LibJS/Bytecode/StringTable.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/FunctionKind.h>
|
||||
|
||||
namespace JS::Bytecode {
|
||||
|
||||
class Generator {
|
||||
public:
|
||||
static Executable generate(ASTNode const&, bool is_in_generator_function = false);
|
||||
static Executable generate(ASTNode const&, FunctionKind = FunctionKind::Regular);
|
||||
|
||||
Register allocate_register();
|
||||
|
||||
|
@ -111,9 +112,9 @@ public:
|
|||
return m_identifier_table->insert(move(string));
|
||||
}
|
||||
|
||||
bool is_in_generator_function() const { return m_is_in_generator_function; }
|
||||
void enter_generator_context() { m_is_in_generator_function = true; }
|
||||
void leave_generator_context() { m_is_in_generator_function = false; }
|
||||
bool is_in_generator_or_async_function() const { return m_enclosing_function_kind == FunctionKind::Async || m_enclosing_function_kind == FunctionKind::Generator; }
|
||||
bool is_in_generator_function() const { return m_enclosing_function_kind == FunctionKind::Generator; }
|
||||
bool is_in_async_function() const { return m_enclosing_function_kind == FunctionKind::Async; }
|
||||
|
||||
private:
|
||||
Generator();
|
||||
|
@ -129,7 +130,7 @@ private:
|
|||
|
||||
u32 m_next_register { 2 };
|
||||
u32 m_next_block { 1 };
|
||||
bool m_is_in_generator_function { false };
|
||||
FunctionKind m_enclosing_function_kind { FunctionKind::Regular };
|
||||
Vector<Label> m_continuable_scopes;
|
||||
Vector<Label> m_breakable_scopes;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue