ronantakizawa/codereview-bench huggingface dataset:
Repository: swc-project/swc
File: crates/swc_ecma_transformer/src/es2021/mod.rs (Rust)

Code before:
use swc_ecma_hooks::VisitMutHook;

use crate::TraverseCtx;

#[derive(Debug, Default)]
pub struct Es2021Options {}

pub fn hook(options: Es2021Options) -> impl VisitMutHook<TraverseCtx> {
    Es2021Pass { options }
}

struct Es2021Pass {
    options: Es2021Options,
}

impl VisitMutHook<TraverseCtx> for Es2021Pass {}


Review comment (bug):
The `#[non_exhaustive]` attribute should be placed on a separate line from `#[derive(Debug, Default)]` for better readability and consistency with Rust formatting conventions. It should be:
```rust
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Es2021Options {}
```

Code after:
use swc_ecma_hooks::VisitMutHook;

use crate::TraverseCtx;

#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Es2021Options {}

pub fn hook(options: Es2021Options) -> impl VisitMutHook<TraverseCtx> {
    Es2021Pass { options }
}

struct Es2021Pass {
    options: Es2021Options,
}

impl VisitMutHook<TraverseCtx> for Es2021Pass {}
Repository: swc-project/swc
File: crates/swc_ecma_transformer/src/es2017/mod.rs (Rust)

Code before:
use swc_ecma_hooks::VisitMutHook;

use crate::TraverseCtx;

#[derive(Debug, Default)]
pub struct Es2017Options {}

pub fn hook(options: Es2017Options) -> impl VisitMutHook<TraverseCtx> {
    Es2017Pass { options }
}

struct Es2017Pass {
    options: Es2017Options,
}

impl VisitMutHook<TraverseCtx> for Es2017Pass {}


Review comment (bug):
The `#[non_exhaustive]` attribute should be placed on a separate line from `#[derive(Debug, Default)]` for better readability and consistency with Rust formatting conventions. It should be:
```rust
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Es2017Options {}
```

Code after:
use swc_ecma_hooks::VisitMutHook;

use crate::TraverseCtx;

#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Es2017Options {}

pub fn hook(options: Es2017Options) -> impl VisitMutHook<TraverseCtx> {
    Es2017Pass { options }
}

struct Es2017Pass {
    options: Es2017Options,
}

impl VisitMutHook<TraverseCtx> for Es2017Pass {}
Repository: swc-project/swc
File: crates/swc_ecma_transformer/src/es2015/mod.rs (Rust)

Code before:
use swc_ecma_hooks::VisitMutHook;

use crate::TraverseCtx;

#[derive(Debug, Default)]
pub struct Es2015Options {}

pub fn hook(options: Es2015Options) -> impl VisitMutHook<TraverseCtx> {
    Es2015Pass { options }
}

struct Es2015Pass {
    options: Es2015Options,
}

impl VisitMutHook<TraverseCtx> for Es2015Pass {}


Review comment (bug):
The `#[non_exhaustive]` attribute should be placed on a separate line from `#[derive(Debug, Default)]` for better readability and consistency with Rust formatting conventions. It should be:
```rust
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Es2015Options {}
```

Code after:
use swc_ecma_hooks::VisitMutHook;

use crate::TraverseCtx;

#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Es2015Options {}

pub fn hook(options: Es2015Options) -> impl VisitMutHook<TraverseCtx> {
    Es2015Pass { options }
}

struct Es2015Pass {
    options: Es2015Options,
}

impl VisitMutHook<TraverseCtx> for Es2015Pass {}
Repository: swc-project/swc
File: crates/swc_ecma_transformer/src/decorators/mod.rs (Rust)

Code before:
use swc_ecma_hooks::VisitMutHook;

use crate::TraverseCtx;

#[derive(Debug, Default)]
pub struct DecoratorOptions {}

pub fn hook(options: DecoratorOptions) -> impl VisitMutHook<TraverseCtx> {
    DecoratorPass { options }
}

struct DecoratorPass {
    options: DecoratorOptions,
}

impl VisitMutHook<TraverseCtx> for DecoratorPass {}


