mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:57:47 +00:00
LibJS: Parse generator functions in object literals
Also add some parser tests
This commit is contained in:
parent
2661a88108
commit
d374295a26
3 changed files with 34 additions and 5 deletions
|
@ -830,6 +830,7 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||||
property_type = ObjectProperty::Type::KeyValue;
|
property_type = ObjectProperty::Type::KeyValue;
|
||||||
RefPtr<Expression> property_name;
|
RefPtr<Expression> property_name;
|
||||||
RefPtr<Expression> property_value;
|
RefPtr<Expression> property_value;
|
||||||
|
FunctionKind function_kind { FunctionKind::Regular };
|
||||||
|
|
||||||
if (match(TokenType::TripleDot)) {
|
if (match(TokenType::TripleDot)) {
|
||||||
consume();
|
consume();
|
||||||
|
@ -841,7 +842,12 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match(TokenType::Identifier)) {
|
if (match(TokenType::Asterisk)) {
|
||||||
|
consume();
|
||||||
|
property_type = ObjectProperty::Type::KeyValue;
|
||||||
|
property_name = parse_property_key();
|
||||||
|
function_kind = FunctionKind ::Generator;
|
||||||
|
} else if (match(TokenType::Identifier)) {
|
||||||
auto identifier = consume().value();
|
auto identifier = consume().value();
|
||||||
if (identifier == "get" && match_property_key()) {
|
if (identifier == "get" && match_property_key()) {
|
||||||
property_type = ObjectProperty::Type::Getter;
|
property_type = ObjectProperty::Type::Getter;
|
||||||
|
@ -872,6 +878,8 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||||
parse_options |= FunctionNodeParseOptions::IsGetterFunction;
|
parse_options |= FunctionNodeParseOptions::IsGetterFunction;
|
||||||
if (property_type == ObjectProperty::Type::Setter)
|
if (property_type == ObjectProperty::Type::Setter)
|
||||||
parse_options |= FunctionNodeParseOptions::IsSetterFunction;
|
parse_options |= FunctionNodeParseOptions::IsSetterFunction;
|
||||||
|
if (function_kind == FunctionKind::Generator)
|
||||||
|
parse_options |= FunctionNodeParseOptions::IsGeneratorFunction;
|
||||||
auto function = parse_function_node<FunctionExpression>(parse_options);
|
auto function = parse_function_node<FunctionExpression>(parse_options);
|
||||||
properties.append(create_ast_node<ObjectProperty>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, *property_name, function, property_type, true));
|
properties.append(create_ast_node<ObjectProperty>({ m_parser_state.m_current_token.filename(), rule_start.position(), position() }, *property_name, function, property_type, true));
|
||||||
} else if (match(TokenType::Colon)) {
|
} else if (match(TokenType::Colon)) {
|
||||||
|
@ -1380,13 +1388,15 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
|
||||||
|
|
||||||
ScopePusher scope(*this, ScopePusher::Var | ScopePusher::Function);
|
ScopePusher scope(*this, ScopePusher::Var | ScopePusher::Function);
|
||||||
|
|
||||||
auto is_generator = false;
|
auto is_generator = (parse_options & FunctionNodeParseOptions::IsGeneratorFunction) != 0;
|
||||||
String name;
|
String name;
|
||||||
if (parse_options & FunctionNodeParseOptions::CheckForFunctionAndName) {
|
if (parse_options & FunctionNodeParseOptions::CheckForFunctionAndName) {
|
||||||
consume(TokenType::Function);
|
consume(TokenType::Function);
|
||||||
|
if (!is_generator) {
|
||||||
is_generator = match(TokenType::Asterisk);
|
is_generator = match(TokenType::Asterisk);
|
||||||
if (is_generator)
|
if (is_generator)
|
||||||
consume(TokenType::Asterisk);
|
consume(TokenType::Asterisk);
|
||||||
|
}
|
||||||
|
|
||||||
if (FunctionNodeType::must_have_name() || match(TokenType::Identifier))
|
if (FunctionNodeType::must_have_name() || match(TokenType::Identifier))
|
||||||
name = consume(TokenType::Identifier).value();
|
name = consume(TokenType::Identifier).value();
|
||||||
|
|
|
@ -29,6 +29,7 @@ struct FunctionNodeParseOptions {
|
||||||
IsGetterFunction = 1 << 3,
|
IsGetterFunction = 1 << 3,
|
||||||
IsSetterFunction = 1 << 4,
|
IsSetterFunction = 1 << 4,
|
||||||
IsArrowFunction = 1 << 5,
|
IsArrowFunction = 1 << 5,
|
||||||
|
IsGeneratorFunction = 1 << 6,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,3 +21,21 @@ describe("parsing freestanding generators", () => {
|
||||||
*bar; }`).toEval();
|
*bar; }`).toEval();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("parsing object literal generator functions", () => {
|
||||||
|
test("simple", () => {
|
||||||
|
expect(`x = { *foo() { } }`).toEval();
|
||||||
|
expect(`x = { * foo() { } }`).toEval();
|
||||||
|
expect(`x = { *
|
||||||
|
foo() { } }`).toEval();
|
||||||
|
});
|
||||||
|
test("yield", () => {
|
||||||
|
expect(`x = { foo() { yield; } }`).toEval();
|
||||||
|
expect(`x = { *foo() { yield; } }`).toEval();
|
||||||
|
expect(`x = { *foo() { yield 42; } }`).toEval();
|
||||||
|
expect(`x = { foo() { yield 42; } }`).not.toEval();
|
||||||
|
expect(`x = { *foo() { yield (yield); } }`).toEval();
|
||||||
|
expect(`x = { *
|
||||||
|
foo() { yield (yield); } }`).toEval();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue