ladybird/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.cpp
Andreas Kling 1d20380859 LibJS: Split the per-call-frame environment into lexical and variable
To better follow the spec, we need to distinguish between the current
execution context's lexical environment and variable environment.

This patch moves us to having two record pointers, although both of
them point at the same environment records for now.
2021-06-22 18:44:53 +02:00

68 lines
2.5 KiB
C++

/*
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Debug.h>
#include <AK/Optional.h>
#include <LibJS/Bytecode/Interpreter.h>
#include <LibJS/Lexer.h>
#include <LibJS/Parser.h>
#include <LibJS/Runtime/FunctionConstructor.h>
#include <LibJS/Runtime/GeneratorFunctionConstructor.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/ScriptFunction.h>
namespace JS {
GeneratorFunctionConstructor::GeneratorFunctionConstructor(GlobalObject& global_object)
: NativeFunction(*static_cast<Object*>(global_object.function_constructor()))
{
}
void GeneratorFunctionConstructor::initialize(GlobalObject& global_object)
{
auto& vm = this->vm();
NativeFunction::initialize(global_object);
// 27.3.2.1 GeneratorFunction.length, https://tc39.es/ecma262/#sec-generatorfunction.length
define_property(vm.names.length, Value(1), Attribute::Configurable);
// 27.3.2.2 GeneratorFunction.prototype, https://tc39.es/ecma262/#sec-generatorfunction.length
define_property(vm.names.prototype, global_object.generator_function_prototype(), 0);
}
GeneratorFunctionConstructor::~GeneratorFunctionConstructor()
{
}
// 27.3.1.1 GeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-generatorfunction
Value GeneratorFunctionConstructor::call()
{
return construct(*this);
}
// 27.3.1.1 GeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-generatorfunction
Value GeneratorFunctionConstructor::construct(Function& new_target)
{
auto function = FunctionConstructor::create_dynamic_function_node(global_object(), new_target, FunctionKind::Generator);
if (!function)
return {};
auto* bytecode_interpreter = Bytecode::Interpreter::current();
VERIFY(bytecode_interpreter);
auto executable = Bytecode::Generator::generate(function->body(), true);
auto& passes = JS::Bytecode::Interpreter::optimization_pipeline();
passes.perform(executable);
if constexpr (JS_BYTECODE_DEBUG) {
dbgln("Optimisation passes took {}us", passes.elapsed());
dbgln("Compiled Bytecode::Block for function '{}':", function->name());
for (auto& block : executable.basic_blocks)
block.dump(executable);
}
return ScriptFunction::create(global_object(), function->name(), function->body(), function->parameters(), function->function_length(), vm().lexical_environment(), FunctionKind::Generator, function->is_strict_mode(), false);
}
}