Review comment (bug):
The `#[non_exhaustive]` attribute should be placed on a separate line from `#[derive(Debug, Default)]` for better readability and consistency with Rust formatting conventions. It should be:
```rust
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct DecoratorOptions {}
```

Code after:
use swc_ecma_hooks::VisitMutHook;

use crate::TraverseCtx;

#[derive(Debug, Default)]
#[non_exhaustive]
pub struct DecoratorOptions {}

pub fn hook(options: DecoratorOptions) -> impl VisitMutHook<TraverseCtx> {
    DecoratorPass { options }
}

struct DecoratorPass {
    options: DecoratorOptions,
}

impl VisitMutHook<TraverseCtx> for DecoratorPass {}
Repository: swc-project/swc
File: crates/swc_ecma_transformer/src/es2021/logical_assignment_operators.rs (Rust)

Code before:
//!
//! ## Example
//!
//! Input:
//! ```js
//! a ||= b;
//! obj.a.b ||= c;
//!
//! a &&= b;
//! obj.a.b &&= c;
//! ```
//!
//! Output:
//! ```js
//! var _obj$a, _obj$a2;
//!
//! a || (a = b);
//! (_obj$a = obj.a).b || (_obj$a.b = c);
//!
//! a && (a = b);
//! (_obj$a2 = obj.a).b && (_obj$a2.b = c);
//! ```
//!
//! ## Implementation
//!
//! Implementation based on [@babel/plugin-transform-logical-assignment-operators](https://babel.dev/docs/babel-plugin-transform-logical-assignment-operators).
//!
//! ## References:
//! * Babel plugin implementation: <https://github.com/babel/babel/tree/v7.26.2/packages/babel-plugin-transform-logical-assignment-operators>
//! * Logical Assignment TC39 proposal: <https://github.com/tc39/proposal-logical-assignment>

use swc_common::{util::take::Take, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_hooks::VisitMutHook;
use swc_ecma_utils::alias_ident_for;

use crate::TraverseCtx;

pub fn hook() -> impl VisitMutHook<TraverseCtx> {
    LogicalAssignmentOperatorsPass {
        vars: vec![],
        vars_stack: vec![],
    }
}

struct LogicalAssignmentOperatorsPass {
    vars: Vec<VarDeclarator>,
    vars_stack: Vec<Vec<VarDeclarator>>,
}

impl VisitMutHook<TraverseCtx> for LogicalAssignmentOperatorsPass {

Review comment (suggestion):
The URL uses "babel.dev/docs" but the correct domain for Babel documentation is "babeljs.io/docs".
```suggestion
//! Implementation based on [@babel/plugin-transform-logical-assignment-operators](https://babeljs.io/docs/babel-plugin-transform-logical-assignment-operators).
```

Code after:
//!
//! ## Example
//!
//! Input:
//! ```js
//! a ||= b;
//! obj.a.b ||= c;
//!
//! a &&= b;
//! obj.a.b &&= c;
//! ```
//!
//! Output:
//! ```js
//! var _obj$a, _obj$a2;
//!
//! a || (a = b);
//! (_obj$a = obj.a).b || (_obj$a.b = c);
//!
//! a && (a = b);
//! (_obj$a2 = obj.a).b && (_obj$a2.b = c);
//! ```
//!
//! ## Implementation
//!
//! Implementation based on [@babel/plugin-transform-logical-assignment-operators](https://babel.dev/docs/babel-plugin-transform-logical-assignment-operators).
//!
//! ## References:
//! * Babel plugin implementation: <https://github.com/babel/babel/tree/v7.26.2/packages/babel-plugin-transform-logical-assignment-operators>
//! * Logical Assignment TC39 proposal: <https://github.com/tc39/proposal-logical-assignment>

use swc_common::{util::take::Take, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_hooks::VisitMutHook;
use swc_ecma_utils::alias_ident_for;

use crate::TraverseCtx;

pub fn hook() -> impl VisitMutHook<TraverseCtx> {
    LogicalAssignmentOperatorsPass::default()
}

#[derive(Default)]
struct LogicalAssignmentOperatorsPass {
    stmt_ptr: Option<*const Stmt>,
    stmt_ptr_stack: Vec<*const Stmt>,
}

impl VisitMutHook<TraverseCtx> for LogicalAssignmentOperatorsPass {
    fn enter_stmt(&mut self, node: &mut Stmt, _: &mut TraverseCtx) {
        self.stmt_ptr = Some(node as *const Stmt);
Repository: swc-project/swc
File: crates/swc_ecma_transformer/src/es2021/logical_assignment_operators.rs (Rust)

Code before:
        });

        (left_expr, assign_target)
    }

    fn inject_var_decl(&mut self, ident: &Ident, ctx: &mut TraverseCtx) {
        let decl = VarDeclarator {
            span: DUMMY_SP,
            name: Pat::Ident(BindingIdent {
                id: ident.clone(),
                type_ann: None,
            }),
            init: None,
            definite: false,
        };

        ctx.statement_injector.insert_before(
            self.stmt_ptr.unwrap(),
            VarDecl {
                kind: VarDeclKind::Var,
                decls: vec![decl],
                ..Default::default()
            }
            .into(),
        );
    }
}


Review comment (bug):
The `unwrap()` call on `self.stmt_ptr` could panic if `stmt_ptr` is `None`. This could happen if the transformation is triggered in a context where no statement has been entered yet, or due to the bug in the `exit_stmt` logic where `stmt_ptr` can be incorrectly set to `None`. Consider adding proper error handling or ensuring `stmt_ptr` is always set when `inject_var_decl` is called.
```suggestion
        if let Some(stmt_ptr) = self.stmt_ptr {
            ctx.statement_injector.insert_before(
                stmt_ptr,
                VarDecl {
                    kind: VarDeclKind::Var,
                    decls: vec![decl],
                    ..Default::default()
                }
                .into(),
            );
        } else {
            debug_assert!(
                false,
                "inject_var_decl called when stmt_ptr is None. This may indicate a bug in statement tracking logic."
            );
            // Optionally, return early or handle error as appropriate.
        }
```

Code after:
            prop: right_prop,
        });

        (left_expr, assign_target)
    }

    fn inject_var_decl(&mut self, ident: &Ident, ctx: &mut TraverseCtx) {
        let decl = VarDeclarator {
            span: DUMMY_SP,
            name: Pat::Ident(BindingIdent {
                id: ident.clone(),
                type_ann: None,
            }),
            init: None,
            definite: false,
        };

        ctx.statement_injector.insert_before(
            self.stmt_ptr.unwrap(),
            VarDecl {
                kind: VarDeclKind::Var,
                decls: vec![decl],
                ..Default::default()
            }
            .into(),
        );
    }
}
Repository: swc-project/swc
File: crates/swc_ecma_compat_es2021/src/logical_assignments.rs (Rust)

Code before:
use swc_ecma_ast::Pass;
use swc_ecma_compiler::{Compiler, Features};

pub fn logical_assignments() -> impl Pass {
    Compiler::new(swc_ecma_compiler::Config {
        includes: Features::LOGICAL_ASSIGNMENTS,
        ..Default::default()
    })
}


Review comment (suggestion):
The documentation states that this enables nullish coalescing to transform the `??` operator generated from `??=`, but the code only enables `logical_assignment_operators` without enabling `nullish_coalescing`. According to the PR description, ES2021 should transform `a ??= b` → `a ?? (a = b)`, and then ES2020 nullish_coalescing should transform the `??` operator. 

However, looking at `es2020/nullish_coalescing.rs` line 70-71, it also handles `AssignOp::NullishAssign`, which could create a conflict or redundancy. Either:
1. The ES2020 nullish_coalescing should be explicitly enabled here, or
2. The documentation should be corrected to clarify the transformation pipeline

Without enabling nullish_coalescing, the `??` operator produced by this pass won't be further transformed for ES2015/ES2019 targets.
```suggestion
    options.env.es2021.logical_assignment_operators = true;
    options.env.es2020.nullish_coalescing = true;
```

Code after:
use swc_ecma_ast::Pass;

/// Creates a logical assignments transformation pass.
///
/// This enables both:
/// - ES2021 logical assignment operators (&&=, ||=, ??=)
/// - ES2020 nullish coalescing (to transform the ?? operator generated from
///   ??=)
pub fn logical_assignments() -> impl Pass {
    let mut options = swc_ecma_transformer::Options::default();
    options.env.es2021.logical_assignment_operators = true;
    options.into_pass()
}
Repository: swc-project/swc
File: crates/swc_ecma_minifier/src/compress/optimize/mod.rs (Rust)

Code before:
        const InVarDeclOfForInOrOfLoop = 1 << 15;

        const DontUseNegatedIife = 1 << 16;

        /// `true` while handling top-level export decls.
        const IsExported = 1 << 17;

        /// `true` while handling top level items.
        const TopLevel = 1 << 18;

        /// `true` while we are in a function or something similar.
        const InFnLike = 1 << 19;

        const InBlock = 1 << 20;

        const InObjOfNonComputedMember = 1 << 21;

        const InTplExpr = 1 << 22;

        /// True while handling callee, except an arrow expression in callee.
        const IsThisAwareCallee = 1 << 23;

        const IsNestedIfReturnMerging = 1 << 24;

        // const DontInvokeIife = 1 << 25;

        const InWithStmt = 1 << 26;

        const InParam = 1 << 27;

        /// `true` while we are inside a class body.
        const InClass = 1 << 28;
    }
}

impl BitCtx {
    #[inline]
    fn with(mut self, flags: Self, value: bool) -> Self {
        self.set(flags, value);
        self
    }
}

impl Ctx {
    pub fn is_top_level_for_block_level_vars(&self) -> bool {
        if !self.bit_ctx.contains(BitCtx::TopLevel) {
            return false;
        }

        if self.bit_ctx.intersects(BitCtx::InFnLike | BitCtx::InBlock) {
            return false;

Review comment (suggestion):
The commented-out code should be removed rather than left in place. The DontInvokeIife flag is no longer used after this PR's changes, as the logic now relies on the more comprehensive `may_add_ident()` check. Leaving commented code in the codebase reduces readability and can cause confusion for future maintainers.
```suggestion

```

Code after:
        const InVarDeclOfForInOrOfLoop = 1 << 15;

        const DontUseNegatedIife = 1 << 16;

        /// `true` while handling top-level export decls.
        const IsExported = 1 << 17;

        /// `true` while handling top level items.
        const TopLevel = 1 << 18;

        /// `true` while we are in a function or something similar.
        const InFnLike = 1 << 19;

        const InBlock = 1 << 20;

        const InObjOfNonComputedMember = 1 << 21;

        const InTplExpr = 1 << 22;

        /// True while handling callee, except an arrow expression in callee.
        const IsThisAwareCallee = 1 << 23;

        const IsNestedIfReturnMerging = 1 << 24;

        const InWithStmt = 1 << 25;

        const InParam = 1 << 26;

        /// `true` while we are inside a class body.
        const InClass = 1 << 27;
    }
}

impl BitCtx {
    #[inline]
    fn with(mut self, flags: Self, value: bool) -> Self {
        self.set(flags, value);
        self
    }
}

impl Ctx {
    pub fn is_top_level_for_block_level_vars(&self) -> bool {
        if !self.bit_ctx.contains(BitCtx::TopLevel) {
            return false;
        }

        if self.bit_ctx.intersects(BitCtx::InFnLike | BitCtx::InBlock) {
            return false;
        }
        true
Repository: swc-project/swc
File: crates/swc_ecma_compat_es2015/src/arrow.rs (Rust)

Code before:
                expr.visit_mut_children_with(self);
            }
        }
    }

    fn visit_mut_function(&mut self, f: &mut Function) {
        let old_rep = self.hoister.take();

        f.visit_mut_children_with(self);

        let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();

        if let (Some(body), Some(stmt)) = (&mut f.body, decl) {
            prepend_stmt(&mut body.stmts, stmt);
        }
    }

    fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) {
        f.key.visit_mut_with(self);

        if let Some(body) = &mut f.body {
            let old_rep = self.hoister.take();

            // First, replace `this` with `_this` in the body
            // This must happen before converting nested arrow functions
            body.visit_mut_with(&mut self.hoister);

            // Then, convert nested arrow functions
            body.visit_mut_with(self);

            let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();

            if let Some(stmt) = decl {
                prepend_stmt(&mut body.stmts, stmt);
            }
        }
    }

    fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
        stmts.visit_mut_children_with(self);

        let decl = self.hoister.take().to_stmt();

        if let Some(stmt) = decl {
            prepend_stmt(stmts, stmt.into());
        }
    }

    fn visit_mut_script(&mut self, script: &mut Script) {
        script.visit_mut_children_with(self);


Review comment (bug):
Referencing the hoister here is incorrect. It introduces redundant visits. I recommend reverting this change.

Code after:
                expr.visit_mut_children_with(self);
            }
        }
    }

    fn visit_mut_function(&mut self, f: &mut Function) {
        let old_rep = self.hoister.take();

        f.visit_mut_children_with(self);

        let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();

        if let (Some(body), Some(stmt)) = (&mut f.body, decl) {
            prepend_stmt(&mut body.stmts, stmt);
        }
    }

    fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) {
        f.key.visit_mut_with(self);

        if let Some(body) = &mut f.body {
            let old_rep = self.hoister.take();

            body.visit_mut_with(self);

            let decl = mem::replace(&mut self.hoister, old_rep).to_stmt();

            if let Some(stmt) = decl {
                prepend_stmt(&mut body.stmts, stmt);
            }
        }
    }

    fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
        stmts.visit_mut_children_with(self);

        let decl = self.hoister.take().to_stmt();

        if let Some(stmt) = decl {
            prepend_stmt(stmts, stmt.into());
        }
    }

    fn visit_mut_script(&mut self, script: &mut Script) {
        script.visit_mut_children_with(self);

        let decl = self.hoister.take().to_stmt();

        if let Some(stmt) = decl {
            prepend_stmt(&mut script.body, stmt);
        }
Repository: swc-project/swc
File: crates/swc_cli_impl/tests/issues.rs (Rust)

Code before:
    cmd.assert().failure();

    Ok(())
}

