mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 21:17:45 +00:00
LibJS: Add a mode to parse JS as a module
In a module strict mode should be enabled at the start of parsing and we allow import and export statements.
This commit is contained in:
parent
d6d7d11590
commit
7613c22b06
8 changed files with 38 additions and 15 deletions
|
@ -168,8 +168,14 @@ private:
|
|||
|
||||
class Program final : public ScopeNode {
|
||||
public:
|
||||
explicit Program(SourceRange source_range)
|
||||
enum class Type {
|
||||
Script,
|
||||
Module
|
||||
};
|
||||
|
||||
explicit Program(SourceRange source_range, Type program_type)
|
||||
: ScopeNode(source_range)
|
||||
, m_type(program_type)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -178,10 +184,13 @@ public:
|
|||
bool is_strict_mode() const { return m_is_strict_mode; }
|
||||
void set_strict_mode() { m_is_strict_mode = true; }
|
||||
|
||||
Type type() const { return m_type; }
|
||||
|
||||
private:
|
||||
virtual bool is_program() const override { return true; }
|
||||
|
||||
bool m_is_strict_mode { false };
|
||||
Type m_type { Type::Script };
|
||||
};
|
||||
|
||||
class BlockStatement final : public ScopeNode {
|
||||
|
|
|
@ -330,11 +330,11 @@ bool Lexer::is_identifier_middle() const
|
|||
bool Lexer::is_line_comment_start(bool line_has_token_yet) const
|
||||
{
|
||||
return match('/', '/')
|
||||
|| match('<', '!', '-', '-')
|
||||
|| (m_allow_html_comments && match('<', '!', '-', '-'))
|
||||
// "-->" is considered a line comment start if the current line is only whitespace and/or
|
||||
// other block comment(s); or in other words: the current line does not have a token or
|
||||
// ongoing line comment yet
|
||||
|| (match('-', '-', '>') && !line_has_token_yet)
|
||||
|| (m_allow_html_comments && !line_has_token_yet && match('-', '-', '>'))
|
||||
// https://tc39.es/proposal-hashbang/out.html#sec-updated-syntax
|
||||
|| (match('#', '!') && m_position == 1);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ public:
|
|||
const StringView& source() const { return m_source; };
|
||||
const StringView& filename() const { return m_filename; };
|
||||
|
||||
void disallow_html_comments() { m_allow_html_comments = false; };
|
||||
|
||||
private:
|
||||
void consume();
|
||||
bool consume_exponent();
|
||||
|
@ -63,6 +65,8 @@ private:
|
|||
};
|
||||
Vector<TemplateState> m_template_states;
|
||||
|
||||
bool m_allow_html_comments { true };
|
||||
|
||||
static HashMap<String, TokenType> s_keywords;
|
||||
static HashMap<String, TokenType> s_three_char_tokens;
|
||||
static HashMap<String, TokenType> s_two_char_tokens;
|
||||
|
|
|
@ -208,10 +208,13 @@ private:
|
|||
|
||||
constexpr OperatorPrecedenceTable g_operator_precedence;
|
||||
|
||||
Parser::ParserState::ParserState(Lexer l)
|
||||
Parser::ParserState::ParserState(Lexer l, Program::Type program_type)
|
||||
: lexer(move(l))
|
||||
, current_token(lexer.next())
|
||||
, current_token(TokenType::Invalid, {}, {}, {}, {}, 0, 0, 0)
|
||||
{
|
||||
if (program_type == Program::Type::Module)
|
||||
lexer.disallow_html_comments();
|
||||
current_token = lexer.next();
|
||||
}
|
||||
|
||||
Parser::Scope::Scope(Parser::Scope::Type type, RefPtr<Parser::Scope> parent_scope)
|
||||
|
@ -232,8 +235,9 @@ RefPtr<Parser::Scope> Parser::Scope::get_current_function_scope()
|
|||
return result;
|
||||
}
|
||||
|
||||
Parser::Parser(Lexer lexer)
|
||||
: m_state(move(lexer))
|
||||
Parser::Parser(Lexer lexer, Program::Type program_type)
|
||||
: m_state(move(lexer), program_type)
|
||||
, m_program_type(program_type)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -282,8 +286,8 @@ NonnullRefPtr<Program> Parser::parse_program(bool starts_in_strict_mode)
|
|||
{
|
||||
auto rule_start = push_start();
|
||||
ScopePusher scope(*this, ScopePusher::Var | ScopePusher::Let, Scope::Function);
|
||||
auto program = adopt_ref(*new Program({ m_filename, rule_start.position(), position() }));
|
||||
if (starts_in_strict_mode) {
|
||||
auto program = adopt_ref(*new Program({ m_filename, rule_start.position(), position() }, m_program_type));
|
||||
if (starts_in_strict_mode || m_program_type == Program::Type::Module) {
|
||||
program->set_strict_mode();
|
||||
m_state.strict_mode = true;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ struct FunctionNodeParseOptions {
|
|||
|
||||
class Parser {
|
||||
public:
|
||||
explicit Parser(Lexer lexer);
|
||||
explicit Parser(Lexer lexer, Program::Type program_type = Program::Type::Script);
|
||||
|
||||
NonnullRefPtr<Program> parse_program(bool starts_in_strict_mode = false);
|
||||
|
||||
|
@ -246,7 +246,7 @@ private:
|
|||
bool in_continue_context { false };
|
||||
bool string_legacy_octal_escape_sequence_in_scope { false };
|
||||
|
||||
explicit ParserState(Lexer);
|
||||
ParserState(Lexer, Program::Type);
|
||||
};
|
||||
|
||||
class PositionKeyTraits {
|
||||
|
@ -267,5 +267,6 @@ private:
|
|||
FlyString m_filename;
|
||||
Vector<ParserState> m_saved_state;
|
||||
HashMap<Position, TokenMemoization, PositionKeyTraits> m_token_memoizations;
|
||||
Program::Type m_program_type;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue