diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index ff0b14e4a8..49e0ab7bf5 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -33,12 +34,6 @@ class Identifier; class MemberExpression; class VariableDeclaration; -enum class FunctionKind { - Generator, - Regular, - Async, -}; - template static inline NonnullRefPtr create_ast_node(SourceRange range, Args&&... args) @@ -575,6 +570,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_argument; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 2f4d6a3b6d..b39cda72f4 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -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(nullptr); else generator.emit(); @@ -1269,4 +1269,16 @@ void ThisExpression::generate_bytecode(Bytecode::Generator& generator) const generator.emit(); } +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::Label { continuation_block }); + generator.switch_to_basic_block(continuation_block); +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 21ee3822c8..adea224ac9 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -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(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()) diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index 669f05a327..6e5f520c79 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -17,12 +17,13 @@ #include #include #include +#include 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