/// Tests that `--root-mode upward-optional` succeeds even without a `.swcrc`.
#[test]
fn root_mode_upward_optional_succeeds_without_config() -> Result<()> {
    let tmp = TempDir::new()?;

    // No .swcrc anywhere
    fs::write(tmp.path().join("input.js"), "const arrow = () => 'hello';")?;

    let mut cmd = cli()?;
    cmd.current_dir(&tmp)
        .arg("compile")
        .arg("--root-mode")
        .arg("upward-optional")
        .arg("--out-dir")
        .arg(".")
        .arg("input.js");

    cmd.assert().success();

    // Should compile with defaults (es5 transforms arrow to function)
    let output = fs::read_to_string(tmp.path().join("input.js"))?;
    assert!(
        output.contains("function"),
        "Should use default es5 target without .swcrc. Got: {output}"
    );

    Ok(())
}

/// Tests that `--root-mode upward-optional` uses parent `.swcrc` when found.
#[test]
fn root_mode_upward_optional_finds_parent_config() -> Result<()> {
    let tmp = TempDir::new()?;

    let subdir = tmp.path().join("subdir");
    create_dir_all(&subdir)?;

    // target: es2022 keeps arrow functions
    fs::write(
        tmp.path().join(".swcrc"),
        r#"{
            "jsc": {
                "parser": { "syntax": "ecmascript" },
                "target": "es2022"
            }
        }"#,

Review comment (suggestion):
Same issue as Comment 1: reading from the input file instead of verifying the compiled output file. The test should read from the actual compilation output to verify the transformation occurred.

Code after:
        }"#,
    )?;

    fs::write(subdir.join("input.js"), "const arrow = () => 'hello';")?;

    let mut cmd = cli()?;
    cmd.current_dir(&subdir)
        .arg("compile")
        .arg("--root-mode")
        .arg("root")
        .arg("--out-file")
        .arg("output.js")
        .arg("input.js");

    cmd.assert().success();

    // Parent .swcrc should be ignored, so default es5 transforms arrow to function
    let output = fs::read_to_string(subdir.join("output.js"))?;
    assert!(
        output.contains("function"),
        "Parent .swcrc should be ignored with root mode. Got: {output}"
    );

    Ok(())
}

