Skip to content

Commit

Permalink
fix(es/compat): Make block-scoping pass rename exports correctly (#…
Browse files Browse the repository at this point in the history
…8175)

**Related issue:**

 - Closes #8148
  • Loading branch information
kdy1 committed Oct 30, 2023
1 parent b77d99d commit b13bc32
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 116 deletions.
19 changes: 19 additions & 0 deletions crates/swc/tests/fixture/issues-8xxx/8148/input/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": false
},
"target": "es5",
"loose": false,
"minify": {
"compress": false,
"mangle": false
}
},
"module": {
"type": "es6"
},
"minify": false,
"isModule": true
}
10 changes: 10 additions & 0 deletions crates/swc/tests/fixture/issues-8xxx/8148/input/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function _toBeMocked() {
return "I am the original function";
}

export let toBeMocked = _toBeMocked

export const mock = {
get toBeMocked() { return toBeMocked; },
set toBeMocked(mock) { toBeMocked = mock; }
}
13 changes: 13 additions & 0 deletions crates/swc/tests/fixture/issues-8xxx/8148/output/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function _toBeMocked() {
return "I am the original function";
}
export var toBeMocked = _toBeMocked;
var _$mock = {
get toBeMocked () {
return toBeMocked;
},
set toBeMocked (mock){
toBeMocked = mock;
}
};
export { _$mock as mock };
1 change: 0 additions & 1 deletion crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use swc_ecma_visit::{
};
use swc_trace_macro::swc_trace;

mod operator;
mod vars;

///
Expand Down
94 changes: 0 additions & 94 deletions crates/swc_ecma_compat_es2015/src/block_scoping/operator.rs

This file was deleted.

8 changes: 3 additions & 5 deletions crates/swc_ecma_compat_es2015/src/block_scoping/vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ use swc_common::{
Mark, SyntaxContext,
};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::scope::ScopeKind;
use swc_ecma_transforms_base::{rename::remap, scope::ScopeKind};
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
use swc_trace_macro::swc_trace;

use super::operator::{rename, Rename};

pub(super) fn block_scoped_vars() -> impl VisitMut {
BlockScopedVars::default()
}
Expand Down Expand Up @@ -62,7 +60,7 @@ impl BlockScopedVars {
/// - For third, we rename all declarations which may conflict.
fn handle_program<N>(&mut self, n: &mut N)
where
N: VisitMutWith<Self> + VisitMutWith<Rename>,
N: VisitMutWith<Self> + for<'aa> VisitMutWith<dyn 'aa + VisitMut>,
{
n.visit_mut_children_with(self);

Expand All @@ -81,7 +79,7 @@ impl BlockScopedVars {

// dbg!(&rename_map);

n.visit_mut_with(&mut rename(rename_map))
n.visit_mut_with(&mut remap(&rename_map, Default::default()) as &mut dyn VisitMut);
}

fn with_scope(&mut self, kind: ScopeKind, op: impl FnOnce(&mut Self)) {
Expand Down
8 changes: 8 additions & 0 deletions crates/swc_ecma_transforms_base/src/rename/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ pub fn rename_with_config(map: &AHashMap<Id, JsWord>, config: Config) -> impl '_
})
}

pub fn remap(map: &AHashMap<Id, Id>, config: Config) -> impl '_ + Fold + VisitMut {
as_folder(Operator {
rename: map,
config,
extra: Default::default(),
})
}

pub fn renamer<R>(config: Config, renamer: R) -> impl Fold + VisitMut
where
R: Renamer,
Expand Down
56 changes: 41 additions & 15 deletions crates/swc_ecma_transforms_base/src/rename/ops.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
use swc_atoms::JsWord;
use swc_common::{
collections::AHashMap,
util::{move_map::MoveMap, take::Take},
Spanned, SyntaxContext, DUMMY_SP,
};
use swc_ecma_ast::*;
use swc_ecma_utils::ident::IdentLike;
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};

use crate::{
hygiene::Config,
perf::{cpu_count, ParExplode, Parallel, ParallelExt},
};

