diff --git a/packages/transformers/js/core/src/hoist.rs b/packages/transformers/js/core/src/hoist.rs index 3d3eb58f331..02e17bce0b1 100644 --- a/packages/transformers/js/core/src/hoist.rs +++ b/packages/transformers/js/core/src/hoist.rs @@ -693,31 +693,6 @@ impl<'a> Fold for Hoist<'a> { } } } - Expr::Unary(ref unary) => { - // typeof require -> "function" - // typeof module -> "object" - if unary.op == UnaryOp::TypeOf { - if let Expr::Ident(ident) = &*unary.arg { - if ident.sym == js_word!("require") && !self.collect.decls.contains(&id!(ident)) { - return Expr::Lit(Lit::Str(Str { - kind: StrKind::Synthesized, - has_escape: false, - span: unary.span, - value: js_word!("function"), - })); - } - - if ident.sym == js_word!("module") && !self.collect.decls.contains(&id!(ident)) { - return Expr::Lit(Lit::Str(Str { - kind: StrKind::Synthesized, - has_escape: false, - span: unary.span, - value: js_word!("object"), - })); - } - } - } - } _ => {} } diff --git a/packages/transformers/js/core/src/lib.rs b/packages/transformers/js/core/src/lib.rs index 58ba9bd4cea..75156b16a52 100644 --- a/packages/transformers/js/core/src/lib.rs +++ b/packages/transformers/js/core/src/lib.rs @@ -18,8 +18,10 @@ mod fs; mod global_replacer; mod hoist; mod modules; +mod typeof_replacer; mod utils; +use crate::typeof_replacer::TypeOfReplacer; use std::collections::{HashMap, HashSet}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -321,6 +323,10 @@ pub fn transform(config: Config) -> Result { let mut diagnostics = vec![]; let module = { let mut passes = chain!( + Optional::new( + TypeOfReplacer { decls: &decls }, + config.source_type != SourceType::Script + ), // Inline process.env and process.browser Optional::new( EnvReplacer { diff --git a/packages/transformers/js/core/src/typeof_replacer.rs b/packages/transformers/js/core/src/typeof_replacer.rs new file mode 100644 index 00000000000..80b0cfad87c --- /dev/null +++ b/packages/transformers/js/core/src/typeof_replacer.rs @@ -0,0 +1,52 @@ +use std::collections::HashSet; + +use swc_atoms::JsWord; +use swc_ecmascript::ast::{Expr, Lit, Str, StrKind, UnaryOp}; +use swc_ecmascript::visit::{Fold, FoldWith}; + +use crate::id; +use crate::utils::IdentId; + +pub struct TypeOfReplacer<'a> { + pub decls: &'a HashSet, +} + +impl<'a> Fold for TypeOfReplacer<'a> { + fn fold_expr(&mut self, node: Expr) -> Expr { + if let Expr::Unary(ref unary) = node { + // typeof require -> "function" + // typeof module -> "object" + if unary.op == UnaryOp::TypeOf { + if let Expr::Ident(ident) = &*unary.arg { + if ident.sym == js_word!("require") && !self.decls.contains(&id!(ident)) { + return Expr::Lit(Lit::Str(Str { + kind: StrKind::Synthesized, + has_escape: false, + span: unary.span, + value: js_word!("function"), + })); + } + let exports: JsWord = "exports".into(); + if ident.sym == exports && !self.decls.contains(&id!(ident)) { + return Expr::Lit(Lit::Str(Str { + kind: StrKind::Synthesized, + has_escape: false, + span: unary.span, + value: js_word!("object"), + })); + } + + if ident.sym == js_word!("module") && !self.decls.contains(&id!(ident)) { + return Expr::Lit(Lit::Str(Str { + kind: StrKind::Synthesized, + has_escape: false, + span: unary.span, + value: js_word!("object"), + })); + } + } + } + } + node.fold_children_with(self) + } +}