Skip to content

Commit

Permalink
refactor(transformer): add more specific methods to `ModuleImportsSto…
Browse files Browse the repository at this point in the history
…re` (#6560)

Make `ImportKind` private implementation detail of `ModuleImports` common transform. Provide `add_default_import` and `add_named_import` methods instead.
  • Loading branch information
overlookmotel committed Oct 15, 2024
1 parent 7e57a1d commit 9542c4e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 29 deletions.
3 changes: 1 addition & 2 deletions crates/oxc_transformer/src/common/helper_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ use oxc_traverse::{BoundIdentifier, Traverse, TraverseCtx};
use rustc_hash::FxHashMap;
use serde::Deserialize;

use super::module_imports::ImportKind;
use crate::TransformCtx;

/// Defines the mode for loading helper functions.
Expand Down Expand Up @@ -150,7 +149,7 @@ impl<'a, 'ctx> HelperLoader<'a, 'ctx> {
fn add_imports(&self) {
self.ctx.helper_loader.loaded_helpers.borrow_mut().drain().for_each(
|(_, (source, import))| {
self.ctx.module_imports.add_import(source, ImportKind::new_default(import), false);
self.ctx.module_imports.add_default_import(source, import, false);
},
);
}
Expand Down
64 changes: 42 additions & 22 deletions crates/oxc_transformer/src/common/module_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,16 @@ impl<'a, 'ctx> Traverse<'a> for ModuleImports<'a, 'ctx> {
}
}

#[derive(Clone)]
pub struct NamedImport<'a> {
struct NamedImport<'a> {
imported: Atom<'a>,
local: BoundIdentifier<'a>,
}

pub enum ImportKind<'a> {
enum ImportKind<'a> {
Named(NamedImport<'a>),
Default(BoundIdentifier<'a>),
}

impl<'a> ImportKind<'a> {
pub fn new_named(imported: Atom<'a>, local: BoundIdentifier<'a>) -> Self {
Self::Named(NamedImport { imported, local })
}

pub fn new_default(local: BoundIdentifier<'a>) -> Self {
Self::Default(local)
}
}

/// Store for `import` / `require` statements to be added at top of program.
///
/// TODO(improve-on-babel): Insertion order does not matter. We only have to use `IndexMap`
Expand All @@ -99,17 +88,56 @@ impl<'a> ModuleImportsStore<'a> {
Self { imports: RefCell::new(IndexMap::default()) }
}

/// Add default `import` or `require` to top of program.
///
/// Which it will be depends on the source type.
///
/// * `import named_import from 'source';` or
/// * `var named_import = require('source');`
///
/// If `front` is `true`, `import`/`require` is added to front of the `import`s/`require`s.
pub fn add_default_import(&self, source: Atom<'a>, local: BoundIdentifier<'a>, front: bool) {
self.add_import(source, ImportKind::Default(local), front);
}

/// Add named `import` to top of program.
///
/// `import { named_import } from 'source';`
///
/// If `front` is `true`, `import` is added to front of the `import`s.
///
/// Adding named `require`s is not supported, and will cause a panic later on.
pub fn add_named_import(
&self,
source: Atom<'a>,
imported: Atom<'a>,
local: BoundIdentifier<'a>,
front: bool,
) {
self.add_import(source, ImportKind::Named(NamedImport { imported, local }), front);
}

/// Returns `true` if no imports have been scheduled for insertion.
pub fn is_empty(&self) -> bool {
self.imports.borrow().is_empty()
}
}

// Internal methods
impl<'a> ModuleImportsStore<'a> {
/// Add `import` or `require` to top of program.
///
/// Which it will be depends on the source type.
///
/// * `import { named_import } from 'source';` or
/// * `var named_import = require('source');`
///
/// Adding a named `require` is not supported, and will cause a panic later on.
///
/// If `front` is `true`, `import`/`require` is added to front of the `import`s/`require`s.
/// TODO(improve-on-babel): `front` option is only required to pass one of Babel's tests. Output
/// without it is still valid. Remove this once our output doesn't need to match Babel exactly.
pub fn add_import(&self, source: Atom<'a>, import: ImportKind<'a>, front: bool) {
fn add_import(&self, source: Atom<'a>, import: ImportKind<'a>, front: bool) {
match self.imports.borrow_mut().entry(source) {
IndexMapEntry::Occupied(mut entry) => {
entry.get_mut().push(import);
Expand All @@ -128,14 +156,6 @@ impl<'a> ModuleImportsStore<'a> {
}
}

/// Returns `true` if no imports have been scheduled for insertion.
pub fn is_empty(&self) -> bool {
self.imports.borrow().is_empty()
}
}

// Internal methods
impl<'a> ModuleImportsStore<'a> {
/// Insert `import` / `require` statements at top of program.
fn insert_into_program(&self, transform_ctx: &TransformCtx<'a>, ctx: &mut TraverseCtx<'a>) {
if transform_ctx.source_type.is_script() {
Expand Down
8 changes: 3 additions & 5 deletions crates/oxc_transformer/src/react/jsx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ use oxc_syntax::{
};
use oxc_traverse::{BoundIdentifier, Traverse, TraverseCtx};

use crate::{common::module_imports::ImportKind, TransformCtx};
use crate::TransformCtx;

use super::diagnostics;
pub use super::{
Expand Down Expand Up @@ -198,8 +198,7 @@ impl<'a, 'ctx> AutomaticScriptBindings<'a, 'ctx> {
) -> BoundIdentifier<'a> {
let binding =
ctx.generate_uid_in_root_scope(variable_name, SymbolFlags::FunctionScopedVariable);
let import = ImportKind::new_default(binding.clone());
self.ctx.module_imports.add_import(source, import, front);
self.ctx.module_imports.add_default_import(source, binding.clone(), front);
binding
}
}
Expand Down Expand Up @@ -297,8 +296,7 @@ impl<'a, 'ctx> AutomaticModuleBindings<'a, 'ctx> {
ctx: &mut TraverseCtx<'a>,
) -> BoundIdentifier<'a> {
let binding = ctx.generate_uid_in_root_scope(name, SymbolFlags::Import);
let import = ImportKind::new_named(Atom::from(name), binding.clone());
self.ctx.module_imports.add_import(source, import, false);
self.ctx.module_imports.add_named_import(source, Atom::from(name), binding.clone(), false);
binding
}
}
Expand Down

0 comments on commit 9542c4e

Please sign in to comment.