pub(super) struct Operator<'a> {
pub rename: &'a AHashMap<Id, JsWord>,
pub(super) struct Operator<'a, I>
where
I: IdentLike,
{
pub rename: &'a AHashMap<Id, I>,
pub config: Config,

pub extra: Vec<ModuleItem>,
}

impl Operator<'_> {
impl<I> Operator<'_, I>
where
I: IdentLike,
{
fn keep_class_name(&mut self, ident: &mut Ident, class: &mut Class) -> Option<ClassExpr> {
if !self.config.keep_class_names {
return None;
Expand Down Expand Up @@ -55,7 +61,10 @@ impl Operator<'_> {
}
}

impl Parallel for Operator<'_> {
impl<I> Parallel for Operator<'_, I>
where
I: IdentLike,
{
fn create(&self) -> Self {
Self {
rename: self.rename,
Expand All @@ -73,15 +82,21 @@ impl Parallel for Operator<'_> {
}
}

impl ParExplode for Operator<'_> {
impl<I> ParExplode for Operator<'_, I>
where
I: IdentLike,
{
fn after_one_stmt(&mut self, _: &mut Vec<Stmt>) {}

fn after_one_module_item(&mut self, stmts: &mut Vec<ModuleItem>) {
stmts.append(&mut self.extra);
}
}

impl<'a> VisitMut for Operator<'a> {
impl<'a, I> VisitMut for Operator<'a, I>
where
I: IdentLike,
{
noop_visit_mut_type!();

/// Preserve key of properties.
Expand Down Expand Up @@ -576,12 +591,18 @@ impl<'a> VisitMut for Operator<'a> {
}
}

struct VarFolder<'a, 'b> {
orig: &'a mut Operator<'b>,
struct VarFolder<'a, 'b, I>
where
I: IdentLike,
{
orig: &'a mut Operator<'b, I>,
renamed: &'a mut Vec<ExportSpecifier>,
}

impl VisitMut for VarFolder<'_, '_> {
impl<I> VisitMut for VarFolder<'_, '_, I>
where
I: IdentLike,
{
noop_visit_mut_type!();

#[inline]
Expand All @@ -601,16 +622,21 @@ impl VisitMut for VarFolder<'_, '_> {
}
}

impl<'a> Operator<'a> {
impl<'a, I> Operator<'a, I>
where
I: IdentLike,
{
/// Returns `Ok(renamed_ident)` if ident should be renamed.
fn rename_ident(&mut self, ident: &mut Ident) -> Result<(), ()> {
if let Some(sym) = self.rename.get(&ident.to_id()) {
if *sym == ident.sym {
if let Some(new_id) = self.rename.get(&ident.to_id()) {
let (new_sym, new_ctxt) = new_id.to_id();

if new_sym == ident.sym {
return Err(());
}

ident.span = ident.span.with_ctxt(SyntaxContext::empty());
ident.sym = sym.clone();
ident.span = ident.span.with_ctxt(new_ctxt);
ident.sym = new_sym;
return Ok(());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

function _toBeMocked() {
return "I am the original function";
}

export let toBeMocked = _toBeMocked

export const mock = {
get toBeMocked() { return toBeMocked; },
set toBeMocked(mock) { toBeMocked = mock; }
}
16 changes: 15 additions & 1 deletion crates/swc_ecma_utils/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@ use swc_atoms::JsWord;
use swc_common::{Span, SyntaxContext};
use swc_ecma_ast::{BindingIdent, Id, Ident};

pub trait IdentLike: Sized {
pub trait IdentLike: Sized + Send + Sync + 'static {
fn from_ident(i: &Ident) -> Self;
fn to_id(&self) -> Id;
fn into_id(self) -> Id;
}

impl IdentLike for JsWord {
fn from_ident(i: &Ident) -> Self {
i.sym.clone()
}

fn to_id(&self) -> Id {
(self.clone(), Default::default())
}

fn into_id(self) -> Id {
(self, Default::default())
}
}

impl IdentLike for BindingIdent {
fn from_ident(i: &Ident) -> Self {
i.clone().into()
Expand Down

0 comments on commit b13bc32

Please sign in to comment.