1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 15:58:11 +00:00

LibJS: Use a synthetic constructor if class with parent doesn't have one

We already did this but it called the @@iterator method of
%Array.prototype% visible to the user for example by overriding that
method. This should not be visible so we use a special version of
SuperCall now.
This commit is contained in:
davidot 2022-08-20 17:27:02 +02:00 committed by Linus Groh
parent b79f03182d
commit ae349ec6a8
4 changed files with 100 additions and 4 deletions

View file

@ -1313,9 +1313,16 @@ NonnullRefPtr<ClassExpression> Parser::parse_class_expression(bool expect_class_
if (!super_class.is_null()) {
// Set constructor to the result of parsing the source text
// constructor(... args){ super (...args);}
// However: The most notable distinction is that while the aforementioned ECMAScript
// source text observably calls the @@iterator method on %Array.prototype%,
// this function does not.
// So we use a custom version of SuperCall which doesn't use the @@iterator
// method on %Array.prototype% visibly.
FlyString argument_name = "args";
auto super_call = create_ast_node<SuperCall>(
{ m_state.current_token.filename(), rule_start.position(), position() },
Vector { CallExpression::Argument { create_ast_node<Identifier>({ m_state.current_token.filename(), rule_start.position(), position() }, "args"), true } });
SuperCall::IsPartOfSyntheticConstructor::Yes,
CallExpression::Argument { create_ast_node<Identifier>({ m_state.current_token.filename(), rule_start.position(), position() }, "args"), true });
// NOTE: While the JS approximation above doesn't do `return super(...args)`, the
// abstract closure is expected to capture and return the result, so we do need a
// return statement here to create the correct completion.
@ -1323,7 +1330,7 @@ NonnullRefPtr<ClassExpression> Parser::parse_class_expression(bool expect_class_
constructor = create_ast_node<FunctionExpression>(
{ m_state.current_token.filename(), rule_start.position(), position() }, class_name, "",
move(constructor_body), Vector { FunctionNode::Parameter { FlyString { "args" }, nullptr, true } }, 0, FunctionKind::Normal,
move(constructor_body), Vector { FunctionNode::Parameter { move(argument_name), nullptr, true } }, 0, FunctionKind::Normal,
/* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false);
} else {
constructor = create_ast_node<FunctionExpression>(