-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
361ab96
commit b4de21e
Showing
3 changed files
with
44 additions
and
176 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String>, | ||
pub reporter: Option<String>, | ||
pub instrumentCwd: Option<String>, | ||
pub branch: Option<String>, | ||
pub sha: Option<String>, | ||
pub projectID: Option<String>, | ||
pub compareTarget: Option<String>, | ||
} | ||
|
||
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<Expr> | ||
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<Prop>,并匹配 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::<Option<Config>>( | ||
&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={};"# | ||
); |