/// Tests that `--root-mode upward` fails when no `.swcrc` is found.
#[test]
fn root_mode_upward_fails_without_config() -> Result<()> {
    let tmp = TempDir::new()?;

    // No .swcrc anywhere
    fs::write(tmp.path().join("input.js"), "const arrow = () => 'hello';")?;

    let mut cmd = cli()?;
    cmd.current_dir(&tmp)
        .arg("compile")
        .arg("--root-mode")
        .arg("upward")
        .arg("--out-file")
        .arg("output.js")
        .arg("input.js");

    cmd.assert().failure();

    Ok(())
}

/// Tests that `--root-mode upward-optional` succeeds even without a `.swcrc`.
#[test]
fn root_mode_upward_optional_succeeds_without_config() -> Result<()> {
Repository: swc-project/swc
File: crates/swc_cli_impl/tests/issues.rs (Rust)

Code before:
    // target: es2022 keeps arrow functions
    fs::write(
        tmp.path().join(".swcrc"),
        r#"{
            "jsc": {
                "parser": { "syntax": "ecmascript" },
                "target": "es2022"
            }
        }"#,
    )?;

    fs::write(subdir.join("input.js"), "const arrow = () => 'hello';")?;

    let mut cmd = cli()?;
    cmd.current_dir(&subdir)
        .arg("compile")
        .arg("--root-mode")
        .arg("upward-optional")
        .arg("--out-dir")
        .arg(".")
        .arg("input.js");

    cmd.assert().success();

    // Verify the config was found: es2022 keeps arrow functions
    let output = fs::read_to_string(subdir.join("input.js"))?;
    assert!(
        output.contains("=>"),
        "Arrow should be kept with es2022 target from parent .swcrc. Got: {output}"
    );

    Ok(())
}

/// ln -s $a $b
fn symlink(a: &Path, b: &Path) {
    #[cfg(unix)]
    {
        std::os::unix::fs::symlink(a, b).unwrap();
    }

    #[cfg(windows)]
    {
        std::os::windows::fs::symlink_file(a, b).unwrap();
    }
}

fn print_ls_alr(path: &Path) {
    let mut cmd = Command::new("ls");
    cmd.arg("-alR").arg(path);
    cmd.status().unwrap();

Review comment (suggestion):
Same issue as Comment 1: reading from the input file instead of verifying the compiled output file. The test should read from the actual compilation output to verify the transformation occurred.
```suggestion
        .arg("out")
        .arg("input.js");

    cmd.assert().success();

    // Verify the config was found: es2022 keeps arrow functions
    let output = fs::read_to_string(subdir.join("out").join("input.js"))?;
```

Code after:

    cmd.assert().failure();

    Ok(())
}

/// Tests that `--root-mode upward-optional` succeeds even without a `.swcrc`.
#[test]
fn root_mode_upward_optional_succeeds_without_config() -> Result<()> {
    let tmp = TempDir::new()?;

    // No .swcrc anywhere
    fs::write(tmp.path().join("input.js"), "const arrow = () => 'hello';")?;

    let mut cmd = cli()?;
    cmd.current_dir(&tmp)
        .arg("compile")
        .arg("--root-mode")
        .arg("upward-optional")
        .arg("--out-file")
        .arg("output.js")
        .arg("input.js");

    cmd.assert().success();

    // Should compile with defaults (es5 transforms arrow to function)
    let output = fs::read_to_string(tmp.path().join("output.js"))?;
    assert!(
        output.contains("function"),
        "Should use default es5 target without .swcrc. Got: {output}"
    );

    Ok(())
}

/// Tests that `--root-mode upward-optional` uses parent `.swcrc` when found.
#[test]
fn root_mode_upward_optional_finds_parent_config() -> Result<()> {
    let tmp = TempDir::new()?;

    let subdir = tmp.path().join("subdir");
    create_dir_all(&subdir)?;

    // target: es2022 keeps arrow functions
    fs::write(
        tmp.path().join(".swcrc"),
        r#"{
            "jsc": {
                "parser": { "syntax": "ecmascript" },
                "target": "es2022"
            }