diff options
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 |