@@ -3,9 +3,9 @@ use std::path::PathBuf;
33use swc_core:: common:: { Span , SyntaxContext } ;
44use swc_core:: ecma:: {
55 ast:: {
6- ArrowExpr , AssignExpr , AssignTarget , BlockStmt , ClassMethod , Expr , FnDecl , FnExpr , Ident ,
7- Lit , MemberProp , MethodProp , Module , ModuleItem , Pat , PropName , Script , SimpleAssignTarget ,
8- Stmt , Str , VarDecl ,
6+ ArrowExpr , AssignExpr , AssignTarget , BlockStmt , ClassDecl , ClassMethod , Constructor , Expr ,
7+ FnDecl , FnExpr , Ident , Lit , MemberProp , MethodProp , Module , ModuleItem , Pat , PropName ,
8+ Script , SimpleAssignTarget , Stmt , Str , VarDecl ,
99 } ,
1010 atoms:: Atom ,
1111} ;
@@ -26,11 +26,16 @@ macro_rules! ident {
2626pub struct Instrumentation {
2727 config : InstrumentationConfig ,
2828 count : usize ,
29+ is_correct_class : bool ,
2930}
3031
3132impl Instrumentation {
3233 pub ( crate ) fn new ( config : InstrumentationConfig ) -> Self {
33- Self { config, count : 0 }
34+ Self {
35+ config,
36+ count : 0 ,
37+ is_correct_class : false ,
38+ }
3439 }
3540
3641 fn new_fn ( & self , body : BlockStmt ) -> ArrowExpr {
@@ -97,6 +102,49 @@ impl Instrumentation {
97102 ] ;
98103 }
99104
105+ fn insert_constructor_tracing ( & self , body : & mut BlockStmt ) {
106+ let original_stmts = std:: mem:: take ( & mut body. stmts ) ;
107+
108+ let ch_ident = ident ! ( format!( "tr_ch_apm${}" , & self . config. channel_name) ) ;
109+ let ctx_ident = ident ! ( format!( "tr_ch_apm_ctx${}" , & self . config. channel_name) ) ;
110+ let mut try_catch = quote ! (
111+ "try {
112+ if ($ch.hasSubscribers) {
113+ $ch.start.publish($ctx);
114+ }
115+ } catch (tr_ch_err) {
116+ if ($ch.hasSubscribers) {
117+ $ctx.error = tr_ch_err;
118+ try {
119+ $ctx.self = this;
120+ } catch (refErr) {
121+ // This can only error out if super hasn't been called yet.
122+ // Safe to ignore, but note that self/this won't get into the context.
123+ }
124+ $ch.error.publish($ctx);
125+ }
126+ throw tr_ch_err;
127+ } finally {
128+ if ($ch.hasSubscribers) {
129+ $ctx.self = this;
130+ $ch.end.publish($ctx);
131+ }
132+ }" as Stmt ,
133+ ch = ch_ident,
134+ ctx = ctx_ident. clone( ) ,
135+ ) ;
136+ if let Some ( try_catch_stmt) = try_catch. as_mut_try_stmt ( ) {
137+ for stmt in & original_stmts {
138+ try_catch_stmt. block . stmts . push ( stmt. clone ( ) ) ;
139+ }
140+ }
141+
142+ body. stmts = vec ! [
143+ quote!( "const $ctx = { arguments };" as Stmt , ctx = ctx_ident, ) ,
144+ try_catch,
145+ ] ;
146+ }
147+
100148 fn trace_expr_or_count ( & mut self , func_expr : & mut FnExpr , name : & Atom ) -> bool {
101149 if self
102150 . config
@@ -163,11 +211,27 @@ impl Instrumentation {
163211 !traced
164212 }
165213
214+ pub fn visit_mut_class_decl ( & mut self , node : & mut ClassDecl ) -> bool {
215+ self . is_correct_class = self
216+ . config
217+ . function_query
218+ . class
219+ . as_ref ( )
220+ . map_or ( true , |class| node. ident . sym . as_ref ( ) == class) ;
221+ true
222+ }
223+
166224 pub fn visit_mut_class_method ( & mut self , node : & mut ClassMethod ) -> bool {
167225 let name = match & node. key {
168226 PropName :: Ident ( ident) => ident. sym . clone ( ) ,
169227 _ => return false ,
170228 } ;
229+
230+ // Only increment count when class matches
231+ if !self . is_correct_class {
232+ return true ;
233+ }
234+
171235 if self
172236 . config
173237 . function_query
@@ -178,6 +242,21 @@ impl Instrumentation {
178242 self . insert_tracing ( body) ;
179243 }
180244 }
245+ true
246+ }
247+
248+ pub fn visit_mut_constructor ( & mut self , node : & mut Constructor ) -> bool {
249+ if !self . is_correct_class || self . config . function_query . name != "constructor" {
250+ return false ;
251+ }
252+
253+ if self . count == self . config . function_query . index && node. body . is_some ( ) {
254+ if let Some ( body) = node. body . as_mut ( ) {
255+ self . insert_constructor_tracing ( body) ;
256+ }
257+ } else {
258+ self . count += 1 ;
259+ }
181260 false
182261 }
183262
0 commit comments