mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:07:34 +00:00
LibJS: Parse dynamic import calls 'import()' and 'import.meta'
For now both just throw when executing but this can be implemented when modules are implemented :^).
This commit is contained in:
parent
73eb29dabe
commit
045a42cf35
4 changed files with 125 additions and 6 deletions
|
@ -874,6 +874,63 @@ RefPtr<MetaProperty> Parser::try_parse_new_target_expression()
|
|||
return create_ast_node<MetaProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, MetaProperty::Type::NewTarget);
|
||||
}
|
||||
|
||||
RefPtr<MetaProperty> Parser::try_parse_import_meta_expression()
|
||||
{
|
||||
// Optimization which skips the save/load state.
|
||||
if (next_token().type() != TokenType::Period)
|
||||
return {};
|
||||
|
||||
save_state();
|
||||
auto rule_start = push_start();
|
||||
ArmedScopeGuard state_rollback_guard = [&] {
|
||||
load_state();
|
||||
};
|
||||
|
||||
consume(TokenType::Import);
|
||||
consume(TokenType::Period);
|
||||
if (!match(TokenType::Identifier))
|
||||
return {};
|
||||
// The string 'meta' cannot have escapes so we check original value.
|
||||
if (consume().original_value() != "meta"sv)
|
||||
return {};
|
||||
|
||||
state_rollback_guard.disarm();
|
||||
discard_saved_state();
|
||||
return create_ast_node<MetaProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, MetaProperty::Type::ImportMeta);
|
||||
}
|
||||
|
||||
NonnullRefPtr<ImportCall> Parser::parse_import_call()
|
||||
{
|
||||
auto rule_start = push_start();
|
||||
|
||||
// We use the extended definition:
|
||||
// ImportCall[Yield, Await]:
|
||||
// import(AssignmentExpression[+In, ?Yield, ?Await] ,opt)
|
||||
// import(AssignmentExpression[+In, ?Yield, ?Await] ,AssignmentExpression[+In, ?Yield, ?Await] ,opt)
|
||||
// From https://tc39.es/proposal-import-assertions/#sec-evaluate-import-call
|
||||
|
||||
consume(TokenType::Import);
|
||||
consume(TokenType::ParenOpen);
|
||||
auto argument = parse_expression(2);
|
||||
|
||||
RefPtr<Expression> options;
|
||||
if (match(TokenType::Comma)) {
|
||||
consume(TokenType::Comma);
|
||||
|
||||
if (!match(TokenType::ParenClose)) {
|
||||
options = parse_expression(2);
|
||||
|
||||
// Second optional comma
|
||||
if (match(TokenType::Comma))
|
||||
consume(TokenType::Comma);
|
||||
}
|
||||
}
|
||||
|
||||
consume(TokenType::ParenClose);
|
||||
|
||||
return create_ast_node<ImportCall>({ m_state.current_token.filename(), rule_start.position(), position() }, move(argument), move(options));
|
||||
}
|
||||
|
||||
NonnullRefPtr<ClassDeclaration> Parser::parse_class_declaration()
|
||||
{
|
||||
auto rule_start = push_start();
|
||||
|
@ -1305,6 +1362,19 @@ Parser::PrimaryExpressionParseResult Parser::parse_primary_expression()
|
|||
}
|
||||
return { parse_new_expression() };
|
||||
}
|
||||
case TokenType::Import: {
|
||||
auto lookahead_token = next_token();
|
||||
VERIFY(lookahead_token.type() == TokenType::Period || lookahead_token.type() == TokenType::ParenOpen);
|
||||
if (lookahead_token.type() == TokenType::ParenOpen)
|
||||
return { parse_import_call() };
|
||||
|
||||
if (auto import_meta = try_parse_import_meta_expression()) {
|
||||
if (m_program_type != Program::Type::Module)
|
||||
syntax_error("import.meta is only allowed in modules");
|
||||
return { import_meta.release_nonnull() };
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TokenType::Yield:
|
||||
if (!m_state.in_generator_function_context)
|
||||
goto read_as_identifier;
|
||||
|
@ -1321,10 +1391,11 @@ Parser::PrimaryExpressionParseResult Parser::parse_primary_expression()
|
|||
default:
|
||||
if (match_identifier_name())
|
||||
goto read_as_identifier;
|
||||
expected("primary expression");
|
||||
consume();
|
||||
return { create_ast_node<ErrorExpression>({ m_state.current_token.filename(), rule_start.position(), position() }) };
|
||||
break;
|
||||
}
|
||||
expected("primary expression");
|
||||
consume();
|
||||
return { create_ast_node<ErrorExpression>({ m_state.current_token.filename(), rule_start.position(), position() }) };
|
||||
}
|
||||
|
||||
NonnullRefPtr<RegExpLiteral> Parser::parse_regexp_literal()
|
||||
|
@ -2115,6 +2186,8 @@ NonnullRefPtr<NewExpression> Parser::parse_new_expression()
|
|||
consume(TokenType::New);
|
||||
|
||||
auto callee = parse_expression(g_operator_precedence.get(TokenType::New), Associativity::Right, { TokenType::ParenOpen, TokenType::QuestionMarkPeriod });
|
||||
if (is<ImportCall>(*callee))
|
||||
syntax_error("Cannot call new on dynamic import", callee->source_range().start);
|
||||
|
||||
Vector<CallExpression::Argument> arguments;
|
||||
|
||||
|
@ -3343,6 +3416,11 @@ bool Parser::match(TokenType type) const
|
|||
bool Parser::match_expression() const
|
||||
{
|
||||
auto type = m_state.current_token.type();
|
||||
if (type == TokenType::Import) {
|
||||
auto lookahead_token = next_token();
|
||||
return lookahead_token.type() == TokenType::Period || lookahead_token.type() == TokenType::ParenOpen;
|
||||
}
|
||||
|
||||
return type == TokenType::BoolLiteral
|
||||
|| type == TokenType::NumericLiteral
|
||||
|| type == TokenType::BigIntLiteral
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue