From eaac5dad73d9c63eeb72b7a48cbb36a1b28b2d3d Mon Sep 17 00:00:00 2001 From: DongYun Kang Date: Mon, 4 May 2026 12:20:51 +0900 Subject: [PATCH] feat(ecma): add node and scope ids --- crates/swc/src/lib.rs | 2 + crates/swc_bundler/src/bundler/chunk/cjs.rs | 1 + crates/swc_bundler/src/bundler/finalize.rs | 1 + crates/swc_bundler/src/modules/mod.rs | 2 + crates/swc_bundler/src/modules/sort/mod.rs | 1 + crates/swc_bundler/src/modules/sort/stmt.rs | 2 + crates/swc_bundler/src/modules/sort/tests.rs | 1 + crates/swc_ecma_ast/src/class.rs | 8 +- crates/swc_ecma_ast/src/expr.rs | 5 +- crates/swc_ecma_ast/src/function.rs | 4 + crates/swc_ecma_ast/src/ident.rs | 18 +- crates/swc_ecma_ast/src/lib.rs | 259 +++++--- crates/swc_ecma_ast/src/module.rs | 12 +- crates/swc_ecma_ast/src/stmt.rs | 16 +- crates/swc_ecma_ast/tests/node_id.rs | 36 + .../src/block_scoping/mod.rs | 1 + .../src/destructuring.rs | 8 +- crates/swc_ecma_compat_es2015/src/for_of.rs | 4 + .../swc_ecma_compat_es2015/src/generator.rs | 3 + .../swc_ecma_compat_es2015/src/parameters.rs | 1 + crates/swc_ecma_hooks/src/generated.rs | 116 ++++ .../src/common/parser/class_and_fn.rs | 1 + .../swc_ecma_lexer/src/common/parser/stmt.rs | 6 + crates/swc_ecma_lexer/src/parser/mod.rs | 6 + .../src/compress/optimize/iife.rs | 1 + .../src/compress/optimize/mod.rs | 1 + .../src/compress/pure/loops.rs | 2 + .../tests/libs-size.snapshot.md | 4 +- .../src/parser/class_and_fn.rs | 1 + crates/swc_ecma_parser/src/parser/mod.rs | 6 + crates/swc_ecma_parser/src/parser/stmt.rs | 14 + .../swc_ecma_parser/src/parser/typescript.rs | 3 + crates/swc_ecma_quote_macros/src/ast/class.rs | 12 +- crates/swc_ecma_quote_macros/src/ast/expr.rs | 2 + crates/swc_ecma_quote_macros/src/ast/mod.rs | 16 +- crates/swc_ecma_quote_macros/src/ast/stmt.rs | 12 +- .../src/es2016/exponentiation_operator.rs | 1 + .../src/es2017/async_to_generator.rs | 2 + .../src/es2022/class_static_block.rs | 2 + .../src/es2022/private_property_in_object.rs | 1 + .../src/hygiene/tests.rs | 1 + .../src/resolver/mod.rs | 381 ++++++++--- .../src/resolver/tests.rs | 56 +- .../swc_ecma_transforms_base/tests/node_id.rs | 110 ++++ .../src/system_js.rs | 1 + crates/swc_ecma_transforms_module/src/util.rs | 1 + .../src/simplify/branch/mod.rs | 26 +- .../src/explicit_resource_management.rs | 1 + crates/swc_ecma_visit/src/generated.rs | 620 +++++++++++++++++- crates/swc_estree_compat/src/swcify/expr.rs | 1 + crates/swc_estree_compat/src/swcify/stmt.rs | 5 + crates/swc_node_bundler/src/loaders/json.rs | 1 + crates/swc_node_bundler/src/loaders/swc.rs | 1 + crates/swc_typescript/src/fast_dts/enum.rs | 1 + packages/types/index.ts | 31 + tools/generate-code/src/main.rs | 4 + 56 files changed, 1614 insertions(+), 221 deletions(-) create mode 100644 crates/swc_ecma_ast/tests/node_id.rs create mode 100644 crates/swc_ecma_transforms_base/tests/node_id.rs diff --git a/crates/swc/src/lib.rs b/crates/swc/src/lib.rs index 8b5c9c0e4cb6..011dc91a5552 100644 --- a/crates/swc/src/lib.rs +++ b/crates/swc/src/lib.rs @@ -294,6 +294,7 @@ fn downgrade_flow_script_like_module(program: Program) -> Result } let Module { + node_id, span, body, shebang, @@ -311,6 +312,7 @@ fn downgrade_flow_script_like_module(program: Program) -> Result .collect::>()?; Ok(Program::Script(Script { + node_id, span, body, shebang, diff --git a/crates/swc_bundler/src/bundler/chunk/cjs.rs b/crates/swc_bundler/src/bundler/chunk/cjs.rs index 428812e6263f..b70093e0d77e 100644 --- a/crates/swc_bundler/src/bundler/chunk/cjs.rs +++ b/crates/swc_bundler/src/bundler/chunk/cjs.rs @@ -80,6 +80,7 @@ where info.id, Module { span: DUMMY_SP, + node_id: Default::default(), body: vec![stmt], shebang: None, }, diff --git a/crates/swc_bundler/src/bundler/finalize.rs b/crates/swc_bundler/src/bundler/finalize.rs index fd6ce8e3cb78..4ce442304396 100644 --- a/crates/swc_bundler/src/bundler/finalize.rs +++ b/crates/swc_bundler/src/bundler/finalize.rs @@ -385,6 +385,7 @@ where Module { span: DUMMY_SP, + node_id: Default::default(), shebang: None, body: vec![ModuleItem::Stmt(Stmt::Expr(ExprStmt { span: DUMMY_SP, diff --git a/crates/swc_bundler/src/modules/mod.rs b/crates/swc_bundler/src/modules/mod.rs index 3084d25d43b6..f4cba3b1e653 100644 --- a/crates/swc_bundler/src/modules/mod.rs +++ b/crates/swc_bundler/src/modules/mod.rs @@ -292,6 +292,7 @@ impl Modules { cm, &Module { span: DUMMY_SP, + node_id: Default::default(), body: stmts, shebang: None, }, @@ -304,6 +305,7 @@ impl From for Module { // TODO Self { span: DUMMY_SP, + node_id: Default::default(), body: modules.into_items(), shebang: None, } diff --git a/crates/swc_bundler/src/modules/sort/mod.rs b/crates/swc_bundler/src/modules/sort/mod.rs index 5efc9b9a0658..b35a1f563bd1 100644 --- a/crates/swc_bundler/src/modules/sort/mod.rs +++ b/crates/swc_bundler/src/modules/sort/mod.rs @@ -45,6 +45,7 @@ impl Modules { let module = Module { span: DUMMY_SP, + node_id: Default::default(), body: buf, shebang: None, }; diff --git a/crates/swc_bundler/src/modules/sort/stmt.rs b/crates/swc_bundler/src/modules/sort/stmt.rs index f3b7366ab667..e296d5b61982 100644 --- a/crates/swc_bundler/src/modules/sort/stmt.rs +++ b/crates/swc_bundler/src/modules/sort/stmt.rs @@ -841,6 +841,7 @@ mod tests { "first item", &t.cm, &Module { + node_id: Default::default(), span: DUMMY_SP, body: vec![module.body[dep].clone()], shebang: None, @@ -850,6 +851,7 @@ mod tests { "second item", &t.cm, &Module { + node_id: Default::default(), span: DUMMY_SP, body: vec![module.body[i].clone()], shebang: None, diff --git a/crates/swc_bundler/src/modules/sort/tests.rs b/crates/swc_bundler/src/modules/sort/tests.rs index 206b3ffb42a6..9ac067881ed5 100644 --- a/crates/swc_bundler/src/modules/sort/tests.rs +++ b/crates/swc_bundler/src/modules/sort/tests.rs @@ -37,6 +37,7 @@ fn assert_sorted_with_free(src: &[&str], free: &str, res: &str) { let sorted = sort_stmts(t.bundler.injected_ctxt, modules, &t.cm); let actual: Module = drop_span(Module { + node_id: Default::default(), span: DUMMY_SP, body: sorted, shebang: None, diff --git a/crates/swc_ecma_ast/src/class.rs b/crates/swc_ecma_ast/src/class.rs index b3591a11ed43..6f42bc4e0908 100644 --- a/crates/swc_ecma_ast/src/class.rs +++ b/crates/swc_ecma_ast/src/class.rs @@ -11,7 +11,7 @@ use crate::{ Accessibility, TsExprWithTypeArgs, TsIndexSignature, TsTypeAnn, TsTypeParamDecl, TsTypeParamInstantiation, }, - BigInt, ComputedPropName, EmptyStmt, Id, Ident, IdentName, Number, + BigInt, ComputedPropName, EmptyStmt, Id, Ident, IdentName, NodeId, Number, }; #[ast_node] @@ -23,6 +23,9 @@ pub struct Class { pub ctxt: SyntaxContext, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, + #[cfg_attr(feature = "serde-impl", serde(default))] pub decorators: Vec, @@ -280,6 +283,9 @@ pub struct Constructor { pub ctxt: SyntaxContext, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, + pub key: PropName, pub params: Vec, diff --git a/crates/swc_ecma_ast/src/expr.rs b/crates/swc_ecma_ast/src/expr.rs index 56ff932ef7cf..06aeed448d31 100644 --- a/crates/swc_ecma_ast/src/expr.rs +++ b/crates/swc_ecma_ast/src/expr.rs @@ -23,7 +23,7 @@ use crate::{ TsTypeAssertion, TsTypeParamDecl, TsTypeParamInstantiation, }, ArrayPat, BindingIdent, ComputedPropName, Id, IdentName, ImportPhase, Invalid, KeyValueProp, - Number, ObjectPat, PropName, Str, + NodeId, Number, ObjectPat, PropName, Str, }; #[ast_node(no_clone)] @@ -1081,6 +1081,9 @@ pub struct ArrowExpr { pub ctxt: SyntaxContext, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, + pub params: Vec, /// This is boxed to reduce the type size of [Expr]. diff --git a/crates/swc_ecma_ast/src/function.rs b/crates/swc_ecma_ast/src/function.rs index 3d0747b3a00b..9b7622ab937e 100644 --- a/crates/swc_ecma_ast/src/function.rs +++ b/crates/swc_ecma_ast/src/function.rs @@ -6,6 +6,7 @@ use crate::{ pat::Pat, stmt::BlockStmt, typescript::{TsParamProp, TsTypeAnn, TsTypeParamDecl}, + NodeId, }; /// Common parts of function and method. @@ -23,6 +24,9 @@ pub struct Function { pub ctxt: SyntaxContext, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, + #[cfg_attr(feature = "serde-impl", serde(default))] #[cfg_attr( feature = "encoding-impl", diff --git a/crates/swc_ecma_ast/src/ident.rs b/crates/swc_ecma_ast/src/ident.rs index 38a68175f0a4..ed8e6915cb8d 100644 --- a/crates/swc_ecma_ast/src/ident.rs +++ b/crates/swc_ecma_ast/src/ident.rs @@ -12,7 +12,7 @@ use swc_common::{ ast_node, util::take::Take, BytePos, EqIgnoreSpan, Mark, Span, Spanned, SyntaxContext, DUMMY_SP, }; -use crate::{typescript::TsTypeAnn, Expr}; +use crate::{typescript::TsTypeAnn, BindingId, Expr, ScopeId}; /// Identifier used as a pattern. #[derive(Clone, Debug, PartialEq, Eq, Hash, EqIgnoreSpan, Default)] @@ -97,6 +97,7 @@ impl From<&'_ BindingIdent> for Ident { Ident { span: bi.span, ctxt: bi.ctxt, + scope_id: bi.scope_id, sym: bi.sym.clone(), optional: bi.optional, } @@ -185,8 +186,13 @@ pub struct Ident { pub span: Span, #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] + #[cfg_attr(feature = "serde-impl", serde(default))] pub ctxt: SyntaxContext, + #[cfg_attr(feature = "serde-impl", serde(default))] + #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] + pub scope_id: ScopeId, + #[cfg_attr(feature = "serde-impl", serde(rename = "value"))] pub sym: Atom, @@ -269,6 +275,14 @@ impl Ident { (self.sym.clone(), self.ctxt) } + /// Creates an id using the resolver-assigned scope id of `self`. + pub fn to_binding_id(&self) -> BindingId { + BindingId { + sym: self.sym.clone(), + scope_id: self.scope_id, + } + } + #[inline] pub fn is_valid_ascii_start(c: u8) -> bool { debug_assert!(c.is_ascii()); @@ -573,6 +587,7 @@ impl<'a> arbitrary::Arbitrary<'a> for Ident { sym, optional, ctxt: Default::default(), + scope_id: Default::default(), }) } } @@ -598,6 +613,7 @@ impl Ident { Ident { span, ctxt, + scope_id: ScopeId::INVALID, sym, optional: false, } diff --git a/crates/swc_ecma_ast/src/lib.rs b/crates/swc_ecma_ast/src/lib.rs index faed62d44fd3..77a78842b11f 100644 --- a/crates/swc_ecma_ast/src/lib.rs +++ b/crates/swc_ecma_ast/src/lib.rs @@ -12,6 +12,7 @@ pub use num_bigint::BigInt as BigIntValue; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use swc_atoms::Atom; use swc_common::{ast_node, pass::Either, util::take::Take, EqIgnoreSpan, Span}; pub use self::{ @@ -74,6 +75,112 @@ pub use self::{ }, }; +/// A stable identifier assigned to AST nodes by analysis passes. +/// +/// `0` means the node has not been assigned an id yet. Parsers and AST +/// builders should leave this as the default value; passes that need node +/// identity are responsible for assigning deterministic ids. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, EqIgnoreSpan)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[cfg_attr( + any(feature = "rkyv-impl"), + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) +)] +#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] +#[cfg_attr(feature = "rkyv-impl", repr(C))] +#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde-impl", serde(transparent))] +#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] +#[cfg_attr( + feature = "encoding-impl", + derive(::swc_common::Encode, ::swc_common::Decode) +)] +pub struct NodeId(pub u32); + +impl NodeId { + pub const INVALID: Self = Self(0); + + #[inline] + pub const fn as_u32(self) -> u32 { + self.0 + } + + #[inline] + pub const fn is_invalid(self) -> bool { + self.0 == Self::INVALID.0 + } +} + +/// A stable identifier for lexical/function scopes. +/// +/// `0` means unassigned, while [`ScopeId::UNRESOLVED`] is used for references +/// that do not resolve to a binding in the current AST. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, EqIgnoreSpan)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[cfg_attr( + any(feature = "rkyv-impl"), + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) +)] +#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] +#[cfg_attr(feature = "rkyv-impl", repr(C))] +#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde-impl", serde(transparent))] +#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] +#[cfg_attr( + feature = "encoding-impl", + derive(::swc_common::Encode, ::swc_common::Decode) +)] +pub struct ScopeId(pub u32); + +impl ScopeId { + pub const INVALID: Self = Self(0); + pub const UNRESOLVED: Self = Self(u32::MAX); + + #[inline] + pub const fn from_node_id(node_id: NodeId) -> Self { + Self(node_id.0) + } + + #[inline] + pub const fn as_node_id(self) -> NodeId { + NodeId(self.0) + } + + #[inline] + pub const fn as_u32(self) -> u32 { + self.0 + } + + #[inline] + pub const fn is_invalid(self) -> bool { + self.0 == Self::INVALID.0 + } + + #[inline] + pub const fn is_unresolved(self) -> bool { + self.0 == Self::UNRESOLVED.0 + } +} + +/// Identifier key based on the resolver-assigned scope id. +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, EqIgnoreSpan)] +#[cfg_attr( + any(feature = "rkyv-impl"), + derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) +)] +#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] +#[cfg_attr(feature = "rkyv-impl", repr(C))] +#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] +#[cfg_attr( + feature = "encoding-impl", + derive(::swc_common::Encode, ::swc_common::Decode) +)] +pub struct BindingId { + pub sym: Atom, + pub scope_id: ScopeId, +} + #[macro_use] mod macros; mod class; @@ -508,14 +615,14 @@ mod rkyv_layout_assert { }; } - assert_size!(ArchivedProgram, 32); - assert_size!(ArchivedModule, 28); - assert_size!(ArchivedScript, 28); - assert_size!(ArchivedModuleItem, 52); + assert_size!(ArchivedProgram, 36); + assert_size!(ArchivedModule, 32); + assert_size!(ArchivedScript, 32); + assert_size!(ArchivedModuleItem, 56); // Class types assert_size!(ArchivedAutoAccessor, 96); - assert_size!(ArchivedClass, 64); + assert_size!(ArchivedClass, 68); assert_size!(ArchivedClassMember, 104); assert_size!(ArchivedClassMethod, 64); assert_size!(ArchivedClassProp, 88); @@ -525,32 +632,32 @@ mod rkyv_layout_assert { assert_size!(ArchivedMethodKind, 1); assert_size!(ArchivedPrivateMethod, 36); assert_size!(ArchivedPrivateProp, 64); - assert_size!(ArchivedStaticBlock, 28); + assert_size!(ArchivedStaticBlock, 32); // Declaration types - assert_size!(ArchivedClassDecl, 32); - assert_size!(ArchivedDecl, 36); - assert_size!(ArchivedFnDecl, 32); + assert_size!(ArchivedClassDecl, 36); + assert_size!(ArchivedDecl, 40); + assert_size!(ArchivedFnDecl, 36); assert_size!(ArchivedUsingDecl, 20); assert_size!(ArchivedVarDecl, 24); assert_size!(ArchivedVarDeclKind, 1); - assert_size!(ArchivedVarDeclarator, 56); + assert_size!(ArchivedVarDeclarator, 60); // Expression types assert_size!(ArchivedArrayLit, 16); - assert_size!(ArchivedArrowExpr, 44); + assert_size!(ArchivedArrowExpr, 48); assert_size!(ArchivedAssignExpr, 60); assert_size!(ArchivedAssignTarget, 44); assert_size!(ArchivedAwaitExpr, 12); assert_size!(ArchivedBinExpr, 20); - assert_size!(ArchivedBlockStmtOrExpr, 24); + assert_size!(ArchivedBlockStmtOrExpr, 28); assert_size!(ArchivedCallExpr, 44); assert_size!(ArchivedCallee, 16); - assert_size!(ArchivedClassExpr, 32); + assert_size!(ArchivedClassExpr, 36); assert_size!(ArchivedCondExpr, 20); assert_size!(ArchivedExpr, 64); assert_size!(ArchivedExprOrSpread, 16); - assert_size!(ArchivedFnExpr, 32); + assert_size!(ArchivedFnExpr, 36); assert_size!(ArchivedImport, 12); assert_size!(ArchivedMemberExpr, 32); assert_size!(ArchivedMemberProp, 20); @@ -577,13 +684,13 @@ mod rkyv_layout_assert { assert_size!(ArchivedYieldExpr, 20); // Function types - assert_size!(ArchivedFunction, 72); - assert_size!(ArchivedParam, 52); - assert_size!(ArchivedParamOrTsParamProp, 60); + assert_size!(ArchivedFunction, 80); + assert_size!(ArchivedParam, 56); + assert_size!(ArchivedParamOrTsParamProp, 64); // Identifier types - assert_size!(ArchivedBindingIdent, 32); - assert_size!(ArchivedIdent, 24); + assert_size!(ArchivedBindingIdent, 36); + assert_size!(ArchivedIdent, 28); assert_size!(ArchivedIdentName, 16); assert_size!(ArchivedPrivateName, 16); @@ -592,19 +699,19 @@ mod rkyv_layout_assert { assert_size!(ArchivedJSXAttrName, 44); assert_size!(ArchivedJSXAttrOrSpread, 96); assert_size!(ArchivedJSXAttrValue, 36); - assert_size!(ArchivedJSXClosingElement, 64); + assert_size!(ArchivedJSXClosingElement, 68); assert_size!(ArchivedJSXClosingFragment, 8); - assert_size!(ArchivedJSXElement, 168); + assert_size!(ArchivedJSXElement, 176); assert_size!(ArchivedJSXElementChild, 36); - assert_size!(ArchivedJSXElementName, 56); + assert_size!(ArchivedJSXElementName, 60); assert_size!(ArchivedJSXEmptyExpr, 8); assert_size!(ArchivedJSXExpr, 12); assert_size!(ArchivedJSXExprContainer, 20); assert_size!(ArchivedJSXFragment, 32); - assert_size!(ArchivedJSXMemberExpr, 52); + assert_size!(ArchivedJSXMemberExpr, 56); assert_size!(ArchivedJSXNamespacedName, 40); - assert_size!(ArchivedJSXObject, 28); - assert_size!(ArchivedJSXOpeningElement, 84); + assert_size!(ArchivedJSXObject, 32); + assert_size!(ArchivedJSXOpeningElement, 88); assert_size!(ArchivedJSXOpeningFragment, 8); assert_size!(ArchivedJSXSpreadChild, 12); assert_size!(ArchivedJSXText, 24); @@ -619,21 +726,21 @@ mod rkyv_layout_assert { assert_size!(ArchivedStr, 28); // Module declaration types - assert_size!(ArchivedDefaultDecl, 36); + assert_size!(ArchivedDefaultDecl, 40); assert_size!(ArchivedExportAll, 24); - assert_size!(ArchivedExportDecl, 44); - assert_size!(ArchivedExportDefaultDecl, 44); + assert_size!(ArchivedExportDecl, 48); + assert_size!(ArchivedExportDefaultDecl, 48); assert_size!(ArchivedExportDefaultExpr, 12); - assert_size!(ArchivedExportDefaultSpecifier, 24); + assert_size!(ArchivedExportDefaultSpecifier, 28); assert_size!(ArchivedExportNamedSpecifier, 80); assert_size!(ArchivedExportNamespaceSpecifier, 40); assert_size!(ArchivedExportSpecifier, 84); assert_size!(ArchivedImportDecl, 36); - assert_size!(ArchivedImportDefaultSpecifier, 32); - assert_size!(ArchivedImportNamedSpecifier, 72); - assert_size!(ArchivedImportSpecifier, 76); - assert_size!(ArchivedImportStarAsSpecifier, 32); - assert_size!(ArchivedModuleDecl, 48); + assert_size!(ArchivedImportDefaultSpecifier, 36); + assert_size!(ArchivedImportNamedSpecifier, 76); + assert_size!(ArchivedImportSpecifier, 80); + assert_size!(ArchivedImportStarAsSpecifier, 36); + assert_size!(ArchivedModuleDecl, 52); assert_size!(ArchivedModuleExportName, 32); assert_size!(ArchivedNamedExport, 36); @@ -646,44 +753,44 @@ mod rkyv_layout_assert { // Pattern types assert_size!(ArchivedArrayPat, 28); assert_size!(ArchivedAssignPat, 16); - assert_size!(ArchivedAssignPatProp, 48); + assert_size!(ArchivedAssignPatProp, 52); assert_size!(ArchivedKeyValuePatProp, 48); assert_size!(ArchivedObjectPat, 28); assert_size!(ArchivedObjectPatProp, 56); - assert_size!(ArchivedPat, 36); + assert_size!(ArchivedPat, 40); assert_size!(ArchivedRestPat, 28); // Property types - assert_size!(ArchivedAssignProp, 36); + assert_size!(ArchivedAssignProp, 40); assert_size!(ArchivedComputedPropName, 12); - assert_size!(ArchivedGetterProp, 80); + assert_size!(ArchivedGetterProp, 88); assert_size!(ArchivedKeyValueProp, 48); assert_size!(ArchivedMethodProp, 48); - assert_size!(ArchivedProp, 128); + assert_size!(ArchivedProp, 136); assert_size!(ArchivedPropName, 40); - assert_size!(ArchivedSetterProp, 120); + assert_size!(ArchivedSetterProp, 128); // Statement types - assert_size!(ArchivedBlockStmt, 20); - assert_size!(ArchivedBreakStmt, 36); - assert_size!(ArchivedCatchClause, 68); - assert_size!(ArchivedContinueStmt, 36); + assert_size!(ArchivedBlockStmt, 24); + assert_size!(ArchivedBreakStmt, 40); + assert_size!(ArchivedCatchClause, 80); + assert_size!(ArchivedContinueStmt, 40); assert_size!(ArchivedDebuggerStmt, 8); assert_size!(ArchivedDoWhileStmt, 16); assert_size!(ArchivedEmptyStmt, 8); assert_size!(ArchivedExprStmt, 12); assert_size!(ArchivedForHead, 8); - assert_size!(ArchivedForInStmt, 24); - assert_size!(ArchivedForOfStmt, 28); - assert_size!(ArchivedForStmt, 40); + assert_size!(ArchivedForInStmt, 28); + assert_size!(ArchivedForOfStmt, 32); + assert_size!(ArchivedForStmt, 44); assert_size!(ArchivedIfStmt, 24); - assert_size!(ArchivedLabeledStmt, 36); + assert_size!(ArchivedLabeledStmt, 40); assert_size!(ArchivedReturnStmt, 16); - assert_size!(ArchivedStmt, 44); + assert_size!(ArchivedStmt, 48); assert_size!(ArchivedSwitchCase, 24); - assert_size!(ArchivedSwitchStmt, 20); + assert_size!(ArchivedSwitchStmt, 24); assert_size!(ArchivedThrowStmt, 12); - assert_size!(ArchivedTryStmt, 124); + assert_size!(ArchivedTryStmt, 144); assert_size!(ArchivedVarDeclOrExpr, 8); assert_size!(ArchivedWhileStmt, 16); assert_size!(ArchivedWithStmt, 16); @@ -698,69 +805,69 @@ mod rkyv_layout_assert { assert_size!(ArchivedTsConstAssertion, 12); assert_size!(ArchivedTsConstructSignatureDecl, 32); assert_size!(ArchivedTsConstructorType, 32); - assert_size!(ArchivedTsEntityName, 28); - assert_size!(ArchivedTsEnumDecl, 44); + assert_size!(ArchivedTsEntityName, 32); + assert_size!(ArchivedTsEnumDecl, 48); assert_size!(ArchivedTsEnumMember, 48); assert_size!(ArchivedTsEnumMemberId, 32); assert_size!(ArchivedTsExportAssignment, 12); assert_size!(ArchivedTsExprWithTypeArgs, 20); assert_size!(ArchivedTsExternalModuleRef, 36); assert_size!(ArchivedTsFnOrConstructorType, 36); - assert_size!(ArchivedTsFnParam, 36); + assert_size!(ArchivedTsFnParam, 40); assert_size!(ArchivedTsFnType, 28); assert_size!(ArchivedTsGetterSignature, 24); - assert_size!(ArchivedTsImportEqualsDecl, 76); - assert_size!(ArchivedTsImportType, 92); + assert_size!(ArchivedTsImportEqualsDecl, 80); + assert_size!(ArchivedTsImportType, 96); assert_size!(ArchivedTsIndexSignature, 28); assert_size!(ArchivedTsIndexedAccessType, 20); - assert_size!(ArchivedTsInferType, 60); + assert_size!(ArchivedTsInferType, 64); assert_size!(ArchivedTsInstantiation, 16); assert_size!(ArchivedTsInterfaceBody, 16); - assert_size!(ArchivedTsInterfaceDecl, 68); + assert_size!(ArchivedTsInterfaceDecl, 72); assert_size!(ArchivedTsIntersectionType, 16); assert_size!(ArchivedTsKeywordType, 12); assert_size!(ArchivedTsKeywordTypeKind, 1); assert_size!(ArchivedTsLit, 40); assert_size!(ArchivedTsLitType, 48); - assert_size!(ArchivedTsMappedType, 84); + assert_size!(ArchivedTsMappedType, 88); assert_size!(ArchivedTsMethodSignature, 40); assert_size!(ArchivedTsModuleBlock, 16); - assert_size!(ArchivedTsModuleDecl, 92); + assert_size!(ArchivedTsModuleDecl, 96); assert_size!(ArchivedTsModuleName, 32); assert_size!(ArchivedTsModuleRef, 40); - assert_size!(ArchivedTsNamespaceBody, 44); - assert_size!(ArchivedTsNamespaceDecl, 40); - assert_size!(ArchivedTsNamespaceExportDecl, 32); + assert_size!(ArchivedTsNamespaceBody, 48); + assert_size!(ArchivedTsNamespaceDecl, 44); + assert_size!(ArchivedTsNamespaceExportDecl, 36); assert_size!(ArchivedTsNonNullExpr, 12); assert_size!(ArchivedTsOptionalType, 12); - assert_size!(ArchivedTsParamProp, 56); - assert_size!(ArchivedTsParamPropParam, 36); + assert_size!(ArchivedTsParamProp, 60); + assert_size!(ArchivedTsParamPropParam, 40); assert_size!(ArchivedTsParenthesizedType, 12); assert_size!(ArchivedTsPropertySignature, 28); - assert_size!(ArchivedTsQualifiedName, 52); + assert_size!(ArchivedTsQualifiedName, 56); assert_size!(ArchivedTsRestType, 12); assert_size!(ArchivedTsSatisfiesExpr, 16); - assert_size!(ArchivedTsSetterSignature, 52); + assert_size!(ArchivedTsSetterSignature, 56); assert_size!(ArchivedTsThisType, 8); - assert_size!(ArchivedTsThisTypeOrIdent, 28); + assert_size!(ArchivedTsThisTypeOrIdent, 32); assert_size!(ArchivedTsTplLitType, 24); - assert_size!(ArchivedTsTupleElement, 52); + assert_size!(ArchivedTsTupleElement, 56); assert_size!(ArchivedTsTupleType, 16); assert_size!(ArchivedTsType, 120); - assert_size!(ArchivedTsTypeAliasDecl, 48); + assert_size!(ArchivedTsTypeAliasDecl, 52); assert_size!(ArchivedTsTypeAnn, 12); assert_size!(ArchivedTsTypeAssertion, 16); - assert_size!(ArchivedTsTypeElement, 56); + assert_size!(ArchivedTsTypeElement, 60); assert_size!(ArchivedTsTypeLit, 16); assert_size!(ArchivedTsTypeOperator, 16); assert_size!(ArchivedTsTypeOperatorOp, 1); - assert_size!(ArchivedTsTypeParam, 52); + assert_size!(ArchivedTsTypeParam, 56); assert_size!(ArchivedTsTypeParamDecl, 16); assert_size!(ArchivedTsTypeParamInstantiation, 16); - assert_size!(ArchivedTsTypePredicate, 48); - assert_size!(ArchivedTsTypeQuery, 112); - assert_size!(ArchivedTsTypeQueryExpr, 96); - assert_size!(ArchivedTsTypeRef, 44); + assert_size!(ArchivedTsTypePredicate, 52); + assert_size!(ArchivedTsTypeQuery, 116); + assert_size!(ArchivedTsTypeQueryExpr, 100); + assert_size!(ArchivedTsTypeRef, 48); assert_size!(ArchivedTsUnionOrIntersectionType, 20); assert_size!(ArchivedTsUnionType, 16); } diff --git a/crates/swc_ecma_ast/src/module.rs b/crates/swc_ecma_ast/src/module.rs index 339f4c45f72f..4d1f26b9f00b 100644 --- a/crates/swc_ecma_ast/src/module.rs +++ b/crates/swc_ecma_ast/src/module.rs @@ -2,7 +2,7 @@ use is_macro::Is; use swc_atoms::Atom; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; -use crate::{module_decl::ModuleDecl, stmt::Stmt}; +use crate::{module_decl::ModuleDecl, stmt::Stmt, NodeId}; #[ast_node] #[derive(Eq, Hash, Is, EqIgnoreSpan)] @@ -27,6 +27,9 @@ impl Take for Program { pub struct Module { pub span: Span, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, + pub body: Vec, #[cfg_attr(feature = "serde-impl", serde(default, rename = "interpreter"))] @@ -45,6 +48,7 @@ impl<'a> arbitrary::Arbitrary<'a> for Module { let body = u.arbitrary()?; Ok(Self { span, + node_id: Default::default(), body, shebang: None, }) @@ -55,6 +59,7 @@ impl Take for Module { fn dummy() -> Self { Module { span: DUMMY_SP, + node_id: Default::default(), body: Take::dummy(), shebang: Take::dummy(), } @@ -67,6 +72,9 @@ impl Take for Module { pub struct Script { pub span: Span, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, + pub body: Vec, #[cfg_attr(feature = "serde-impl", serde(default, rename = "interpreter"))] @@ -85,6 +93,7 @@ impl<'a> arbitrary::Arbitrary<'a> for Script { let body = u.arbitrary()?; Ok(Self { span, + node_id: Default::default(), body, shebang: None, }) @@ -95,6 +104,7 @@ impl Take for Script { fn dummy() -> Self { Script { span: DUMMY_SP, + node_id: Default::default(), body: Take::dummy(), shebang: Take::dummy(), } diff --git a/crates/swc_ecma_ast/src/stmt.rs b/crates/swc_ecma_ast/src/stmt.rs index 328308aec6d2..a5330d029d0e 100644 --- a/crates/swc_ecma_ast/src/stmt.rs +++ b/crates/swc_ecma_ast/src/stmt.rs @@ -5,7 +5,7 @@ use crate::{ decl::{Decl, VarDecl}, expr::Expr, pat::Pat, - Ident, Lit, Str, UsingDecl, + Ident, Lit, NodeId, Str, UsingDecl, }; /// Use when only block statements are allowed. @@ -19,6 +19,9 @@ pub struct BlockStmt { pub ctxt: SyntaxContext, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, + pub stmts: Vec, } @@ -28,6 +31,7 @@ impl Take for BlockStmt { span: DUMMY_SP, stmts: Vec::new(), ctxt: Default::default(), + node_id: Default::default(), } } } @@ -328,6 +332,8 @@ pub struct IfStmt { #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct SwitchStmt { pub span: Span, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, pub discriminant: Box, pub cases: Vec, } @@ -392,6 +398,8 @@ pub struct DoWhileStmt { #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct ForStmt { pub span: Span, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, #[cfg_attr(feature = "serde-impl", serde(default))] #[cfg_attr( @@ -423,6 +431,8 @@ pub struct ForStmt { #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct ForInStmt { pub span: Span, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, pub left: ForHead, pub right: Box, pub body: Box, @@ -434,6 +444,8 @@ pub struct ForInStmt { #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct ForOfStmt { pub span: Span, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, /// Span of the await token. /// /// es2018 @@ -487,6 +499,8 @@ impl Take for SwitchCase { #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct CatchClause { pub span: Span, + #[cfg_attr(feature = "serde-impl", serde(default))] + pub node_id: NodeId, /// es2019 /// /// The param is null if the catch binding is omitted. E.g., try { foo() } diff --git a/crates/swc_ecma_ast/tests/node_id.rs b/crates/swc_ecma_ast/tests/node_id.rs new file mode 100644 index 000000000000..94bd61032db7 --- /dev/null +++ b/crates/swc_ecma_ast/tests/node_id.rs @@ -0,0 +1,36 @@ +#![cfg(feature = "serde-impl")] + +use serde_json::Value; +use swc_atoms::atom; +use swc_common::{SyntaxContext, DUMMY_SP}; +use swc_ecma_ast::{Ident, Module, NodeId, ScopeId}; + +#[test] +fn module_node_id_serde_defaults_to_invalid() { + let module = Module { + span: DUMMY_SP, + node_id: NodeId(7), + body: Vec::new(), + shebang: None, + }; + + let mut value = serde_json::to_value(&module).unwrap(); + assert_eq!(value["nodeId"], Value::from(7)); + + value.as_object_mut().unwrap().remove("nodeId"); + let module: Module = serde_json::from_value(value).unwrap(); + assert_eq!(module.node_id, NodeId::INVALID); +} + +#[test] +fn ident_scope_id_serde_defaults_to_invalid() { + let mut ident = Ident::new(atom!("foo"), DUMMY_SP, SyntaxContext::empty()); + ident.scope_id = ScopeId(11); + + let mut value = serde_json::to_value(&ident).unwrap(); + assert_eq!(value["scopeId"], Value::from(11)); + + value.as_object_mut().unwrap().remove("scopeId"); + let ident: Ident = serde_json::from_value(value).unwrap(); + assert_eq!(ident.scope_id, ScopeId::INVALID); +} diff --git a/crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs b/crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs index 5d6de652aba4..6bbd2d99cf19 100644 --- a/crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs +++ b/crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs @@ -346,6 +346,7 @@ impl BlockScoping { stmts.push( SwitchStmt { span: DUMMY_SP, + node_id: Default::default(), discriminant: Box::new(ret.into()), cases: flow_helper .label diff --git a/crates/swc_ecma_compat_es2015/src/destructuring.rs b/crates/swc_ecma_compat_es2015/src/destructuring.rs index ac1a465a0b05..c2be6c0aa131 100644 --- a/crates/swc_ecma_compat_es2015/src/destructuring.rs +++ b/crates/swc_ecma_compat_es2015/src/destructuring.rs @@ -132,10 +132,16 @@ macro_rules! impl_for_for_stmt { for_stmt.left = left; for_stmt.body = Box::new(Stmt::Block(match &mut *for_stmt.body { - Stmt::Block(BlockStmt { span, stmts, ctxt }) => BlockStmt { + Stmt::Block(BlockStmt { + span, + stmts, + ctxt, + node_id, + }) => BlockStmt { span: *span, stmts: iter::once(stmt).chain(stmts.take()).collect(), ctxt: *ctxt, + node_id: *node_id, }, body => BlockStmt { stmts: vec![stmt, body.take()], diff --git a/crates/swc_ecma_compat_es2015/src/for_of.rs b/crates/swc_ecma_compat_es2015/src/for_of.rs index 203569fbfb48..e6dd444b1c4b 100644 --- a/crates/swc_ecma_compat_es2015/src/for_of.rs +++ b/crates/swc_ecma_compat_es2015/src/for_of.rs @@ -192,6 +192,7 @@ impl ForOf { let stmt = ForStmt { span, + node_id: Default::default(), init: Some( VarDecl { span: DUMMY_SP, @@ -317,6 +318,7 @@ impl ForOf { let stmt = ForStmt { span, + node_id: Default::default(), init: Some( VarDecl { kind: VarDeclKind::Var, @@ -417,6 +419,7 @@ impl ForOf { let for_stmt = ForStmt { span, + node_id: Default::default(), init: Some( VarDecl { span: DUMMY_SP, @@ -519,6 +522,7 @@ impl ForOf { }, handler: Some(CatchClause { span: DUMMY_SP, + node_id: Default::default(), param: Some(quote_ident!("err").into()), // _didIteratorError = true; // _iteratorError = err; diff --git a/crates/swc_ecma_compat_es2015/src/generator.rs b/crates/swc_ecma_compat_es2015/src/generator.rs index 26bd31cb8704..19cee5ae31a0 100644 --- a/crates/swc_ecma_compat_es2015/src/generator.rs +++ b/crates/swc_ecma_compat_es2015/src/generator.rs @@ -1858,6 +1858,7 @@ impl Generator { self.emit_stmt( ForInStmt { span: DUMMY_SP, + node_id: Default::default(), left: ForHead::Pat(key.clone().into()), right: Box::new(obj.clone().into()), body: Box::new(Stmt::Expr(ExprStmt { @@ -2104,6 +2105,7 @@ impl Generator { self.emit_stmt( SwitchStmt { span: DUMMY_SP, + node_id: Default::default(), discriminant: expression.clone().into(), cases: take(&mut pending_clauses), } @@ -2973,6 +2975,7 @@ impl Generator { let label_expr = self.state.clone().make_member(quote_ident!("label")); let switch_stmt = SwitchStmt { span: DUMMY_SP, + node_id: Default::default(), discriminant: label_expr.into(), cases: clauses, }; diff --git a/crates/swc_ecma_compat_es2015/src/parameters.rs b/crates/swc_ecma_compat_es2015/src/parameters.rs index e02fe8df34a3..aa56395bbcd6 100644 --- a/crates/swc_ecma_compat_es2015/src/parameters.rs +++ b/crates/swc_ecma_compat_es2015/src/parameters.rs @@ -310,6 +310,7 @@ impl Params { unpack_rest = Some( ForStmt { span, + node_id: Default::default(), init: Some( VarDecl { kind: VarDeclKind::Var, diff --git a/crates/swc_ecma_hooks/src/generated.rs b/crates/swc_ecma_hooks/src/generated.rs index 6d687e7fb44e..4b49bcc6d3cb 100644 --- a/crates/swc_ecma_hooks/src/generated.rs +++ b/crates/swc_ecma_hooks/src/generated.rs @@ -153,6 +153,14 @@ pub trait VisitHook { #[inline] #[allow(unused_variables)] fn exit_binary_op(&mut self, node: &BinaryOp, ctx: &mut C) {} + #[doc = "Called when entering a node of type `BindingId` before visiting its children."] + #[inline] + #[allow(unused_variables)] + fn enter_binding_id(&mut self, node: &BindingId, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `BindingId` after visiting its children."] + #[inline] + #[allow(unused_variables)] + fn exit_binding_id(&mut self, node: &BindingId, ctx: &mut C) {} #[doc = "Called when entering a node of type `BindingIdent` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -2737,6 +2745,18 @@ where self.first.exit_binary_op(node, ctx); } + #[inline] + fn enter_binding_id(&mut self, node: &BindingId, ctx: &mut C) { + self.first.enter_binding_id(node, ctx); + self.second.enter_binding_id(node, ctx); + } + + #[inline] + fn exit_binding_id(&mut self, node: &BindingId, ctx: &mut C) { + self.second.exit_binding_id(node, ctx); + self.first.exit_binding_id(node, ctx); + } + #[inline] fn enter_binding_ident(&mut self, node: &BindingIdent, ctx: &mut C) { self.first.enter_binding_ident(node, ctx); @@ -6374,6 +6394,22 @@ where } } + #[inline] + fn enter_binding_id(&mut self, node: &BindingId, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_binding_id(node, ctx), + Self::Right(hook) => hook.enter_binding_id(node, ctx), + } + } + + #[inline] + fn exit_binding_id(&mut self, node: &BindingId, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_binding_id(node, ctx), + Self::Right(hook) => hook.exit_binding_id(node, ctx), + } + } + #[inline] fn enter_binding_ident(&mut self, node: &BindingIdent, ctx: &mut C) { match self { @@ -11082,6 +11118,20 @@ where } } + #[inline] + fn enter_binding_id(&mut self, node: &BindingId, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_binding_id(node, ctx); + } + } + + #[inline] + fn exit_binding_id(&mut self, node: &BindingId, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_binding_id(node, ctx); + } + } + #[inline] fn enter_binding_ident(&mut self, node: &BindingIdent, ctx: &mut C) { if let Some(hook) = self { @@ -15134,6 +15184,14 @@ impl, C> Visit for VisitWithHook { self.hook.exit_binary_op(node, &mut self.context); } + #[doc = "Visits a node of type `BindingId` using the hook's enter and exit methods."] + #[inline] + fn visit_binding_id(&mut self, node: &BindingId) { + self.hook.enter_binding_id(node, &mut self.context); + node.visit_children_with(self); + self.hook.exit_binding_id(node, &mut self.context); + } + #[doc = "Visits a node of type `BindingIdent` using the hook's enter and exit methods."] #[inline] fn visit_binding_ident(&mut self, node: &BindingIdent) { @@ -17611,6 +17669,14 @@ pub trait VisitMutHook { #[inline] #[allow(unused_variables)] fn exit_binary_op(&mut self, node: &mut BinaryOp, ctx: &mut C) {} + #[doc = "Called when entering a node of type `BindingId` before visiting its children."] + #[inline] + #[allow(unused_variables)] + fn enter_binding_id(&mut self, node: &mut BindingId, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `BindingId` after visiting its children."] + #[inline] + #[allow(unused_variables)] + fn exit_binding_id(&mut self, node: &mut BindingId, ctx: &mut C) {} #[doc = "Called when entering a node of type `BindingIdent` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -20241,6 +20307,18 @@ where self.first.exit_binary_op(node, ctx); } + #[inline] + fn enter_binding_id(&mut self, node: &mut BindingId, ctx: &mut C) { + self.first.enter_binding_id(node, ctx); + self.second.enter_binding_id(node, ctx); + } + + #[inline] + fn exit_binding_id(&mut self, node: &mut BindingId, ctx: &mut C) { + self.second.exit_binding_id(node, ctx); + self.first.exit_binding_id(node, ctx); + } + #[inline] fn enter_binding_ident(&mut self, node: &mut BindingIdent, ctx: &mut C) { self.first.enter_binding_ident(node, ctx); @@ -23914,6 +23992,22 @@ where } } + #[inline] + fn enter_binding_id(&mut self, node: &mut BindingId, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_binding_id(node, ctx), + Self::Right(hook) => hook.enter_binding_id(node, ctx), + } + } + + #[inline] + fn exit_binding_id(&mut self, node: &mut BindingId, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_binding_id(node, ctx), + Self::Right(hook) => hook.exit_binding_id(node, ctx), + } + } + #[inline] fn enter_binding_ident(&mut self, node: &mut BindingIdent, ctx: &mut C) { match self { @@ -28658,6 +28752,20 @@ where } } + #[inline] + fn enter_binding_id(&mut self, node: &mut BindingId, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_binding_id(node, ctx); + } + } + + #[inline] + fn exit_binding_id(&mut self, node: &mut BindingId, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_binding_id(node, ctx); + } + } + #[inline] fn enter_binding_ident(&mut self, node: &mut BindingIdent, ctx: &mut C) { if let Some(hook) = self { @@ -32746,6 +32854,14 @@ impl, C> VisitMut for VisitMutWithHook { self.hook.exit_binary_op(node, &mut self.context); } + #[doc = "Visits a node of type `BindingId` using the hook's enter and exit methods."] + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId) { + self.hook.enter_binding_id(node, &mut self.context); + node.visit_mut_children_with(self); + self.hook.exit_binding_id(node, &mut self.context); + } + #[doc = "Visits a node of type `BindingIdent` using the hook's enter and exit methods."] #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent) { diff --git a/crates/swc_ecma_lexer/src/common/parser/class_and_fn.rs b/crates/swc_ecma_lexer/src/common/parser/class_and_fn.rs index 11dd4ba50944..8bd0804d24d4 100644 --- a/crates/swc_ecma_lexer/src/common/parser/class_and_fn.rs +++ b/crates/swc_ecma_lexer/src/common/parser/class_and_fn.rs @@ -323,6 +323,7 @@ where is_generator, return_type, ctxt: Default::default(), + node_id: Default::default(), })) }; diff --git a/crates/swc_ecma_lexer/src/common/parser/stmt.rs b/crates/swc_ecma_lexer/src/common/parser/stmt.rs index 307e029e6bdc..284497c78d0e 100644 --- a/crates/swc_ecma_lexer/src/common/parser/stmt.rs +++ b/crates/swc_ecma_lexer/src/common/parser/stmt.rs @@ -545,6 +545,7 @@ fn parse_for_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult { ForStmt { span, + node_id: Default::default(), init, test, update, @@ -559,6 +560,7 @@ fn parse_for_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult { ForInStmt { span, + node_id: Default::default(), left, right, body, @@ -567,6 +569,7 @@ fn parse_for_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult { } TempForHead::ForOf { left, right } => ForOfStmt { span, + node_id: Default::default(), is_await: await_token.is_some(), left, right, @@ -886,6 +889,7 @@ pub fn parse_block<'a, P: Parser<'a>>(p: &mut P, allow_directives: bool) -> PRes let span = p.span(start); Ok(BlockStmt { span, + node_id: Default::default(), stmts, ctxt: Default::default(), }) @@ -906,6 +910,7 @@ fn parse_catch_clause<'a, P: Parser<'a>>(p: &mut P) -> PResult>(p: &mut P) -> PResult { Ok(SwitchStmt { span: p.span(switch_start), + node_id: Default::default(), discriminant, cases, } diff --git a/crates/swc_ecma_lexer/src/parser/mod.rs b/crates/swc_ecma_lexer/src/parser/mod.rs index 51481a5f1eab..5f2cf491710a 100644 --- a/crates/swc_ecma_lexer/src/parser/mod.rs +++ b/crates/swc_ecma_lexer/src/parser/mod.rs @@ -153,6 +153,7 @@ impl> Parser { let ret = parse_stmt_block_body(self, true, None).map(|body| Script { span: self.span(start), + node_id: Default::default(), body, shebang, })?; @@ -174,6 +175,7 @@ impl> Parser { let ret = parse_stmt_block_body(self, true, None).map(|body| Script { span: self.span(start), + node_id: Default::default(), body, shebang, })?; @@ -198,6 +200,7 @@ impl> Parser { let shebang = parse_shebang(self)?; let ret = parse_module_item_block_body(self, true, None).map(|body| Module { + node_id: Default::default(), span: self.span(start), body, shebang, @@ -239,6 +242,7 @@ impl> Parser { let ret = if has_module_item { Program::Module(Module { span: self.span(start), + node_id: Default::default(), body, shebang, }) @@ -257,6 +261,7 @@ impl> Parser { .collect(); Program::Script(Script { span: self.span(start), + node_id: Default::default(), body, shebang, }) @@ -282,6 +287,7 @@ impl> Parser { let ret = parse_module_item_block_body(self, true, None).map(|body| Module { span: self.span(start), + node_id: Default::default(), body, shebang, })?; diff --git a/crates/swc_ecma_minifier/src/compress/optimize/iife.rs b/crates/swc_ecma_minifier/src/compress/optimize/iife.rs index 91ecb4de7f56..c7209ae55efa 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/iife.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/iife.rs @@ -1347,6 +1347,7 @@ impl Optimizer<'_> { Some(BlockStmt { span, + node_id: Default::default(), ctxt: SyntaxContext::empty().apply_mark(self.marks.fake_block), stmts, }) diff --git a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs index be24a24dbb62..a91704461431 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs @@ -2688,6 +2688,7 @@ impl VisitMut for Optimizer<'_> { let span = s.span(); *s = BlockStmt { span, + node_id: Default::default(), ctxt: SyntaxContext::empty().apply_mark(self.marks.fake_block), stmts: self .prepend_stmts diff --git a/crates/swc_ecma_minifier/src/compress/pure/loops.rs b/crates/swc_ecma_minifier/src/compress/pure/loops.rs index 0f92308dfaa6..a75dfa4f1b48 100644 --- a/crates/swc_ecma_minifier/src/compress/pure/loops.rs +++ b/crates/swc_ecma_minifier/src/compress/pure/loops.rs @@ -72,6 +72,7 @@ impl Pure<'_> { report_change!("loops: Converting a while loop to a for loop"); *s = ForStmt { span: stmt.span, + node_id: Default::default(), init: None, test: Some(stmt.test.take()), update: None, @@ -87,6 +88,7 @@ impl Pure<'_> { *s = ForStmt { span: stmt.span, + node_id: Default::default(), init: None, test: Some(stmt.test.take()), update: None, diff --git a/crates/swc_ecma_minifier/tests/libs-size.snapshot.md b/crates/swc_ecma_minifier/tests/libs-size.snapshot.md index bc636ecfcdad..b6a962d9b10e 100644 --- a/crates/swc_ecma_minifier/tests/libs-size.snapshot.md +++ b/crates/swc_ecma_minifier/tests/libs-size.snapshot.md @@ -2,13 +2,13 @@ | --- | --- | --- | --- | | antd.js | 6.38 MiB | 2.06 MiB | 445.45 KiB | | d3.js | 542.74 KiB | 261.43 KiB | 85.33 KiB | -| echarts.js | 3.41 MiB | 977.04 KiB | 314.11 KiB | +| echarts.js | 3.41 MiB | 977.09 KiB | 314.11 KiB | | jquery.js | 280.89 KiB | 87.79 KiB | 30.20 KiB | | lodash.js | 531.35 KiB | 68.92 KiB | 24.60 KiB | | moment.js | 169.83 KiB | 57.34 KiB | 18.25 KiB | | react.js | 70.45 KiB | 22.45 KiB | 8.04 KiB | | terser.js | 1.08 MiB | 446.63 KiB | 120.49 KiB | | three.js | 1.19 MiB | 630.55 KiB | 154.77 KiB | -| typescript.js | 10.45 MiB | 3.17 MiB | 840.61 KiB | +| typescript.js | 10.45 MiB | 3.17 MiB | 840.63 KiB | | victory.js | 2.30 MiB | 694.04 KiB | 154.18 KiB | | vue.js | 334.13 KiB | 113.56 KiB | 41.80 KiB | diff --git a/crates/swc_ecma_parser/src/parser/class_and_fn.rs b/crates/swc_ecma_parser/src/parser/class_and_fn.rs index bb4915dc7b44..b45af0f519e7 100644 --- a/crates/swc_ecma_parser/src/parser/class_and_fn.rs +++ b/crates/swc_ecma_parser/src/parser/class_and_fn.rs @@ -378,6 +378,7 @@ impl Parser { is_generator, return_type, ctxt: Default::default(), + node_id: Default::default(), })) }; diff --git a/crates/swc_ecma_parser/src/parser/mod.rs b/crates/swc_ecma_parser/src/parser/mod.rs index f52e7f5e7a34..2042cc585261 100644 --- a/crates/swc_ecma_parser/src/parser/mod.rs +++ b/crates/swc_ecma_parser/src/parser/mod.rs @@ -224,6 +224,7 @@ impl Parser { let ret = self.parse_stmt_block_body(true, None).map(|body| Script { span: self.span(start), + node_id: Default::default(), body, shebang, })?; @@ -248,6 +249,7 @@ impl Parser { let ret = self.parse_stmt_block_body(true, None).map(|body| Script { span: self.span(start), + node_id: Default::default(), body, shebang, })?; @@ -275,6 +277,7 @@ impl Parser { .parse_module_item_block_body(true, None) .map(|body| Module { span: self.span(start), + node_id: Default::default(), body, shebang, })?; @@ -318,6 +321,7 @@ impl Parser { } Program::Module(Module { span: self.span(start), + node_id: Default::default(), body, shebang, }) @@ -333,6 +337,7 @@ impl Parser { .collect(); Program::Script(Script { span: self.span(start), + node_id: Default::default(), body, shebang, }) @@ -360,6 +365,7 @@ impl Parser { .parse_module_item_block_body(true, None) .map(|body| Module { span: self.span(start), + node_id: Default::default(), body, shebang, })?; diff --git a/crates/swc_ecma_parser/src/parser/stmt.rs b/crates/swc_ecma_parser/src/parser/stmt.rs index 9ebd7da3f326..6b42a915280b 100644 --- a/crates/swc_ecma_parser/src/parser/stmt.rs +++ b/crates/swc_ecma_parser/src/parser/stmt.rs @@ -569,6 +569,7 @@ impl Parser { ForStmt { span, + node_id: Default::default(), init, test, update, @@ -583,6 +584,7 @@ impl Parser { ForInStmt { span, + node_id: Default::default(), left, right, body, @@ -599,6 +601,7 @@ impl Parser { ForOfStmt { span, + node_id: Default::default(), is_await: await_token.is_some(), left, right, @@ -920,6 +923,7 @@ impl Parser { let span = self.span(start); Ok(BlockStmt { span, + node_id: Default::default(), stmts, ctxt: Default::default(), }) @@ -940,6 +944,7 @@ impl Parser { self.parse_block(false) .map(|body| CatchClause { span: self.span(start), + node_id: Default::default(), param, body, }) @@ -1035,6 +1040,7 @@ impl Parser { Ok(SwitchStmt { span: self.span(switch_start), + node_id: Default::default(), discriminant, cases, } @@ -1689,6 +1695,7 @@ impl Parser { decorators: Vec::new(), body: Some(BlockStmt { span, + node_id: Default::default(), stmts, ctxt: Default::default(), }), @@ -1697,6 +1704,7 @@ impl Parser { type_params: None, return_type: None, ctxt: Default::default(), + node_id: Default::default(), }), })); @@ -1749,6 +1757,7 @@ impl Parser { test, cons: Box::new(Stmt::Block(BlockStmt { span, + node_id: Default::default(), stmts: cons_stmts, ctxt: Default::default(), })), @@ -1788,6 +1797,7 @@ impl Parser { let expr = self.allow_in_expr(Self::parse_assignment_expr)?; BlockStmt { span, + node_id: Default::default(), stmts: vec![Stmt::Expr(ExprStmt { span, expr })], ctxt: Default::default(), } @@ -1811,6 +1821,7 @@ impl Parser { test, cons: Box::new(Stmt::Block(BlockStmt { span, + node_id: Default::default(), stmts, ctxt: Default::default(), })), @@ -1835,6 +1846,7 @@ impl Parser { Ok(Stmt::Block(BlockStmt { span, + node_id: Default::default(), stmts, ctxt: Default::default(), })) @@ -2304,6 +2316,7 @@ mod tests { ..Default::default() }, handler: Some(CatchClause { + node_id: Default::default(), span, param: Pat::Object(ObjectPat { span, @@ -2345,6 +2358,7 @@ mod tests { assert_eq_ignore_span!( stmt("for await (const a of b) ;"), Stmt::ForOf(ForOfStmt { + node_id: Default::default(), span, is_await: true, left: ForHead::VarDecl(Box::new(VarDecl { diff --git a/crates/swc_ecma_parser/src/parser/typescript.rs b/crates/swc_ecma_parser/src/parser/typescript.rs index d118be6243a2..50238cecff24 100644 --- a/crates/swc_ecma_parser/src/parser/typescript.rs +++ b/crates/swc_ecma_parser/src/parser/typescript.rs @@ -466,6 +466,7 @@ impl Parser { is_generator: false, return_type, ctxt: Default::default(), + node_id: Default::default(), }), })) } @@ -5239,6 +5240,7 @@ mod tests { ); let expected = Module { + node_id: Default::default(), span: DUMMY_SP, shebang: None, body: { @@ -5273,6 +5275,7 @@ mod tests { ); let expected = Module { + node_id: Default::default(), span: DUMMY_SP, shebang: None, body: { diff --git a/crates/swc_ecma_quote_macros/src/ast/class.rs b/crates/swc_ecma_quote_macros/src/ast/class.rs index 2018d90f6ceb..4eba83ac2892 100644 --- a/crates/swc_ecma_quote_macros/src/ast/class.rs +++ b/crates/swc_ecma_quote_macros/src/ast/class.rs @@ -3,6 +3,7 @@ use swc_ecma_ast::*; impl_struct!( Class, [ + node_id, span, ctxt, decorators, @@ -17,7 +18,16 @@ impl_struct!( impl_struct!( Constructor, - [span, ctxt, key, params, body, accessibility, is_optional] + [ + node_id, + span, + ctxt, + key, + params, + body, + accessibility, + is_optional + ] ); impl_struct!( diff --git a/crates/swc_ecma_quote_macros/src/ast/expr.rs b/crates/swc_ecma_quote_macros/src/ast/expr.rs index c3364e766a3f..2274c1851a6e 100644 --- a/crates/swc_ecma_quote_macros/src/ast/expr.rs +++ b/crates/swc_ecma_quote_macros/src/ast/expr.rs @@ -70,6 +70,7 @@ impl_struct!(FnExpr, [ident, function]); impl_struct!( ArrowExpr, [ + node_id, span, ctxt, params, @@ -112,6 +113,7 @@ impl_struct!(ParenExpr, [span, expr]); impl_struct!( Function, [ + node_id, ctxt, params, decorators, diff --git a/crates/swc_ecma_quote_macros/src/ast/mod.rs b/crates/swc_ecma_quote_macros/src/ast/mod.rs index 28d5b162388d..c67e0974136c 100644 --- a/crates/swc_ecma_quote_macros/src/ast/mod.rs +++ b/crates/swc_ecma_quote_macros/src/ast/mod.rs @@ -67,7 +67,7 @@ macro_rules! impl_struct { fn to_code(&self, cx: &crate::ctxt::Ctx) -> syn::Expr { let mut builder = crate::builder::Builder::new(stringify!($name)); - let Self { $($v,)* } = self; + let Self { $($v,)* .. } = self; $( builder.add( @@ -139,6 +139,20 @@ impl ToCode for SyntaxContext { } } +impl ToCode for NodeId { + fn to_code(&self, _: &Ctx) -> syn::Expr { + let id = self.as_u32(); + parse_quote!(swc_core::ecma::ast::NodeId(#id)) + } +} + +impl ToCode for ScopeId { + fn to_code(&self, _: &Ctx) -> syn::Expr { + let id = self.as_u32(); + parse_quote!(swc_core::ecma::ast::ScopeId(#id)) + } +} + impl_enum!(ModuleItem, [ModuleDecl, Stmt]); impl_enum!( diff --git a/crates/swc_ecma_quote_macros/src/ast/stmt.rs b/crates/swc_ecma_quote_macros/src/ast/stmt.rs index 07d30a484d47..93d33d51720b 100644 --- a/crates/swc_ecma_quote_macros/src/ast/stmt.rs +++ b/crates/swc_ecma_quote_macros/src/ast/stmt.rs @@ -9,21 +9,21 @@ impl_enum!( ); impl_struct!(EmptyStmt, [span]); -impl_struct!(BlockStmt, [span, ctxt, stmts]); +impl_struct!(BlockStmt, [node_id, span, ctxt, stmts]); impl_struct!(DebuggerStmt, [span]); impl_struct!(WithStmt, [span, obj, body]); impl_struct!(LabeledStmt, [span, label, body]); impl_struct!(BreakStmt, [span, label]); impl_struct!(ContinueStmt, [span, label]); impl_struct!(IfStmt, [span, test, cons, alt]); -impl_struct!(SwitchStmt, [span, discriminant, cases]); +impl_struct!(SwitchStmt, [node_id, span, discriminant, cases]); impl_struct!(ThrowStmt, [span, arg]); impl_struct!(TryStmt, [span, block, handler, finalizer]); impl_struct!(WhileStmt, [span, test, body]); impl_struct!(DoWhileStmt, [span, test, body]); -impl_struct!(ForStmt, [span, init, test, update, body]); -impl_struct!(ForInStmt, [span, left, right, body]); -impl_struct!(ForOfStmt, [span, is_await, left, right, body]); +impl_struct!(ForStmt, [node_id, span, init, test, update, body]); +impl_struct!(ForInStmt, [node_id, span, left, right, body]); +impl_struct!(ForOfStmt, [node_id, span, is_await, left, right, body]); impl_struct!(ReturnStmt, [span, arg]); impl_struct!(ExprStmt, [span, expr]); @@ -32,4 +32,4 @@ impl_enum!(ForHead, [VarDecl, UsingDecl, Pat]); impl_struct!(SwitchCase, [span, test, cons]); -impl_struct!(CatchClause, [span, param, body]); +impl_struct!(CatchClause, [node_id, span, param, body]); diff --git a/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs b/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs index d3427a125aaa..8ea296522eab 100644 --- a/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/swc_ecma_transformer/src/es2016/exponentiation_operator.rs @@ -289,6 +289,7 @@ fn create_math_pow(left: Box, right: Box) -> Expr { span: DUMMY_SP, ctxt: SyntaxContext::empty(), sym: "Math".into(), + scope_id: Default::default(), optional: false, })), prop: MemberProp::Ident(IdentName { diff --git a/crates/swc_ecma_transformer/src/es2017/async_to_generator.rs b/crates/swc_ecma_transformer/src/es2017/async_to_generator.rs index 910dbe171c76..14c999812804 100644 --- a/crates/swc_ecma_transformer/src/es2017/async_to_generator.rs +++ b/crates/swc_ecma_transformer/src/es2017/async_to_generator.rs @@ -603,6 +603,7 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) { let for_stmt = ForStmt { span: s.span, + node_id: Default::default(), // var _iterator = _async_iterator(lol()), _step; init: Some( VarDecl { @@ -717,6 +718,7 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) { CatchClause { span: DUMMY_SP, + node_id: Default::default(), param: Some(err_param.into()), body: BlockStmt { stmts: vec![mark_as_errorred, store_error], diff --git a/crates/swc_ecma_transformer/src/es2022/class_static_block.rs b/crates/swc_ecma_transformer/src/es2022/class_static_block.rs index 2c1504ccc71a..3583b1803cba 100644 --- a/crates/swc_ecma_transformer/src/es2022/class_static_block.rs +++ b/crates/swc_ecma_transformer/src/es2022/class_static_block.rs @@ -148,9 +148,11 @@ impl ClassStaticBlock { fn wrap_in_iife(&self, stmts: Vec) -> Expr { let arrow = ArrowExpr { span: DUMMY_SP, + node_id: Default::default(), params: vec![], body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { span: DUMMY_SP, + node_id: Default::default(), stmts, ctxt: Default::default(), })), diff --git a/crates/swc_ecma_transformer/src/es2022/private_property_in_object.rs b/crates/swc_ecma_transformer/src/es2022/private_property_in_object.rs index b717e7c4cdf7..3ac1ee2394c9 100644 --- a/crates/swc_ecma_transformer/src/es2022/private_property_in_object.rs +++ b/crates/swc_ecma_transformer/src/es2022/private_property_in_object.rs @@ -307,6 +307,7 @@ impl VisitMutHook for PrivatePropertyInObjectPass { span: DUMMY_SP, callee: ArrowExpr { span: DUMMY_SP, + node_id: Default::default(), params: Default::default(), body: Box::new(BlockStmtOrExpr::BlockStmt(bs)), is_async: false, diff --git a/crates/swc_ecma_transforms_base/src/hygiene/tests.rs b/crates/swc_ecma_transforms_base/src/hygiene/tests.rs index bc7d5401a8f3..03e9d91eb910 100644 --- a/crates/swc_ecma_transforms_base/src/hygiene/tests.rs +++ b/crates/swc_ecma_transforms_base/src/hygiene/tests.rs @@ -91,6 +91,7 @@ where |tester| { Ok(Module { span: DUMMY_SP, + node_id: Default::default(), body: op(tester)?.into_iter().map(ModuleItem::Stmt).collect(), shebang: None, }) diff --git a/crates/swc_ecma_transforms_base/src/resolver/mod.rs b/crates/swc_ecma_transforms_base/src/resolver/mod.rs index 14379a6d8375..b55ec3a4e22e 100644 --- a/crates/swc_ecma_transforms_base/src/resolver/mod.rs +++ b/crates/swc_ecma_transforms_base/src/resolver/mod.rs @@ -1,3 +1,5 @@ +use std::{cell::Cell, rc::Rc}; + use rustc_hash::{FxHashMap, FxHashSet}; use swc_atoms::Atom; use swc_common::{Mark, SyntaxContext}; @@ -142,7 +144,14 @@ pub fn resolver( let _ = SyntaxContext::empty().apply_mark(top_level_mark); visit_mut_pass(Resolver { - current: Scope::new(ScopeKind::Fn, top_level_mark, None), + current: Scope::new( + ScopeKind::Fn, + top_level_mark, + ScopeId::from_node_id(NodeId(1)), + Some(NodeId(1)), + None, + ), + node_id_generator: NodeIdGenerator::default(), ident_type: IdentType::Ref, in_type: false, is_module: false, @@ -168,31 +177,111 @@ struct Scope<'a> { /// [Mark] of the current scope. mark: Mark, + /// Stable id of the current scope. + id: ScopeId, + + /// AST node owning this scope, if the scope has a concrete owner. + owner_node_id: Option, + /// All declarations in the scope - declared_symbols: FxHashMap, + declared_symbols: FxHashMap, /// All types declared in the scope - declared_types: FxHashSet, + declared_types: FxHashMap, } impl<'a> Scope<'a> { - pub fn new(kind: ScopeKind, mark: Mark, parent: Option<&'a Scope<'a>>) -> Self { + pub fn new( + kind: ScopeKind, + mark: Mark, + id: ScopeId, + owner_node_id: Option, + parent: Option<&'a Scope<'a>>, + ) -> Self { Scope { parent, kind, mark, + id, + owner_node_id, declared_symbols: Default::default(), declared_types: Default::default(), } } - fn is_declared(&self, symbol: &Atom) -> Option<&DeclKind> { + fn is_declared(&self, symbol: &Atom) -> Option { self.declared_symbols .get(symbol) + .map(|binding| binding.kind) .or_else(|| self.parent?.is_declared(symbol)) } } +#[derive(Debug, Clone, Copy)] +struct ResolvedBinding { + kind: DeclKind, + scope_id: ScopeId, + legacy_mark: Mark, +} + +#[derive(Debug, Clone, Copy)] +struct ResolvedRef { + scope_id: ScopeId, + legacy_mark: Mark, +} + +impl ResolvedRef { + fn from_binding(binding: ResolvedBinding, unresolved_mark: Mark) -> Self { + let scope_id = if binding.legacy_mark == unresolved_mark { + ScopeId::UNRESOLVED + } else { + binding.scope_id + }; + + Self { + scope_id, + legacy_mark: binding.legacy_mark, + } + } + + fn unresolved(unresolved_mark: Mark) -> Self { + Self { + scope_id: ScopeId::UNRESOLVED, + legacy_mark: unresolved_mark, + } + } +} + +#[derive(Debug, Clone)] +struct NodeIdGenerator { + next: Rc>, +} + +impl Default for NodeIdGenerator { + fn default() -> Self { + Self { + // The top-level Module/Script scope is always id 1. + next: Rc::new(Cell::new(2)), + } + } +} + +impl NodeIdGenerator { + fn fresh(&self) -> NodeId { + let id = self.next.get(); + self.next.set(id + 1); + NodeId(id) + } + + fn reserve(&self, id: NodeId) { + if id.is_invalid() || id.0 == u32::MAX { + return; + } + + self.next.set(self.next.get().max(id.0 + 1)); + } +} + /// # Phases /// /// ## Hoisting phase @@ -200,6 +289,7 @@ impl<'a> Scope<'a> { /// ## Resolving phase struct Resolver<'a> { current: Scope<'a>, + node_id_generator: NodeIdGenerator, ident_type: IdentType, in_type: bool, is_module: bool, @@ -223,6 +313,7 @@ impl<'a> Resolver<'a> { fn new(current: Scope<'a>, config: InnerConfig) -> Self { Resolver { current, + node_id_generator: NodeIdGenerator::default(), ident_type: IdentType::Ref, in_type: false, is_module: false, @@ -237,12 +328,16 @@ impl<'a> Resolver<'a> { where F: for<'aa> FnOnce(&mut Resolver<'aa>), { + let scope_id = ScopeId::from_node_id(self.node_id_generator.fresh()); let mut child = Resolver { current: Scope::new( kind, Mark::fresh(self.config.top_level_mark), + scope_id, + None, Some(&self.current), ), + node_id_generator: self.node_id_generator.clone(), ident_type: IdentType::Ref, config: self.config, in_type: self.in_type, @@ -255,53 +350,124 @@ impl<'a> Resolver<'a> { op(&mut child); } + fn with_child_for_node(&self, kind: ScopeKind, owner_node_id: NodeId, op: F) + where + F: for<'aa> FnOnce(&mut Resolver<'aa>), + { + self.node_id_generator.reserve(owner_node_id); + let mut child = Resolver { + current: Scope::new( + kind, + Mark::fresh(self.config.top_level_mark), + ScopeId::from_node_id(owner_node_id), + Some(owner_node_id), + Some(&self.current), + ), + node_id_generator: self.node_id_generator.clone(), + ident_type: IdentType::Ref, + config: self.config, + in_type: self.in_type, + is_module: self.is_module, + in_ts_module: self.in_ts_module, + decl_kind: self.decl_kind, + strict_mode: self.strict_mode, + }; + + op(&mut child); + } + + fn ensure_node_id(&self, node_id: &mut NodeId) -> NodeId { + if node_id.is_invalid() { + *node_id = self.node_id_generator.fresh(); + } else { + self.node_id_generator.reserve(*node_id); + } + + *node_id + } + + fn use_current_scope_node_id(&mut self, node_id: &mut NodeId) { + if node_id.is_invalid() { + *node_id = self.current.id.as_node_id(); + return; + } + + self.node_id_generator.reserve(*node_id); + self.current.id = ScopeId::from_node_id(*node_id); + self.current.owner_node_id = Some(*node_id); + } + + fn declare_symbol(&mut self, sym: Atom, kind: DeclKind) { + self.current.declared_symbols.insert( + sym, + ResolvedBinding { + kind, + scope_id: self.current.id, + legacy_mark: self.current.mark, + }, + ); + } + + fn declare_type(&mut self, sym: Atom) { + self.current.declared_types.insert( + sym, + ResolvedBinding { + kind: DeclKind::Type, + scope_id: self.current.id, + legacy_mark: self.current.mark, + }, + ); + } + fn visit_mut_stmt_within_child_scope(&mut self, s: &mut Stmt) { - self.with_child(ScopeKind::Block, |child| match s { + match s { Stmt::Block(s) => { - child.mark_block(&mut s.ctxt); - s.visit_mut_children_with(child); + let node_id = self.ensure_node_id(&mut s.node_id); + self.with_child_for_node(ScopeKind::Block, node_id, |child| { + child.mark_ctxt(&mut s.ctxt); + s.visit_mut_children_with(child); + }); } - _ => s.visit_mut_with(child), - }); + _ => self.with_child(ScopeKind::Block, |child| s.visit_mut_with(child)), + } } - /// Returns a [Mark] for an identifier reference. - fn mark_for_ref(&self, sym: &Atom) -> Option { + /// Returns the resolved scope and legacy [Mark] for an identifier + /// reference. + fn mark_for_ref(&self, sym: &Atom) -> Option { self.mark_for_ref_inner(sym, false) } - fn mark_for_ref_inner(&self, sym: &Atom, stop_an_fn_scope: bool) -> Option { + fn mark_for_ref_inner(&self, sym: &Atom, stop_an_fn_scope: bool) -> Option { if self.config.handle_types && self.in_type { - let mut mark = self.current.mark; let mut scope = Some(&self.current); while let Some(cur) = scope { // if cur.declared_types.contains(sym) || // cur.hoisted_symbols.borrow().contains(sym) { - if cur.declared_types.contains(sym) { - if mark == Mark::root() { + if let Some(binding) = cur.declared_types.get(sym) { + if binding.legacy_mark == Mark::root() { break; } - return Some(mark); + return Some(ResolvedRef::from_binding( + *binding, + self.config.unresolved_mark, + )); } if cur.kind == ScopeKind::Fn && stop_an_fn_scope { return None; } - if let Some(parent) = &cur.parent { - mark = parent.mark; - } scope = cur.parent; } } - let mut mark = self.current.mark; let mut scope = Some(&self.current); while let Some(cur) = scope { - if cur.declared_symbols.contains_key(sym) { - if mark == Mark::root() { + if let Some(binding) = cur.declared_symbols.get(sym) { + if binding.legacy_mark == Mark::root() { return None; } @@ -309,11 +475,14 @@ impl<'a> Resolver<'a> { // https://tc39.es/ecma262/multipage/global-object.html#sec-value-properties-of-the-global-object-infinity // non configurable global value "undefined" | "NaN" | "Infinity" - if mark == self.config.top_level_mark && !self.is_module => + if binding.legacy_mark == self.config.top_level_mark && !self.is_module => { - Some(self.config.unresolved_mark) + Some(ResolvedRef::unresolved(self.config.unresolved_mark)) } - _ => Some(mark), + _ => Some(ResolvedRef::from_binding( + *binding, + self.config.unresolved_mark, + )), }; } @@ -321,9 +490,6 @@ impl<'a> Resolver<'a> { return None; } - if let Some(parent) = &cur.parent { - mark = parent.mark; - } scope = cur.parent; } @@ -344,11 +510,12 @@ impl<'a> Resolver<'a> { } if self.in_type { - self.current.declared_types.insert(id.sym.clone()); + self.declare_type(id.sym.clone()); } else { - self.current.declared_symbols.insert(id.sym.clone(), kind); + self.declare_symbol(id.sym.clone(), kind); } + id.scope_id = self.current.id; let mark = self.current.mark; if mark != Mark::root() { @@ -356,15 +523,23 @@ impl<'a> Resolver<'a> { } } - fn mark_block(&mut self, ctxt: &mut SyntaxContext) { - if *ctxt != SyntaxContext::empty() { - return; - } + fn mark_block(&mut self, ctxt: &mut SyntaxContext, node_id: &mut NodeId) { + self.use_current_scope_node_id(node_id); - let mark = self.current.mark; + debug_assert_eq!( + self.current + .owner_node_id + .map(ScopeId::from_node_id) + .unwrap_or(self.current.id), + self.current.id + ); - if mark != Mark::root() { - *ctxt = ctxt.apply_mark(mark) + self.mark_ctxt(ctxt); + } + + fn mark_ctxt(&self, ctxt: &mut SyntaxContext) { + if *ctxt == SyntaxContext::empty() && self.current.mark != Mark::root() { + *ctxt = ctxt.apply_mark(self.current.mark) } } @@ -526,7 +701,8 @@ impl VisitMut for Resolver<'_> { typed!(visit_mut_ts_namespace_export_decl, TsNamespaceExportDecl); fn visit_mut_arrow_expr(&mut self, e: &mut ArrowExpr) { - self.with_child(ScopeKind::Fn, |child| { + let node_id = self.ensure_node_id(&mut e.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { e.type_params.visit_mut_with(child); let old = child.ident_type; @@ -539,7 +715,7 @@ impl VisitMut for Resolver<'_> { .flat_map(find_pat_ids::<_, Id>); for id in params { - child.current.declared_symbols.insert(id.0, DeclKind::Param); + child.declare_symbol(id.0, DeclKind::Param); } } e.params.visit_mut_with(child); @@ -547,7 +723,8 @@ impl VisitMut for Resolver<'_> { match &mut *e.body { BlockStmtOrExpr::BlockStmt(s) => { - child.mark_block(&mut s.ctxt); + child.ensure_node_id(&mut s.node_id); + child.mark_ctxt(&mut s.ctxt); let old_strict_mode = child.strict_mode; @@ -593,8 +770,9 @@ impl VisitMut for Resolver<'_> { } fn visit_mut_block_stmt(&mut self, block: &mut BlockStmt) { - self.with_child(ScopeKind::Block, |child| { - child.mark_block(&mut block.ctxt); + let node_id = self.ensure_node_id(&mut block.node_id); + self.with_child_for_node(ScopeKind::Block, node_id, |child| { + child.mark_ctxt(&mut block.ctxt); block.visit_mut_children_with(child); }) } @@ -609,17 +787,21 @@ impl VisitMut for Resolver<'_> { fn visit_mut_catch_clause(&mut self, c: &mut CatchClause) { // Child folder - self.with_child(ScopeKind::Fn, |child| { + let node_id = self.ensure_node_id(&mut c.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { child.ident_type = IdentType::Binding; c.param.visit_mut_with(child); child.ident_type = IdentType::Ref; - child.mark_block(&mut c.body.ctxt); + child.ensure_node_id(&mut c.body.node_id); + child.mark_ctxt(&mut c.body.ctxt); c.body.visit_mut_children_with(child); }); } fn visit_mut_class(&mut self, c: &mut Class) { + self.ensure_node_id(&mut c.node_id); + let old_strict_mode = self.strict_mode; self.strict_mode = true; @@ -654,7 +836,8 @@ impl VisitMut for Resolver<'_> { // Create a child scope. The class name is only accessible within the class. - self.with_child(ScopeKind::Fn, |child| { + let node_id = self.ensure_node_id(&mut n.class.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { child.ident_type = IdentType::Ref; n.class.visit_mut_with(child); @@ -666,7 +849,8 @@ impl VisitMut for Resolver<'_> { n.class.super_class.visit_mut_with(self); - self.with_child(ScopeKind::Fn, |child| { + let node_id = self.ensure_node_id(&mut n.class.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { child.ident_type = IdentType::Binding; n.ident.visit_mut_with(child); child.ident_type = IdentType::Ref; @@ -682,7 +866,10 @@ impl VisitMut for Resolver<'_> { p.decorators.visit_mut_with(self); } - self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child)); + let node_id = self.ensure_node_id(&mut m.function.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { + m.function.visit_mut_with(child) + }); } fn visit_mut_class_prop(&mut self, p: &mut ClassProp) { @@ -717,7 +904,8 @@ impl VisitMut for Resolver<'_> { } } - self.with_child(ScopeKind::Fn, |child| { + let node_id = self.ensure_node_id(&mut c.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { let old = child.ident_type; child.ident_type = IdentType::Binding; { @@ -733,14 +921,15 @@ impl VisitMut for Resolver<'_> { .flat_map(find_pat_ids::<_, Id>); for id in params { - child.current.declared_symbols.insert(id.0, DeclKind::Param); + child.declare_symbol(id.0, DeclKind::Param); } } c.params.visit_mut_with(child); child.ident_type = old; if let Some(body) = &mut c.body { - child.mark_block(&mut body.ctxt); + child.ensure_node_id(&mut body.node_id); + child.mark_ctxt(&mut body.ctxt); body.visit_mut_children_with(child); } }); @@ -759,7 +948,8 @@ impl VisitMut for Resolver<'_> { match &mut e.decl { DefaultDecl::Fn(f) => { if f.ident.is_some() { - self.with_child(ScopeKind::Fn, |child| { + let node_id = self.ensure_node_id(&mut f.function.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { f.function.visit_mut_with(child); }); } else { @@ -768,7 +958,10 @@ impl VisitMut for Resolver<'_> { } DefaultDecl::Class(c) => { // Skip class expression visitor to treat as a declaration. - c.class.visit_mut_with(self) + let node_id = self.ensure_node_id(&mut c.class.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { + c.class.visit_mut_with(child) + }) } _ => e.visit_mut_children_with(self), } @@ -827,7 +1020,10 @@ impl VisitMut for Resolver<'_> { // We don't fold ident as Hoister handles this. node.function.decorators.visit_mut_with(self); - self.with_child(ScopeKind::Fn, |child| node.function.visit_mut_with(child)); + let node_id = self.ensure_node_id(&mut node.function.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { + node.function.visit_mut_with(child) + }); } fn visit_mut_fn_expr(&mut self, e: &mut FnExpr) { @@ -836,19 +1032,22 @@ impl VisitMut for Resolver<'_> { if let Some(ident) = &mut e.ident { self.with_child(ScopeKind::Fn, |child| { child.modify(ident, DeclKind::Function); - child.with_child(ScopeKind::Fn, |child| { + let node_id = child.ensure_node_id(&mut e.function.node_id); + child.with_child_for_node(ScopeKind::Fn, node_id, |child| { e.function.visit_mut_with(child); }); }); } else { - self.with_child(ScopeKind::Fn, |child| { + let node_id = self.ensure_node_id(&mut e.function.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { e.function.visit_mut_with(child); }); } } fn visit_mut_for_in_stmt(&mut self, n: &mut ForInStmt) { - self.with_child(ScopeKind::Block, |child| { + let node_id = self.ensure_node_id(&mut n.node_id); + self.with_child_for_node(ScopeKind::Block, node_id, |child| { n.left.visit_mut_with(child); n.right.visit_mut_with(child); @@ -857,7 +1056,8 @@ impl VisitMut for Resolver<'_> { } fn visit_mut_for_of_stmt(&mut self, n: &mut ForOfStmt) { - self.with_child(ScopeKind::Block, |child| { + let node_id = self.ensure_node_id(&mut n.node_id); + self.with_child_for_node(ScopeKind::Block, node_id, |child| { n.left.visit_mut_with(child); n.right.visit_mut_with(child); @@ -866,7 +1066,8 @@ impl VisitMut for Resolver<'_> { } fn visit_mut_for_stmt(&mut self, n: &mut ForStmt) { - self.with_child(ScopeKind::Block, |child| { + let node_id = self.ensure_node_id(&mut n.node_id); + self.with_child_for_node(ScopeKind::Block, node_id, |child| { child.ident_type = IdentType::Binding; n.init.visit_mut_with(child); child.ident_type = IdentType::Ref; @@ -879,7 +1080,7 @@ impl VisitMut for Resolver<'_> { } fn visit_mut_function(&mut self, f: &mut Function) { - self.mark_block(&mut f.ctxt); + self.mark_block(&mut f.ctxt, &mut f.node_id); f.type_params.visit_mut_with(self); self.ident_type = IdentType::Ref; @@ -893,7 +1094,7 @@ impl VisitMut for Resolver<'_> { .flat_map(find_pat_ids::<_, Id>); for id in params { - self.current.declared_symbols.insert(id.0, DeclKind::Param); + self.declare_symbol(id.0, DeclKind::Param); } } self.ident_type = IdentType::Binding; @@ -903,7 +1104,8 @@ impl VisitMut for Resolver<'_> { self.ident_type = IdentType::Ref; if let Some(body) = &mut f.body { - self.mark_block(&mut body.ctxt); + self.ensure_node_id(&mut body.node_id); + self.mark_ctxt(&mut body.ctxt); let old_strict_mode = self.strict_mode; if !self.strict_mode { self.strict_mode = body @@ -943,6 +1145,7 @@ impl VisitMut for Resolver<'_> { } i.ctxt = ctxt; + i.scope_id = ScopeId::UNRESOLVED; return; } @@ -969,13 +1172,14 @@ impl VisitMut for Resolver<'_> { return; } - if let Some(mark) = self.mark_for_ref(sym) { - let ctxt = ctxt.apply_mark(mark); + if let Some(resolved) = self.mark_for_ref(sym) { + let ctxt = ctxt.apply_mark(resolved.legacy_mark); if cfg!(debug_assertions) && LOG { debug!("\t -> {:?}", ctxt); } i.ctxt = ctxt; + i.scope_id = resolved.scope_id; } else { if cfg!(debug_assertions) && LOG { debug!("\t -> Unresolved"); @@ -988,6 +1192,7 @@ impl VisitMut for Resolver<'_> { } i.ctxt = ctxt; + i.scope_id = ScopeId::UNRESOLVED; // Support hoisting self.modify(i, self.decl_kind) } @@ -1012,7 +1217,7 @@ impl VisitMut for Resolver<'_> { self.ident_type = IdentType::Binding; s.local.visit_mut_with(self); if self.config.handle_types { - self.current.declared_types.insert(s.local.sym.clone()); + self.declare_type(s.local.sym.clone()); } self.ident_type = old; } @@ -1056,10 +1261,14 @@ impl VisitMut for Resolver<'_> { m.key.visit_mut_with(self); // Child folder - self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child)); + let node_id = self.ensure_node_id(&mut m.function.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { + m.function.visit_mut_with(child) + }); } fn visit_mut_module(&mut self, module: &mut Module) { + self.use_current_scope_node_id(&mut module.node_id); self.strict_mode = true; self.is_module = true; module.visit_mut_children_with(self) @@ -1116,7 +1325,10 @@ impl VisitMut for Resolver<'_> { { // Child folder - self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child)); + let node_id = self.ensure_node_id(&mut m.function.node_id); + self.with_child_for_node(ScopeKind::Fn, node_id, |child| { + m.function.visit_mut_with(child) + }); } } @@ -1134,6 +1346,7 @@ impl VisitMut for Resolver<'_> { } fn visit_mut_script(&mut self, script: &mut Script) { + self.use_current_scope_node_id(&mut script.node_id); self.strict_mode = script .body .first() @@ -1194,7 +1407,8 @@ impl VisitMut for Resolver<'_> { fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) { s.discriminant.visit_mut_with(self); - self.with_child(ScopeKind::Block, |child| { + let node_id = self.ensure_node_id(&mut s.node_id); + self.with_child_for_node(ScopeKind::Block, node_id, |child| { s.cases.visit_mut_with(child); }); } @@ -1278,15 +1492,14 @@ impl VisitMut for Resolver<'_> { // add the enum member names as declared symbols for this scope // Ex. `enum Foo { a, b = a }` let member_names = decl.members.iter().filter_map(|m| match &m.id { - TsEnumMemberId::Ident(id) => Some((id.sym.clone(), DeclKind::Lexical)), - TsEnumMemberId::Str(s) => s - .value - .as_atom() - .map(|atom| (atom.clone(), DeclKind::Lexical)), + TsEnumMemberId::Ident(id) => Some(id.sym.clone()), + TsEnumMemberId::Str(s) => s.value.as_atom().cloned(), #[cfg(swc_ast_unknown)] _ => None, }); - child.current.declared_symbols.extend(member_names); + for member_name in member_names { + child.declare_symbol(member_name, DeclKind::Lexical); + } decl.members.visit_mut_with(child); }); @@ -1709,10 +1922,7 @@ impl VisitMut for Hoister<'_, '_> { self.resolver.modify(&mut node.ident, DeclKind::Lexical); if self.resolver.config.handle_types { - self.resolver - .current - .declared_types - .insert(node.ident.sym.clone()); + self.resolver.declare_type(node.ident.sym.clone()); } } @@ -1833,10 +2043,7 @@ impl VisitMut for Hoister<'_, '_> { self.resolver.modify(&mut n.local, DeclKind::Lexical); if self.resolver.config.handle_types { - self.resolver - .current - .declared_types - .insert(n.local.sym.clone()); + self.resolver.declare_type(n.local.sym.clone()); } } @@ -1846,10 +2053,7 @@ impl VisitMut for Hoister<'_, '_> { self.resolver.modify(&mut n.local, DeclKind::Lexical); if self.resolver.config.handle_types { - self.resolver - .current - .declared_types - .insert(n.local.sym.clone()); + self.resolver.declare_type(n.local.sym.clone()); } } @@ -1859,10 +2063,7 @@ impl VisitMut for Hoister<'_, '_> { self.resolver.modify(&mut n.local, DeclKind::Lexical); if self.resolver.config.handle_types { - self.resolver - .current - .declared_types - .insert(n.local.sym.clone()); + self.resolver.declare_type(n.local.sym.clone()); } } diff --git a/crates/swc_ecma_transforms_base/src/resolver/tests.rs b/crates/swc_ecma_transforms_base/src/resolver/tests.rs index d32b9b91f67f..b8e7a65e09d1 100644 --- a/crates/swc_ecma_transforms_base/src/resolver/tests.rs +++ b/crates/swc_ecma_transforms_base/src/resolver/tests.rs @@ -63,7 +63,7 @@ fn test_mark_for() { let mark4 = Mark::fresh(mark3); let folder1 = Resolver::new( - Scope::new(ScopeKind::Block, mark1, None), + Scope::new(ScopeKind::Block, mark1, ScopeId(1), Some(NodeId(1)), None), InnerConfig { handle_types: true, unresolved_mark: Mark::fresh(Mark::root()), @@ -71,47 +71,65 @@ fn test_mark_for() { }, ); let mut folder2 = Resolver::new( - Scope::new(ScopeKind::Block, mark2, Some(&folder1.current)), + Scope::new( + ScopeKind::Block, + mark2, + ScopeId(2), + Some(NodeId(2)), + Some(&folder1.current), + ), InnerConfig { handle_types: true, unresolved_mark: Mark::fresh(Mark::root()), top_level_mark: mark2, }, ); - folder2 - .current - .declared_symbols - .insert(atom!("foo"), DeclKind::Var); + folder2.declare_symbol(atom!("foo"), DeclKind::Var); let mut folder3 = Resolver::new( - Scope::new(ScopeKind::Block, mark3, Some(&folder2.current)), + Scope::new( + ScopeKind::Block, + mark3, + ScopeId(3), + Some(NodeId(3)), + Some(&folder2.current), + ), InnerConfig { handle_types: true, unresolved_mark: Mark::fresh(Mark::root()), top_level_mark: mark3, }, ); - folder3 - .current - .declared_symbols - .insert(atom!("bar"), DeclKind::Var); - assert_eq!(folder3.mark_for_ref(&atom!("bar")), Some(mark3)); + folder3.declare_symbol(atom!("bar"), DeclKind::Var); + assert_eq!( + folder3.mark_for_ref(&atom!("bar")).map(|v| v.legacy_mark), + Some(mark3) + ); let mut folder4 = Resolver::new( - Scope::new(ScopeKind::Block, mark4, Some(&folder3.current)), + Scope::new( + ScopeKind::Block, + mark4, + ScopeId(4), + Some(NodeId(4)), + Some(&folder3.current), + ), InnerConfig { handle_types: true, unresolved_mark: Mark::fresh(Mark::root()), top_level_mark: mark4, }, ); - folder4 - .current - .declared_symbols - .insert(atom!("foo"), DeclKind::Var); + folder4.declare_symbol(atom!("foo"), DeclKind::Var); - assert_eq!(folder4.mark_for_ref(&atom!("foo")), Some(mark4)); - assert_eq!(folder4.mark_for_ref(&atom!("bar")), Some(mark3)); + assert_eq!( + folder4.mark_for_ref(&atom!("foo")).map(|v| v.legacy_mark), + Some(mark4) + ); + assert_eq!( + folder4.mark_for_ref(&atom!("bar")).map(|v| v.legacy_mark), + Some(mark3) + ); Ok(()) }) .unwrap(); diff --git a/crates/swc_ecma_transforms_base/tests/node_id.rs b/crates/swc_ecma_transforms_base/tests/node_id.rs new file mode 100644 index 000000000000..5289256762bd --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/node_id.rs @@ -0,0 +1,110 @@ +use swc_common::{Mark, SyntaxContext}; +use swc_ecma_ast::*; +use swc_ecma_parser::{lexer::Lexer, EsSyntax, Parser, StringInput, Syntax}; +use swc_ecma_transforms_base::resolver; +use swc_ecma_visit::{Visit, VisitMutWith, VisitWith}; +use testing::run_test2; + +fn resolved_program(src: &str) -> Program { + run_test2(false, |cm, handler| { + let fm = cm.new_source_file(swc_common::FileName::Anon.into(), src.to_string()); + let lexer = Lexer::new( + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + }), + EsVersion::latest(), + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program = parser + .parse_program() + .map_err(|err| err.into_diagnostic(&handler).emit())?; + + program.visit_mut_with(&mut resolver(Mark::new(), Mark::new(), false)); + + Ok(program) + }) + .unwrap() +} + +struct Recorder { + lines: Vec, +} + +impl Recorder { + fn record_node(&mut self, kind: &str, id: NodeId) { + self.lines.push(format!("{kind} node={}", id.as_u32())); + } + + fn record_ident(&mut self, ident: &Ident) { + let ctxt = if ident.ctxt == SyntaxContext::empty() { + "empty".to_string() + } else { + format!("{:?}", ident.ctxt).replace('#', "") + }; + + self.lines.push(format!( + "ident {} scope={} ctxt={ctxt}", + ident.sym, + ident.scope_id.as_u32() + )); + } +} + +impl Visit for Recorder { + fn visit_module(&mut self, node: &Module) { + self.record_node("module", node.node_id); + node.visit_children_with(self); + } + + fn visit_function(&mut self, node: &Function) { + self.record_node("function", node.node_id); + node.visit_children_with(self); + } + + fn visit_block_stmt(&mut self, node: &BlockStmt) { + self.record_node("block", node.node_id); + node.visit_children_with(self); + } + + fn visit_ident(&mut self, node: &Ident) { + self.record_ident(node); + } +} + +#[test] +fn resolver_assigns_stable_node_and_scope_ids() { + let program = resolved_program( + r#" +export function outer(a) { + let b = a; + { + let a = b; + c(a); + } +} +"#, + ); + + let mut recorder = Recorder { lines: Vec::new() }; + program.visit_with(&mut recorder); + + assert_eq!( + recorder.lines.join("\n"), + "\ +module node=1 +ident outer scope=1 ctxt=2 +function node=2 +ident a scope=2 ctxt=3 +block node=3 +ident b scope=2 ctxt=3 +ident a scope=2 ctxt=3 +block node=4 +ident a scope=4 ctxt=4 +ident b scope=2 ctxt=3 +ident c scope=4294967295 ctxt=1 +ident a scope=4 ctxt=4" + ); +} diff --git a/crates/swc_ecma_transforms_module/src/system_js.rs b/crates/swc_ecma_transforms_module/src/system_js.rs index 03b682cac2c3..45cfce370050 100644 --- a/crates/swc_ecma_transforms_module/src/system_js.rs +++ b/crates/swc_ecma_transforms_module/src/system_js.rs @@ -267,6 +267,7 @@ impl SystemJs { meta.setter_fn_stmts.push( ForInStmt { span: DUMMY_SP, + node_id: Default::default(), left: VarDecl { kind: VarDeclKind::Var, decls: vec![VarDeclarator { diff --git a/crates/swc_ecma_transforms_module/src/util.rs b/crates/swc_ecma_transforms_module/src/util.rs index 970af03a5c45..46e240e46440 100644 --- a/crates/swc_ecma_transforms_module/src/util.rs +++ b/crates/swc_ecma_transforms_module/src/util.rs @@ -307,6 +307,7 @@ pub(crate) fn esm_export() -> Function { let for_in_stmt: Stmt = ForInStmt { span: DUMMY_SP, + node_id: Default::default(), left: VarDecl { decls: vec![VarDeclarator { span: DUMMY_SP, diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs b/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs index 42163d610c9f..72d244c89cae 100644 --- a/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs +++ b/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs @@ -522,7 +522,12 @@ impl VisitMut for Remover { } } - Stmt::Block(BlockStmt { span, stmts, ctxt }) => { + Stmt::Block(BlockStmt { + span, + stmts, + ctxt, + node_id, + }) => { if stmts.is_empty() { if cfg!(feature = "debug") { debug!("Drooping an empty block statement"); @@ -541,7 +546,13 @@ impl VisitMut for Remover { v.visit_mut_with(self); v } else { - BlockStmt { span, stmts, ctxt }.into() + BlockStmt { + span, + stmts, + ctxt, + node_id, + } + .into() } } Stmt::Try(s) => { @@ -1146,6 +1157,7 @@ impl VisitMut for Remover { // `for(;;);` is shorter than `do ; while(true);` ForStmt { span: s.span, + node_id: Default::default(), init: None, test: None, update: None, @@ -1349,7 +1361,7 @@ impl Remover { span, mut stmts, ctxt, - .. + node_id, }) => { if stmts.is_empty() { continue; @@ -1357,7 +1369,13 @@ impl Remover { if !is_ok_to_inline_block(&stmts) { stmts.visit_mut_with(self); - BlockStmt { span, stmts, ctxt }.into() + BlockStmt { + span, + stmts, + ctxt, + node_id, + } + .into() } else { new_stmts.extend( stmts diff --git a/crates/swc_ecma_transforms_proposal/src/explicit_resource_management.rs b/crates/swc_ecma_transforms_proposal/src/explicit_resource_management.rs index b64739bbc325..ef3ff018a4e5 100644 --- a/crates/swc_ecma_transforms_proposal/src/explicit_resource_management.rs +++ b/crates/swc_ecma_transforms_proposal/src/explicit_resource_management.rs @@ -255,6 +255,7 @@ impl ExplicitResourceManagement { let catch_clause = CatchClause { span: DUMMY_SP, + node_id: Default::default(), param: Some(Pat::Ident(catch_e.clone().into())), body: BlockStmt { span: DUMMY_SP, diff --git a/crates/swc_ecma_visit/src/generated.rs b/crates/swc_ecma_visit/src/generated.rs index 36f4b37713a4..e2e9af5ecbbe 100644 --- a/crates/swc_ecma_visit/src/generated.rs +++ b/crates/swc_ecma_visit/src/generated.rs @@ -130,6 +130,13 @@ pub trait Visit { fn visit_binary_op(&mut self, node: &BinaryOp) { >::visit_children_with(node, self) } + #[doc = "Visit a node of type `BindingId`.\n\nBy default, this method calls \ + [`BindingId::visit_children_with`]. If you want to recurse, you need to call it \ + manually."] + #[inline] + fn visit_binding_id(&mut self, node: &BindingId) { + >::visit_children_with(node, self) + } #[doc = "Visit a node of type `BindingIdent`.\n\nBy default, this method calls \ [`BindingIdent::visit_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -2136,6 +2143,11 @@ where ::visit_binary_op(&mut **self, node) } + #[inline] + fn visit_binding_id(&mut self, node: &BindingId) { + ::visit_binding_id(&mut **self, node) + } + #[inline] fn visit_binding_ident(&mut self, node: &BindingIdent) { ::visit_binding_ident(&mut **self, node) @@ -3618,6 +3630,11 @@ where ::visit_binary_op(&mut **self, node) } + #[inline] + fn visit_binding_id(&mut self, node: &BindingId) { + ::visit_binding_id(&mut **self, node) + } + #[inline] fn visit_binding_ident(&mut self, node: &BindingIdent) { ::visit_binding_ident(&mut **self, node) @@ -5155,6 +5172,14 @@ where } } + #[inline] + fn visit_binding_id(&mut self, node: &BindingId) { + match self { + swc_visit::Either::Left(visitor) => Visit::visit_binding_id(visitor, node), + swc_visit::Either::Right(visitor) => Visit::visit_binding_id(visitor, node), + } + } + #[inline] fn visit_binding_ident(&mut self, node: &BindingIdent) { match self { @@ -7574,6 +7599,14 @@ where } } + #[inline] + fn visit_binding_id(&mut self, node: &BindingId) { + if self.enabled { + ::visit_binding_id(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_binding_ident(&mut self, node: &BindingIdent) { if self.enabled { @@ -9873,6 +9906,7 @@ impl VisitWith for ArrowExpr { ArrowExpr { span, ctxt, + node_id, params, body, is_async, @@ -10219,6 +10253,22 @@ impl VisitWith for BinaryOp { } } } +impl VisitWith for BindingId { + #[doc = "Calls [Visit`::visit_binding_id`] with `self`."] + fn visit_with(&self, visitor: &mut V) { + ::visit_binding_id(visitor, self) + } + + fn visit_children_with(&self, visitor: &mut V) { + match self { + BindingId { sym, scope_id } => { + { + >::visit_with(sym, visitor) + }; + } + } + } +} impl VisitWith for BindingIdent { #[doc = "Calls [Visit`::visit_binding_ident`] with `self`."] fn visit_with(&self, visitor: &mut V) { @@ -10246,7 +10296,12 @@ impl VisitWith for BlockStmt { fn visit_children_with(&self, visitor: &mut V) { match self { - BlockStmt { span, ctxt, stmts } => { + BlockStmt { + span, + ctxt, + node_id, + stmts, + } => { { >::visit_with(span, visitor) }; @@ -10380,7 +10435,12 @@ impl VisitWith for CatchClause { fn visit_children_with(&self, visitor: &mut V) { match self { - CatchClause { span, param, body } => { + CatchClause { + span, + node_id, + param, + body, + } => { { >::visit_with(span, visitor) }; @@ -10405,6 +10465,7 @@ impl VisitWith for Class { Class { span, ctxt, + node_id, decorators, body, super_class, @@ -10669,6 +10730,7 @@ impl VisitWith for Constructor { Constructor { span, ctxt, + node_id, key, params, body, @@ -11255,6 +11317,7 @@ impl VisitWith for ForInStmt { match self { ForInStmt { span, + node_id, left, right, body, @@ -11285,6 +11348,7 @@ impl VisitWith for ForOfStmt { match self { ForOfStmt { span, + node_id, is_await, left, right, @@ -11316,6 +11380,7 @@ impl VisitWith for ForStmt { match self { ForStmt { span, + node_id, init, test, update, @@ -11353,6 +11418,7 @@ impl VisitWith for Function { decorators, span, ctxt, + node_id, body, is_generator, is_async, @@ -11425,6 +11491,7 @@ impl VisitWith for Ident { Ident { span, ctxt, + scope_id, sym, optional, } => { @@ -12374,6 +12441,7 @@ impl VisitWith for Module { match self { Module { span, + node_id, body, shebang, } => { @@ -13096,6 +13164,7 @@ impl VisitWith for Script { match self { Script { span, + node_id, body, shebang, } => { @@ -13430,6 +13499,7 @@ impl VisitWith for SwitchStmt { match self { SwitchStmt { span, + node_id, discriminant, cases, } => { @@ -16753,6 +16823,17 @@ pub trait VisitAstPath { ) { >::visit_children_with_ast_path(node, self, __ast_path) } + #[doc = "Visit a node of type `BindingId`.\n\nBy default, this method calls \ + [`BindingId::visit_children_with_ast_path`]. If you want to recurse, you need to call \ + it manually."] + #[inline] + fn visit_binding_id<'ast: 'r, 'r>( + &mut self, + node: &'ast BindingId, + __ast_path: &mut AstNodePath<'r>, + ) { + >::visit_children_with_ast_path(node, self, __ast_path) + } #[doc = "Visit a node of type `BindingIdent`.\n\nBy default, this method calls \ [`BindingIdent::visit_children_with_ast_path`]. If you want to recurse, you need to \ call it manually."] @@ -20226,6 +20307,15 @@ where ::visit_binary_op(&mut **self, node, __ast_path) } + #[inline] + fn visit_binding_id<'ast: 'r, 'r>( + &mut self, + node: &'ast BindingId, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_binding_id(&mut **self, node, __ast_path) + } + #[inline] fn visit_binding_ident<'ast: 'r, 'r>( &mut self, @@ -22791,6 +22881,15 @@ where ::visit_binary_op(&mut **self, node, __ast_path) } + #[inline] + fn visit_binding_id<'ast: 'r, 'r>( + &mut self, + node: &'ast BindingId, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_binding_id(&mut **self, node, __ast_path) + } + #[inline] fn visit_binding_ident<'ast: 'r, 'r>( &mut self, @@ -25481,6 +25580,22 @@ where } } + #[inline] + fn visit_binding_id<'ast: 'r, 'r>( + &mut self, + node: &'ast BindingId, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitAstPath::visit_binding_id(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitAstPath::visit_binding_id(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_binding_ident<'ast: 'r, 'r>( &mut self, @@ -30003,6 +30118,18 @@ where } } + #[inline] + fn visit_binding_id<'ast: 'r, 'r>( + &mut self, + node: &'ast BindingId, + __ast_path: &mut AstNodePath<'r>, + ) { + if self.enabled { + ::visit_binding_id(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_binding_ident<'ast: 'r, 'r>( &mut self, @@ -33429,6 +33556,7 @@ impl VisitWithAstPath for ArrowExpr { ArrowExpr { span, ctxt, + node_id, params, body, is_async, @@ -34209,6 +34337,40 @@ impl VisitWithAstPath for BinaryOp { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitWithAstPath for BindingId { + #[doc = "Calls [VisitAstPath`::visit_binding_id`] with `self`."] + fn visit_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_binding_id(visitor, self, __ast_path) + } + + fn visit_children_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + BindingId { sym, scope_id } => { + { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::BindingId( + self, + self::fields::BindingIdField::Sym, + )); + >::visit_with_ast_path( + sym, + visitor, + &mut *__ast_path, + ) + }; + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitWithAstPath for BindingIdent { #[doc = "Calls [VisitAstPath`::visit_binding_ident`] with `self`."] fn visit_with_ast_path<'ast: 'r, 'r>( @@ -34270,7 +34432,12 @@ impl VisitWithAstPath for BlockStmt { __ast_path: &mut AstNodePath<'r>, ) { match self { - BlockStmt { span, ctxt, stmts } => { + BlockStmt { + span, + ctxt, + node_id, + stmts, + } => { { let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::BlockStmt( self, @@ -34584,7 +34751,12 @@ impl VisitWithAstPath for CatchClause { __ast_path: &mut AstNodePath<'r>, ) { match self { - CatchClause { span, param, body } => { + CatchClause { + span, + node_id, + param, + body, + } => { { let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::CatchClause( self, @@ -34643,6 +34815,7 @@ impl VisitWithAstPath for Class { Class { span, ctxt, + node_id, decorators, body, super_class, @@ -35284,6 +35457,7 @@ impl VisitWithAstPath for Constructor { Constructor { span, ctxt, + node_id, key, params, body, @@ -36800,6 +36974,7 @@ impl VisitWithAstPath for ForInStmt { match self { ForInStmt { span, + node_id, left, right, body, @@ -36872,6 +37047,7 @@ impl VisitWithAstPath for ForOfStmt { match self { ForOfStmt { span, + node_id, is_await, left, right, @@ -36945,6 +37121,7 @@ impl VisitWithAstPath for ForStmt { match self { ForStmt { span, + node_id, init, test, update, @@ -37032,6 +37209,7 @@ impl VisitWithAstPath for Function { decorators, span, ctxt, + node_id, body, is_generator, is_async, @@ -37212,6 +37390,7 @@ impl VisitWithAstPath for Ident { Ident { span, ctxt, + scope_id, sym, optional, } => { @@ -39473,6 +39652,7 @@ impl VisitWithAstPath for Module { match self { Module { span, + node_id, body, shebang, } => { @@ -41219,6 +41399,7 @@ impl VisitWithAstPath for Script { match self { Script { span, + node_id, body, shebang, } => { @@ -42089,6 +42270,7 @@ impl VisitWithAstPath for SwitchStmt { match self { SwitchStmt { span, + node_id, discriminant, cases, } => { @@ -49209,6 +49391,13 @@ pub trait VisitMut { fn visit_mut_binary_op(&mut self, node: &mut BinaryOp) { >::visit_mut_children_with(node, self) } + #[doc = "Visit a node of type `BindingId`.\n\nBy default, this method calls \ + [`BindingId::visit_mut_children_with`]. If you want to recurse, you need to call it \ + manually."] + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId) { + >::visit_mut_children_with(node, self) + } #[doc = "Visit a node of type `BindingIdent`.\n\nBy default, this method calls \ [`BindingIdent::visit_mut_children_with`]. If you want to recurse, you need to call \ it manually."] @@ -51245,6 +51434,11 @@ where ::visit_mut_binary_op(&mut **self, node) } + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId) { + ::visit_mut_binding_id(&mut **self, node) + } + #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent) { ::visit_mut_binding_ident(&mut **self, node) @@ -52727,6 +52921,11 @@ where ::visit_mut_binary_op(&mut **self, node) } + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId) { + ::visit_mut_binding_id(&mut **self, node) + } + #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent) { ::visit_mut_binding_ident(&mut **self, node) @@ -54268,6 +54467,14 @@ where } } + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId) { + match self { + swc_visit::Either::Left(visitor) => VisitMut::visit_mut_binding_id(visitor, node), + swc_visit::Either::Right(visitor) => VisitMut::visit_mut_binding_id(visitor, node), + } + } + #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent) { match self { @@ -56991,6 +57198,14 @@ where } } + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId) { + if self.enabled { + ::visit_mut_binding_id(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent) { if self.enabled { @@ -59290,6 +59505,7 @@ impl VisitMutWith for ArrowExpr { ArrowExpr { span, ctxt, + node_id, params, body, is_async, @@ -59645,6 +59861,22 @@ impl VisitMutWith for BinaryOp { } } } +impl VisitMutWith for BindingId { + #[doc = "Calls [VisitMut`::visit_mut_binding_id`] with `self`."] + fn visit_mut_with(&mut self, visitor: &mut V) { + ::visit_mut_binding_id(visitor, self) + } + + fn visit_mut_children_with(&mut self, visitor: &mut V) { + match self { + BindingId { sym, scope_id } => { + { + >::visit_mut_with(sym, visitor) + }; + } + } + } +} impl VisitMutWith for BindingIdent { #[doc = "Calls [VisitMut`::visit_mut_binding_ident`] with `self`."] fn visit_mut_with(&mut self, visitor: &mut V) { @@ -59672,7 +59904,12 @@ impl VisitMutWith for BlockStmt { fn visit_mut_children_with(&mut self, visitor: &mut V) { match self { - BlockStmt { span, ctxt, stmts } => { + BlockStmt { + span, + ctxt, + node_id, + stmts, + } => { { >::visit_mut_with(span, visitor) }; @@ -59806,7 +60043,12 @@ impl VisitMutWith for CatchClause { fn visit_mut_children_with(&mut self, visitor: &mut V) { match self { - CatchClause { span, param, body } => { + CatchClause { + span, + node_id, + param, + body, + } => { { >::visit_mut_with(span, visitor) }; @@ -59831,6 +60073,7 @@ impl VisitMutWith for Class { Class { span, ctxt, + node_id, decorators, body, super_class, @@ -60106,6 +60349,7 @@ impl VisitMutWith for Constructor { Constructor { span, ctxt, + node_id, key, params, body, @@ -60695,6 +60939,7 @@ impl VisitMutWith for ForInStmt { match self { ForInStmt { span, + node_id, left, right, body, @@ -60725,6 +60970,7 @@ impl VisitMutWith for ForOfStmt { match self { ForOfStmt { span, + node_id, is_await, left, right, @@ -60756,6 +61002,7 @@ impl VisitMutWith for ForStmt { match self { ForStmt { span, + node_id, init, test, update, @@ -60793,6 +61040,7 @@ impl VisitMutWith for Function { decorators, span, ctxt, + node_id, body, is_generator, is_async, @@ -60871,6 +61119,7 @@ impl VisitMutWith for Ident { Ident { span, ctxt, + scope_id, sym, optional, } => { @@ -61820,6 +62069,7 @@ impl VisitMutWith for Module { match self { Module { span, + node_id, body, shebang, } => { @@ -62548,6 +62798,7 @@ impl VisitMutWith for Script { match self { Script { span, + node_id, body, shebang, } => { @@ -62882,6 +63133,7 @@ impl VisitMutWith for SwitchStmt { match self { SwitchStmt { span, + node_id, discriminant, cases, } => { @@ -66180,6 +66432,15 @@ pub trait VisitMutAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `BindingId`.\n\nBy default, this method calls \ + [`BindingId::visit_mut_children_with_ast_path`]. If you want to recurse, you need to \ + call it manually."] + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId, __ast_path: &mut AstKindPath) { + >::visit_mut_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `BindingIdent`.\n\nBy default, this method calls \ [`BindingIdent::visit_mut_children_with_ast_path`]. If you want to recurse, you need \ to call it manually."] @@ -69241,6 +69502,11 @@ where ::visit_mut_binary_op(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId, __ast_path: &mut AstKindPath) { + ::visit_mut_binding_id(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent, __ast_path: &mut AstKindPath) { ::visit_mut_binding_ident(&mut **self, node, __ast_path) @@ -71214,6 +71480,11 @@ where ::visit_mut_binary_op(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId, __ast_path: &mut AstKindPath) { + ::visit_mut_binding_id(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent, __ast_path: &mut AstKindPath) { ::visit_mut_binding_ident(&mut **self, node, __ast_path) @@ -73314,6 +73585,18 @@ where } } + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId, __ast_path: &mut AstKindPath) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMutAstPath::visit_mut_binding_id(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitMutAstPath::visit_mut_binding_id(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent, __ast_path: &mut AstKindPath) { match self { @@ -77276,6 +77559,14 @@ where } } + #[inline] + fn visit_mut_binding_id(&mut self, node: &mut BindingId, __ast_path: &mut AstKindPath) { + if self.enabled { + ::visit_mut_binding_id(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_mut_binding_ident(&mut self, node: &mut BindingIdent, __ast_path: &mut AstKindPath) { if self.enabled { @@ -80359,6 +80650,7 @@ impl VisitMutWithAstPath for ArrowExpr { ArrowExpr { span, ctxt, + node_id, params, body, is_async, @@ -80985,6 +81277,30 @@ impl VisitMutWithAstPath for BinaryOp { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitMutWithAstPath for BindingId { + #[doc = "Calls [VisitMutAstPath`::visit_mut_binding_id`] with `self`."] + fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + ::visit_mut_binding_id(visitor, self, __ast_path) + } + + fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + match self { + BindingId { sym, scope_id } => { + { + let mut __ast_path = __ast_path + .with_guard(AstParentKind::BindingId(self::fields::BindingIdField::Sym)); + >::visit_mut_with_ast_path( + sym, + visitor, + &mut *__ast_path, + ) + }; + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitMutWithAstPath for BindingIdent { #[doc = "Calls [VisitMutAstPath`::visit_mut_binding_ident`] with `self`."] fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { @@ -81028,7 +81344,12 @@ impl VisitMutWithAstPath for BlockStmt { fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { match self { - BlockStmt { span, ctxt, stmts } => { + BlockStmt { + span, + ctxt, + node_id, + stmts, + } => { { let mut __ast_path = __ast_path .with_guard(AstParentKind::BlockStmt(self::fields::BlockStmtField::Span)); @@ -81270,7 +81591,12 @@ impl VisitMutWithAstPath for CatchClause { fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { match self { - CatchClause { span, param, body } => { + CatchClause { + span, + node_id, + param, + body, + } => { { let mut __ast_path = __ast_path.with_guard(AstParentKind::CatchClause( self::fields::CatchClauseField::Span, @@ -81318,6 +81644,7 @@ impl VisitMutWithAstPath for Class { Class { span, ctxt, + node_id, decorators, body, super_class, @@ -81843,6 +82170,7 @@ impl VisitMutWithAstPath for Constructor { Constructor { span, ctxt, + node_id, key, params, body, @@ -83074,6 +83402,7 @@ impl VisitMutWithAstPath for ForInStmt { match self { ForInStmt { span, + node_id, left, right, body, @@ -83131,6 +83460,7 @@ impl VisitMutWithAstPath for ForOfStmt { match self { ForOfStmt { span, + node_id, is_await, left, right, @@ -83189,6 +83519,7 @@ impl VisitMutWithAstPath for ForStmt { match self { ForStmt { span, + node_id, init, test, update, @@ -83258,6 +83589,7 @@ impl VisitMutWithAstPath for Function { decorators, span, ctxt, + node_id, body, is_generator, is_async, @@ -83404,6 +83736,7 @@ impl VisitMutWithAstPath for Ident { Ident { span, ctxt, + scope_id, sym, optional, } => { @@ -85184,6 +85517,7 @@ impl VisitMutWithAstPath for Module { match self { Module { span, + node_id, body, shebang, } => { @@ -86585,6 +86919,7 @@ impl VisitMutWithAstPath for Script { match self { Script { span, + node_id, body, shebang, } => { @@ -87309,6 +87644,7 @@ impl VisitMutWithAstPath for SwitchStmt { match self { SwitchStmt { span, + node_id, discriminant, cases, } => { @@ -92833,6 +93169,13 @@ pub trait Fold { fn fold_binary_op(&mut self, node: BinaryOp) -> BinaryOp { >::fold_children_with(node, self) } + #[doc = "Visit a node of type `BindingId`.\n\nBy default, this method calls \ + [`BindingId::fold_children_with`]. If you want to recurse, you need to call it \ + manually."] + #[inline] + fn fold_binding_id(&mut self, node: BindingId) -> BindingId { + >::fold_children_with(node, self) + } #[doc = "Visit a node of type `BindingIdent`.\n\nBy default, this method calls \ [`BindingIdent::fold_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -94885,6 +95228,11 @@ where ::fold_binary_op(&mut **self, node) } + #[inline] + fn fold_binding_id(&mut self, node: BindingId) -> BindingId { + ::fold_binding_id(&mut **self, node) + } + #[inline] fn fold_binding_ident(&mut self, node: BindingIdent) -> BindingIdent { ::fold_binding_ident(&mut **self, node) @@ -96427,6 +96775,11 @@ where ::fold_binary_op(&mut **self, node) } + #[inline] + fn fold_binding_id(&mut self, node: BindingId) -> BindingId { + ::fold_binding_id(&mut **self, node) + } + #[inline] fn fold_binding_ident(&mut self, node: BindingIdent) -> BindingIdent { ::fold_binding_ident(&mut **self, node) @@ -98024,6 +98377,14 @@ where } } + #[inline] + fn fold_binding_id(&mut self, node: BindingId) -> BindingId { + match self { + swc_visit::Either::Left(visitor) => Fold::fold_binding_id(visitor, node), + swc_visit::Either::Right(visitor) => Fold::fold_binding_id(visitor, node), + } + } + #[inline] fn fold_binding_ident(&mut self, node: BindingIdent) -> BindingIdent { match self { @@ -100495,6 +100856,15 @@ where } } + #[inline] + fn fold_binding_id(&mut self, node: BindingId) -> BindingId { + if self.enabled { + ::fold_binding_id(&mut self.visitor, node) + } else { + node + } + } + #[inline] fn fold_binding_ident(&mut self, node: BindingIdent) -> BindingIdent { if self.enabled { @@ -103130,6 +103500,7 @@ impl FoldWith for ArrowExpr { ArrowExpr { span, ctxt, + node_id, params, body, is_async, @@ -103149,6 +103520,7 @@ impl FoldWith for ArrowExpr { ArrowExpr { span, ctxt, + node_id, params, body, is_async, @@ -103458,6 +103830,21 @@ impl FoldWith for BinaryOp { } } } +impl FoldWith for BindingId { + #[doc = "Calls [Fold`::fold_binding_id`] with `self`."] + fn fold_with(self, visitor: &mut V) -> Self { + ::fold_binding_id(visitor, self) + } + + fn fold_children_with(self, visitor: &mut V) -> Self { + match self { + BindingId { sym, scope_id } => { + let sym = { >::fold_with(sym, visitor) }; + BindingId { sym, scope_id } + } + } + } +} impl FoldWith for BindingIdent { #[doc = "Calls [Fold`::fold_binding_ident`] with `self`."] fn fold_with(self, visitor: &mut V) -> Self { @@ -103483,11 +103870,21 @@ impl FoldWith for BlockStmt { fn fold_children_with(self, visitor: &mut V) -> Self { match self { - BlockStmt { span, ctxt, stmts } => { + BlockStmt { + span, + ctxt, + node_id, + stmts, + } => { let span = { >::fold_with(span, visitor) }; let ctxt = { >::fold_with(ctxt, visitor) }; let stmts = { as FoldWith>::fold_with(stmts, visitor) }; - BlockStmt { span, ctxt, stmts } + BlockStmt { + span, + ctxt, + node_id, + stmts, + } } } } @@ -103612,11 +104009,21 @@ impl FoldWith for CatchClause { fn fold_children_with(self, visitor: &mut V) -> Self { match self { - CatchClause { span, param, body } => { + CatchClause { + span, + node_id, + param, + body, + } => { let span = { >::fold_with(span, visitor) }; let param = { as FoldWith>::fold_with(param, visitor) }; let body = { >::fold_with(body, visitor) }; - CatchClause { span, param, body } + CatchClause { + span, + node_id, + param, + body, + } } } } @@ -103632,6 +104039,7 @@ impl FoldWith for Class { Class { span, ctxt, + node_id, decorators, body, super_class, @@ -103661,6 +104069,7 @@ impl FoldWith for Class { Class { span, ctxt, + node_id, decorators, body, super_class, @@ -103908,6 +104317,7 @@ impl FoldWith for Constructor { Constructor { span, ctxt, + node_id, key, params, body, @@ -103925,6 +104335,7 @@ impl FoldWith for Constructor { Constructor { span, ctxt, + node_id, key, params, body, @@ -104518,6 +104929,7 @@ impl FoldWith for ForInStmt { match self { ForInStmt { span, + node_id, left, right, body, @@ -104528,6 +104940,7 @@ impl FoldWith for ForInStmt { let body = { as FoldWith>::fold_with(body, visitor) }; ForInStmt { span, + node_id, left, right, body, @@ -104546,6 +104959,7 @@ impl FoldWith for ForOfStmt { match self { ForOfStmt { span, + node_id, is_await, left, right, @@ -104557,6 +104971,7 @@ impl FoldWith for ForOfStmt { let body = { as FoldWith>::fold_with(body, visitor) }; ForOfStmt { span, + node_id, is_await, left, right, @@ -104576,6 +104991,7 @@ impl FoldWith for ForStmt { match self { ForStmt { span, + node_id, init, test, update, @@ -104588,6 +105004,7 @@ impl FoldWith for ForStmt { let body = { as FoldWith>::fold_with(body, visitor) }; ForStmt { span, + node_id, init, test, update, @@ -104610,6 +105027,7 @@ impl FoldWith for Function { decorators, span, ctxt, + node_id, body, is_generator, is_async, @@ -104632,6 +105050,7 @@ impl FoldWith for Function { decorators, span, ctxt, + node_id, body, is_generator, is_async, @@ -104682,6 +105101,7 @@ impl FoldWith for Ident { Ident { span, ctxt, + scope_id, sym, optional, } => { @@ -104691,6 +105111,7 @@ impl FoldWith for Ident { Ident { span, ctxt, + scope_id, sym, optional, } @@ -105592,6 +106013,7 @@ impl FoldWith for Module { match self { Module { span, + node_id, body, shebang, } => { @@ -105601,6 +106023,7 @@ impl FoldWith for Module { { as FoldWith>::fold_with(shebang, visitor) }; Module { span, + node_id, body, shebang, } @@ -106341,6 +106764,7 @@ impl FoldWith for Script { match self { Script { span, + node_id, body, shebang, } => { @@ -106350,6 +106774,7 @@ impl FoldWith for Script { { as FoldWith>::fold_with(shebang, visitor) }; Script { span, + node_id, body, shebang, } @@ -106680,6 +107105,7 @@ impl FoldWith for SwitchStmt { match self { SwitchStmt { span, + node_id, discriminant, cases, } => { @@ -106688,6 +107114,7 @@ impl FoldWith for SwitchStmt { let cases = { as FoldWith>::fold_with(cases, visitor) }; SwitchStmt { span, + node_id, discriminant, cases, } @@ -109861,6 +110288,13 @@ pub trait FoldAstPath { fn fold_binary_op(&mut self, node: BinaryOp, __ast_path: &mut AstKindPath) -> BinaryOp { >::fold_children_with_ast_path(node, self, __ast_path) } + #[doc = "Visit a node of type `BindingId`.\n\nBy default, this method calls \ + [`BindingId::fold_children_with_ast_path`]. If you want to recurse, you need to call \ + it manually."] + #[inline] + fn fold_binding_id(&mut self, node: BindingId, __ast_path: &mut AstKindPath) -> BindingId { + >::fold_children_with_ast_path(node, self, __ast_path) + } #[doc = "Visit a node of type `BindingIdent`.\n\nBy default, this method calls \ [`BindingIdent::fold_children_with_ast_path`]. If you want to recurse, you need to \ call it manually."] @@ -112888,6 +113322,11 @@ where ::fold_binary_op(&mut **self, node, __ast_path) } + #[inline] + fn fold_binding_id(&mut self, node: BindingId, __ast_path: &mut AstKindPath) -> BindingId { + ::fold_binding_id(&mut **self, node, __ast_path) + } + #[inline] fn fold_binding_ident( &mut self, @@ -115093,6 +115532,11 @@ where ::fold_binary_op(&mut **self, node, __ast_path) } + #[inline] + fn fold_binding_id(&mut self, node: BindingId, __ast_path: &mut AstKindPath) -> BindingId { + ::fold_binding_id(&mut **self, node, __ast_path) + } + #[inline] fn fold_binding_ident( &mut self, @@ -117421,6 +117865,18 @@ where } } + #[inline] + fn fold_binding_id(&mut self, node: BindingId, __ast_path: &mut AstKindPath) -> BindingId { + match self { + swc_visit::Either::Left(visitor) => { + FoldAstPath::fold_binding_id(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + FoldAstPath::fold_binding_id(visitor, node, __ast_path) + } + } + } + #[inline] fn fold_binding_ident( &mut self, @@ -121543,6 +121999,15 @@ where } } + #[inline] + fn fold_binding_id(&mut self, node: BindingId, __ast_path: &mut AstKindPath) -> BindingId { + if self.enabled { + ::fold_binding_id(&mut self.visitor, node, __ast_path) + } else { + node + } + } + #[inline] fn fold_binding_ident( &mut self, @@ -124878,6 +125343,7 @@ impl FoldWithAstPath for ArrowExpr { ArrowExpr { span, ctxt, + node_id, params, body, is_async, @@ -124945,6 +125411,7 @@ impl FoldWithAstPath for ArrowExpr { ArrowExpr { span, ctxt, + node_id, params, body, is_async, @@ -125548,6 +126015,31 @@ impl FoldWithAstPath for BinaryOp { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl FoldWithAstPath for BindingId { + #[doc = "Calls [FoldAstPath`::fold_binding_id`] with `self`."] + fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + ::fold_binding_id(visitor, self, __ast_path) + } + + fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + match self { + BindingId { sym, scope_id } => { + let sym = { + let mut __ast_path = __ast_path + .with_guard(AstParentKind::BindingId(self::fields::BindingIdField::Sym)); + >::fold_with_ast_path( + sym, + visitor, + &mut *__ast_path, + ) + }; + BindingId { sym, scope_id } + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl FoldWithAstPath for BindingIdent { #[doc = "Calls [FoldAstPath`::fold_binding_ident`] with `self`."] fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { @@ -125588,7 +126080,12 @@ impl FoldWithAstPath for BlockStmt { fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { match self { - BlockStmt { span, ctxt, stmts } => { + BlockStmt { + span, + ctxt, + node_id, + stmts, + } => { let span = { let mut __ast_path = __ast_path .with_guard(AstParentKind::BlockStmt(self::fields::BlockStmtField::Span)); @@ -125617,7 +126114,12 @@ impl FoldWithAstPath for BlockStmt { &mut *__ast_path, ) }; - BlockStmt { span, ctxt, stmts } + BlockStmt { + span, + ctxt, + node_id, + stmts, + } } } } @@ -125845,7 +126347,12 @@ impl FoldWithAstPath for CatchClause { fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { match self { - CatchClause { span, param, body } => { + CatchClause { + span, + node_id, + param, + body, + } => { let span = { let mut __ast_path = __ast_path.with_guard(AstParentKind::CatchClause( self::fields::CatchClauseField::Span, @@ -125876,7 +126383,12 @@ impl FoldWithAstPath for CatchClause { &mut *__ast_path, ) }; - CatchClause { span, param, body } + CatchClause { + span, + node_id, + param, + body, + } } } } @@ -125894,6 +126406,7 @@ impl FoldWithAstPath for Class { Class { span, ctxt, + node_id, decorators, body, super_class, @@ -125977,6 +126490,7 @@ impl FoldWithAstPath for Class { Class { span, ctxt, + node_id, decorators, body, super_class, @@ -126482,6 +126996,7 @@ impl FoldWithAstPath for Constructor { Constructor { span, ctxt, + node_id, key, params, body, @@ -126551,6 +127066,7 @@ impl FoldWithAstPath for Constructor { Constructor { span, ctxt, + node_id, key, params, body, @@ -127807,6 +128323,7 @@ impl FoldWithAstPath for ForInStmt { match self { ForInStmt { span, + node_id, left, right, body, @@ -127850,6 +128367,7 @@ impl FoldWithAstPath for ForInStmt { }; ForInStmt { span, + node_id, left, right, body, @@ -127870,6 +128388,7 @@ impl FoldWithAstPath for ForOfStmt { match self { ForOfStmt { span, + node_id, is_await, left, right, @@ -127914,6 +128433,7 @@ impl FoldWithAstPath for ForOfStmt { }; ForOfStmt { span, + node_id, is_await, left, right, @@ -127935,6 +128455,7 @@ impl FoldWithAstPath for ForStmt { match self { ForStmt { span, + node_id, init, test, update, @@ -127987,6 +128508,7 @@ impl FoldWithAstPath for ForStmt { }; ForStmt { span, + node_id, init, test, update, @@ -128011,6 +128533,7 @@ impl FoldWithAstPath for Function { decorators, span, ctxt, + node_id, body, is_generator, is_async, @@ -128089,6 +128612,7 @@ impl FoldWithAstPath for Function { decorators, span, ctxt, + node_id, body, is_generator, is_async, @@ -128178,6 +128702,7 @@ impl FoldWithAstPath for Ident { Ident { span, ctxt, + scope_id, sym, optional, } => { @@ -128211,6 +128736,7 @@ impl FoldWithAstPath for Ident { Ident { span, ctxt, + scope_id, sym, optional, } @@ -130061,6 +130587,7 @@ impl FoldWithAstPath for Module { match self { Module { span, + node_id, body, shebang, } => { @@ -130094,6 +130621,7 @@ impl FoldWithAstPath for Module { }; Module { span, + node_id, body, shebang, } @@ -131580,6 +132108,7 @@ impl FoldWithAstPath for Script { match self { Script { span, + node_id, body, shebang, } => { @@ -131613,6 +132142,7 @@ impl FoldWithAstPath for Script { }; Script { span, + node_id, body, shebang, } @@ -132355,6 +132885,7 @@ impl FoldWithAstPath for SwitchStmt { match self { SwitchStmt { span, + node_id, discriminant, cases, } => { @@ -132390,6 +132921,7 @@ impl FoldWithAstPath for SwitchStmt { }; SwitchStmt { span, + node_id, discriminant, cases, } @@ -138176,6 +138708,8 @@ pub mod fields { Span, #[doc = "Represents [`ArrowExpr::ctxt`]"] Ctxt, + #[doc = "Represents [`ArrowExpr::node_id`]"] + NodeId, #[doc = "Represents [`ArrowExpr::params`]"] Params(usize), #[doc = "Represents [`ArrowExpr::body`]"] @@ -138477,6 +139011,21 @@ pub mod fields { #[doc = "Represents [`BinaryOp::NullishCoalescing`]"] NullishCoalescing, } + impl BindingIdField { + pub(crate) fn set_index(&mut self, index: usize) { + match self { + _ => swc_visit::wrong_ast_path(), + } + } + } + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] + pub enum BindingIdField { + #[doc = "Represents [`BindingId::sym`]"] + Sym, + #[doc = "Represents [`BindingId::scope_id`]"] + ScopeId, + } impl BindingIdentField { pub(crate) fn set_index(&mut self, index: usize) { match self { @@ -138510,6 +139059,8 @@ pub mod fields { Span, #[doc = "Represents [`BlockStmt::ctxt`]"] Ctxt, + #[doc = "Represents [`BlockStmt::node_id`]"] + NodeId, #[doc = "Represents [`BlockStmt::stmts`]"] Stmts(usize), } @@ -138610,6 +139161,8 @@ pub mod fields { pub enum CatchClauseField { #[doc = "Represents [`CatchClause::span`]"] Span, + #[doc = "Represents [`CatchClause::node_id`]"] + NodeId, #[doc = "Represents [`CatchClause::param`]"] Param, #[doc = "Represents [`CatchClause::body`]"] @@ -138641,6 +139194,8 @@ pub mod fields { Span, #[doc = "Represents [`Class::ctxt`]"] Ctxt, + #[doc = "Represents [`Class::node_id`]"] + NodeId, #[doc = "Represents [`Class::decorators`]"] Decorators(usize), #[doc = "Represents [`Class::body`]"] @@ -138838,6 +139393,8 @@ pub mod fields { Span, #[doc = "Represents [`Constructor::ctxt`]"] Ctxt, + #[doc = "Represents [`Constructor::node_id`]"] + NodeId, #[doc = "Represents [`Constructor::key`]"] Key, #[doc = "Represents [`Constructor::params`]"] @@ -139267,6 +139824,8 @@ pub mod fields { pub enum ForInStmtField { #[doc = "Represents [`ForInStmt::span`]"] Span, + #[doc = "Represents [`ForInStmt::node_id`]"] + NodeId, #[doc = "Represents [`ForInStmt::left`]"] Left, #[doc = "Represents [`ForInStmt::right`]"] @@ -139286,6 +139845,8 @@ pub mod fields { pub enum ForOfStmtField { #[doc = "Represents [`ForOfStmt::span`]"] Span, + #[doc = "Represents [`ForOfStmt::node_id`]"] + NodeId, #[doc = "Represents [`ForOfStmt::is_await`]"] IsAwait, #[doc = "Represents [`ForOfStmt::left`]"] @@ -139307,6 +139868,8 @@ pub mod fields { pub enum ForStmtField { #[doc = "Represents [`ForStmt::span`]"] Span, + #[doc = "Represents [`ForStmt::node_id`]"] + NodeId, #[doc = "Represents [`ForStmt::init`]"] Init, #[doc = "Represents [`ForStmt::test`]"] @@ -139342,6 +139905,8 @@ pub mod fields { Span, #[doc = "Represents [`Function::ctxt`]"] Ctxt, + #[doc = "Represents [`Function::node_id`]"] + NodeId, #[doc = "Represents [`Function::body`]"] Body, #[doc = "Represents [`Function::is_generator`]"] @@ -139386,6 +139951,8 @@ pub mod fields { Span, #[doc = "Represents [`Ident::ctxt`]"] Ctxt, + #[doc = "Represents [`Ident::scope_id`]"] + ScopeId, #[doc = "Represents [`Ident::sym`]"] Sym, #[doc = "Represents [`Ident::optional`]"] @@ -140122,6 +140689,8 @@ pub mod fields { pub enum ModuleField { #[doc = "Represents [`Module::span`]"] Span, + #[doc = "Represents [`Module::node_id`]"] + NodeId, #[doc = "Represents [`Module::body`]"] Body(usize), #[doc = "Represents [`Module::shebang`]"] @@ -140671,6 +141240,8 @@ pub mod fields { pub enum ScriptField { #[doc = "Represents [`Script::span`]"] Span, + #[doc = "Represents [`Script::node_id`]"] + NodeId, #[doc = "Represents [`Script::body`]"] Body(usize), #[doc = "Represents [`Script::shebang`]"] @@ -140924,6 +141495,8 @@ pub mod fields { pub enum SwitchStmtField { #[doc = "Represents [`SwitchStmt::span`]"] Span, + #[doc = "Represents [`SwitchStmt::node_id`]"] + NodeId, #[doc = "Represents [`SwitchStmt::discriminant`]"] Discriminant, #[doc = "Represents [`SwitchStmt::cases`]"] @@ -142689,6 +143262,7 @@ pub mod fields { BigInt(BigIntField), BinExpr(BinExprField), BinaryOp(BinaryOpField), + BindingId(BindingIdField), BindingIdent(BindingIdentField), BlockStmt(BlockStmtField), BlockStmtOrExpr(BlockStmtOrExprField), @@ -142930,6 +143504,7 @@ pub mod fields { Self::BigInt(v) => v.set_index(index), Self::BinExpr(v) => v.set_index(index), Self::BinaryOp(v) => v.set_index(index), + Self::BindingId(v) => v.set_index(index), Self::BindingIdent(v) => v.set_index(index), Self::BlockStmt(v) => v.set_index(index), Self::BlockStmtOrExpr(v) => v.set_index(index), @@ -143171,6 +143746,7 @@ pub mod fields { BigInt(&'ast BigInt, BigIntField), BinExpr(&'ast BinExpr, BinExprField), BinaryOp(&'ast BinaryOp, BinaryOpField), + BindingId(&'ast BindingId, BindingIdField), BindingIdent(&'ast BindingIdent, BindingIdentField), BlockStmt(&'ast BlockStmt, BlockStmtField), BlockStmtOrExpr(&'ast BlockStmtOrExpr, BlockStmtOrExprField), @@ -143430,6 +144006,7 @@ pub mod fields { Self::BigInt(_, __field_kind) => __field_kind.set_index(index), Self::BinExpr(_, __field_kind) => __field_kind.set_index(index), Self::BinaryOp(_, __field_kind) => __field_kind.set_index(index), + Self::BindingId(_, __field_kind) => __field_kind.set_index(index), Self::BindingIdent(_, __field_kind) => __field_kind.set_index(index), Self::BlockStmt(_, __field_kind) => __field_kind.set_index(index), Self::BlockStmtOrExpr(_, __field_kind) => __field_kind.set_index(index), @@ -143676,6 +144253,7 @@ pub mod fields { Self::BigInt(_, __field_kind) => AstParentKind::BigInt(*__field_kind), Self::BinExpr(_, __field_kind) => AstParentKind::BinExpr(*__field_kind), Self::BinaryOp(_, __field_kind) => AstParentKind::BinaryOp(*__field_kind), + Self::BindingId(_, __field_kind) => AstParentKind::BindingId(*__field_kind), Self::BindingIdent(_, __field_kind) => AstParentKind::BindingIdent(*__field_kind), Self::BlockStmt(_, __field_kind) => AstParentKind::BlockStmt(*__field_kind), Self::BlockStmtOrExpr(_, __field_kind) => { @@ -144118,6 +144696,11 @@ impl<'ast> From<&'ast BinaryOp> for NodeRef<'ast> { NodeRef::BinaryOp(node) } } +impl<'ast> From<&'ast BindingId> for NodeRef<'ast> { + fn from(node: &'ast BindingId) -> Self { + NodeRef::BindingId(node) + } +} impl<'ast> From<&'ast BindingIdent> for NodeRef<'ast> { fn from(node: &'ast BindingIdent) -> Self { NodeRef::BindingIdent(node) @@ -145236,6 +145819,7 @@ pub enum NodeRef<'ast> { BigInt(&'ast BigInt), BinExpr(&'ast BinExpr), BinaryOp(&'ast BinaryOp), + BindingId(&'ast BindingId), BindingIdent(&'ast BindingIdent), BlockStmt(&'ast BlockStmt), BlockStmtOrExpr(&'ast BlockStmtOrExpr), @@ -145613,6 +146197,10 @@ impl<'ast> NodeRef<'ast> { NodeRef::BinaryOp(node) => match node { _ => Box::new(::std::iter::empty::>()), }, + NodeRef::BindingId(node) => { + let iterator = ::std::iter::empty::>(); + Box::new(iterator) + } NodeRef::BindingIdent(node) => { let iterator = ::std::iter::empty::>() .chain(::std::iter::once(NodeRef::Ident(&node.id))) diff --git a/crates/swc_estree_compat/src/swcify/expr.rs b/crates/swc_estree_compat/src/swcify/expr.rs index 3174da392f1e..690e67ebcec8 100644 --- a/crates/swc_estree_compat/src/swcify/expr.rs +++ b/crates/swc_estree_compat/src/swcify/expr.rs @@ -321,6 +321,7 @@ impl Swcify for Identifier { sym: self.name, optional: self.optional.unwrap_or(false), ctxt: Default::default(), + scope_id: Default::default(), }, type_ann: self.type_annotation.swcify(ctx).flatten().map(Box::new), } diff --git a/crates/swc_estree_compat/src/swcify/stmt.rs b/crates/swc_estree_compat/src/swcify/stmt.rs index 1bc43a167157..da5034739864 100644 --- a/crates/swc_estree_compat/src/swcify/stmt.rs +++ b/crates/swc_estree_compat/src/swcify/stmt.rs @@ -159,6 +159,7 @@ impl Swcify for ForInStatement { fn swcify(self, ctx: &Context) -> Self::Output { ForInStmt { span: ctx.span(&self.base), + node_id: Default::default(), left: self.left.swcify(ctx), right: self.right.swcify(ctx), body: Box::new(self.body.swcify(ctx).expect_stmt()), @@ -183,6 +184,7 @@ impl Swcify for ForStatement { fn swcify(self, ctx: &Context) -> Self::Output { ForStmt { span: ctx.span(&self.base), + node_id: Default::default(), init: self.init.swcify(ctx), test: self.test.swcify(ctx), update: self.update.swcify(ctx), @@ -269,6 +271,7 @@ impl Swcify for SwitchStatement { fn swcify(self, ctx: &Context) -> Self::Output { SwitchStmt { span: ctx.span(&self.base), + node_id: Default::default(), discriminant: self.discriminant.swcify(ctx), cases: self.cases.swcify(ctx), } @@ -322,6 +325,7 @@ impl Swcify for swc_estree_ast::CatchClause { fn swcify(self, ctx: &Context) -> Self::Output { swc_ecma_ast::CatchClause { span: ctx.span(&self.base), + node_id: Default::default(), param: self.param.swcify(ctx), body: self.body.swcify(ctx), } @@ -595,6 +599,7 @@ impl Swcify for ForOfStatement { fn swcify(self, ctx: &Context) -> Self::Output { ForOfStmt { span: ctx.span(&self.base), + node_id: Default::default(), is_await: false, left: self.left.swcify(ctx), right: self.right.swcify(ctx), diff --git a/crates/swc_node_bundler/src/loaders/json.rs b/crates/swc_node_bundler/src/loaders/json.rs index a0b8948f468a..453a476bd03a 100644 --- a/crates/swc_node_bundler/src/loaders/json.rs +++ b/crates/swc_node_bundler/src/loaders/json.rs @@ -34,6 +34,7 @@ pub(super) fn load_json_as_module(fm: &Arc) -> Result .into(); Ok(Module { + node_id: Default::default(), span: DUMMY_SP, body: vec![export], shebang: None, diff --git a/crates/swc_node_bundler/src/loaders/swc.rs b/crates/swc_node_bundler/src/loaders/swc.rs index e612ab959c21..7b66473d8846 100644 --- a/crates/swc_node_bundler/src/loaders/swc.rs +++ b/crates/swc_node_bundler/src/loaders/swc.rs @@ -95,6 +95,7 @@ impl SwcLoader { return Ok(ModuleData { fm, module: Module { + node_id: Default::default(), span: DUMMY_SP, body: Default::default(), shebang: Default::default(), diff --git a/crates/swc_typescript/src/fast_dts/enum.rs b/crates/swc_typescript/src/fast_dts/enum.rs index f43b385acc18..4488128f569c 100644 --- a/crates/swc_typescript/src/fast_dts/enum.rs +++ b/crates/swc_typescript/src/fast_dts/enum.rs @@ -58,6 +58,7 @@ impl FastDts { span: DUMMY_SP, sym: atom!("Infinity"), ctxt: SyntaxContext::empty(), + scope_id: Default::default(), optional: false, }) } else { diff --git a/packages/types/index.ts b/packages/types/index.ts index fadfefef5dab..413c3de02a98 100644 --- a/packages/types/index.ts +++ b/packages/types/index.ts @@ -1302,6 +1302,10 @@ export interface Span { ctxt: number; } +export type NodeId = number; + +export type ScopeId = number; + export interface Node { type: string; } @@ -1315,6 +1319,8 @@ export interface HasDecorator { } export interface Class extends HasSpan, HasDecorator { + nodeId: NodeId; + body: ClassMember[]; superClass?: Expression; @@ -1380,6 +1386,8 @@ export interface Param extends Node, HasSpan, HasDecorator { export interface Constructor extends Node, HasSpan { type: "Constructor"; + nodeId: NodeId; + key: PropertyName; params: (TsParameterProperty | Param)[]; @@ -1529,6 +1537,8 @@ export interface Identifier extends ExpressionBase { value: string; + scopeId: ScopeId; + /// TypeScript only. Used in case of an optional parameter. optional: boolean; } @@ -1696,6 +1706,8 @@ export interface SequenceExpression extends ExpressionBase { export interface ArrowFunctionExpression extends ExpressionBase { type: "ArrowFunctionExpression"; + nodeId: NodeId; + params: Pattern[]; body: BlockStatement | Expression; @@ -1762,6 +1774,8 @@ export interface ParenthesisExpression extends ExpressionBase { } export interface Fn extends HasSpan, HasDecorator { + nodeId: NodeId; + params: Param[]; body?: BlockStatement; @@ -2106,12 +2120,16 @@ export type Program = Module | Script; export interface Module extends Node, HasSpan, HasInterpreter { type: "Module"; + nodeId: NodeId; + body: ModuleItem[]; } export interface Script extends Node, HasSpan, HasInterpreter { type: "Script"; + nodeId: NodeId; + body: Statement[]; } @@ -2185,6 +2203,7 @@ export type Pattern = export interface BindingIdentifier extends PatternBase { type: "Identifier"; value: string; + scopeId: ScopeId; optional: boolean; } @@ -2304,6 +2323,8 @@ export interface ComputedPropName extends Node, HasSpan { export interface BlockStatement extends Node, HasSpan { type: "BlockStatement"; + nodeId: NodeId; + stmts: Statement[]; } @@ -2384,6 +2405,8 @@ export interface IfStatement extends Node, HasSpan { export interface SwitchStatement extends Node, HasSpan { type: "SwitchStatement"; + nodeId: NodeId; + discriminant: Expression; cases: SwitchCase[]; } @@ -2419,6 +2442,8 @@ export interface DoWhileStatement extends Node, HasSpan { export interface ForStatement extends Node, HasSpan { type: "ForStatement"; + nodeId: NodeId; + init?: VariableDeclaration | Expression; test?: Expression; update?: Expression; @@ -2428,6 +2453,8 @@ export interface ForStatement extends Node, HasSpan { export interface ForInStatement extends Node, HasSpan { type: "ForInStatement"; + nodeId: NodeId; + left: VariableDeclaration | Pattern; right: Expression; body: Statement; @@ -2436,6 +2463,8 @@ export interface ForInStatement extends Node, HasSpan { export interface ForOfStatement extends Node, HasSpan { type: "ForOfStatement"; + nodeId: NodeId; + /** * Span of the await token. * @@ -2460,6 +2489,8 @@ export interface SwitchCase extends Node, HasSpan { export interface CatchClause extends Node, HasSpan { type: "CatchClause"; + nodeId: NodeId; + /** * The param is `undefined` if the catch binding is omitted. E.g., `try { foo() } catch {}` */ diff --git a/tools/generate-code/src/main.rs b/tools/generate-code/src/main.rs index 3d2fa7bf69c1..52b53a47c11a 100644 --- a/tools/generate-code/src/main.rs +++ b/tools/generate-code/src/main.rs @@ -200,6 +200,8 @@ fn test_ecmascript() { "EncodeBigInt".into(), "EsVersion".into(), "FnPass".into(), + "NodeId".into(), + "ScopeId".into(), ], ) .unwrap(); @@ -212,6 +214,8 @@ fn test_ecmascript() { "EncodeBigInt".into(), "EsVersion".into(), "FnPass".into(), + "NodeId".into(), + "ScopeId".into(), ], ) .unwrap();