mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 05:07:35 +00:00
LibJS: Follow the spec with storing im- and export entries
Because we can have arbitrary in- and export names with strings we can have '*' and '' which means using '*' as an indicating namespace imports failed / behaved incorrectly for string imports '*'. We now use more specific types to indicate these special states instead of these 'magic' string values. Do note that 'default' is not actually a magic string value but one specified by the spec. And you can in fact export the default value by doing: `export { 1 as default }`.
This commit is contained in:
parent
8473f6caee
commit
e0e4ead2c8
11 changed files with 190 additions and 96 deletions
|
@ -268,19 +268,18 @@ struct ModuleRequest {
|
|||
|
||||
class ImportStatement final : public Statement {
|
||||
public:
|
||||
// ImportEntry Record, https://tc39.es/ecma262/#table-importentry-record-fields
|
||||
struct ImportEntry {
|
||||
FlyString import_name;
|
||||
FlyString local_name;
|
||||
FlyString import_name; // [[ImportName]] if a String
|
||||
FlyString local_name; // [[LocalName]]
|
||||
bool is_namespace { false }; // [[ImportName]] if `namespace-object`
|
||||
|
||||
ImportEntry(FlyString import_name_, FlyString local_name_)
|
||||
ImportEntry(FlyString import_name_, FlyString local_name_, bool is_namespace_ = false)
|
||||
: import_name(move(import_name_))
|
||||
, local_name(move(local_name_))
|
||||
, is_namespace(is_namespace_)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_namespace() const
|
||||
{
|
||||
return import_name == "*"sv;
|
||||
VERIFY(!is_namespace || import_name.is_null());
|
||||
}
|
||||
|
||||
ModuleRequest const& module_request() const
|
||||
|
@ -291,7 +290,7 @@ public:
|
|||
|
||||
private:
|
||||
friend ImportStatement;
|
||||
ModuleRequest* m_module_request;
|
||||
ModuleRequest* m_module_request; // [[ModuleRequest]]
|
||||
};
|
||||
|
||||
explicit ImportStatement(SourceRange source_range, ModuleRequest from_module, Vector<ImportEntry> entries = {})
|
||||
|
@ -320,52 +319,74 @@ class ExportStatement final : public Statement {
|
|||
public:
|
||||
static FlyString local_name_for_default;
|
||||
|
||||
// ExportEntry Record, https://tc39.es/ecma262/#table-exportentry-records
|
||||
struct ExportEntry {
|
||||
enum class Kind {
|
||||
ModuleRequest,
|
||||
LocalExport
|
||||
NamedExport,
|
||||
ModuleRequestAll,
|
||||
ModuleRequestAllButDefault,
|
||||
} kind;
|
||||
// Can always have
|
||||
FlyString export_name;
|
||||
|
||||
// Only if module request
|
||||
ModuleRequest module_request;
|
||||
FlyString export_name; // [[ExportName]]
|
||||
FlyString local_or_import_name; // Either [[ImportName]] or [[LocalName]]
|
||||
|
||||
// Has just one of ones below
|
||||
FlyString local_or_import_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)
|
||||
ExportEntry(Kind export_kind, FlyString export_name_, FlyString local_or_import_name_)
|
||||
: kind(export_kind)
|
||||
, export_name(move(export_name_))
|
||||
, module_request(move(module_request_))
|
||||
, local_or_import_name(move(import_name))
|
||||
, local_or_import_name(move(local_or_import_name_))
|
||||
{
|
||||
}
|
||||
|
||||
bool is_all_but_default() const
|
||||
bool is_module_request() const
|
||||
{
|
||||
return kind == Kind::ModuleRequest && local_or_import_name == "*"sv && export_name.is_null();
|
||||
return m_module_request != nullptr;
|
||||
}
|
||||
|
||||
bool is_all() const
|
||||
static ExportEntry indirect_export_entry(ModuleRequest const& module_request, FlyString export_name, FlyString import_name)
|
||||
{
|
||||
return kind == Kind::ModuleRequest && local_or_import_name == "*"sv && !export_name.is_empty();
|
||||
ExportEntry entry { Kind::NamedExport, move(export_name), move(import_name) };
|
||||
entry.m_module_request = &module_request;
|
||||
return entry;
|
||||
}
|
||||
|
||||
ModuleRequest const& module_request() const
|
||||
{
|
||||
VERIFY(m_module_request);
|
||||
return *m_module_request;
|
||||
}
|
||||
|
||||
private:
|
||||
ModuleRequest const* m_module_request { nullptr }; // [[ModuleRequest]]
|
||||
friend ExportStatement;
|
||||
|
||||
public:
|
||||
static ExportEntry named_export(FlyString export_name, FlyString local_name)
|
||||
{
|
||||
return ExportEntry { Kind::NamedExport, move(export_name), move(local_name) };
|
||||
}
|
||||
|
||||
static ExportEntry all_but_default_entry()
|
||||
{
|
||||
return ExportEntry { Kind::ModuleRequestAllButDefault, {}, {} };
|
||||
}
|
||||
|
||||
static ExportEntry all_module_request(FlyString export_name)
|
||||
{
|
||||
return ExportEntry { Kind::ModuleRequestAll, move(export_name), {} };
|
||||
}
|
||||
};
|
||||
|
||||
explicit ExportStatement(SourceRange source_range, RefPtr<ASTNode> statement, Vector<ExportEntry> entries, bool is_default_export)
|
||||
ExportStatement(SourceRange source_range, RefPtr<ASTNode> statement, Vector<ExportEntry> entries, bool is_default_export, ModuleRequest module_request)
|
||||
: Statement(source_range)
|
||||
, m_statement(move(statement))
|
||||
, m_entries(move(entries))
|
||||
, m_is_default_export(is_default_export)
|
||||
, m_module_request(move(module_request))
|
||||
{
|
||||
if (!m_module_request.module_specifier.is_null()) {
|
||||
for (auto& entry : m_entries)
|
||||
entry.m_module_request = &m_module_request;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Completion execute(Interpreter&, GlobalObject&) const override;
|
||||
|
@ -389,6 +410,7 @@ private:
|
|||
RefPtr<ASTNode> m_statement;
|
||||
Vector<ExportEntry> m_entries;
|
||||
bool m_is_default_export { false };
|
||||
ModuleRequest m_module_request;
|
||||
};
|
||||
|
||||
class Program final : public ScopeNode {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue