diff options
author | Linus Groh <mail@linusgroh.de> | 2022-05-05 08:47:36 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-05-05 22:40:57 +0200 |
commit | 0c65624a32e0af2961c32a54f4ea8147397c52ab (patch) | |
tree | 10000c2afc723e9c4cabe49ed346365a5897cd3e /Userland | |
parent | 2c68ec90974918a6eb3c2e9a6d3169bd3c840f47 (diff) | |
download | serenity-0c65624a32e0af2961c32a54f4ea8147397c52ab.zip |
LibJS: Add AsyncGenerator / AsyncGeneratorPrototype
Not implementing any prototype functions yet, but stubbing out async
generator infrastructure will allow us to make some progress in that
direction.
Diffstat (limited to 'Userland')
10 files changed, 162 insertions, 9 deletions
diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index b96734afba..1d540be54e 100644 --- a/Userland/Libraries/LibJS/CMakeLists.txt +++ b/Userland/Libraries/LibJS/CMakeLists.txt @@ -49,8 +49,10 @@ set(SOURCES Runtime/AsyncFunctionConstructor.cpp Runtime/AsyncFunctionDriverWrapper.cpp Runtime/AsyncFunctionPrototype.cpp + Runtime/AsyncGenerator.cpp Runtime/AsyncGeneratorFunctionConstructor.cpp Runtime/AsyncGeneratorFunctionPrototype.cpp + Runtime/AsyncGeneratorPrototype.cpp Runtime/AsyncIteratorPrototype.cpp Runtime/AtomicsObject.cpp Runtime/BigInt.cpp diff --git a/Userland/Libraries/LibJS/Forward.h b/Userland/Libraries/LibJS/Forward.h index 60adffd533..dbc3641854 100644 --- a/Userland/Libraries/LibJS/Forward.h +++ b/Userland/Libraries/LibJS/Forward.h @@ -196,8 +196,10 @@ class ProxyObject; class ProxyConstructor; // Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor -class GeneratorPrototype; class AsyncFromSyncIteratorPrototype; +class AsyncGenerator; +class AsyncGeneratorPrototype; +class GeneratorPrototype; class TypedArrayConstructor; class TypedArrayPrototype; diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGenerator.cpp b/Userland/Libraries/LibJS/Runtime/AsyncGenerator.cpp new file mode 100644 index 0000000000..db83d52a25 --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/AsyncGenerator.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, Linus Groh <linusg@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibJS/Runtime/AsyncGenerator.h> +#include <LibJS/Runtime/AsyncGeneratorPrototype.h> +#include <LibJS/Runtime/GlobalObject.h> + +namespace JS { + +AsyncGenerator::AsyncGenerator(Object& prototype) + : Object(prototype) +{ +} + +void AsyncGenerator::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + for (auto const& request : m_async_generator_queue) { + if (request.completion.value().has_value()) + visitor.visit(*request.completion.value()); + visitor.visit(request.capability.promise); + visitor.visit(request.capability.reject); + visitor.visit(request.capability.resolve); + } +} + +} diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGenerator.h b/Userland/Libraries/LibJS/Runtime/AsyncGenerator.h new file mode 100644 index 0000000000..7154b851e1 --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/AsyncGenerator.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022, Linus Groh <linusg@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Variant.h> +#include <LibJS/Runtime/AsyncGeneratorRequest.h> +#include <LibJS/Runtime/ExecutionContext.h> +#include <LibJS/Runtime/Object.h> + +namespace JS { + +// 27.6.2 Properties of AsyncGenerator Instances, https://tc39.es/ecma262/#sec-properties-of-asyncgenerator-intances +class AsyncGenerator final : public Object { + JS_OBJECT(AsyncGenerator, Object); + +public: + enum class State { + SuspendedStart, + SuspendedYield, + Executing, + AwaitingReturn, + Completed, + }; + + explicit AsyncGenerator(Object& prototype); + virtual ~AsyncGenerator() override = default; + +private: + virtual void visit_edges(Cell::Visitor&) override; + + // At the time of constructing an AsyncGenerator, we still need to point to an + // execution context on the stack, but later need to 'adopt' it. + using ExecutionContextVariant = Variant<ExecutionContext, ExecutionContext*, Empty>; + + Optional<State> m_async_generator_state; // [[AsyncGeneratorState]] + ExecutionContextVariant m_async_generator_context; // [[AsyncGeneratorContext]] + Vector<AsyncGeneratorRequest> m_async_generator_queue; // [[AsyncGeneratorQueue]] + Optional<String> m_generator_brand; // [[GeneratorBrand]] +}; + +} diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorFunctionPrototype.cpp b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorFunctionPrototype.cpp index ccf76ab7c7..a2afd60eca 100644 --- a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorFunctionPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorFunctionPrototype.cpp @@ -6,6 +6,7 @@ #include <LibJS/Runtime/AsyncGeneratorFunctionConstructor.h> #include <LibJS/Runtime/AsyncGeneratorFunctionPrototype.h> +#include <LibJS/Runtime/AsyncGeneratorPrototype.h> #include <LibJS/Runtime/GlobalObject.h> namespace JS { @@ -23,8 +24,7 @@ void AsyncGeneratorFunctionPrototype::initialize(GlobalObject& global_object) // The constructor cannot be set at this point since it has not been initialized. // 27.4.3.2 AsyncGeneratorFunction.prototype.prototype, https://tc39.es/ecma262/#sec-asyncgeneratorfunction-prototype-prototype - // FIXME: AsyncGenerator does not exist yet. - // define_direct_property(vm.names.prototype, global_object.async_generator_prototype(), Attribute::Configurable); + define_direct_property(vm.names.prototype, global_object.async_generator_prototype(), Attribute::Configurable); // 27.4.3.3 AsyncGeneratorFunction.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-asyncgeneratorfunction-prototype-tostringtag define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(vm, vm.names.AsyncGeneratorFunction.as_string()), Attribute::Configurable); diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.cpp new file mode 100644 index 0000000000..ba6bb4f23e --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022, Linus Groh <linusg@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibJS/Runtime/AsyncGeneratorPrototype.h> + +namespace JS { + +// 27.6.1 Properties of the AsyncGenerator Prototype Object, https://tc39.es/ecma262/#sec-properties-of-asyncgenerator-prototype +AsyncGeneratorPrototype::AsyncGeneratorPrototype(GlobalObject& global_object) + : PrototypeObject(*global_object.async_iterator_prototype()) +{ +} + +void AsyncGeneratorPrototype::initialize(GlobalObject& global_object) +{ + auto& vm = this->vm(); + Object::initialize(global_object); + + // 27.6.1.5 AsyncGenerator.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-asyncgenerator-prototype-tostringtag + define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(vm, "AsyncGenerator"), Attribute::Configurable); +} + +} diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.h b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.h new file mode 100644 index 0000000000..6ba8d53b89 --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022, Linus Groh <linusg@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibJS/Runtime/AsyncGenerator.h> +#include <LibJS/Runtime/PrototypeObject.h> + +namespace JS { + +class AsyncGeneratorPrototype final : public PrototypeObject<AsyncGeneratorPrototype, AsyncGenerator> { + JS_PROTOTYPE_OBJECT(AsyncGeneratorPrototype, AsyncGenerator, AsyncGenerator) + +public: + explicit AsyncGeneratorPrototype(GlobalObject&); + virtual void initialize(GlobalObject&) override; + virtual ~AsyncGeneratorPrototype() override = default; +}; + +} diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorRequest.h b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorRequest.h new file mode 100644 index 0000000000..14270be7b1 --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorRequest.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022, Linus Groh <linusg@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibJS/Runtime/Completion.h> +#include <LibJS/Runtime/PromiseReaction.h> + +namespace JS { + +// 27.6.3.1 AsyncGeneratorRequest Records, https://tc39.es/ecma262/#sec-asyncgeneratorrequest-records +struct AsyncGeneratorRequest { + Completion completion; // [[Completion]] + PromiseCapability capability; // [[Capability]] +}; + +} diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp index 43e1f4e15c..5190f5845c 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -28,6 +28,7 @@ #include <LibJS/Runtime/AsyncFunctionPrototype.h> #include <LibJS/Runtime/AsyncGeneratorFunctionConstructor.h> #include <LibJS/Runtime/AsyncGeneratorFunctionPrototype.h> +#include <LibJS/Runtime/AsyncGeneratorPrototype.h> #include <LibJS/Runtime/AsyncIteratorPrototype.h> #include <LibJS/Runtime/AtomicsObject.h> #include <LibJS/Runtime/BigIntConstructor.h> @@ -177,12 +178,10 @@ void GlobalObject::initialize_global_object() JS_ENUMERATE_ITERATOR_PROTOTYPES #undef __JS_ENUMERATE - // %GeneratorFunction.prototype.prototype% must be initialized separately as it has no - // companion constructor - m_generator_prototype = heap().allocate<GeneratorPrototype>(*this, *this); - + // These must be initialized separately as they have no companion constructor m_async_from_sync_iterator_prototype = heap().allocate<AsyncFromSyncIteratorPrototype>(*this, *this); - + m_async_generator_prototype = heap().allocate<AsyncGeneratorPrototype>(*this, *this); + m_generator_prototype = heap().allocate<GeneratorPrototype>(*this, *this); m_intl_segments_prototype = heap().allocate<Intl::SegmentsPrototype>(*this, *this); #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \ @@ -298,6 +297,9 @@ void GlobalObject::initialize_global_object() // 27.5.1.1 Generator.prototype.constructor, https://tc39.es/ecma262/#sec-generator.prototype.constructor m_generator_prototype->define_direct_property(vm.names.constructor, m_generator_function_prototype, Attribute::Configurable); + // 27.6.1.1 AsyncGenerator.prototype.constructor, https://tc39.es/ecma262/#sec-asyncgenerator-prototype-constructor + m_async_generator_prototype->define_direct_property(vm.names.constructor, m_async_generator_function_prototype, Attribute::Configurable); + m_array_prototype_values_function = &m_array_prototype->get_without_side_effects(vm.names.values).as_function(); m_date_constructor_now_function = &m_date_constructor->get_without_side_effects(vm.names.now).as_function(); m_eval_function = &get_without_side_effects(vm.names.eval).as_function(); @@ -315,8 +317,9 @@ void GlobalObject::visit_edges(Visitor& visitor) visitor.visit(m_new_object_shape); visitor.visit(m_new_ordinary_function_prototype_object_shape); visitor.visit(m_proxy_constructor); - visitor.visit(m_generator_prototype); visitor.visit(m_async_from_sync_iterator_prototype); + visitor.visit(m_async_generator_prototype); + visitor.visit(m_generator_prototype); visitor.visit(m_intl_segments_prototype); visitor.visit(m_array_prototype_values_function); visitor.visit(m_date_constructor_now_function); diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.h b/Userland/Libraries/LibJS/Runtime/GlobalObject.h index 651c0300c8..2bcc49bf3c 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalObject.h +++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.h @@ -37,6 +37,7 @@ public: // Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor Object* async_from_sync_iterator_prototype() { return m_async_from_sync_iterator_prototype; } + Object* async_generator_prototype() { return m_async_generator_prototype; } Object* generator_prototype() { return m_generator_prototype; } // Not included in JS_ENUMERATE_INTL_OBJECTS due to missing distinct constructor @@ -109,6 +110,7 @@ private: // Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor Object* m_async_from_sync_iterator_prototype { nullptr }; + Object* m_async_generator_prototype { nullptr }; Object* m_generator_prototype { nullptr }; // Not included in JS_ENUMERATE_INTL_OBJECTS due to missing distinct constructor |