mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 13:47:35 +00:00
LibJS: Parse async generator functions
This commit is contained in:
parent
5d0f666f22
commit
0982a73d1d
13 changed files with 270 additions and 40 deletions
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Interpreter.h>
|
||||
#include <LibJS/Runtime/AsyncGeneratorFunctionConstructor.h>
|
||||
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
|
||||
#include <LibJS/Runtime/FunctionConstructor.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
AsyncGeneratorFunctionConstructor::AsyncGeneratorFunctionConstructor(GlobalObject& global_object)
|
||||
: NativeFunction(vm().names.AsyncGeneratorFunction.as_string(), *global_object.function_prototype())
|
||||
{
|
||||
}
|
||||
|
||||
void AsyncGeneratorFunctionConstructor::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
|
||||
// 27.4.2.2 AsyncGeneratorFunction.prototype, https://tc39.es/ecma262/#sec-asyncgeneratorfunction-prototype
|
||||
define_direct_property(vm.names.prototype, global_object.async_generator_function_prototype(), 0);
|
||||
|
||||
// 27.4.2.1 AsyncGeneratorFunction.length, https://tc39.es/ecma262/#sec-asyncgeneratorfunction-length
|
||||
define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
|
||||
// 27.4.2.2 AsyncGeneratorFunction.prototype, https://tc39.es/ecma262/#sec-asyncgeneratorfunction-prototype
|
||||
define_direct_property(vm.names.prototype, global_object.async_generator_function_prototype(), 0);
|
||||
}
|
||||
|
||||
// 27.4.1.1 AsyncGeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-asyncgeneratorfunction
|
||||
ThrowCompletionOr<Value> AsyncGeneratorFunctionConstructor::call()
|
||||
{
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 27.4.1.1 AsyncGeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-asyncgeneratorfunction
|
||||
ThrowCompletionOr<Object*> AsyncGeneratorFunctionConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto function = TRY(FunctionConstructor::create_dynamic_function_node(global_object(), new_target, FunctionKind::AsyncGenerator));
|
||||
|
||||
OwnPtr<Interpreter> local_interpreter;
|
||||
Interpreter* interpreter = vm.interpreter_if_exists();
|
||||
|
||||
if (!interpreter) {
|
||||
local_interpreter = Interpreter::create_with_existing_realm(*realm());
|
||||
interpreter = local_interpreter.ptr();
|
||||
}
|
||||
|
||||
VM::InterpreterExecutionScope scope(*interpreter);
|
||||
auto result = function->execute(*interpreter, global_object());
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
VERIFY(result.is_object() && is<ECMAScriptFunctionObject>(result.as_object()));
|
||||
return &result.as_object();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibJS/Runtime/NativeFunction.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
class AsyncGeneratorFunctionConstructor final : public NativeFunction {
|
||||
JS_OBJECT(AsyncGeneratorFunctionConstructor, NativeFunction);
|
||||
|
||||
public:
|
||||
explicit AsyncGeneratorFunctionConstructor(GlobalObject&);
|
||||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~AsyncGeneratorFunctionConstructor() override = default;
|
||||
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AsyncGeneratorFunctionConstructor.h>
|
||||
#include <LibJS/Runtime/AsyncGeneratorFunctionPrototype.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
AsyncGeneratorFunctionPrototype::AsyncGeneratorFunctionPrototype(GlobalObject& global_object)
|
||||
: PrototypeObject(*global_object.function_prototype())
|
||||
{
|
||||
}
|
||||
|
||||
void AsyncGeneratorFunctionPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibJS/Runtime/PrototypeObject.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
class AsyncGeneratorFunctionPrototype final : public PrototypeObject<AsyncGeneratorFunctionPrototype, AsyncGeneratorFunction> {
|
||||
JS_PROTOTYPE_OBJECT(AsyncGeneratorFunctionPrototype, AsyncGeneratorFunction, AsyncGeneratorFunction);
|
||||
|
||||
public:
|
||||
explicit AsyncGeneratorFunctionPrototype(GlobalObject&);
|
||||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~AsyncGeneratorFunctionPrototype() override = default;
|
||||
};
|
||||
|
||||
}
|
|
@ -41,6 +41,9 @@ ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_
|
|||
case FunctionKind::Async:
|
||||
prototype = global_object.async_function_prototype();
|
||||
break;
|
||||
case FunctionKind::AsyncGenerator:
|
||||
prototype = global_object.async_generator_function_prototype();
|
||||
break;
|
||||
}
|
||||
return global_object.heap().allocate<ECMAScriptFunctionObject>(global_object, move(name), ecmascript_code, move(parameters), m_function_length, parent_scope, private_scope, *prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function);
|
||||
}
|
||||
|
@ -106,6 +109,9 @@ void ECMAScriptFunctionObject::initialize(GlobalObject& global_object)
|
|||
break;
|
||||
case FunctionKind::Async:
|
||||
break;
|
||||
case FunctionKind::AsyncGenerator:
|
||||
// FIXME: Add the AsyncGeneratorObject and set it as prototype.
|
||||
break;
|
||||
}
|
||||
define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
||||
}
|
||||
|
@ -750,6 +756,9 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
|||
auto& vm = this->vm();
|
||||
auto* bytecode_interpreter = Bytecode::Interpreter::current();
|
||||
|
||||
if (m_kind == FunctionKind::AsyncGenerator)
|
||||
return vm.throw_completion<InternalError>(global_object(), ErrorType::NotImplemented, "Async Generator function execution");
|
||||
|
||||
if (bytecode_interpreter) {
|
||||
// FIXME: pass something to evaluate default arguments with
|
||||
TRY(function_declaration_instantiation(nullptr));
|
||||
|
|
|
@ -53,8 +53,8 @@ ThrowCompletionOr<RefPtr<FunctionExpression>> FunctionConstructor::create_dynami
|
|||
parameters_source = parameters_builder.build();
|
||||
body_source = TRY(vm.argument(vm.argument_count() - 1).to_string(global_object));
|
||||
}
|
||||
auto is_generator = kind == FunctionKind::Generator;
|
||||
auto is_async = kind == FunctionKind::Async;
|
||||
auto is_generator = kind == FunctionKind::Generator || kind == FunctionKind::AsyncGenerator;
|
||||
auto is_async = kind == FunctionKind::Async || kind == FunctionKind::AsyncGenerator;
|
||||
auto source = String::formatted("{}function{} anonymous({}\n) {{\n{}\n}}", is_async ? "async " : "", is_generator ? "*" : "", parameters_source, body_source);
|
||||
auto parser = Parser(Lexer(source));
|
||||
auto function = parser.parse_function_node<FunctionExpression>();
|
||||
|
|
|
@ -12,6 +12,7 @@ enum class FunctionKind {
|
|||
Generator,
|
||||
Regular,
|
||||
Async,
|
||||
AsyncGenerator
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <LibJS/Runtime/ArrayPrototype.h>
|
||||
#include <LibJS/Runtime/AsyncFunctionConstructor.h>
|
||||
#include <LibJS/Runtime/AsyncFunctionPrototype.h>
|
||||
#include <LibJS/Runtime/AsyncGeneratorFunctionConstructor.h>
|
||||
#include <LibJS/Runtime/AsyncGeneratorFunctionPrototype.h>
|
||||
#include <LibJS/Runtime/AtomicsObject.h>
|
||||
#include <LibJS/Runtime/BigIntConstructor.h>
|
||||
#include <LibJS/Runtime/BigIntPrototype.h>
|
||||
|
@ -273,6 +275,11 @@ void GlobalObject::initialize_global_object()
|
|||
// 27.3.3.1 GeneratorFunction.prototype.constructor, https://tc39.es/ecma262/#sec-generatorfunction.prototype.constructor
|
||||
m_generator_function_prototype->define_direct_property(vm.names.constructor, m_generator_function_constructor, Attribute::Configurable);
|
||||
|
||||
// The async generator constructor cannot be initialized with add_constructor as it has no global binding
|
||||
m_async_generator_function_constructor = heap().allocate<AsyncGeneratorFunctionConstructor>(*this, *this);
|
||||
// 27.4.3.1 AsyncGeneratorFunction.prototype.constructor, https://tc39.es/ecma262/#sec-asyncgeneratorfunction-prototype-constructor
|
||||
m_async_generator_function_prototype->define_direct_property(vm.names.constructor, m_async_generator_function_constructor, Attribute::Configurable);
|
||||
|
||||
m_array_prototype_values_function = &m_array_prototype->get_without_side_effects(vm.names.values).as_function();
|
||||
m_eval_function = &get_without_side_effects(vm.names.eval).as_function();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue