mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 05:39:11 +00:00
LibJS: Keep parsed function parameters in a shared data structure
Instead of making a copy of the Vector<FunctionParameter> from the AST every time we instantiate an ECMAScriptFunctionObject, we now keep the parameters in a ref-counted FunctionParameters object. This reduces memory usage, and also allows us to cache the bytecode executables for default parameter expressions without recompiling them for every instantiation. :^)
This commit is contained in:
parent
634f0c2469
commit
7477002e46
Notes:
github-actions[bot]
2025-03-27 15:02:02 +00:00
Author: https://github.com/awesomekling
Commit: 7477002e46
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4119
Reviewed-by: https://github.com/gmta ✅
11 changed files with 68 additions and 38 deletions
|
@ -241,7 +241,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation
|
||||||
FunctionParsingInsights parsing_insights;
|
FunctionParsingInsights parsing_insights;
|
||||||
parsing_insights.uses_this_from_environment = true;
|
parsing_insights.uses_this_from_environment = true;
|
||||||
parsing_insights.uses_this = true;
|
parsing_insights.uses_this = true;
|
||||||
initializer = ECMAScriptFunctionObject::create(realm, "field"_string, ByteString::empty(), *function_code, {}, 0, {}, vm.lexical_environment(), vm.running_execution_context().private_environment, FunctionKind::Normal, true, parsing_insights, false, property_key_or_private_name);
|
initializer = ECMAScriptFunctionObject::create(realm, "field"_string, ByteString::empty(), *function_code, FunctionParameters::empty(), 0, {}, vm.lexical_environment(), vm.running_execution_context().private_environment, FunctionKind::Normal, true, parsing_insights, false, property_key_or_private_name);
|
||||||
initializer->make_method(target);
|
initializer->make_method(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_eva
|
||||||
FunctionParsingInsights parsing_insights;
|
FunctionParsingInsights parsing_insights;
|
||||||
parsing_insights.uses_this_from_environment = true;
|
parsing_insights.uses_this_from_environment = true;
|
||||||
parsing_insights.uses_this = true;
|
parsing_insights.uses_this = true;
|
||||||
auto body_function = ECMAScriptFunctionObject::create(realm, ""_string, ByteString::empty(), *m_function_body, {}, 0, m_function_body->local_variables_names(), lexical_environment, private_environment, FunctionKind::Normal, true, parsing_insights, false);
|
auto body_function = ECMAScriptFunctionObject::create(realm, ""_string, ByteString::empty(), *m_function_body, FunctionParameters::empty(), 0, m_function_body->local_variables_names(), lexical_environment, private_environment, FunctionKind::Normal, true, parsing_insights, false);
|
||||||
|
|
||||||
// 6. Perform MakeMethod(bodyFunction, homeObject).
|
// 6. Perform MakeMethod(bodyFunction, homeObject).
|
||||||
body_function->make_method(home_object);
|
body_function->make_method(home_object);
|
||||||
|
@ -833,11 +833,11 @@ void FunctionNode::dump(int indent, ByteString const& class_name) const
|
||||||
print_indent(indent + 1);
|
print_indent(indent + 1);
|
||||||
outln("\033[31;1m(direct eval)\033[0m");
|
outln("\033[31;1m(direct eval)\033[0m");
|
||||||
}
|
}
|
||||||
if (!m_parameters.is_empty()) {
|
if (!m_parameters->is_empty()) {
|
||||||
print_indent(indent + 1);
|
print_indent(indent + 1);
|
||||||
outln("(Parameters)");
|
outln("(Parameters)");
|
||||||
|
|
||||||
for (auto& parameter : m_parameters) {
|
for (auto& parameter : m_parameters->parameters()) {
|
||||||
parameter.binding.visit(
|
parameter.binding.visit(
|
||||||
[&](Identifier const& identifier) {
|
[&](Identifier const& identifier) {
|
||||||
if (parameter.is_rest) {
|
if (parameter.is_rest) {
|
||||||
|
@ -1880,4 +1880,10 @@ NonnullRefPtr<NewExpression> NewExpression::create(SourceRange source_range, Non
|
||||||
return ASTNodeWithTailArray::create<NewExpression>(arguments.size(), move(source_range), move(callee), arguments, invocation_style, inside_parens);
|
return ASTNodeWithTailArray::create<NewExpression>(arguments.size(), move(source_range), move(callee), arguments, invocation_style, inside_parens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<FunctionParameters> FunctionParameters::empty()
|
||||||
|
{
|
||||||
|
static auto empty = adopt_ref(*new FunctionParameters({}));
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -692,6 +692,28 @@ struct FunctionParameter {
|
||||||
GC::Root<Bytecode::Executable> bytecode_executable {};
|
GC::Root<Bytecode::Executable> bytecode_executable {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FunctionParameters : public RefCounted<FunctionParameters> {
|
||||||
|
public:
|
||||||
|
static NonnullRefPtr<FunctionParameters> create(Vector<FunctionParameter> parameters)
|
||||||
|
{
|
||||||
|
return adopt_ref(*new FunctionParameters(move(parameters)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static NonnullRefPtr<FunctionParameters> empty();
|
||||||
|
|
||||||
|
bool is_empty() const { return m_parameters.is_empty(); }
|
||||||
|
size_t size() const { return m_parameters.size(); }
|
||||||
|
Vector<FunctionParameter> const& parameters() const { return m_parameters; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionParameters(Vector<FunctionParameter> parameters)
|
||||||
|
: m_parameters(move(parameters))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<FunctionParameter> m_parameters;
|
||||||
|
};
|
||||||
|
|
||||||
struct FunctionParsingInsights {
|
struct FunctionParsingInsights {
|
||||||
bool uses_this { false };
|
bool uses_this { false };
|
||||||
bool uses_this_from_environment { false };
|
bool uses_this_from_environment { false };
|
||||||
|
@ -705,7 +727,8 @@ public:
|
||||||
RefPtr<Identifier const> name_identifier() const { return m_name; }
|
RefPtr<Identifier const> name_identifier() const { return m_name; }
|
||||||
ByteString const& source_text() const { return m_source_text; }
|
ByteString const& source_text() const { return m_source_text; }
|
||||||
Statement const& body() const { return *m_body; }
|
Statement const& body() const { return *m_body; }
|
||||||
Vector<FunctionParameter> const& parameters() const { return m_parameters; }
|
auto const& body_ptr() const { return m_body; }
|
||||||
|
auto const& parameters() const { return m_parameters; }
|
||||||
i32 function_length() const { return m_function_length; }
|
i32 function_length() const { return m_function_length; }
|
||||||
Vector<FlyString> const& local_variables_names() const { return m_local_variables_names; }
|
Vector<FlyString> const& local_variables_names() const { return m_local_variables_names; }
|
||||||
bool is_strict_mode() const { return m_is_strict_mode; }
|
bool is_strict_mode() const { return m_is_strict_mode; }
|
||||||
|
@ -722,7 +745,7 @@ public:
|
||||||
virtual ~FunctionNode() { }
|
virtual ~FunctionNode() { }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FunctionNode(RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, Vector<FunctionParameter> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, FunctionParsingInsights parsing_insights, bool is_arrow_function, Vector<FlyString> local_variables_names)
|
FunctionNode(RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, FunctionParsingInsights parsing_insights, bool is_arrow_function, Vector<FlyString> local_variables_names)
|
||||||
: m_name(move(name))
|
: m_name(move(name))
|
||||||
, m_source_text(move(source_text))
|
, m_source_text(move(source_text))
|
||||||
, m_body(move(body))
|
, m_body(move(body))
|
||||||
|
@ -745,7 +768,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
ByteString m_source_text;
|
ByteString m_source_text;
|
||||||
NonnullRefPtr<Statement const> m_body;
|
NonnullRefPtr<Statement const> m_body;
|
||||||
Vector<FunctionParameter> const m_parameters;
|
NonnullRefPtr<FunctionParameters const> m_parameters;
|
||||||
i32 const m_function_length;
|
i32 const m_function_length;
|
||||||
FunctionKind m_kind;
|
FunctionKind m_kind;
|
||||||
bool m_is_strict_mode : 1 { false };
|
bool m_is_strict_mode : 1 { false };
|
||||||
|
@ -761,7 +784,7 @@ class FunctionDeclaration final
|
||||||
public:
|
public:
|
||||||
static bool must_have_name() { return true; }
|
static bool must_have_name() { return true; }
|
||||||
|
|
||||||
FunctionDeclaration(SourceRange source_range, RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, Vector<FunctionParameter> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, FunctionParsingInsights insights, Vector<FlyString> local_variables_names)
|
FunctionDeclaration(SourceRange source_range, RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, FunctionParsingInsights insights, Vector<FlyString> local_variables_names)
|
||||||
: Declaration(move(source_range))
|
: Declaration(move(source_range))
|
||||||
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, insights, false, move(local_variables_names))
|
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, insights, false, move(local_variables_names))
|
||||||
{
|
{
|
||||||
|
@ -791,7 +814,7 @@ class FunctionExpression final
|
||||||
public:
|
public:
|
||||||
static bool must_have_name() { return false; }
|
static bool must_have_name() { return false; }
|
||||||
|
|
||||||
FunctionExpression(SourceRange source_range, RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, Vector<FunctionParameter> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, FunctionParsingInsights insights, Vector<FlyString> local_variables_names, bool is_arrow_function = false)
|
FunctionExpression(SourceRange source_range, RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, FunctionParsingInsights insights, Vector<FlyString> local_variables_names, bool is_arrow_function = false)
|
||||||
: Expression(move(source_range))
|
: Expression(move(source_range))
|
||||||
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, insights, is_arrow_function, move(local_variables_names))
|
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, insights, is_arrow_function, move(local_variables_names))
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,8 +68,8 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const& formal_parameters = function.formal_parameters();
|
auto const& formal_parameters = function.formal_parameters();
|
||||||
for (u32 param_index = 0; param_index < formal_parameters.size(); ++param_index) {
|
for (u32 param_index = 0; param_index < formal_parameters->size(); ++param_index) {
|
||||||
auto const& parameter = formal_parameters[param_index];
|
auto const& parameter = formal_parameters->parameters()[param_index];
|
||||||
|
|
||||||
if (parameter.is_rest) {
|
if (parameter.is_rest) {
|
||||||
auto argument_reg = allocate_register();
|
auto argument_reg = allocate_register();
|
||||||
|
|
|
@ -179,6 +179,7 @@ class ForStatement;
|
||||||
class FunctionEnvironment;
|
class FunctionEnvironment;
|
||||||
class FunctionNode;
|
class FunctionNode;
|
||||||
struct FunctionParameter;
|
struct FunctionParameter;
|
||||||
|
class FunctionParameters;
|
||||||
class GlobalEnvironment;
|
class GlobalEnvironment;
|
||||||
class GlobalObject;
|
class GlobalObject;
|
||||||
struct GraphLoadingState;
|
struct GraphLoadingState;
|
||||||
|
|
|
@ -1136,7 +1136,7 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
||||||
auto source_text = ByteString { m_state.lexer.source().substring_view(function_start_offset, function_end_offset - function_start_offset) };
|
auto source_text = ByteString { m_state.lexer.source().substring_view(function_start_offset, function_end_offset - function_start_offset) };
|
||||||
return create_ast_node<FunctionExpression>(
|
return create_ast_node<FunctionExpression>(
|
||||||
{ m_source_code, rule_start.position(), position() }, nullptr, move(source_text),
|
{ m_source_code, rule_start.position(), position() }, nullptr, move(source_text),
|
||||||
move(body), move(parameters), function_length, function_kind, body->in_strict_mode(),
|
move(body), FunctionParameters::create(move(parameters)), function_length, function_kind, body->in_strict_mode(),
|
||||||
parsing_insights, move(local_variables_names), /* is_arrow_function */ true);
|
parsing_insights, move(local_variables_names), /* is_arrow_function */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1633,13 +1633,13 @@ NonnullRefPtr<ClassExpression const> Parser::parse_class_expression(bool expect_
|
||||||
FunctionParsingInsights parsing_insights;
|
FunctionParsingInsights parsing_insights;
|
||||||
constructor = create_ast_node<FunctionExpression>(
|
constructor = create_ast_node<FunctionExpression>(
|
||||||
{ m_source_code, rule_start.position(), position() }, class_name, "",
|
{ m_source_code, rule_start.position(), position() }, class_name, "",
|
||||||
move(constructor_body), Vector { FunctionParameter { move(argument_name), nullptr, true } }, 0, FunctionKind::Normal,
|
move(constructor_body), FunctionParameters::create(Vector { FunctionParameter { move(argument_name), nullptr, true } }), 0, FunctionKind::Normal,
|
||||||
/* is_strict_mode */ true, parsing_insights, /* local_variables_names */ Vector<FlyString> {});
|
/* is_strict_mode */ true, parsing_insights, /* local_variables_names */ Vector<FlyString> {});
|
||||||
} else {
|
} else {
|
||||||
FunctionParsingInsights parsing_insights;
|
FunctionParsingInsights parsing_insights;
|
||||||
constructor = create_ast_node<FunctionExpression>(
|
constructor = create_ast_node<FunctionExpression>(
|
||||||
{ m_source_code, rule_start.position(), position() }, class_name, "",
|
{ m_source_code, rule_start.position(), position() }, class_name, "",
|
||||||
move(constructor_body), Vector<FunctionParameter> {}, 0, FunctionKind::Normal,
|
move(constructor_body), FunctionParameters::empty(), 0, FunctionKind::Normal,
|
||||||
/* is_strict_mode */ true, parsing_insights, /* local_variables_names */ Vector<FlyString> {});
|
/* is_strict_mode */ true, parsing_insights, /* local_variables_names */ Vector<FlyString> {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2991,7 +2991,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u16 parse_options, O
|
||||||
parsing_insights.might_need_arguments_object = m_state.function_might_need_arguments_object;
|
parsing_insights.might_need_arguments_object = m_state.function_might_need_arguments_object;
|
||||||
return create_ast_node<FunctionNodeType>(
|
return create_ast_node<FunctionNodeType>(
|
||||||
{ m_source_code, rule_start.position(), position() },
|
{ m_source_code, rule_start.position(), position() },
|
||||||
name, move(source_text), move(body), move(parameters), function_length,
|
name, move(source_text), move(body), FunctionParameters::create(move(parameters)), function_length,
|
||||||
function_kind, has_strict_directive, parsing_insights,
|
function_kind, has_strict_directive, parsing_insights,
|
||||||
move(local_variables_names));
|
move(local_variables_names));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1074,7 +1074,7 @@ Object* create_unmapped_arguments_object(VM& vm, ReadonlySpan<Value> arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env ), https://tc39.es/ecma262/#sec-createmappedargumentsobject
|
// 10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env ), https://tc39.es/ecma262/#sec-createmappedargumentsobject
|
||||||
Object* create_mapped_arguments_object(VM& vm, FunctionObject& function, Vector<FunctionParameter> const& formals, ReadonlySpan<Value> arguments, Environment& environment)
|
Object* create_mapped_arguments_object(VM& vm, FunctionObject& function, NonnullRefPtr<FunctionParameters const> const& formals, ReadonlySpan<Value> arguments, Environment& environment)
|
||||||
{
|
{
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
|
|
||||||
|
@ -1113,10 +1113,10 @@ Object* create_mapped_arguments_object(VM& vm, FunctionObject& function, Vector<
|
||||||
|
|
||||||
// 18. Set index to numberOfParameters - 1.
|
// 18. Set index to numberOfParameters - 1.
|
||||||
// 19. Repeat, while index ≥ 0,
|
// 19. Repeat, while index ≥ 0,
|
||||||
VERIFY(formals.size() <= NumericLimits<i32>::max());
|
VERIFY(formals->size() <= NumericLimits<i32>::max());
|
||||||
for (i32 index = static_cast<i32>(formals.size()) - 1; index >= 0; --index) {
|
for (i32 index = static_cast<i32>(formals->size()) - 1; index >= 0; --index) {
|
||||||
// a. Let name be parameterNames[index].
|
// a. Let name be parameterNames[index].
|
||||||
auto const& name = formals[index].binding.get<NonnullRefPtr<Identifier const>>()->string();
|
auto const& name = formals->parameters()[index].binding.get<NonnullRefPtr<Identifier const>>()->string();
|
||||||
|
|
||||||
// b. If name is not an element of mappedNames, then
|
// b. If name is not an element of mappedNames, then
|
||||||
if (mapped_names.contains(name))
|
if (mapped_names.contains(name))
|
||||||
|
|
|
@ -43,7 +43,7 @@ bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const
|
||||||
bool validate_and_apply_property_descriptor(Object*, PropertyKey const&, bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
|
bool validate_and_apply_property_descriptor(Object*, PropertyKey const&, bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
|
||||||
ThrowCompletionOr<Object*> get_prototype_from_constructor(VM&, FunctionObject const& constructor, GC::Ref<Object> (Intrinsics::*intrinsic_default_prototype)());
|
ThrowCompletionOr<Object*> get_prototype_from_constructor(VM&, FunctionObject const& constructor, GC::Ref<Object> (Intrinsics::*intrinsic_default_prototype)());
|
||||||
Object* create_unmapped_arguments_object(VM&, ReadonlySpan<Value> arguments);
|
Object* create_unmapped_arguments_object(VM&, ReadonlySpan<Value> arguments);
|
||||||
Object* create_mapped_arguments_object(VM&, FunctionObject&, Vector<FunctionParameter> const&, ReadonlySpan<Value> arguments, Environment&);
|
Object* create_mapped_arguments_object(VM&, FunctionObject&, NonnullRefPtr<FunctionParameters const> const&, ReadonlySpan<Value> arguments, Environment&);
|
||||||
|
|
||||||
// 2.1.1 DisposeCapability Records, https://tc39.es/proposal-explicit-resource-management/#sec-disposecapability-records
|
// 2.1.1 DisposeCapability Records, https://tc39.es/proposal-explicit-resource-management/#sec-disposecapability-records
|
||||||
struct DisposeCapability {
|
struct DisposeCapability {
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace JS {
|
||||||
|
|
||||||
GC_DEFINE_ALLOCATOR(ECMAScriptFunctionObject);
|
GC_DEFINE_ALLOCATOR(ECMAScriptFunctionObject);
|
||||||
|
|
||||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, FlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||||
{
|
{
|
||||||
Object* prototype = nullptr;
|
Object* prototype = nullptr;
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
@ -53,12 +53,12 @@ GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm,
|
||||||
return realm.create<ECMAScriptFunctionObject>(move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, move(local_variables_names), parent_environment, private_environment, *prototype, kind, is_strict, parsing_insights, is_arrow_function, move(class_field_initializer_name));
|
return realm.create<ECMAScriptFunctionObject>(move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, move(local_variables_names), parent_environment, private_environment, *prototype, kind, is_strict, parsing_insights, is_arrow_function, move(class_field_initializer_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||||
{
|
{
|
||||||
return realm.create<ECMAScriptFunctionObject>(move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, move(local_variables_names), parent_environment, private_environment, prototype, kind, is_strict, parsing_insights, is_arrow_function, move(class_field_initializer_name));
|
return realm.create<ECMAScriptFunctionObject>(move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, move(local_variables_names), parent_environment, private_environment, prototype, kind, is_strict, parsing_insights, is_arrow_function, move(class_field_initializer_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
ECMAScriptFunctionObject::ECMAScriptFunctionObject(FlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> formal_parameters, i32 function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, Object& prototype, FunctionKind kind, bool strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
ECMAScriptFunctionObject::ECMAScriptFunctionObject(FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> formal_parameters, i32 function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, Object& prototype, FunctionKind kind, bool strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||||
: FunctionObject(prototype)
|
: FunctionObject(prototype)
|
||||||
, m_name(move(name))
|
, m_name(move(name))
|
||||||
, m_function_length(function_length)
|
, m_function_length(function_length)
|
||||||
|
@ -92,7 +92,7 @@ ECMAScriptFunctionObject::ECMAScriptFunctionObject(FlyString name, ByteString so
|
||||||
m_script_or_module = vm().get_active_script_or_module();
|
m_script_or_module = vm().get_active_script_or_module();
|
||||||
|
|
||||||
// 15.1.3 Static Semantics: IsSimpleParameterList, https://tc39.es/ecma262/#sec-static-semantics-issimpleparameterlist
|
// 15.1.3 Static Semantics: IsSimpleParameterList, https://tc39.es/ecma262/#sec-static-semantics-issimpleparameterlist
|
||||||
m_has_simple_parameter_list = all_of(m_formal_parameters, [&](auto& parameter) {
|
m_has_simple_parameter_list = all_of(m_formal_parameters->parameters(), [&](auto& parameter) {
|
||||||
if (parameter.is_rest)
|
if (parameter.is_rest)
|
||||||
return false;
|
return false;
|
||||||
if (parameter.default_value)
|
if (parameter.default_value)
|
||||||
|
@ -121,7 +121,7 @@ ECMAScriptFunctionObject::ECMAScriptFunctionObject(FlyString name, ByteString so
|
||||||
size_t parameters_in_environment = 0;
|
size_t parameters_in_environment = 0;
|
||||||
|
|
||||||
// NOTE: This loop performs step 5, 6, and 8.
|
// NOTE: This loop performs step 5, 6, and 8.
|
||||||
for (auto const& parameter : formals) {
|
for (auto const& parameter : formals->parameters()) {
|
||||||
if (parameter.default_value)
|
if (parameter.default_value)
|
||||||
m_has_parameter_expressions = true;
|
m_has_parameter_expressions = true;
|
||||||
|
|
||||||
|
@ -385,11 +385,11 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
|
||||||
auto callee_context = ExecutionContext::create();
|
auto callee_context = ExecutionContext::create();
|
||||||
|
|
||||||
// Non-standard
|
// Non-standard
|
||||||
callee_context->arguments.ensure_capacity(max(arguments_list.size(), m_formal_parameters.size()));
|
callee_context->arguments.ensure_capacity(max(arguments_list.size(), m_formal_parameters->size()));
|
||||||
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
||||||
callee_context->passed_argument_count = arguments_list.size();
|
callee_context->passed_argument_count = arguments_list.size();
|
||||||
if (arguments_list.size() < m_formal_parameters.size()) {
|
if (arguments_list.size() < m_formal_parameters->size()) {
|
||||||
for (size_t i = arguments_list.size(); i < m_formal_parameters.size(); ++i)
|
for (size_t i = arguments_list.size(); i < m_formal_parameters->size(); ++i)
|
||||||
callee_context->arguments.append(js_undefined());
|
callee_context->arguments.append(js_undefined());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,11 +442,11 @@ ThrowCompletionOr<GC::Ref<Object>> ECMAScriptFunctionObject::internal_construct(
|
||||||
auto callee_context = ExecutionContext::create();
|
auto callee_context = ExecutionContext::create();
|
||||||
|
|
||||||
// Non-standard
|
// Non-standard
|
||||||
callee_context->arguments.ensure_capacity(max(arguments_list.size(), m_formal_parameters.size()));
|
callee_context->arguments.ensure_capacity(max(arguments_list.size(), m_formal_parameters->size()));
|
||||||
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
||||||
callee_context->passed_argument_count = arguments_list.size();
|
callee_context->passed_argument_count = arguments_list.size();
|
||||||
if (arguments_list.size() < m_formal_parameters.size()) {
|
if (arguments_list.size() < m_formal_parameters->size()) {
|
||||||
for (size_t i = arguments_list.size(); i < m_formal_parameters.size(); ++i)
|
for (size_t i = arguments_list.size(); i < m_formal_parameters->size(); ++i)
|
||||||
callee_context->arguments.append(js_undefined());
|
callee_context->arguments.append(js_undefined());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,8 @@ public:
|
||||||
Global,
|
Global,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GC::Ref<ECMAScriptFunctionObject> create(Realm&, FlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
|
static GC::Ref<ECMAScriptFunctionObject> create(Realm&, FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
|
||||||
static GC::Ref<ECMAScriptFunctionObject> create(Realm&, FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
|
static GC::Ref<ECMAScriptFunctionObject> create(Realm&, FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
|
||||||
|
|
||||||
virtual void initialize(Realm&) override;
|
virtual void initialize(Realm&) override;
|
||||||
virtual ~ECMAScriptFunctionObject() override = default;
|
virtual ~ECMAScriptFunctionObject() override = default;
|
||||||
|
@ -54,7 +54,7 @@ public:
|
||||||
void set_is_module_wrapper(bool b) { m_is_module_wrapper = b; }
|
void set_is_module_wrapper(bool b) { m_is_module_wrapper = b; }
|
||||||
|
|
||||||
Statement const& ecmascript_code() const { return m_ecmascript_code; }
|
Statement const& ecmascript_code() const { return m_ecmascript_code; }
|
||||||
Vector<FunctionParameter> const& formal_parameters() const override { return m_formal_parameters; }
|
virtual NonnullRefPtr<FunctionParameters const> const& formal_parameters() const override { return m_formal_parameters; }
|
||||||
|
|
||||||
virtual FlyString const& name() const override { return m_name; }
|
virtual FlyString const& name() const override { return m_name; }
|
||||||
void set_name(FlyString const& name);
|
void set_name(FlyString const& name);
|
||||||
|
@ -109,7 +109,7 @@ protected:
|
||||||
virtual Completion ordinary_call_evaluate_body();
|
virtual Completion ordinary_call_evaluate_body();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ECMAScriptFunctionObject(FlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, Object& prototype, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name);
|
ECMAScriptFunctionObject(FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const>, i32 m_function_length, Vector<FlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, Object& prototype, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name);
|
||||||
|
|
||||||
virtual bool is_ecmascript_function_object() const override { return true; }
|
virtual bool is_ecmascript_function_object() const override { return true; }
|
||||||
virtual void visit_edges(Visitor&) override;
|
virtual void visit_edges(Visitor&) override;
|
||||||
|
@ -127,7 +127,7 @@ private:
|
||||||
// Internal Slots of ECMAScript Function Objects, https://tc39.es/ecma262/#table-internal-slots-of-ecmascript-function-objects
|
// Internal Slots of ECMAScript Function Objects, https://tc39.es/ecma262/#table-internal-slots-of-ecmascript-function-objects
|
||||||
GC::Ptr<Environment> m_environment; // [[Environment]]
|
GC::Ptr<Environment> m_environment; // [[Environment]]
|
||||||
GC::Ptr<PrivateEnvironment> m_private_environment; // [[PrivateEnvironment]]
|
GC::Ptr<PrivateEnvironment> m_private_environment; // [[PrivateEnvironment]]
|
||||||
Vector<FunctionParameter> const m_formal_parameters; // [[FormalParameters]]
|
NonnullRefPtr<FunctionParameters const> m_formal_parameters; // [[FormalParameters]]
|
||||||
NonnullRefPtr<Statement const> m_ecmascript_code; // [[ECMAScriptCode]]
|
NonnullRefPtr<Statement const> m_ecmascript_code; // [[ECMAScriptCode]]
|
||||||
GC::Ptr<Realm> m_realm; // [[Realm]]
|
GC::Ptr<Realm> m_realm; // [[Realm]]
|
||||||
ScriptOrModule m_script_or_module; // [[ScriptOrModule]]
|
ScriptOrModule m_script_or_module; // [[ScriptOrModule]]
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
|
|
||||||
virtual Vector<FlyString> const& local_variables_names() const { VERIFY_NOT_REACHED(); }
|
virtual Vector<FlyString> const& local_variables_names() const { VERIFY_NOT_REACHED(); }
|
||||||
|
|
||||||
virtual Vector<FunctionParameter> const& formal_parameters() const { VERIFY_NOT_REACHED(); }
|
virtual NonnullRefPtr<FunctionParameters const> const& formal_parameters() const { VERIFY_NOT_REACHED(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit FunctionObject(Realm&, Object* prototype, MayInterfereWithIndexedPropertyAccess = MayInterfereWithIndexedPropertyAccess::No);
|
explicit FunctionObject(Realm&, Object* prototype, MayInterfereWithIndexedPropertyAccess = MayInterfereWithIndexedPropertyAccess::No);
|
||||||
|
|
|
@ -770,7 +770,7 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GC::Ptr<Promise
|
||||||
parsing_insights.uses_this = true;
|
parsing_insights.uses_this = true;
|
||||||
auto module_wrapper_function = ECMAScriptFunctionObject::create(
|
auto module_wrapper_function = ECMAScriptFunctionObject::create(
|
||||||
realm(), "module code with top-level await"_fly_string, StringView {}, this->m_ecmascript_code,
|
realm(), "module code with top-level await"_fly_string, StringView {}, this->m_ecmascript_code,
|
||||||
{}, 0, {}, environment(), nullptr, FunctionKind::Async, true, parsing_insights);
|
FunctionParameters::empty(), 0, {}, environment(), nullptr, FunctionKind::Async, true, parsing_insights);
|
||||||
module_wrapper_function->set_is_module_wrapper(true);
|
module_wrapper_function->set_is_module_wrapper(true);
|
||||||
|
|
||||||
vm.pop_execution_context();
|
vm.pop_execution_context();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue