use super::{ModuleSpecifier, VarDeclaration};
use crate::{
Declaration, Expression,
function::{
AsyncFunctionDeclaration, AsyncGeneratorDeclaration, ClassDeclaration, FunctionDeclaration,
GeneratorDeclaration,
},
visitor::{VisitWith, Visitor, VisitorMut},
};
use boa_interner::Sym;
use std::ops::ControlFlow;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ReExportKind {
Namespaced {
name: Option<Sym>,
},
Named {
names: Box<[ExportSpecifier]>,
},
}
impl VisitWith for ReExportKind {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
Self::Namespaced { name: Some(name) } => visitor.visit_sym(name),
Self::Namespaced { name: None } => ControlFlow::Continue(()),
Self::Named { names } => {
for name in &**names {
visitor.visit_export_specifier(name)?;
}
ControlFlow::Continue(())
}
}
}
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
Self::Namespaced { name: Some(name) } => visitor.visit_sym_mut(name),
Self::Namespaced { name: None } => ControlFlow::Continue(()),
Self::Named { names } => {
for name in &mut **names {
visitor.visit_export_specifier_mut(name)?;
}
ControlFlow::Continue(())
}
}
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub enum ExportDeclaration {
ReExport {
kind: ReExportKind,
specifier: ModuleSpecifier,
},
List(Box<[ExportSpecifier]>),
VarStatement(VarDeclaration),
Declaration(Declaration),
DefaultFunctionDeclaration(FunctionDeclaration),
DefaultGeneratorDeclaration(GeneratorDeclaration),
DefaultAsyncFunctionDeclaration(AsyncFunctionDeclaration),
DefaultAsyncGeneratorDeclaration(AsyncGeneratorDeclaration),
DefaultClassDeclaration(Box<ClassDeclaration>),
DefaultAssignmentExpression(Expression),
}
impl VisitWith for ExportDeclaration {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
Self::ReExport { specifier, kind } => {
visitor.visit_module_specifier(specifier)?;
visitor.visit_re_export_kind(kind)
}
Self::List(list) => {
for item in &**list {
visitor.visit_export_specifier(item)?;
}
ControlFlow::Continue(())
}
Self::VarStatement(var) => visitor.visit_var_declaration(var),
Self::Declaration(decl) => visitor.visit_declaration(decl),
Self::DefaultFunctionDeclaration(f) => visitor.visit_function_declaration(f),
Self::DefaultGeneratorDeclaration(g) => visitor.visit_generator_declaration(g),
Self::DefaultAsyncFunctionDeclaration(af) => {
visitor.visit_async_function_declaration(af)
}
Self::DefaultAsyncGeneratorDeclaration(ag) => {
visitor.visit_async_generator_declaration(ag)
}
Self::DefaultClassDeclaration(c) => visitor.visit_class_declaration(c),
Self::DefaultAssignmentExpression(expr) => visitor.visit_expression(expr),
}
}
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
Self::ReExport { specifier, kind } => {
visitor.visit_module_specifier_mut(specifier)?;
visitor.visit_re_export_kind_mut(kind)
}
Self::List(list) => {
for item in &mut **list {
visitor.visit_export_specifier_mut(item)?;
}
ControlFlow::Continue(())
}
Self::VarStatement(var) => visitor.visit_var_declaration_mut(var),
Self::Declaration(decl) => visitor.visit_declaration_mut(decl),
Self::DefaultFunctionDeclaration(f) => visitor.visit_function_declaration_mut(f),
Self::DefaultGeneratorDeclaration(g) => visitor.visit_generator_declaration_mut(g),
Self::DefaultAsyncFunctionDeclaration(af) => {
visitor.visit_async_function_declaration_mut(af)
}
Self::DefaultAsyncGeneratorDeclaration(ag) => {
visitor.visit_async_generator_declaration_mut(ag)
}
Self::DefaultClassDeclaration(c) => visitor.visit_class_declaration_mut(c),
Self::DefaultAssignmentExpression(expr) => visitor.visit_expression_mut(expr),
}
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Copy, PartialEq, Eq)]
pub struct ExportSpecifier {
alias: Sym,
private_name: Sym,
string_literal: bool,
}
impl ExportSpecifier {
#[inline]
#[must_use]
pub const fn new(alias: Sym, private_name: Sym, string_literal: bool) -> Self {
Self {
alias,
private_name,
string_literal,
}
}
#[inline]
#[must_use]
pub const fn alias(self) -> Sym {
self.alias
}
#[inline]
#[must_use]
pub const fn private_name(self) -> Sym {
self.private_name
}
#[inline]
#[must_use]
pub const fn string_literal(&self) -> bool {
self.string_literal
}
}
impl VisitWith for ExportSpecifier {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
visitor.visit_sym(&self.alias)?;
visitor.visit_sym(&self.private_name)
}
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
visitor.visit_sym_mut(&mut self.alias)?;
visitor.visit_sym_mut(&mut self.private_name)
}
}
#[derive(Debug, Clone, Copy)]
pub enum ReExportImportName {
Name(Sym),
Star,
}
#[derive(Debug, Clone, Copy)]
pub enum ExportEntry {
Ordinary(LocalExportEntry),
StarReExport {
module_request: Sym,
},
ReExport(IndirectExportEntry),
}
impl From<IndirectExportEntry> for ExportEntry {
fn from(v: IndirectExportEntry) -> Self {
Self::ReExport(v)
}
}
impl From<LocalExportEntry> for ExportEntry {
fn from(v: LocalExportEntry) -> Self {
Self::Ordinary(v)
}
}
#[derive(Debug, Clone, Copy)]
pub struct LocalExportEntry {
local_name: Sym,
export_name: Sym,
}
impl LocalExportEntry {
#[must_use]
pub const fn new(local_name: Sym, export_name: Sym) -> Self {
Self {
local_name,
export_name,
}
}
#[must_use]
pub const fn local_name(&self) -> Sym {
self.local_name
}
#[must_use]
pub const fn export_name(&self) -> Sym {
self.export_name
}
}
#[derive(Debug, Clone, Copy)]
pub struct IndirectExportEntry {
module_request: Sym,
import_name: ReExportImportName,
export_name: Sym,
}
impl IndirectExportEntry {
#[must_use]
pub const fn new(
module_request: Sym,
import_name: ReExportImportName,
export_name: Sym,
) -> Self {
Self {
module_request,
import_name,
export_name,
}
}
#[must_use]
pub const fn module_request(&self) -> Sym {
self.module_request
}
#[must_use]
pub const fn import_name(&self) -> ReExportImportName {
self.import_name
}
#[must_use]
pub const fn export_name(&self) -> Sym {
self.export_name
}
}