From 9a5d48d80ebc0466481ff87d9451d33e3dbe2d57 Mon Sep 17 00:00:00 2001 From: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com> Date: Fri, 27 May 2022 16:15:05 +0200 Subject: [PATCH] Apply unresolved mark to inserted `undefined` identifiers (#8151) --- .../integration/env-unused-require/index.js | 7 +++++ .../integration/env-unused-require/unused.js | 1 + .../core/integration-tests/test/javascript.js | 22 +++++++++++++ .../js/core/src/decl_collector.rs | 8 ++--- .../js/core/src/dependency_collector.rs | 17 ++++++---- .../transformers/js/core/src/env_replacer.rs | 9 +++--- packages/transformers/js/core/src/fs.rs | 4 +-- .../js/core/src/global_replacer.rs | 4 +-- packages/transformers/js/core/src/hoist.rs | 31 +++++++++++-------- packages/transformers/js/core/src/lib.rs | 15 +++++---- packages/transformers/js/core/src/modules.rs | 10 +++--- .../transformers/js/core/src/node_replacer.rs | 4 +-- .../js/core/src/typeof_replacer.rs | 5 ++- packages/transformers/js/core/src/utils.rs | 29 +++++++---------- 14 files changed, 101 insertions(+), 65 deletions(-) create mode 100644 packages/core/integration-tests/test/integration/env-unused-require/index.js create mode 100644 packages/core/integration-tests/test/integration/env-unused-require/unused.js diff --git a/packages/core/integration-tests/test/integration/env-unused-require/index.js b/packages/core/integration-tests/test/integration/env-unused-require/index.js new file mode 100644 index 00000000000..1c84632ac0c --- /dev/null +++ b/packages/core/integration-tests/test/integration/env-unused-require/index.js @@ -0,0 +1,7 @@ +module.exports = function () { + if(process.env.ABC === 'a') { + return require("./unused.js"); + } else { + return "ok"; + } +}; diff --git a/packages/core/integration-tests/test/integration/env-unused-require/unused.js b/packages/core/integration-tests/test/integration/env-unused-require/unused.js new file mode 100644 index 00000000000..266db37eae0 --- /dev/null +++ b/packages/core/integration-tests/test/integration/env-unused-require/unused.js @@ -0,0 +1 @@ +module.exports = "unused"; diff --git a/packages/core/integration-tests/test/javascript.js b/packages/core/integration-tests/test/javascript.js index 8c0d8e32037..3dfe9405ed0 100644 --- a/packages/core/integration-tests/test/javascript.js +++ b/packages/core/integration-tests/test/javascript.js @@ -347,6 +347,28 @@ describe('javascript', function () { assert(!contents.includes('import')); }); + it('should ignore unused requires after process.env inlining', async function () { + let b = await bundle( + path.join(__dirname, '/integration/env-unused-require/index.js'), + { + env: {ABC: 'XYZ'}, + }, + ); + + assertBundles(b, [ + { + type: 'js', + assets: ['index.js'], + }, + ]); + + let contents = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8'); + assert(!contents.includes('unused')); + + let output = await run(b); + assert.strictEqual(output(), 'ok'); + }); + it('should produce a basic JS bundle with object rest spread support', async function () { let b = await bundle( path.join( diff --git a/packages/transformers/js/core/src/decl_collector.rs b/packages/transformers/js/core/src/decl_collector.rs index 9201f11f78a..8bc321dc249 100644 --- a/packages/transformers/js/core/src/decl_collector.rs +++ b/packages/transformers/js/core/src/decl_collector.rs @@ -1,14 +1,12 @@ use std::collections::HashSet; -use swc_atoms::JsWord; -use swc_common::SyntaxContext; -use swc_ecmascript::ast; +use swc_ecmascript::ast::{self, Id}; use swc_ecmascript::visit::{Visit, VisitWith}; /// This pass collects all declarations in a module into a single HashSet of tuples /// containing identifier names and their associated syntax context (scope). /// This is used later to determine whether an identifier references a declared variable. -pub fn collect_decls(module: &ast::Module) -> HashSet<(JsWord, SyntaxContext)> { +pub fn collect_decls(module: &ast::Module) -> HashSet { let mut c = DeclCollector { decls: HashSet::new(), in_var: false, @@ -18,7 +16,7 @@ pub fn collect_decls(module: &ast::Module) -> HashSet<(JsWord, SyntaxContext)> { } struct DeclCollector { - decls: HashSet<(JsWord, SyntaxContext)>, + decls: HashSet, in_var: bool, } diff --git a/packages/transformers/js/core/src/dependency_collector.rs b/packages/transformers/js/core/src/dependency_collector.rs index b1d83f65650..9f9bd07deea 100644 --- a/packages/transformers/js/core/src/dependency_collector.rs +++ b/packages/transformers/js/core/src/dependency_collector.rs @@ -5,8 +5,8 @@ use std::path::Path; use serde::{Deserialize, Serialize}; use swc_atoms::JsWord; -use swc_common::{Mark, SourceMap, Span, SyntaxContext, DUMMY_SP}; -use swc_ecmascript::ast::{self, Callee, MemberProp}; +use swc_common::{Mark, SourceMap, Span, DUMMY_SP}; +use swc_ecmascript::ast::{self, Callee, Id, MemberProp}; use swc_ecmascript::visit::{Fold, FoldWith}; use crate::fold_member_expr_skip_prop; @@ -59,8 +59,9 @@ pub struct DependencyDescriptor { pub fn dependency_collector<'a>( source_map: &'a SourceMap, items: &'a mut Vec, - decls: &'a HashSet<(JsWord, SyntaxContext)>, + decls: &'a HashSet, ignore_mark: swc_common::Mark, + unresolved_mark: swc_common::Mark, config: &'a Config, diagnostics: &'a mut Vec, ) -> impl Fold + 'a { @@ -72,6 +73,7 @@ pub fn dependency_collector<'a>( require_node: None, decls, ignore_mark, + unresolved_mark, config, diagnostics, import_meta: None, @@ -84,8 +86,9 @@ struct DependencyCollector<'a> { in_try: bool, in_promise: bool, require_node: Option, - decls: &'a HashSet<(JsWord, SyntaxContext)>, + decls: &'a HashSet, ignore_mark: swc_common::Mark, + unresolved_mark: swc_common::Mark, config: &'a Config, diagnostics: &'a mut Vec, import_meta: Option, @@ -828,7 +831,7 @@ impl<'a> Fold for DependencyCollector<'a> { }; if is_require { - return ast::Expr::Ident(ast::Ident::new("undefined".into(), DUMMY_SP)); + return ast::Expr::Ident(get_undefined_ident(self.unresolved_mark)); } node.fold_children_with(self) @@ -1096,7 +1099,7 @@ impl<'a> DependencyCollector<'a> { fn match_new_url( &mut self, expr: &ast::Expr, - decls: &HashSet<(JsWord, SyntaxContext)>, + decls: &HashSet, ) -> Option<(JsWord, swc_common::Span)> { use ast::*; @@ -1139,6 +1142,7 @@ impl<'a> DependencyCollector<'a> { None } + #[allow(clippy::wrong_self_convention)] fn is_import_meta_url(&mut self, expr: &ast::Expr) -> bool { use ast::*; @@ -1175,6 +1179,7 @@ impl<'a> DependencyCollector<'a> { } } + #[allow(clippy::wrong_self_convention)] fn is_import_meta(&mut self, expr: &ast::Expr) -> bool { use ast::*; diff --git a/packages/transformers/js/core/src/env_replacer.rs b/packages/transformers/js/core/src/env_replacer.rs index 421370248ab..78ba22ba49e 100644 --- a/packages/transformers/js/core/src/env_replacer.rs +++ b/packages/transformers/js/core/src/env_replacer.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::vec; use swc_atoms::JsWord; -use swc_common::{SyntaxContext, DUMMY_SP}; +use swc_common::{Mark, DUMMY_SP}; use swc_ecmascript::ast; use swc_ecmascript::visit::{Fold, FoldWith}; @@ -13,10 +13,11 @@ pub struct EnvReplacer<'a> { pub replace_env: bool, pub is_browser: bool, pub env: &'a HashMap, - pub decls: &'a HashSet<(JsWord, SyntaxContext)>, + pub decls: &'a HashSet, pub used_env: &'a mut HashSet, pub source_map: &'a swc_common::SourceMap, pub diagnostics: &'a mut Vec, + pub unresolved_mark: Mark, } impl<'a> Fold for EnvReplacer<'a> { @@ -105,7 +106,7 @@ impl<'a> Fold for EnvReplacer<'a> { right: Box::new(if let Some(init) = &decl.init { *init.clone() } else { - Expr::Ident(Ident::new(js_word!("undefined"), DUMMY_SP)) + Expr::Ident(get_undefined_ident(self.unresolved_mark)) }), })) }) @@ -214,7 +215,7 @@ impl<'a> EnvReplacer<'a> { | "valueOf" => {} _ => { self.used_env.insert(sym.clone()); - return Some(Expr::Ident(Ident::new(js_word!("undefined"), DUMMY_SP))); + return Some(Expr::Ident(get_undefined_ident(self.unresolved_mark))); } }; } diff --git a/packages/transformers/js/core/src/fs.rs b/packages/transformers/js/core/src/fs.rs index 1c8816ba91d..3b97b9ece52 100644 --- a/packages/transformers/js/core/src/fs.rs +++ b/packages/transformers/js/core/src/fs.rs @@ -1,7 +1,7 @@ use crate::dependency_collector::{DependencyDescriptor, DependencyKind}; use crate::hoist::{Collect, Import}; use crate::id; -use crate::utils::{IdentId, SourceLocation}; +use crate::utils::SourceLocation; use data_encoding::{BASE64, HEXLOWER}; use std::collections::HashSet; use std::path::{Path, PathBuf}; @@ -13,7 +13,7 @@ use swc_ecmascript::visit::{Fold, FoldWith, VisitWith}; pub fn inline_fs<'a>( filename: &str, source_map: swc_common::sync::Lrc, - decls: HashSet, + decls: HashSet, global_mark: Mark, project_root: &'a str, deps: &'a mut Vec, diff --git a/packages/transformers/js/core/src/global_replacer.rs b/packages/transformers/js/core/src/global_replacer.rs index f2c5417e5f2..e249e6da2ba 100644 --- a/packages/transformers/js/core/src/global_replacer.rs +++ b/packages/transformers/js/core/src/global_replacer.rs @@ -4,7 +4,7 @@ use std::path::Path; use swc_atoms::JsWord; use swc_common::{Mark, SourceMap, SyntaxContext, DUMMY_SP}; -use swc_ecmascript::ast::{self, ComputedPropName}; +use swc_ecmascript::ast::{self, ComputedPropName, Id}; use swc_ecmascript::visit::{Fold, FoldWith}; use crate::dependency_collector::{DependencyDescriptor, DependencyKind}; @@ -17,7 +17,7 @@ pub struct GlobalReplacer<'a> { pub globals: HashMap, pub project_root: &'a Path, pub filename: &'a Path, - pub decls: &'a mut HashSet<(JsWord, SyntaxContext)>, + pub decls: &'a mut HashSet, pub scope_hoist: bool, } diff --git a/packages/transformers/js/core/src/hoist.rs b/packages/transformers/js/core/src/hoist.rs index af55e1b3e61..a7d7ed65578 100644 --- a/packages/transformers/js/core/src/hoist.rs +++ b/packages/transformers/js/core/src/hoist.rs @@ -1,4 +1,6 @@ -use crate::utils::{match_export_name, match_export_name_ident, match_property_name}; +use crate::utils::{ + get_undefined_ident, match_export_name, match_export_name_ident, match_property_name, +}; use serde::{Deserialize, Serialize}; use std::collections::hash_map::DefaultHasher; use std::collections::{HashMap, HashSet}; @@ -11,7 +13,7 @@ use swc_ecmascript::visit::{Fold, FoldWith, Visit, VisitWith}; use crate::id; use crate::utils::{ match_import, match_member_expr, match_require, Bailout, BailoutReason, CodeHighlight, - Diagnostic, DiagnosticSeverity, IdentId, SourceLocation, + Diagnostic, DiagnosticSeverity, SourceLocation, }; macro_rules! hash { @@ -25,9 +27,10 @@ macro_rules! hash { pub fn hoist( module: Module, module_id: &str, + unresolved_mark: Mark, collect: &Collect, ) -> Result<(Module, HoistResult, Vec), Vec> { - let mut hoist = Hoist::new(module_id, collect); + let mut hoist = Hoist::new(module_id, unresolved_mark, collect); let module = module.fold_with(&mut hoist); if !hoist.diagnostics.is_empty() { @@ -66,6 +69,7 @@ struct Hoist<'a> { dynamic_imports: HashMap, in_function_scope: bool, diagnostics: Vec, + unresolved_mark: Mark, } #[derive(Debug, Default, Serialize, Deserialize)] @@ -83,7 +87,7 @@ pub struct HoistResult { } impl<'a> Hoist<'a> { - fn new(module_id: &'a str, collect: &'a Collect) -> Self { + fn new(module_id: &'a str, unresolved_mark: Mark, collect: &'a Collect) -> Self { Hoist { module_id, collect, @@ -97,6 +101,7 @@ impl<'a> Hoist<'a> { dynamic_imports: HashMap::new(), in_function_scope: false, diagnostics: vec![], + unresolved_mark, } } @@ -672,7 +677,7 @@ impl<'a> Fold for Hoist<'a> { if !self.in_function_scope { // If ESM, replace `this` with `undefined`, otherwise with the CJS exports object. if self.collect.is_esm { - return Expr::Ident(Ident::new("undefined".into(), DUMMY_SP)); + return Expr::Ident(get_undefined_ident(self.unresolved_mark)); } else if !self.collect.should_wrap { self.self_references.insert("*".into()); return Expr::Ident(self.get_export_ident(this.span, &"*".into())); @@ -1097,7 +1102,7 @@ pub struct Export { pub struct Collect { pub source_map: Lrc, - pub decls: HashSet, + pub decls: HashSet, pub ignore_mark: Mark, pub global_mark: Mark, pub static_cjs_exports: bool, @@ -1105,14 +1110,14 @@ pub struct Collect { pub is_esm: bool, pub should_wrap: bool, // local name -> descriptor - pub imports: HashMap, + pub imports: HashMap, // exported name -> descriptor pub exports: HashMap, // local name -> exported name - pub exports_locals: HashMap, + pub exports_locals: HashMap, pub exports_all: HashMap, - pub non_static_access: HashMap>, - pub non_const_bindings: HashMap>, + pub non_static_access: HashMap>, + pub non_const_bindings: HashMap>, pub non_static_requires: HashSet, pub wrapped_requires: HashSet, pub bailouts: Option>, @@ -1156,7 +1161,7 @@ pub struct CollectResult { impl Collect { pub fn new( source_map: Lrc, - decls: HashSet, + decls: HashSet, ignore_mark: Mark, global_mark: Mark, trace_bailouts: bool, @@ -2067,7 +2072,7 @@ impl Collect { } } -fn has_binding_identifier(node: &Pat, sym: &JsWord, decls: &HashSet) -> bool { +fn has_binding_identifier(node: &Pat, sym: &JsWord, decls: &HashSet) -> bool { match node { Pat::Ident(ident) => { if ident.id.sym == *sym && !decls.contains(&id!(ident.id)) { @@ -2155,7 +2160,7 @@ mod tests { module.visit_with(&mut collect); let (module, res) = { - let mut hoist = Hoist::new("abc", &collect); + let mut hoist = Hoist::new("abc", unresolved_mark, &collect); let module = module.fold_with(&mut hoist); (module, hoist.get_result()) }; diff --git a/packages/transformers/js/core/src/lib.rs b/packages/transformers/js/core/src/lib.rs index 0c16aa3cf13..6e4b31979f8 100644 --- a/packages/transformers/js/core/src/lib.rs +++ b/packages/transformers/js/core/src/lib.rs @@ -28,10 +28,11 @@ use std::str::FromStr; use path_slash::PathExt; use serde::{Deserialize, Serialize}; +use swc_atoms::JsWord; use swc_common::comments::SingleThreadedComments; use swc_common::errors::{DiagnosticBuilder, Emitter, Handler}; use swc_common::{chain, sync::Lrc, FileName, Globals, Mark, SourceMap}; -use swc_ecmascript::ast::Module; +use swc_ecmascript::ast::{Ident, Module}; use swc_ecmascript::codegen::text_writer::JsWriter; use swc_ecmascript::parser::lexer::Lexer; use swc_ecmascript::parser::{EsConfig, PResult, Parser, StringInput, Syntax, TsConfig}; @@ -43,7 +44,7 @@ use swc_ecmascript::transforms::{ optimization::simplify::dead_branch_remover, optimization::simplify::expr_simplifier, pass::Optional, proposals::decorators, react, typescript, }; -use swc_ecmascript::visit::{FoldWith, VisitWith}; +use swc_ecmascript::visit::{Fold, FoldWith, VisitWith}; use decl_collector::*; use dependency_collector::*; @@ -310,7 +311,8 @@ pub fn transform(config: Config) -> Result { decls: &decls, used_env: &mut result.used_env, source_map: &source_map, - diagnostics: &mut diagnostics + diagnostics: &mut diagnostics, + unresolved_mark }, config.source_type != SourceType::Script ), @@ -388,7 +390,7 @@ pub fn transform(config: Config) -> Result { module.fold_with(&mut passes) }; - // Flush (JsWord, SyntaxContexts) into unique names and reresolve to + // Flush Id=(JsWord, SyntaxContexts) into unique names and reresolve to // set global_mark for all nodes, even generated ones. // - This changes the syntax context ids and therefore invalidates decls // - This will also remove any other other marks (like ignore_mark) @@ -412,6 +414,7 @@ pub fn transform(config: Config) -> Result { &mut result.dependencies, &decls, ignore_mark, + unresolved_mark, &config, &mut diagnostics, ), @@ -440,7 +443,7 @@ pub fn transform(config: Config) -> Result { } let module = if config.scope_hoist { - let res = hoist(module, config.module_id.as_str(), &collect); + let res = hoist(module, config.module_id.as_str(), unresolved_mark, &collect); match res { Ok((module, hoist_result, hoist_diagnostics)) => { result.hoist_result = Some(hoist_result); @@ -458,7 +461,7 @@ pub fn transform(config: Config) -> Result { result.symbol_result = Some(collect.into()); } - let (module, needs_helpers) = esm2cjs(module, versions); + let (module, needs_helpers) = esm2cjs(module, unresolved_mark, versions); result.needs_esm_helpers = needs_helpers; module }; diff --git a/packages/transformers/js/core/src/modules.rs b/packages/transformers/js/core/src/modules.rs index 27620202b49..ad38d5c783d 100644 --- a/packages/transformers/js/core/src/modules.rs +++ b/packages/transformers/js/core/src/modules.rs @@ -1,5 +1,5 @@ use crate::id; -use crate::utils::{match_export_name, match_export_name_ident, IdentId}; +use crate::utils::{get_undefined_ident, match_export_name, match_export_name_ident}; use inflector::Inflector; use std::collections::{HashMap, HashSet}; use swc_atoms::JsWord; @@ -10,7 +10,7 @@ use swc_ecmascript::visit::{Fold, FoldWith}; use crate::fold_member_expr_skip_prop; -pub fn esm2cjs(node: Module, versions: Option) -> (Module, bool) { +pub fn esm2cjs(node: Module, unresolved_mark: Mark, versions: Option) -> (Module, bool) { let mut fold = ESMFold { imports: HashMap::new(), require_names: HashMap::new(), @@ -21,6 +21,7 @@ pub fn esm2cjs(node: Module, versions: Option) -> (Module, bool) { in_export_decl: false, in_function_scope: false, mark: Mark::fresh(Mark::root()), + unresolved_mark, versions, }; @@ -30,7 +31,7 @@ pub fn esm2cjs(node: Module, versions: Option) -> (Module, bool) { struct ESMFold { // Map of imported identifier to (source, specifier) - imports: HashMap, + imports: HashMap, // Map of source to (require identifier, mark) require_names: HashMap, // Set of declared default interops, by source. @@ -43,6 +44,7 @@ struct ESMFold { in_export_decl: bool, in_function_scope: bool, mark: Mark, + unresolved_mark: Mark, versions: Option, } @@ -590,7 +592,7 @@ impl Fold for ESMFold { } Expr::This(_this) => { if !self.in_function_scope { - Expr::Ident(Ident::new(js_word!("undefined"), DUMMY_SP)) + Expr::Ident(get_undefined_ident(self.unresolved_mark)) } else { node } diff --git a/packages/transformers/js/core/src/node_replacer.rs b/packages/transformers/js/core/src/node_replacer.rs index 4055805f194..6c82d5af913 100644 --- a/packages/transformers/js/core/src/node_replacer.rs +++ b/packages/transformers/js/core/src/node_replacer.rs @@ -4,7 +4,7 @@ use std::path::Path; use swc_atoms::JsWord; use swc_common::{Mark, SourceMap, SyntaxContext, DUMMY_SP}; -use swc_ecmascript::ast::{self}; +use swc_ecmascript::ast::{self, Id}; use swc_ecmascript::visit::{Fold, FoldWith}; use crate::dependency_collector::{DependencyDescriptor, DependencyKind}; @@ -17,7 +17,7 @@ pub struct NodeReplacer<'a> { pub globals: HashMap, pub project_root: &'a Path, pub filename: &'a Path, - pub decls: &'a mut HashSet<(JsWord, SyntaxContext)>, + pub decls: &'a mut HashSet, pub scope_hoist: bool, pub has_node_replacements: &'a mut bool, } diff --git a/packages/transformers/js/core/src/typeof_replacer.rs b/packages/transformers/js/core/src/typeof_replacer.rs index b3ac418cb49..75c11840640 100644 --- a/packages/transformers/js/core/src/typeof_replacer.rs +++ b/packages/transformers/js/core/src/typeof_replacer.rs @@ -1,14 +1,13 @@ use std::collections::HashSet; use swc_atoms::js_word; -use swc_ecmascript::ast::{Expr, Lit, Str, UnaryOp}; +use swc_ecmascript::ast::{Expr, Id, Lit, Str, UnaryOp}; use swc_ecmascript::visit::{Fold, FoldWith}; use crate::id; -use crate::utils::IdentId; pub struct TypeofReplacer<'a> { - pub decls: &'a HashSet, + pub decls: &'a HashSet, } impl<'a> Fold for TypeofReplacer<'a> { diff --git a/packages/transformers/js/core/src/utils.rs b/packages/transformers/js/core/src/utils.rs index 8d65d20f3e9..4827a2db502 100644 --- a/packages/transformers/js/core/src/utils.rs +++ b/packages/transformers/js/core/src/utils.rs @@ -1,16 +1,13 @@ use std::cmp::Ordering; use std::collections::HashSet; +use crate::id; use serde::{Deserialize, Serialize}; use swc_atoms::JsWord; use swc_common::{Mark, Span, SyntaxContext, DUMMY_SP}; -use swc_ecmascript::ast; +use swc_ecmascript::ast::{self, Id}; -pub fn match_member_expr( - expr: &ast::MemberExpr, - idents: Vec<&str>, - decls: &HashSet<(JsWord, SyntaxContext)>, -) -> bool { +pub fn match_member_expr(expr: &ast::MemberExpr, idents: Vec<&str>, decls: &HashSet) -> bool { use ast::{Expr, Ident, Lit, MemberProp, Str}; let mut member = expr; @@ -35,10 +32,8 @@ pub fn match_member_expr( match &*member.obj { Expr::Member(m) => member = m, - Expr::Ident(Ident { ref sym, span, .. }) => { - return idents.len() == 1 - && sym == idents.pop().unwrap() - && !decls.contains(&(sym.clone(), span.ctxt())); + Expr::Ident(id) => { + return idents.len() == 1 && &id.sym == idents.pop().unwrap() && !decls.contains(&id!(id)); } _ => return false, } @@ -119,11 +114,7 @@ pub fn match_export_name_ident(name: &ast::ModuleExportName) -> &ast::Ident { } } -pub fn match_require( - node: &ast::Expr, - decls: &HashSet<(JsWord, SyntaxContext)>, - ignore_mark: Mark, -) -> Option { +pub fn match_require(node: &ast::Expr, decls: &HashSet, ignore_mark: Mark) -> Option { use ast::*; match node { @@ -201,6 +192,10 @@ pub fn create_global_decl_stmt( ) } +pub fn get_undefined_ident(unresolved_mark: Mark) -> ast::Ident { + ast::Ident::new(js_word!("undefined"), DUMMY_SP.apply_mark(unresolved_mark)) +} + #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] pub struct SourceLocation { pub start_line: usize, @@ -385,8 +380,6 @@ macro_rules! fold_member_expr_skip_prop { #[macro_export] macro_rules! id { ($ident: expr) => { - ($ident.sym.clone(), $ident.span.ctxt) + $ident.to_id() }; } - -pub type IdentId = (JsWord, SyntaxContext);