mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-01 16:02:53 +00:00
LibJS+LibWeb: Pass function metadata collected in parsing using a struct
By using separate struct we can avoid updating AST node and ECMAScriptFunctionObject constructors every time there is a need to add or remove some additional information colllected during parsing.
This commit is contained in:
parent
99f6528009
commit
e934132442
Notes:
sideshowbarker
2024-07-17 09:49:48 +09:00
Author: https://github.com/kalenikaliaksandr
Commit: e934132442
Pull-request: https://github.com/SerenityOS/serenity/pull/24414
12 changed files with 75 additions and 73 deletions
|
@ -107,7 +107,7 @@ Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, Depre
|
|||
auto private_environment = vm.running_execution_context().private_environment;
|
||||
|
||||
auto closure = ECMAScriptFunctionObject::create(realm, used_name, source_text(), body(), parameters(), function_length(), local_variables_names(), environment, private_environment, kind(), is_strict_mode(),
|
||||
uses_this_from_environment(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function());
|
||||
parsing_insights(), is_arrow_function());
|
||||
|
||||
// FIXME: 6. Perform SetFunctionName(closure, name).
|
||||
// FIXME: 7. Perform MakeConstructor(closure).
|
||||
|
@ -153,7 +153,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
|
|||
auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key));
|
||||
|
||||
auto& method_function = *ECMAScriptFunctionObject::create(*vm.current_realm(), m_function->name(), m_function->source_text(), m_function->body(), m_function->parameters(), m_function->function_length(), m_function->local_variables_names(), vm.lexical_environment(), vm.running_execution_context().private_environment, m_function->kind(), m_function->is_strict_mode(),
|
||||
m_function->uses_this_from_environment(), m_function->might_need_arguments_object(), m_function->contains_direct_call_to_eval(), m_function->is_arrow_function());
|
||||
m_function->parsing_insights(), m_function->is_arrow_function());
|
||||
|
||||
auto method_value = Value(&method_function);
|
||||
method_function.make_method(target);
|
||||
|
@ -240,7 +240,9 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation
|
|||
|
||||
// FIXME: A potential optimization is not creating the functions here since these are never directly accessible.
|
||||
auto function_code = create_ast_node<ClassFieldInitializerStatement>(m_initializer->source_range(), copy_initializer.release_nonnull(), name);
|
||||
initializer = make_handle(*ECMAScriptFunctionObject::create(realm, "field", ByteString::empty(), *function_code, {}, 0, {}, vm.lexical_environment(), vm.running_execution_context().private_environment, FunctionKind::Normal, true, UsesThisFromEnvironment::Yes, false, m_contains_direct_call_to_eval, false, property_key_or_private_name));
|
||||
FunctionParsingInsights parsing_insights;
|
||||
parsing_insights.uses_this_from_environment = true;
|
||||
initializer = make_handle(*ECMAScriptFunctionObject::create(realm, "field", 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->make_method(target);
|
||||
}
|
||||
|
||||
|
@ -284,7 +286,9 @@ ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_eva
|
|||
// 4. Let formalParameters be an instance of the production FormalParameters : [empty] .
|
||||
// 5. Let bodyFunction be OrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameters, ClassStaticBlockBody, non-lexical-this, lex, privateEnv).
|
||||
// Note: The function bodyFunction is never directly accessible to ECMAScript code.
|
||||
auto body_function = ECMAScriptFunctionObject::create(realm, ByteString::empty(), ByteString::empty(), *m_function_body, {}, 0, m_function_body->local_variables_names(), lexical_environment, private_environment, FunctionKind::Normal, true, UsesThisFromEnvironment::Yes, false, m_contains_direct_call_to_eval, false);
|
||||
FunctionParsingInsights parsing_insights;
|
||||
parsing_insights.uses_this_from_environment = true;
|
||||
auto body_function = ECMAScriptFunctionObject::create(realm, ByteString::empty(), ByteString::empty(), *m_function_body, {}, 0, m_function_body->local_variables_names(), lexical_environment, private_environment, FunctionKind::Normal, true, parsing_insights, false);
|
||||
|
||||
// 6. Perform MakeMethod(bodyFunction, homeObject).
|
||||
body_function->make_method(home_object);
|
||||
|
@ -331,6 +335,8 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
|
|||
|
||||
// FIXME: Step 14.a is done in the parser. By using a synthetic super(...args) which does not call @@iterator of %Array.prototype%
|
||||
auto const& constructor = *m_constructor;
|
||||
auto parsing_insights = constructor.parsing_insights();
|
||||
parsing_insights.uses_this_from_environment = true;
|
||||
auto class_constructor = ECMAScriptFunctionObject::create(
|
||||
realm,
|
||||
constructor.name(),
|
||||
|
@ -343,9 +349,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
|
|||
vm.running_execution_context().private_environment,
|
||||
constructor.kind(),
|
||||
constructor.is_strict_mode(),
|
||||
UsesThisFromEnvironment::Yes,
|
||||
constructor.might_need_arguments_object(),
|
||||
constructor.contains_direct_call_to_eval(),
|
||||
parsing_insights,
|
||||
constructor.is_arrow_function());
|
||||
|
||||
class_constructor->set_name(class_name);
|
||||
|
@ -824,7 +828,7 @@ void FunctionNode::dump(int indent, ByteString const& class_name) const
|
|||
auto is_async = m_kind == FunctionKind::Async || m_kind == FunctionKind::AsyncGenerator;
|
||||
auto is_generator = m_kind == FunctionKind::Generator || m_kind == FunctionKind::AsyncGenerator;
|
||||
outln("{}{}{} '{}'", class_name, is_async ? " async" : "", is_generator ? "*" : "", name());
|
||||
if (m_contains_direct_call_to_eval) {
|
||||
if (m_parsing_insights.contains_direct_call_to_eval) {
|
||||
print_indent(indent + 1);
|
||||
outln("\033[31;1m(direct eval)\033[0m");
|
||||
}
|
||||
|
@ -1623,7 +1627,7 @@ void ScopeNode::block_declaration_instantiation(VM& vm, Environment* environment
|
|||
|
||||
// ii. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
|
||||
auto function = ECMAScriptFunctionObject::create(realm, function_declaration.name(), function_declaration.source_text(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), function_declaration.local_variables_names(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(),
|
||||
function_declaration.uses_this_from_environment(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval());
|
||||
function_declaration.parsing_insights());
|
||||
|
||||
// iii. Perform ! env.InitializeBinding(fn, fo). NOTE: This step is replaced in section B.3.2.6.
|
||||
if (function_declaration.name_identifier()->is_local()) {
|
||||
|
@ -1831,7 +1835,7 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(VM& vm, Global
|
|||
// a. Let fn be the sole element of the BoundNames of f.
|
||||
// b. Let fo be InstantiateFunctionObject of f with arguments env and privateEnv.
|
||||
auto function = ECMAScriptFunctionObject::create(realm, declaration.name(), declaration.source_text(), declaration.body(), declaration.parameters(), declaration.function_length(), declaration.local_variables_names(), &global_environment, private_environment, declaration.kind(), declaration.is_strict_mode(),
|
||||
declaration.uses_this_from_environment(), declaration.might_need_arguments_object(), declaration.contains_direct_call_to_eval());
|
||||
declaration.parsing_insights());
|
||||
|
||||
// c. Perform ? env.CreateGlobalFunctionBinding(fn, fo, false).
|
||||
TRY(global_environment.create_global_function_binding(declaration.name(), function, false));
|
||||
|
|
|
@ -693,9 +693,10 @@ struct FunctionParameter {
|
|||
Handle<Bytecode::Executable> bytecode_executable {};
|
||||
};
|
||||
|
||||
enum class UsesThisFromEnvironment {
|
||||
Yes,
|
||||
No
|
||||
struct FunctionParsingInsights {
|
||||
bool uses_this_from_environment { false };
|
||||
bool contains_direct_call_to_eval { false };
|
||||
bool might_need_arguments_object { false };
|
||||
};
|
||||
|
||||
class FunctionNode {
|
||||
|
@ -708,11 +709,12 @@ public:
|
|||
i32 function_length() const { return m_function_length; }
|
||||
Vector<DeprecatedFlyString> const& local_variables_names() const { return m_local_variables_names; }
|
||||
bool is_strict_mode() const { return m_is_strict_mode; }
|
||||
bool might_need_arguments_object() const { return m_might_need_arguments_object; }
|
||||
bool contains_direct_call_to_eval() const { return m_contains_direct_call_to_eval; }
|
||||
bool might_need_arguments_object() const { return m_parsing_insights.might_need_arguments_object; }
|
||||
bool contains_direct_call_to_eval() const { return m_parsing_insights.contains_direct_call_to_eval; }
|
||||
bool is_arrow_function() const { return m_is_arrow_function; }
|
||||
FunctionParsingInsights const& parsing_insights() const { return m_parsing_insights; }
|
||||
FunctionKind kind() const { return m_kind; }
|
||||
UsesThisFromEnvironment uses_this_from_environment() const { return m_uses_this_from_environment; }
|
||||
bool uses_this_from_environment() const { return m_parsing_insights.uses_this_from_environment; }
|
||||
|
||||
virtual bool has_name() const = 0;
|
||||
virtual Value instantiate_ordinary_function_expression(VM&, DeprecatedFlyString given_name) const = 0;
|
||||
|
@ -720,7 +722,7 @@ public:
|
|||
virtual ~FunctionNode() {};
|
||||
|
||||
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, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Vector<DeprecatedFlyString> local_variables_names, UsesThisFromEnvironment uses_this_from_environment)
|
||||
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<DeprecatedFlyString> local_variables_names)
|
||||
: m_name(move(name))
|
||||
, m_source_text(move(source_text))
|
||||
, m_body(move(body))
|
||||
|
@ -728,14 +730,12 @@ protected:
|
|||
, m_function_length(function_length)
|
||||
, m_kind(kind)
|
||||
, m_is_strict_mode(is_strict_mode)
|
||||
, m_might_need_arguments_object(might_need_arguments_object)
|
||||
, m_contains_direct_call_to_eval(contains_direct_call_to_eval)
|
||||
, m_is_arrow_function(is_arrow_function)
|
||||
, m_uses_this_from_environment(uses_this_from_environment)
|
||||
, m_parsing_insights(parsing_insights)
|
||||
, m_local_variables_names(move(local_variables_names))
|
||||
{
|
||||
if (m_is_arrow_function)
|
||||
VERIFY(!m_might_need_arguments_object);
|
||||
VERIFY(!parsing_insights.might_need_arguments_object);
|
||||
}
|
||||
|
||||
void dump(int indent, ByteString const& class_name) const;
|
||||
|
@ -749,10 +749,8 @@ private:
|
|||
i32 const m_function_length;
|
||||
FunctionKind m_kind;
|
||||
bool m_is_strict_mode : 1 { false };
|
||||
bool m_might_need_arguments_object : 1 { false };
|
||||
bool m_contains_direct_call_to_eval : 1 { false };
|
||||
bool m_is_arrow_function : 1 { false };
|
||||
UsesThisFromEnvironment m_uses_this_from_environment : 1 { UsesThisFromEnvironment::No };
|
||||
FunctionParsingInsights m_parsing_insights;
|
||||
|
||||
Vector<DeprecatedFlyString> m_local_variables_names;
|
||||
};
|
||||
|
@ -763,9 +761,9 @@ class FunctionDeclaration final
|
|||
public:
|
||||
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, bool might_need_arguments_object, bool contains_direct_call_to_eval, Vector<DeprecatedFlyString> local_variables_names, UsesThisFromEnvironment uses_this_from_environment)
|
||||
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<DeprecatedFlyString> local_variables_names)
|
||||
: Declaration(move(source_range))
|
||||
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, might_need_arguments_object, contains_direct_call_to_eval, false, move(local_variables_names), uses_this_from_environment)
|
||||
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, insights, false, move(local_variables_names))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -793,9 +791,9 @@ class FunctionExpression final
|
|||
public:
|
||||
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, bool might_need_arguments_object, bool contains_direct_call_to_eval, Vector<DeprecatedFlyString> local_variables_names, UsesThisFromEnvironment uses_this_from_environment = UsesThisFromEnvironment::No, bool is_arrow_function = 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<DeprecatedFlyString> local_variables_names, bool is_arrow_function = false)
|
||||
: Expression(move(source_range))
|
||||
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(local_variables_names), uses_this_from_environment)
|
||||
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, insights, is_arrow_function, move(local_variables_names))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -418,7 +418,7 @@ inline Value new_function(VM& vm, FunctionNode const& function_node, Optional<Id
|
|||
value = function_node.instantiate_ordinary_function_expression(vm, name);
|
||||
} else {
|
||||
value = ECMAScriptFunctionObject::create(*vm.current_realm(), function_node.name(), function_node.source_text(), function_node.body(), function_node.parameters(), function_node.function_length(), function_node.local_variables_names(), vm.lexical_environment(), vm.running_execution_context().private_environment, function_node.kind(), function_node.is_strict_mode(),
|
||||
function_node.uses_this_from_environment(), function_node.might_need_arguments_object(), function_node.contains_direct_call_to_eval(), function_node.is_arrow_function());
|
||||
function_node.parsing_insights(), function_node.is_arrow_function());
|
||||
}
|
||||
|
||||
if (home_object.has_value()) {
|
||||
|
|
|
@ -1015,8 +1015,8 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
|||
|
||||
Vector<FunctionParameter> parameters;
|
||||
i32 function_length = -1;
|
||||
bool contains_direct_call_to_eval = false;
|
||||
bool uses_this_from_environment = false;
|
||||
FunctionParsingInsights parsing_insights;
|
||||
parsing_insights.might_need_arguments_object = false;
|
||||
auto function_body_result = [&]() -> RefPtr<FunctionBody const> {
|
||||
ScopePusher function_scope = ScopePusher::function_scope(*this);
|
||||
function_scope.set_is_arrow_function();
|
||||
|
@ -1071,7 +1071,7 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
|||
if (match(TokenType::CurlyOpen)) {
|
||||
// Parse a function body with statements
|
||||
consume(TokenType::CurlyOpen);
|
||||
auto body = parse_function_body(parameters, function_kind, contains_direct_call_to_eval, uses_this_from_environment);
|
||||
auto body = parse_function_body(parameters, function_kind, parsing_insights);
|
||||
consume(TokenType::CurlyClose);
|
||||
return body;
|
||||
}
|
||||
|
@ -1090,8 +1090,8 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
|||
return_block->append<ReturnStatement const>({ m_source_code, rule_start.position(), position() }, move(return_expression));
|
||||
if (m_state.strict_mode)
|
||||
const_cast<FunctionBody&>(*return_block).set_strict_mode();
|
||||
contains_direct_call_to_eval = m_state.current_scope_pusher->contains_direct_call_to_eval();
|
||||
uses_this_from_environment = m_state.current_scope_pusher->uses_this_from_environment();
|
||||
parsing_insights.contains_direct_call_to_eval = m_state.current_scope_pusher->contains_direct_call_to_eval();
|
||||
parsing_insights.uses_this_from_environment = m_state.current_scope_pusher->uses_this_from_environment();
|
||||
return return_block;
|
||||
}
|
||||
// Invalid arrow function body
|
||||
|
@ -1123,7 +1123,7 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
|||
return create_ast_node<FunctionExpression>(
|
||||
{ m_source_code, rule_start.position(), position() }, nullptr, move(source_text),
|
||||
move(body), move(parameters), function_length, function_kind, body->in_strict_mode(),
|
||||
/* might_need_arguments_object */ false, contains_direct_call_to_eval, move(local_variables_names), uses_this_from_environment ? UsesThisFromEnvironment::Yes : UsesThisFromEnvironment::No, /* is_arrow_function */ true);
|
||||
parsing_insights, move(local_variables_names), /* is_arrow_function */ true);
|
||||
}
|
||||
|
||||
RefPtr<LabelledStatement const> Parser::try_parse_labelled_statement(AllowLabelledFunction allow_function)
|
||||
|
@ -1616,15 +1616,17 @@ NonnullRefPtr<ClassExpression const> Parser::parse_class_expression(bool expect_
|
|||
// return statement here to create the correct completion.
|
||||
constructor_body->append(create_ast_node<ReturnStatement>({ m_source_code, rule_start.position(), position() }, move(super_call)));
|
||||
|
||||
FunctionParsingInsights parsing_insights;
|
||||
constructor = create_ast_node<FunctionExpression>(
|
||||
{ m_source_code, rule_start.position(), position() }, class_name, "",
|
||||
move(constructor_body), Vector { FunctionParameter { move(argument_name), nullptr, true } }, 0, FunctionKind::Normal,
|
||||
/* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false, /* local_variables_names */ Vector<DeprecatedFlyString> {});
|
||||
/* is_strict_mode */ true, parsing_insights, /* local_variables_names */ Vector<DeprecatedFlyString> {});
|
||||
} else {
|
||||
FunctionParsingInsights parsing_insights;
|
||||
constructor = create_ast_node<FunctionExpression>(
|
||||
{ m_source_code, rule_start.position(), position() }, class_name, "",
|
||||
move(constructor_body), Vector<FunctionParameter> {}, 0, FunctionKind::Normal,
|
||||
/* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false, /* local_variables_names */ Vector<DeprecatedFlyString> {});
|
||||
/* is_strict_mode */ true, parsing_insights, /* local_variables_names */ Vector<DeprecatedFlyString> {});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2766,7 +2768,7 @@ void Parser::parse_statement_list(ScopeNode& output_node, AllowLabelledFunction
|
|||
}
|
||||
|
||||
// FunctionBody, https://tc39.es/ecma262/#prod-FunctionBody
|
||||
NonnullRefPtr<FunctionBody const> Parser::parse_function_body(Vector<FunctionParameter> const& parameters, FunctionKind function_kind, bool& contains_direct_call_to_eval, bool& uses_this)
|
||||
NonnullRefPtr<FunctionBody const> Parser::parse_function_body(Vector<FunctionParameter> const& parameters, FunctionKind function_kind, FunctionParsingInsights& parsing_insights)
|
||||
{
|
||||
auto rule_start = push_start();
|
||||
auto function_body = create_ast_node<FunctionBody>({ m_source_code, rule_start.position(), position() });
|
||||
|
@ -2841,8 +2843,8 @@ NonnullRefPtr<FunctionBody const> Parser::parse_function_body(Vector<FunctionPar
|
|||
|
||||
m_state.strict_mode = previous_strict_mode;
|
||||
VERIFY(m_state.current_scope_pusher->type() == ScopePusher::ScopeType::Function);
|
||||
contains_direct_call_to_eval = m_state.current_scope_pusher->contains_direct_call_to_eval();
|
||||
uses_this = m_state.current_scope_pusher->uses_this_from_environment();
|
||||
parsing_insights.contains_direct_call_to_eval = m_state.current_scope_pusher->contains_direct_call_to_eval();
|
||||
parsing_insights.uses_this_from_environment = m_state.current_scope_pusher->uses_this_from_environment();
|
||||
return function_body;
|
||||
}
|
||||
|
||||
|
@ -2927,8 +2929,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u16 parse_options, O
|
|||
|
||||
i32 function_length = -1;
|
||||
Vector<FunctionParameter> parameters;
|
||||
bool contains_direct_call_to_eval = false;
|
||||
bool uses_this_from_environment = false;
|
||||
FunctionParsingInsights parsing_insights;
|
||||
auto body = [&] {
|
||||
ScopePusher function_scope = ScopePusher::function_scope(*this, name);
|
||||
|
||||
|
@ -2948,7 +2949,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u16 parse_options, O
|
|||
|
||||
consume(TokenType::CurlyOpen);
|
||||
|
||||
auto body = parse_function_body(parameters, function_kind, contains_direct_call_to_eval, uses_this_from_environment);
|
||||
auto body = parse_function_body(parameters, function_kind, parsing_insights);
|
||||
return body;
|
||||
}();
|
||||
|
||||
|
@ -2963,13 +2964,12 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u16 parse_options, O
|
|||
auto function_start_offset = rule_start.position().offset;
|
||||
auto function_end_offset = position().offset - m_state.current_token.trivia().length();
|
||||
auto source_text = ByteString { m_state.lexer.source().substring_view(function_start_offset, function_end_offset - function_start_offset) };
|
||||
parsing_insights.might_need_arguments_object = m_state.function_might_need_arguments_object;
|
||||
return create_ast_node<FunctionNodeType>(
|
||||
{ m_source_code, rule_start.position(), position() },
|
||||
name, move(source_text), move(body), move(parameters), function_length,
|
||||
function_kind, has_strict_directive, m_state.function_might_need_arguments_object,
|
||||
contains_direct_call_to_eval,
|
||||
move(local_variables_names),
|
||||
uses_this_from_environment ? UsesThisFromEnvironment::Yes : UsesThisFromEnvironment::No);
|
||||
function_kind, has_strict_directive, parsing_insights,
|
||||
move(local_variables_names));
|
||||
}
|
||||
|
||||
Vector<FunctionParameter> Parser::parse_formal_parameters(int& function_length, u16 parse_options)
|
||||
|
@ -5153,7 +5153,7 @@ NonnullRefPtr<Identifier const> Parser::create_identifier_and_register_in_curren
|
|||
return id;
|
||||
}
|
||||
|
||||
Parser Parser::parse_function_body_from_string(ByteString const& body_string, u16 parse_options, Vector<FunctionParameter> const& parameters, FunctionKind kind, bool& contains_direct_call_to_eval, bool& uses_this_from_environment)
|
||||
Parser Parser::parse_function_body_from_string(ByteString const& body_string, u16 parse_options, Vector<FunctionParameter> const& parameters, FunctionKind kind, FunctionParsingInsights& parsing_insights)
|
||||
{
|
||||
RefPtr<FunctionBody const> function_body;
|
||||
|
||||
|
@ -5166,7 +5166,7 @@ Parser Parser::parse_function_body_from_string(ByteString const& body_string, u1
|
|||
body_parser.m_state.await_expression_is_valid = true;
|
||||
if ((parse_options & FunctionNodeParseOptions::IsGeneratorFunction) != 0)
|
||||
body_parser.m_state.in_generator_function_context = true;
|
||||
function_body = body_parser.parse_function_body(parameters, kind, contains_direct_call_to_eval, uses_this_from_environment);
|
||||
function_body = body_parser.parse_function_body(parameters, kind, parsing_insights);
|
||||
}
|
||||
|
||||
return body_parser;
|
||||
|
|
|
@ -87,7 +87,7 @@ public:
|
|||
|
||||
NonnullRefPtr<Statement const> parse_statement(AllowLabelledFunction allow_labelled_function = AllowLabelledFunction::No);
|
||||
NonnullRefPtr<BlockStatement const> parse_block_statement();
|
||||
NonnullRefPtr<FunctionBody const> parse_function_body(Vector<FunctionParameter> const& parameters, FunctionKind function_kind, bool& contains_direct_call_to_eval, bool& uses_this);
|
||||
NonnullRefPtr<FunctionBody const> parse_function_body(Vector<FunctionParameter> const& parameters, FunctionKind function_kind, FunctionParsingInsights&);
|
||||
NonnullRefPtr<ReturnStatement const> parse_return_statement();
|
||||
|
||||
enum class IsForLoopVariableDeclaration {
|
||||
|
@ -211,7 +211,7 @@ public:
|
|||
// Needs to mess with m_state, and we're not going to expose a non-const getter for that :^)
|
||||
friend ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic_function(VM&, FunctionObject&, FunctionObject*, FunctionKind, MarkedVector<Value> const&);
|
||||
|
||||
static Parser parse_function_body_from_string(ByteString const& body_string, u16 parse_options, Vector<FunctionParameter> const& parameters, FunctionKind kind, bool& contains_direct_call_to_eval, bool& uses_this_from_environment);
|
||||
static Parser parse_function_body_from_string(ByteString const& body_string, u16 parse_options, Vector<FunctionParameter> const& parameters, FunctionKind kind, FunctionParsingInsights&);
|
||||
|
||||
private:
|
||||
friend class ScopePusher;
|
||||
|
|
|
@ -973,7 +973,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
|
|||
// a. Let fn be the sole element of the BoundNames of f.
|
||||
// b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
|
||||
auto function = ECMAScriptFunctionObject::create(realm, declaration.name(), declaration.source_text(), declaration.body(), declaration.parameters(), declaration.function_length(), declaration.local_variables_names(), lexical_environment, private_environment, declaration.kind(), declaration.is_strict_mode(),
|
||||
declaration.uses_this_from_environment(), declaration.might_need_arguments_object());
|
||||
declaration.parsing_insights());
|
||||
|
||||
// c. If varEnv is a global Environment Record, then
|
||||
if (global_var_environment) {
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace JS {
|
|||
|
||||
JS_DEFINE_ALLOCATOR(ECMAScriptFunctionObject);
|
||||
|
||||
NonnullGCPtr<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, DeprecatedFlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, UsesThisFromEnvironment uses_this_from_environment, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||
NonnullGCPtr<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, DeprecatedFlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> 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;
|
||||
switch (kind) {
|
||||
|
@ -50,15 +50,15 @@ NonnullGCPtr<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& r
|
|||
prototype = realm.intrinsics().async_generator_function_prototype();
|
||||
break;
|
||||
}
|
||||
return realm.heap().allocate<ECMAScriptFunctionObject>(realm, move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, move(local_variables_names), parent_environment, private_environment, *prototype, kind, is_strict, uses_this_from_environment, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(class_field_initializer_name));
|
||||
return realm.heap().allocate<ECMAScriptFunctionObject>(realm, 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));
|
||||
}
|
||||
|
||||
NonnullGCPtr<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, DeprecatedFlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, UsesThisFromEnvironment uses_this_from_environment, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||
NonnullGCPtr<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, DeprecatedFlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> 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.heap().allocate<ECMAScriptFunctionObject>(realm, move(name), move(source_text), ecmascript_code, move(parameters), m_function_length, move(local_variables_names), parent_environment, private_environment, prototype, kind, is_strict, uses_this_from_environment, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(class_field_initializer_name));
|
||||
return realm.heap().allocate<ECMAScriptFunctionObject>(realm, 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(DeprecatedFlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> formal_parameters, i32 function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, Object& prototype, FunctionKind kind, bool strict, UsesThisFromEnvironment uses_this_from_environment, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||
ECMAScriptFunctionObject::ECMAScriptFunctionObject(DeprecatedFlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> formal_parameters, i32 function_length, Vector<DeprecatedFlyString> 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)
|
||||
, m_name(move(name))
|
||||
, m_function_length(function_length)
|
||||
|
@ -71,8 +71,8 @@ ECMAScriptFunctionObject::ECMAScriptFunctionObject(DeprecatedFlyString name, Byt
|
|||
, m_source_text(move(source_text))
|
||||
, m_class_field_initializer_name(move(class_field_initializer_name))
|
||||
, m_strict(strict)
|
||||
, m_might_need_arguments_object(might_need_arguments_object)
|
||||
, m_contains_direct_call_to_eval(contains_direct_call_to_eval)
|
||||
, m_might_need_arguments_object(parsing_insights.might_need_arguments_object)
|
||||
, m_contains_direct_call_to_eval(parsing_insights.contains_direct_call_to_eval)
|
||||
, m_is_arrow_function(is_arrow_function)
|
||||
, m_kind(kind)
|
||||
{
|
||||
|
@ -331,7 +331,7 @@ ECMAScriptFunctionObject::ECMAScriptFunctionObject(DeprecatedFlyString name, Byt
|
|||
}));
|
||||
}
|
||||
|
||||
m_function_environment_needed = arguments_object_needs_binding || m_function_environment_bindings_count > 0 || m_var_environment_bindings_count > 0 || m_lex_environment_bindings_count > 0 || uses_this_from_environment == UsesThisFromEnvironment::Yes || m_contains_direct_call_to_eval;
|
||||
m_function_environment_needed = arguments_object_needs_binding || m_function_environment_bindings_count > 0 || m_var_environment_bindings_count > 0 || m_lex_environment_bindings_count > 0 || parsing_insights.uses_this_from_environment || m_contains_direct_call_to_eval;
|
||||
}
|
||||
|
||||
void ECMAScriptFunctionObject::initialize(Realm& realm)
|
||||
|
|
|
@ -39,8 +39,8 @@ public:
|
|||
Global,
|
||||
};
|
||||
|
||||
static NonnullGCPtr<ECMAScriptFunctionObject> create(Realm&, DeprecatedFlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, UsesThisFromEnvironment, bool might_need_arguments_object = true, bool contains_direct_call_to_eval = true, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
|
||||
static NonnullGCPtr<ECMAScriptFunctionObject> create(Realm&, DeprecatedFlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, UsesThisFromEnvironment, bool might_need_arguments_object = true, bool contains_direct_call_to_eval = true, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
|
||||
static NonnullGCPtr<ECMAScriptFunctionObject> create(Realm&, DeprecatedFlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> 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 NonnullGCPtr<ECMAScriptFunctionObject> create(Realm&, DeprecatedFlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> 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 ~ECMAScriptFunctionObject() override = default;
|
||||
|
@ -109,7 +109,7 @@ protected:
|
|||
virtual Completion ordinary_call_evaluate_body();
|
||||
|
||||
private:
|
||||
ECMAScriptFunctionObject(DeprecatedFlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, Object& prototype, FunctionKind, bool is_strict, UsesThisFromEnvironment, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name);
|
||||
ECMAScriptFunctionObject(DeprecatedFlyString name, ByteString source_text, Statement const& ecmascript_code, Vector<FunctionParameter> parameters, i32 m_function_length, Vector<DeprecatedFlyString> 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 void visit_edges(Visitor&) override;
|
||||
|
|
|
@ -182,9 +182,8 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
|||
}
|
||||
|
||||
// 18. Let body be ParseText(StringToCodePoints(bodyString), bodySym).
|
||||
bool contains_direct_call_to_eval = false;
|
||||
bool uses_this_from_environment = false;
|
||||
auto body_parser = Parser::parse_function_body_from_string(body_string, parse_options, parameters, kind, contains_direct_call_to_eval, uses_this_from_environment);
|
||||
FunctionParsingInsights parsing_insights;
|
||||
auto body_parser = Parser::parse_function_body_from_string(body_string, parse_options, parameters, kind, parsing_insights);
|
||||
|
||||
// 19. If body is a List of errors, throw a SyntaxError exception.
|
||||
if (body_parser.has_errors()) {
|
||||
|
@ -219,7 +218,8 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
|
|||
PrivateEnvironment* private_environment = nullptr;
|
||||
|
||||
// 28. Let F be OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv).
|
||||
auto function = ECMAScriptFunctionObject::create(realm, "anonymous", *prototype, move(source_text), expr->body(), expr->parameters(), expr->function_length(), expr->local_variables_names(), &environment, private_environment, expr->kind(), expr->is_strict_mode(), uses_this_from_environment ? UsesThisFromEnvironment::Yes : UsesThisFromEnvironment::No, expr->might_need_arguments_object(), contains_direct_call_to_eval);
|
||||
parsing_insights.might_need_arguments_object = true;
|
||||
auto function = ECMAScriptFunctionObject::create(realm, "anonymous", *prototype, move(source_text), expr->body(), expr->parameters(), expr->function_length(), expr->local_variables_names(), &environment, private_environment, expr->kind(), expr->is_strict_mode(), parsing_insights);
|
||||
|
||||
// FIXME: Remove the name argument from create() and do this instead.
|
||||
// 29. Perform SetFunctionName(F, "anonymous").
|
||||
|
|
|
@ -499,7 +499,7 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
|
|||
if (function_name == ExportStatement::local_name_for_default)
|
||||
function_name = "default"sv;
|
||||
auto function = ECMAScriptFunctionObject::create(realm(), function_name, function_declaration.source_text(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), function_declaration.local_variables_names(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(),
|
||||
function_declaration.uses_this_from_environment(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval());
|
||||
function_declaration.parsing_insights());
|
||||
|
||||
// 2. Perform ! env.InitializeBinding(dn, fo, normal).
|
||||
MUST(environment->initialize_binding(vm, name, function, Environment::InitializeBindingHint::Normal));
|
||||
|
@ -758,9 +758,11 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GCPtr<PromiseCa
|
|||
// the top-level module code.
|
||||
// FIXME: Improve this situation, so we can match the spec better.
|
||||
|
||||
FunctionParsingInsights parsing_insights;
|
||||
parsing_insights.uses_this_from_environment = true;
|
||||
auto module_wrapper_function = ECMAScriptFunctionObject::create(
|
||||
realm(), "module code with top-level await", StringView {}, this->m_ecmascript_code,
|
||||
{}, 0, {}, environment(), nullptr, FunctionKind::Async, true, UsesThisFromEnvironment::Yes, false, false);
|
||||
{}, 0, {}, environment(), nullptr, FunctionKind::Async, true, parsing_insights);
|
||||
module_wrapper_function->set_is_module_wrapper(true);
|
||||
|
||||
// AD-HOC: We push/pop the moduleContext around the call to ensure that the async execution context
|
||||
|
|
|
@ -486,7 +486,7 @@ WebIDL::CallbackType* EventTarget::get_current_value_of_event_handler(FlyString
|
|||
// 6. Return scope. (NOTE: Not necessary)
|
||||
|
||||
auto function = JS::ECMAScriptFunctionObject::create(realm, name.to_deprecated_fly_string(), builder.to_byte_string(), program->body(), program->parameters(), program->function_length(), program->local_variables_names(), scope, nullptr, JS::FunctionKind::Normal, program->is_strict_mode(),
|
||||
program->uses_this_from_environment(), program->might_need_arguments_object(), is_arrow_function);
|
||||
program->parsing_insights(), is_arrow_function);
|
||||
|
||||
// 10. Remove settings object's realm execution context from the JavaScript execution context stack.
|
||||
VERIFY(vm.execution_context_stack().last() == &settings_object.realm_execution_context());
|
||||
|
|
|
@ -237,7 +237,6 @@ static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(Web::Page& page,
|
|||
|
||||
auto& realm = window->realm();
|
||||
|
||||
bool contains_direct_call_to_eval = false;
|
||||
auto source_text = ByteString::formatted("function() {{ {} }}", body);
|
||||
auto parser = JS::Parser { JS::Lexer { source_text } };
|
||||
auto function_expression = parser.parse_function_node<JS::FunctionExpression>();
|
||||
|
@ -266,8 +265,7 @@ static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(Web::Page& page,
|
|||
// The result of parsing global scope above.
|
||||
// strict
|
||||
// The result of parsing strict above.
|
||||
auto function = JS::ECMAScriptFunctionObject::create(realm, "", move(source_text), function_expression->body(), function_expression->parameters(), function_expression->function_length(), function_expression->local_variables_names(), &global_scope, nullptr, function_expression->kind(), function_expression->is_strict_mode(),
|
||||
function_expression->uses_this_from_environment(), function_expression->might_need_arguments_object(), contains_direct_call_to_eval);
|
||||
auto function = JS::ECMAScriptFunctionObject::create(realm, "", move(source_text), function_expression->body(), function_expression->parameters(), function_expression->function_length(), function_expression->local_variables_names(), &global_scope, nullptr, function_expression->kind(), function_expression->is_strict_mode(), function_expression->parsing_insights());
|
||||
|
||||
// 9. Let completion be Function.[[Call]](window, parameters) with function as the this value.
|
||||
// NOTE: This is not entirely clear, but I don't think they mean actually passing `function` as
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue