diff --git a/Cargo.toml b/Cargo.toml index 2780ec3a..c04ec1ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ sourcemap = "9.0.0" swc_atoms = "2.0.0" swc_cached = "1.0.0" swc_common = "1.0.0" -swc_core = "0.96.0" +swc_core = "1.0.3" swc_css_ast = "1.0.0" swc_css_codegen = "1.0.0" swc_css_compat = "1.0.0" diff --git a/plugins/swc-plugin-canyon/package.json b/plugins/swc-plugin-canyon/package.json index 9dd848c4..40999ff2 100644 --- a/plugins/swc-plugin-canyon/package.json +++ b/plugins/swc-plugin-canyon/package.json @@ -1,6 +1,6 @@ { "name": "swc-plugin-canyon", - "version": "0.0.2-alpha.26", + "version": "0.0.2-alpha.27", "description": "A SWC plugin cooperates with istanbul to report the coverage", "main": "swc_plugin_canyon.wasm", "scripts": { diff --git a/plugins/swc-plugin-canyon/src/lib.rs b/plugins/swc-plugin-canyon/src/lib.rs index c21671e1..2346556e 100644 --- a/plugins/swc-plugin-canyon/src/lib.rs +++ b/plugins/swc-plugin-canyon/src/lib.rs @@ -1,204 +1,72 @@ +use swc_core::ecma::ast::{IdentName, PropOrSpread}; use swc_core::ecma::{ ast::{ - Program, Module, Expr, Stmt, ModuleItem, Ident, Lit, KeyValueProp, Prop, PropName, - ObjectLit, ExprStmt, AssignExpr, AssignOp, MemberExpr, MemberProp, + Expr, KeyValueProp, ObjectLit, Program, + Prop, + PropName }, transforms::testing::test_inline, visit::{as_folder, FoldWith, VisitMut}, }; -use swc_core::ecma::ast::{AssignTarget}; -use swc_core::ecma::visit::VisitMutWith; use swc_core::plugin::{plugin_transform, proxies::TransformPluginProgramMetadata}; -use swc_core::plugin::metadata::TransformPluginMetadataContextKind; -// Add this to the top of your file or a relevant module -use serde::{Deserialize, Serialize}; - - -// https://github.com/swc-project/plugins/blob/main/packages/react-remove-properties/transform/src/lib.rs -// 暂时方案,先一股脑把环境变量都注入,例如CI_COMMIT_BRANCH、CI_COMMIT_SHA、CI_PROJECT_ID等, -// 可配置的是compareTarget - - - -#[derive(Debug, Serialize, Deserialize)] -pub struct Config { - pub dsn: Option, - pub reporter: Option, - pub instrumentCwd: Option, - pub branch: Option, - pub sha: Option, - pub projectID: Option, - pub compareTarget: Option, -} - -impl Default for Config { - fn default() -> Self { - Self { - dsn: None, - reporter: None, - instrumentCwd: None, - branch: None, - sha: None, - projectID: None, - compareTarget: None, - } - } -} +use serde::Deserialize; pub struct TransformVisitor { - injected: bool, - config: Config, } - impl TransformVisitor { - pub fn new() -> Self { - Self { injected: false, - config: Config::default() } - } } impl VisitMut for TransformVisitor { - fn visit_mut_module(&mut self, module: &mut Module) { - module.visit_mut_children_with(self); - if !self.injected { - let window_canyon = Expr::Member(MemberExpr { - obj: Box::new(Expr::Ident(Ident::new("(new Function('return this')())".into(), Default::default()))), - prop: MemberProp::Ident(Ident::from(Ident::new("__canyon__".into(), Default::default()))), - span: Default::default(), - }); - // let dsn = std::env::var("DSN").unwrap_or("-".to_string()); - // let reporter = std::env::var("REPORTER").unwrap_or("-".to_string()); - // let instrumentCwd = std::env::current_dir().unwrap().to_str().unwrap_or("-").to_string(); - // let branch = std::env::var("CI_COMMIT_BRANCH").unwrap_or("-".to_string()); - // let sha = std::env::var("CI_COMMIT_SHA").unwrap_or("-".to_string()); - // let projectID = std::env::var("CI_PROJECT_ID").unwrap_or("-".to_string()); - - let dsn = self.config.dsn.clone().unwrap_or("-".to_string()); - let reporter = self.config.reporter.clone().unwrap_or("-".to_string()); - let instrumentCwd = self.config.instrumentCwd.clone().unwrap_or("-".to_string()); - let branch = self.config.branch.clone().unwrap_or("-".to_string()); - let sha = self.config.sha.clone().unwrap_or("-".to_string()); - let projectID = self.config.projectID.clone().unwrap_or("-".to_string()); - let compareTarget = self.config.compareTarget.clone().unwrap_or("-".to_string()); - - // 打印出这些 - - // println!("dsn: {}", dsn); - // println!("reporter: {}", reporter); - // println!("instrumentCwd: {}", instrumentCwd); - // println!("branch: {}", branch); - // println!("sha: {}", sha); - // println!("projectID: {}", projectID); - - let object_lit = Expr::Object(ObjectLit { - props: vec![ - Prop::KeyValue(KeyValueProp { - key: PropName::Ident(Ident::from(Ident::new("dsn".into(), Default::default()))), - value: Box::new(Expr::Lit(Lit::Str(dsn.into()))), - }).into(), - - Prop::KeyValue(KeyValueProp { - key: PropName::Ident(Ident::from(Ident::new("reporter".into(), Default::default()))), - value: Box::new(Expr::Lit(Lit::Str(reporter.into()))), - }).into(), - - Prop::KeyValue(KeyValueProp { - key: PropName::Ident(Ident::from(Ident::new("instrumentCwd".into(), Default::default()))), - value: Box::new(Expr::Lit(Lit::Str(instrumentCwd.into()))), - }).into(), - - Prop::KeyValue(KeyValueProp { - key: PropName::Ident(Ident::from(Ident::new("branch".into(), Default::default()))), - value: Box::new(Expr::Lit(Lit::Str(branch.into()))), - }).into(), - - Prop::KeyValue(KeyValueProp { - key: PropName::Ident(Ident::from(Ident::new("sha".into(), Default::default()))), - value: Box::new(Expr::Lit(Lit::Str(sha.into()))), - }).into(), - - Prop::KeyValue(KeyValueProp { - key: PropName::Ident(Ident::from(Ident::new("projectID".into(), Default::default()))), - value: Box::new(Expr::Lit(Lit::Str(projectID.into()))), - }).into(), - - Prop::KeyValue(KeyValueProp { - key: PropName::Ident(Ident::from(Ident::new("compareTarget".into(), Default::default()))), - value: Box::new(Expr::Lit(Lit::Str(compareTarget.into()))), - }).into(), - ], - span: Default::default(), - }); - - let assign_expr = AssignExpr { - left: AssignTarget::try_from(Box::new(window_canyon)).unwrap(), // 直接使用 Box - op: AssignOp::Assign, - right: Box::new(object_lit), - span: Default::default(), - }; - - let assign_stmt = Stmt::Expr(ExprStmt { - expr: Box::new(Expr::Assign(assign_expr)), - span: Default::default(), - }); - - module.body.push(ModuleItem::Stmt(assign_stmt)); - self.injected = true; + // 遍历每个表达式时,修改表达式 + fn visit_mut_expr(&mut self, expr: &mut Expr) { + match expr { + // 当表达式是对象字面量时 + Expr::Object(ref mut obj) => { + // 调用 visit_mut_object_lit 来处理对象字面量的属性 + self.visit_mut_object_lit(obj); + } + _ => {} } } -} - -// https://github.com/swc-project/plugins/blob/main/packages/react-remove-properties/transform/src/lib.rs -// 暂时方案,先一股脑把环境变量都注入,例如CI_COMMIT_BRANCH、CI_COMMIT_SHA、CI_PROJECT_ID等, -// 可配置的是compareTarget - + fn visit_mut_object_lit(&mut self, obj: &mut ObjectLit) { + // 定义一个字符串数组,包含需要排除的属性名 + let excluded_keys = ["statementMap", "fnMap", "branchMap","inputSourceMap"]; + + obj.props.retain(|prop| { + match prop { + PropOrSpread::Prop(prop) => { + // 解引用 Box,并匹配 KeyValueProp + if let Prop::KeyValue(KeyValueProp { + key: PropName::Ident(IdentName { sym, .. }), // 使用 Ident 类型 + .. + }) = &**prop + { + // 使用 as_ref() 将 JsWord 转换为 &str 进行比较 + return !excluded_keys.contains(&sym.as_ref()); + } + // 对于其他类型的属性,保留它们 + true + } + _ => true, // 对于其他类型的属性,保留 + } + }); + } +} #[plugin_transform] pub fn process_transform(program: Program, metadata: TransformPluginProgramMetadata) -> Program { - - // 定义react_remove_properties - - - - let config = serde_json::from_str::>( - &metadata - .get_transform_plugin_config() - .expect("failed to get plugin config for react-remove-properties"), - ) - .expect("invalid config for react-remove-properties") - .unwrap_or_default(); // Use default if config is None - - // 打印config - // println!("config: {:?}", config); - - // 使用TransformPluginProgramMetadata获取环境变量 - let env = metadata.get_context(&TransformPluginMetadataContextKind::Env).unwrap_or("-".to_string()); - let filename = metadata.get_context(&TransformPluginMetadataContextKind::Filename).unwrap_or("-".to_string()); - let cwd = metadata.get_context(&TransformPluginMetadataContextKind::Cwd).unwrap_or("-".to_string()); - // println!("env: {}", env); - // println!("filename: {}", filename); - // println!("cwd: {}", cwd); - program.fold_with(&mut as_folder(TransformVisitor { injected: false, config })) + program.fold_with(&mut as_folder(TransformVisitor { })) } test_inline!( Default::default(), - |_| as_folder(TransformVisitor::new()), + |_| as_folder(TransformVisitor { }), boo, // 输入代码 - r#"console.log("transform");"#, + r#"const coverageData={fnMap:"nihao"};"#, // 经插件转换后的输出代码 - r#"console.log("transform"); -(new Function('return this')()).__canyon__ = { - dsn: "-", - reporter: "-", - instrumentCwd: "/", - branch: "-", - sha: "-", - projectID: "-" -}; -"# + r#"const coverageData={};"# );