|
@@ -435,6 +435,19 @@ public:
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ bool uses_this()
|
|
|
|
+ {
|
|
|
|
+ return m_uses_this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void set_uses_this()
|
|
|
|
+ {
|
|
|
|
+ for (auto scope_ptr = this; scope_ptr; scope_ptr = scope_ptr->m_parent_scope) {
|
|
|
|
+ if (scope_ptr->m_type == ScopeType::Function)
|
|
|
|
+ scope_ptr->m_uses_this = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private:
|
|
private:
|
|
void throw_identifier_declared(DeprecatedFlyString const& name, NonnullRefPtr<Declaration const> const& declaration)
|
|
void throw_identifier_declared(DeprecatedFlyString const& name, NonnullRefPtr<Declaration const> const& declaration)
|
|
{
|
|
{
|
|
@@ -475,6 +488,7 @@ private:
|
|
bool m_contains_direct_call_to_eval { false };
|
|
bool m_contains_direct_call_to_eval { false };
|
|
bool m_contains_await_expression { false };
|
|
bool m_contains_await_expression { false };
|
|
bool m_screwed_by_eval_in_scope_chain { false };
|
|
bool m_screwed_by_eval_in_scope_chain { false };
|
|
|
|
+ bool m_uses_this { false };
|
|
};
|
|
};
|
|
|
|
|
|
class OperatorPrecedenceTable {
|
|
class OperatorPrecedenceTable {
|
|
@@ -978,6 +992,7 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
|
Vector<FunctionParameter> parameters;
|
|
Vector<FunctionParameter> parameters;
|
|
i32 function_length = -1;
|
|
i32 function_length = -1;
|
|
bool contains_direct_call_to_eval = false;
|
|
bool contains_direct_call_to_eval = false;
|
|
|
|
+ bool uses_this = false;
|
|
auto function_body_result = [&]() -> RefPtr<FunctionBody const> {
|
|
auto function_body_result = [&]() -> RefPtr<FunctionBody const> {
|
|
ScopePusher function_scope = ScopePusher::function_scope(*this);
|
|
ScopePusher function_scope = ScopePusher::function_scope(*this);
|
|
|
|
|
|
@@ -1031,7 +1046,7 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
|
if (match(TokenType::CurlyOpen)) {
|
|
if (match(TokenType::CurlyOpen)) {
|
|
// Parse a function body with statements
|
|
// Parse a function body with statements
|
|
consume(TokenType::CurlyOpen);
|
|
consume(TokenType::CurlyOpen);
|
|
- auto body = parse_function_body(parameters, function_kind, contains_direct_call_to_eval);
|
|
|
|
|
|
+ auto body = parse_function_body(parameters, function_kind, contains_direct_call_to_eval, uses_this);
|
|
consume(TokenType::CurlyClose);
|
|
consume(TokenType::CurlyClose);
|
|
return body;
|
|
return body;
|
|
}
|
|
}
|
|
@@ -1051,6 +1066,7 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
|
if (m_state.strict_mode)
|
|
if (m_state.strict_mode)
|
|
const_cast<FunctionBody&>(*return_block).set_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();
|
|
contains_direct_call_to_eval = m_state.current_scope_pusher->contains_direct_call_to_eval();
|
|
|
|
+ uses_this = m_state.current_scope_pusher->uses_this();
|
|
return return_block;
|
|
return return_block;
|
|
}
|
|
}
|
|
// Invalid arrow function body
|
|
// Invalid arrow function body
|
|
@@ -1082,7 +1098,7 @@ RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(boo
|
|
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), move(parameters), function_length, function_kind, body->in_strict_mode(),
|
|
- /* might_need_arguments_object */ false, contains_direct_call_to_eval, move(local_variables_names), /* is_arrow_function */ true);
|
|
|
|
|
|
+ /* might_need_arguments_object */ false, contains_direct_call_to_eval, move(local_variables_names), uses_this ? UsesThis::Yes : UsesThis::No, /* is_arrow_function */ true);
|
|
}
|
|
}
|
|
|
|
|
|
RefPtr<LabelledStatement const> Parser::try_parse_labelled_statement(AllowLabelledFunction allow_function)
|
|
RefPtr<LabelledStatement const> Parser::try_parse_labelled_statement(AllowLabelledFunction allow_function)
|
|
@@ -1194,6 +1210,10 @@ RefPtr<MetaProperty const> Parser::try_parse_new_target_expression()
|
|
|
|
|
|
state_rollback_guard.disarm();
|
|
state_rollback_guard.disarm();
|
|
discard_saved_state();
|
|
discard_saved_state();
|
|
|
|
+
|
|
|
|
+ if (m_state.current_scope_pusher)
|
|
|
|
+ m_state.current_scope_pusher->set_uses_this();
|
|
|
|
+
|
|
return create_ast_node<MetaProperty>({ m_source_code, rule_start.position(), position() }, MetaProperty::Type::NewTarget);
|
|
return create_ast_node<MetaProperty>({ m_source_code, rule_start.position(), position() }, MetaProperty::Type::NewTarget);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1639,15 +1659,20 @@ Parser::PrimaryExpressionParseResult Parser::parse_primary_expression()
|
|
}
|
|
}
|
|
return { move(expression) };
|
|
return { move(expression) };
|
|
}
|
|
}
|
|
- case TokenType::This:
|
|
|
|
|
|
+ case TokenType::This: {
|
|
|
|
+ if (m_state.current_scope_pusher)
|
|
|
|
+ m_state.current_scope_pusher->set_uses_this();
|
|
consume_and_allow_division();
|
|
consume_and_allow_division();
|
|
return { create_ast_node<ThisExpression>({ m_source_code, rule_start.position(), position() }) };
|
|
return { create_ast_node<ThisExpression>({ m_source_code, rule_start.position(), position() }) };
|
|
|
|
+ }
|
|
case TokenType::Class:
|
|
case TokenType::Class:
|
|
return { parse_class_expression(false) };
|
|
return { parse_class_expression(false) };
|
|
case TokenType::Super:
|
|
case TokenType::Super:
|
|
consume();
|
|
consume();
|
|
if (!m_state.allow_super_property_lookup)
|
|
if (!m_state.allow_super_property_lookup)
|
|
syntax_error("'super' keyword unexpected here");
|
|
syntax_error("'super' keyword unexpected here");
|
|
|
|
+ if (m_state.current_scope_pusher)
|
|
|
|
+ m_state.current_scope_pusher->set_uses_this();
|
|
return { create_ast_node<SuperExpression>({ m_source_code, rule_start.position(), position() }) };
|
|
return { create_ast_node<SuperExpression>({ m_source_code, rule_start.position(), position() }) };
|
|
case TokenType::EscapedKeyword:
|
|
case TokenType::EscapedKeyword:
|
|
if (match_invalid_escaped_keyword())
|
|
if (match_invalid_escaped_keyword())
|
|
@@ -2716,7 +2741,7 @@ void Parser::parse_statement_list(ScopeNode& output_node, AllowLabelledFunction
|
|
}
|
|
}
|
|
|
|
|
|
// FunctionBody, https://tc39.es/ecma262/#prod-FunctionBody
|
|
// 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)
|
|
|
|
|
|
+NonnullRefPtr<FunctionBody const> Parser::parse_function_body(Vector<FunctionParameter> const& parameters, FunctionKind function_kind, bool& contains_direct_call_to_eval, bool& uses_this)
|
|
{
|
|
{
|
|
auto rule_start = push_start();
|
|
auto rule_start = push_start();
|
|
auto function_body = create_ast_node<FunctionBody>({ m_source_code, rule_start.position(), position() });
|
|
auto function_body = create_ast_node<FunctionBody>({ m_source_code, rule_start.position(), position() });
|
|
@@ -2792,6 +2817,7 @@ NonnullRefPtr<FunctionBody const> Parser::parse_function_body(Vector<FunctionPar
|
|
m_state.strict_mode = previous_strict_mode;
|
|
m_state.strict_mode = previous_strict_mode;
|
|
VERIFY(m_state.current_scope_pusher->type() == ScopePusher::ScopeType::Function);
|
|
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();
|
|
contains_direct_call_to_eval = m_state.current_scope_pusher->contains_direct_call_to_eval();
|
|
|
|
+ uses_this = m_state.current_scope_pusher->uses_this();
|
|
return function_body;
|
|
return function_body;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2877,6 +2903,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u16 parse_options, O
|
|
i32 function_length = -1;
|
|
i32 function_length = -1;
|
|
Vector<FunctionParameter> parameters;
|
|
Vector<FunctionParameter> parameters;
|
|
bool contains_direct_call_to_eval = false;
|
|
bool contains_direct_call_to_eval = false;
|
|
|
|
+ bool uses_this = false;
|
|
auto body = [&] {
|
|
auto body = [&] {
|
|
ScopePusher function_scope = ScopePusher::function_scope(*this, name);
|
|
ScopePusher function_scope = ScopePusher::function_scope(*this, name);
|
|
|
|
|
|
@@ -2896,7 +2923,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u16 parse_options, O
|
|
|
|
|
|
consume(TokenType::CurlyOpen);
|
|
consume(TokenType::CurlyOpen);
|
|
|
|
|
|
- auto body = parse_function_body(parameters, function_kind, contains_direct_call_to_eval);
|
|
|
|
|
|
+ auto body = parse_function_body(parameters, function_kind, contains_direct_call_to_eval, uses_this);
|
|
return body;
|
|
return body;
|
|
}();
|
|
}();
|
|
|
|
|
|
@@ -2916,7 +2943,8 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u16 parse_options, O
|
|
name, move(source_text), move(body), move(parameters), function_length,
|
|
name, move(source_text), move(body), move(parameters), function_length,
|
|
function_kind, has_strict_directive, m_state.function_might_need_arguments_object,
|
|
function_kind, has_strict_directive, m_state.function_might_need_arguments_object,
|
|
contains_direct_call_to_eval,
|
|
contains_direct_call_to_eval,
|
|
- move(local_variables_names));
|
|
|
|
|
|
+ move(local_variables_names),
|
|
|
|
+ uses_this ? UsesThis::Yes : UsesThis::No);
|
|
}
|
|
}
|
|
|
|
|
|
Vector<FunctionParameter> Parser::parse_formal_parameters(int& function_length, u16 parse_options)
|
|
Vector<FunctionParameter> Parser::parse_formal_parameters(int& function_length, u16 parse_options)
|
|
@@ -5100,7 +5128,7 @@ NonnullRefPtr<Identifier const> Parser::create_identifier_and_register_in_curren
|
|
return id;
|
|
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)
|
|
|
|
|
|
+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)
|
|
{
|
|
{
|
|
RefPtr<FunctionBody const> function_body;
|
|
RefPtr<FunctionBody const> function_body;
|
|
|
|
|
|
@@ -5113,7 +5141,7 @@ Parser Parser::parse_function_body_from_string(ByteString const& body_string, u1
|
|
body_parser.m_state.await_expression_is_valid = true;
|
|
body_parser.m_state.await_expression_is_valid = true;
|
|
if ((parse_options & FunctionNodeParseOptions::IsGeneratorFunction) != 0)
|
|
if ((parse_options & FunctionNodeParseOptions::IsGeneratorFunction) != 0)
|
|
body_parser.m_state.in_generator_function_context = true;
|
|
body_parser.m_state.in_generator_function_context = true;
|
|
- function_body = body_parser.parse_function_body(parameters, kind, contains_direct_call_to_eval);
|
|
|
|
|
|
+ function_body = body_parser.parse_function_body(parameters, kind, contains_direct_call_to_eval, uses_this);
|
|
}
|
|
}
|
|
|
|
|
|
return body_parser;
|
|
return body_parser;
|