mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 09:37:34 +00:00
LibJS: Make parsing import and export entries follow the spec
The big changes are: - Allow strings as Module{Export, Import}Name - Properly track declarations in default export statements However, the spec is a little strange in that it allows function and class declarations without a name in default export statements. This is quite hard to fully implement without rewriting more of the parser so for now this behavior is emulated by faking things with function and class expressions. See the comments in parse_export_statement for details on the hacks and where it goes wrong.
This commit is contained in:
parent
631bbcd00a
commit
aca427fc8c
4 changed files with 278 additions and 73 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
|
||||
* Copyright (c) 2021-2022, David Tuin <davidot@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -252,7 +252,7 @@ struct ModuleRequest {
|
|||
|
||||
ModuleRequest() = default;
|
||||
|
||||
explicit ModuleRequest(String specifier)
|
||||
explicit ModuleRequest(FlyString specifier)
|
||||
: module_specifier(move(specifier))
|
||||
{
|
||||
}
|
||||
|
@ -262,15 +262,36 @@ struct ModuleRequest {
|
|||
assertions.empend(move(key), move(value));
|
||||
}
|
||||
|
||||
String module_specifier; // [[Specifier]]
|
||||
FlyString module_specifier; // [[Specifier]]
|
||||
Vector<Assertion> assertions; // [[Assertions]]
|
||||
};
|
||||
|
||||
class ImportStatement final : public Statement {
|
||||
public:
|
||||
struct ImportEntry {
|
||||
String import_name;
|
||||
String local_name;
|
||||
FlyString import_name;
|
||||
FlyString local_name;
|
||||
|
||||
ImportEntry(FlyString import_name_, FlyString local_name_)
|
||||
: import_name(move(import_name_))
|
||||
, local_name(move(local_name_))
|
||||
{
|
||||
}
|
||||
|
||||
bool is_namespace() const
|
||||
{
|
||||
return import_name == "*"sv;
|
||||
}
|
||||
|
||||
ModuleRequest const& module_request() const
|
||||
{
|
||||
VERIFY(m_module_request);
|
||||
return *m_module_request;
|
||||
}
|
||||
|
||||
private:
|
||||
friend ImportStatement;
|
||||
ModuleRequest* m_module_request;
|
||||
};
|
||||
|
||||
explicit ImportStatement(SourceRange source_range, ModuleRequest from_module, Vector<ImportEntry> entries = {})
|
||||
|
@ -278,13 +299,17 @@ public:
|
|||
, m_module_request(move(from_module))
|
||||
, m_entries(move(entries))
|
||||
{
|
||||
for (auto& entry : m_entries)
|
||||
entry.m_module_request = &m_module_request;
|
||||
}
|
||||
|
||||
virtual Completion execute(Interpreter&, GlobalObject&) const override;
|
||||
|
||||
virtual void dump(int indent) const override;
|
||||
|
||||
bool has_bound_name(StringView name) const;
|
||||
bool has_bound_name(FlyString const& name) const;
|
||||
Vector<ImportEntry> const& entries() const { return m_entries; }
|
||||
ModuleRequest const& module_request() const { return m_module_request; }
|
||||
|
||||
private:
|
||||
ModuleRequest m_module_request;
|
||||
|
@ -293,32 +318,53 @@ private:
|
|||
|
||||
class ExportStatement final : public Statement {
|
||||
public:
|
||||
static FlyString local_name_for_default;
|
||||
|
||||
struct ExportEntry {
|
||||
enum class Kind {
|
||||
ModuleRequest,
|
||||
LocalExport
|
||||
} kind;
|
||||
// Can always have
|
||||
String export_name;
|
||||
FlyString export_name;
|
||||
|
||||
// Only if module request
|
||||
ModuleRequest module_request;
|
||||
|
||||
// Has just one of ones below
|
||||
String local_or_import_name;
|
||||
FlyString local_or_import_name;
|
||||
|
||||
ExportEntry(String export_name, String local_name)
|
||||
ExportEntry(FlyString export_name, FlyString local_name)
|
||||
: kind(Kind::LocalExport)
|
||||
, export_name(move(export_name))
|
||||
, local_or_import_name(move(local_name))
|
||||
{
|
||||
}
|
||||
|
||||
ExportEntry(ModuleRequest module_request_, FlyString import_name, FlyString export_name_)
|
||||
: kind(Kind::ModuleRequest)
|
||||
, export_name(move(export_name_))
|
||||
, module_request(move(module_request_))
|
||||
, local_or_import_name(move(import_name))
|
||||
{
|
||||
}
|
||||
|
||||
bool is_all_but_default() const
|
||||
{
|
||||
return kind == Kind::ModuleRequest && local_or_import_name == "*"sv && export_name.is_null();
|
||||
}
|
||||
|
||||
bool is_all() const
|
||||
{
|
||||
return kind == Kind::ModuleRequest && local_or_import_name == "*"sv && !export_name.is_empty();
|
||||
}
|
||||
};
|
||||
|
||||
explicit ExportStatement(SourceRange source_range, RefPtr<ASTNode> statement, Vector<ExportEntry> entries)
|
||||
explicit ExportStatement(SourceRange source_range, RefPtr<ASTNode> statement, Vector<ExportEntry> entries, bool is_default_export)
|
||||
: Statement(source_range)
|
||||
, m_statement(move(statement))
|
||||
, m_entries(move(entries))
|
||||
, m_is_default_export(is_default_export)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -326,14 +372,23 @@ public:
|
|||
|
||||
virtual void dump(int indent) const override;
|
||||
|
||||
bool has_export(StringView export_name) const;
|
||||
bool has_export(FlyString const& export_name) const;
|
||||
|
||||
bool has_statement() const { return m_statement; }
|
||||
Vector<ExportEntry> const& entries() const { return m_entries; }
|
||||
|
||||
bool is_default_export() const { return m_is_default_export; }
|
||||
|
||||
ASTNode const& statement() const
|
||||
{
|
||||
VERIFY(m_statement);
|
||||
return *m_statement;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<ASTNode> m_statement;
|
||||
Vector<ExportEntry> m_entries;
|
||||
bool m_is_default_export { false };
|
||||
};
|
||||
|
||||
class Program final : public ScopeNode {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue