From 76862688e92a9e22b439da146d2087bd26a266ea Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Tue, 5 Dec 2023 13:44:46 +0800 Subject: [PATCH 1/2] feat: support env replacement --- crates/loader_compilation/src/lib.rs | 10 +- .../src/transform/env_replacement.rs | 384 ++++++++++++++++++ .../loader_compilation/src/transform/mod.rs | 17 +- crates/loader_compilation/tests/fixtures.rs | 51 ++- .../fixtures/basic/.ice/route-manifest.json | 22 - .../tests/fixtures/basic/input.js | 11 +- .../tests/fixtures/basic/output.js | 7 +- .../tests/fixtures/default/input.js | 5 + .../tests/fixtures/default/output.js | 19 + .../tests/fixtures/multiple/input.js | 5 + .../tests/fixtures/multiple/output.js | 5 + .../tests/fixtures/named/input.js | 5 + .../tests/fixtures/named/output.js | 4 + .../tests/fixtures/require_basic/input.js | 5 + .../tests/fixtures/require_basic/output.js | 4 + .../tests/fixtures/require_default/input.js | 5 + .../tests/fixtures/require_default/output.js | 19 + .../tests/fixtures/require_named/input.js | 5 + .../tests/fixtures/require_named/output.js | 4 + .../tests/fixtures/require_rest/input.js | 5 + .../tests/fixtures/require_rest/output.js | 20 + .../tests/fixtures/require_scoped/input.js | 8 + .../tests/fixtures/require_scoped/output.js | 9 + 23 files changed, 586 insertions(+), 43 deletions(-) create mode 100644 crates/loader_compilation/src/transform/env_replacement.rs delete mode 100644 crates/loader_compilation/tests/fixtures/basic/.ice/route-manifest.json create mode 100644 crates/loader_compilation/tests/fixtures/default/input.js create mode 100644 crates/loader_compilation/tests/fixtures/default/output.js create mode 100644 crates/loader_compilation/tests/fixtures/multiple/input.js create mode 100644 crates/loader_compilation/tests/fixtures/multiple/output.js create mode 100644 crates/loader_compilation/tests/fixtures/named/input.js create mode 100644 crates/loader_compilation/tests/fixtures/named/output.js create mode 100644 crates/loader_compilation/tests/fixtures/require_basic/input.js create mode 100644 crates/loader_compilation/tests/fixtures/require_basic/output.js create mode 100644 crates/loader_compilation/tests/fixtures/require_default/input.js create mode 100644 crates/loader_compilation/tests/fixtures/require_default/output.js create mode 100644 crates/loader_compilation/tests/fixtures/require_named/input.js create mode 100644 crates/loader_compilation/tests/fixtures/require_named/output.js create mode 100644 crates/loader_compilation/tests/fixtures/require_rest/input.js create mode 100644 crates/loader_compilation/tests/fixtures/require_rest/output.js create mode 100644 crates/loader_compilation/tests/fixtures/require_scoped/input.js create mode 100644 crates/loader_compilation/tests/fixtures/require_scoped/output.js diff --git a/crates/loader_compilation/src/lib.rs b/crates/loader_compilation/src/lib.rs index 5bcb3c9..197808d 100644 --- a/crates/loader_compilation/src/lib.rs +++ b/crates/loader_compilation/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(box_patterns)] use std::{path::Path, collections::HashMap, sync::Mutex}; use lazy_static::lazy_static; use rspack_ast::RspackAst; @@ -163,8 +164,11 @@ impl Loader for CompilationLoader { if routes_config.is_none() || file_accessed { // Load routes config for transform. let routes_config_path: std::path::PathBuf = Path::new(compiler_context).join(".ice/route-manifest.json"); - *routes_config = Some(load_routes_config(&routes_config_path).unwrap()); - + let routes_content = load_routes_config(&routes_config_path); + if routes_content.is_ok() { + *routes_config = Some(routes_content?); + } + if file_accessed { // If file accessed, then we need to clear the map for the current compilation. file_access.clear(); @@ -175,7 +179,7 @@ impl Loader for CompilationLoader { let built = compiler.parse(None, |_| { transform( &resource_path, - routes_config.as_ref().unwrap(), + routes_config.as_ref(), transform_options ) })?; diff --git a/crates/loader_compilation/src/transform/env_replacement.rs b/crates/loader_compilation/src/transform/env_replacement.rs new file mode 100644 index 0000000..ef9e597 --- /dev/null +++ b/crates/loader_compilation/src/transform/env_replacement.rs @@ -0,0 +1,384 @@ +use swc_core::{ + ecma::{ + ast::*, + visit::{Fold, FoldWith}, + }, + common::DUMMY_SP, +}; +struct EnvReplacement { + sources: Vec, +} + +fn create_check_expr(meta_value: &str, renderer: &str) -> Expr { + Expr::Bin(BinExpr { + span: DUMMY_SP, + op: BinaryOp::EqEqEq, + left: Box::new(Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: Box::new(Expr::MetaProp(MetaPropExpr { span: DUMMY_SP, kind: MetaPropKind::ImportMeta })), + prop: Ident::new(meta_value.into(), DUMMY_SP).into(), + })), + right: Box::new(Expr::Lit(Lit::Str(Str { + value: renderer.into(), + span: DUMMY_SP, + raw: None, + }))), + }) +} + +fn create_typeof_check(expr: Expr, check_value: &str, op: BinaryOp) -> Expr { + // Create `typeof pha` unary expression + let typeof_expr = Expr::Unary(UnaryExpr { + op: UnaryOp::TypeOf, + arg: Box::new(expr), + span: DUMMY_SP, + }); + + // Create `typeof pha === 'object'` binary expression + Expr::Bin(BinExpr { + left: Box::new(typeof_expr), + op, + right: Box::new(Expr::Lit(Lit::Str(Str { + value: check_value.into(), + span: DUMMY_SP, + raw: None, + }))), + span: DUMMY_SP, + }) +} + +fn combine_check_exprs(exprs: Vec, op: BinaryOp) -> Expr { + let mut result = exprs[0].clone(); + for expr in exprs[1..].iter() { + result = Expr::Bin(BinExpr { + span: DUMMY_SP, + op, + left: Box::new(result), + right: Box::new(expr.clone()), + }); + } + result +} + +fn build_regex_test_expression() -> Expr { + // Create the regex literal + let regex_pattern = Expr::Lit(Lit::Regex(Regex { + exp: ".+AliApp\\((\\w+)\\/((?:\\d+\\.)+\\d+)\\).* .*(WindVane)(?:\\/((?:\\d+\\.)+\\d+))?.*".into(), + flags: "".into(), + span: DUMMY_SP, + })); + + // Create the typeof expression for `navigator` + let typeof_navigator = Expr::Unary(UnaryExpr { + op: UnaryOp::TypeOf, + arg: Box::new(Expr::Ident(Ident::new("navigator".into(), DUMMY_SP))), + span: DUMMY_SP, + }); + + // Create the conditional expression + let conditional = Expr::Cond(CondExpr { + test: Box::new(typeof_navigator), + cons: Box::new(Expr::Bin(BinExpr { + left: Box::new(Expr::Member(MemberExpr { + obj: Box::new(Expr::Ident(Ident::new("navigator".into(), DUMMY_SP))), + prop: MemberProp::Ident(Ident::new("userAgent".into(), DUMMY_SP)), + span: DUMMY_SP, + })), + op: BinaryOp::LogicalOr, + right: Box::new(Expr::Member(MemberExpr { + obj: Box::new(Expr::Ident(Ident::new("navigator".into(), DUMMY_SP))), + prop: MemberProp::Ident(Ident::new("swuserAgent".into(), DUMMY_SP)), + span: DUMMY_SP, + })), + span: DUMMY_SP, + })), + alt: Box::new(Expr::Lit(Lit::Str(Str { + value: "".into(), + span: DUMMY_SP, + raw: None, + }))), + span: DUMMY_SP, + }); + + // Create the 'test' method call on the regex pattern + let test_call = Expr::Call(CallExpr { + callee: Callee::Expr(Box::new(Expr::Member(MemberExpr { + obj: Box::new(regex_pattern), + prop: MemberProp::Ident(Ident::new("test".into(), DUMMY_SP)), + span: DUMMY_SP, + }))), + args: vec![ExprOrSpread { + spread: None, + expr: Box::new(conditional), + }], + span: DUMMY_SP, + type_args: None, + }); + + test_call +} + +fn get_env_expr(specifier: &Ident) -> Expr { + match specifier.sym.as_ref() { + "isClient" => { + create_check_expr("renderer", "client") + }, + "isServer" => { + create_check_expr("renderer", "server") + }, + "isWeb" => { + combine_check_exprs(vec![ + create_check_expr("renderer", "client"), + create_check_expr("target", "web"), + ], BinaryOp::LogicalAnd) + }, + "isNode" => { + create_check_expr("renderer", "server") + }, + "isWeex" => { + combine_check_exprs(vec![ + create_check_expr("renderer", "client"), + create_check_expr("target", "weex"), + ], BinaryOp::LogicalAnd) + }, + "isKraken" => { + combine_check_exprs(vec![ + create_check_expr("renderer", "client"), + create_check_expr("target", "kraken"), + ], BinaryOp::LogicalAnd) + }, + "isPHA" => { + combine_check_exprs(vec![ + create_check_expr("renderer", "client"), + create_check_expr("target", "web"), + create_typeof_check( + Expr::Ident(Ident::new("pha".into(), DUMMY_SP)), + "object", + BinaryOp::EqEqEq, + ), + ], BinaryOp::LogicalAnd) + }, + "isWindVane" => { + combine_check_exprs(vec![ + create_check_expr("renderer", "client"), + build_regex_test_expression(), + create_typeof_check( + Expr::Ident(Ident::new("WindVane".into(), DUMMY_SP)), + "undefined", + BinaryOp::NotEqEq, + ), + create_typeof_check( + Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: Box::new(Expr::Ident(Ident::new("WindVane".into(), DUMMY_SP))), + prop: Ident::new("call".into(), DUMMY_SP).into(), + }), + "undefined", + BinaryOp::NotEqEq, + ), + ], BinaryOp::LogicalAnd) + }, + _ => { + // Do not support miniapp env. + Expr::Lit(Lit::Bool(Bool { + span: DUMMY_SP, + value: false, + })) + } + } +} + +fn create_env_declare(specifier: &Ident, imported: &Ident) -> Stmt { + let expr = get_env_expr(&specifier); + + return Stmt::Decl(Decl::Var(Box::new(VarDecl { + span: DUMMY_SP, + kind: VarDeclKind::Var, + declare: false, + decls: vec![VarDeclarator { + span: DUMMY_SP, + name: Pat::Ident(BindingIdent { + id: imported.clone(), + type_ann: Default::default(), + }), + init: Some(Box::new(expr)), + definite: false, + }], + }))); +} + +fn create_env_default_export(export_name: Ident) -> Stmt { + Stmt::Decl(Decl::Var(Box::new(VarDecl { + span: DUMMY_SP, + kind: VarDeclKind::Const, + declare: false, + decls: vec![VarDeclarator { + span: DUMMY_SP, + name: Pat::Ident(BindingIdent { + id: export_name.clone(), + type_ann: Default::default(), + }), + init: Some(Box::new(Expr::Object(ObjectLit { + span: DUMMY_SP, + props: vec![ + "isWeb", + "isClient", + "isNode", + "isWeex", + "isKraken", + "isMiniApp", + "isByteDanceMicroApp", + "isBaiduSmartProgram", + "isKuaiShouMiniProgram", + "isWeChatMiniProgram", + "isQuickApp", + "isPHA", + "isWindVane", + "isFRM", + ].into_iter().map(|target| PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(Ident::new(target.into(), DUMMY_SP)), + value: Box::new(get_env_expr(&Ident::new(target.into(), DUMMY_SP))), + })))).collect(), + }))), + definite: false, + }], + }))) +} + +fn get_env_stmt(sources: &Vec, decls: Vec) -> Vec { + let mut stmts = vec![]; + for decl in decls { + if let Some(init) = decl.init { + if let Expr::Call(CallExpr { + args: ref call_args, + callee: Callee::Expr(box Expr::Ident(Ident { ref sym, .. })), + .. + }) = *init { + if sym == "require" && call_args.len() == 1 { + // Case const env = require('env'); + if let ExprOrSpread { expr: box Expr::Lit(Lit::Str(Str { ref value, .. })), .. } = call_args[0] { + if sources.iter().any(|s| value == s) { + match &decl.name { + Pat::Ident(BindingIdent { id, .. }) => { + stmts.push(create_env_default_export(id.clone())); + } + Pat::Object(ObjectPat { props, .. }) => { + props.iter().for_each(|prop| { + match prop { + ObjectPatProp::Assign(AssignPatProp { key, value, .. }) => { + if value.is_some() { + if let box Expr::Ident(ident) = &value.as_ref().unwrap() { + stmts.push(create_env_declare(key, &ident)); + } + } else { + stmts.push(create_env_declare(key, key)); + } + } + ObjectPatProp::KeyValue(KeyValuePatProp { key, value, .. }) => { + if let box Pat::Ident(BindingIdent { id , ..}) = &value { + if let PropName::Ident(i) = key { + stmts.push(create_env_declare(i, &id)); + } + } + } + ObjectPatProp::Rest(RestPat {arg, ..}) => { + if let box Pat::Ident(BindingIdent { id , ..}) = arg { + stmts.push(create_env_default_export(id.clone())); + } + } + } + }); + } + _ => {} + } + continue; + } + } + } + } + } + } + stmts +} + +impl Fold for EnvReplacement { + fn fold_module_items(&mut self, items: Vec) -> Vec { + let mut new_module_items: Vec = vec![]; + for item in items.iter() { + match &item { + // Import declaration. + ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) => { + let src = &import_decl.src.value; + if self.sources.iter().any(|s| src == s) { + // Collect all specifiers. + import_decl.specifiers.iter().for_each(|specifier| { + match specifier { + ImportSpecifier::Named(named_specifier) => { + let imported = match &named_specifier.imported { + Some(ModuleExportName::Ident(ident)) => Some(ident), + _ => None, + }; + let s = if imported.is_some() { + imported.unwrap() + } else { + &named_specifier.local + }; + new_module_items.push(ModuleItem::Stmt(create_env_declare(s, &named_specifier.local))); + } + ImportSpecifier::Default(default_specifier) => { + new_module_items.push(ModuleItem::Stmt(create_env_default_export(default_specifier.local.clone()))); + } + ImportSpecifier::Namespace(namespace_specifier) => { + new_module_items.push(ModuleItem::Stmt(create_env_default_export(namespace_specifier.local.clone()))); + } + } + }); + + } else { + new_module_items.push(item.clone()); + } + } + ModuleItem::Stmt(Stmt::Decl(Decl::Var(var_decl))) => { + let stmt = get_env_stmt(&self.sources, var_decl.decls.clone()); + if stmt.len() > 0 { + let module_stmts = stmt.into_iter().map(|s| ModuleItem::Stmt(s)).collect::>(); + new_module_items.extend_from_slice(&module_stmts); + } else { + new_module_items.push(item.clone()); + } + } + _ => { + new_module_items.push(item.clone().fold_children_with(self)); + } + } + } + new_module_items + } + + fn fold_block_stmt(&mut self, block: BlockStmt) -> BlockStmt { + let mut new_stmts: Vec = vec![]; + block.stmts.clone().into_iter().for_each(|stmt| { + match &stmt { + Stmt::Decl(Decl::Var(var_decl)) => { + let env_stmts = get_env_stmt(&self.sources, var_decl.decls.clone()); + if env_stmts.len() > 0 { + new_stmts.extend_from_slice(&env_stmts); + } else { + new_stmts.push(stmt); + } + } + _ => { + new_stmts.push(stmt.fold_children_with(self)); + } + } + }); + BlockStmt { + stmts: new_stmts, + ..block + } + } +} + +pub fn env_replacement(sources: Vec) -> impl Fold { + EnvReplacement { sources } +} \ No newline at end of file diff --git a/crates/loader_compilation/src/transform/mod.rs b/crates/loader_compilation/src/transform/mod.rs index 9bc09dd..34a69d4 100644 --- a/crates/loader_compilation/src/transform/mod.rs +++ b/crates/loader_compilation/src/transform/mod.rs @@ -9,9 +9,11 @@ use swc_core::ecma::{ mod keep_export; mod remove_export; +mod env_replacement; use keep_export::keep_export; use remove_export::remove_export; +use env_replacement::env_replacement; macro_rules! either { ($config:expr, $f:expr) => { @@ -63,11 +65,13 @@ pub(crate) fn load_routes_config(path: &Path) -> Result, Error> { parse_routes_config(content) } -fn match_route_entry(resource_path: &Path, routes: &Vec) -> bool { +fn match_route_entry(resource_path: &Path, routes: Option<&Vec>) -> bool { let resource_path_str = resource_path.to_str().unwrap(); - for route in routes { - if resource_path_str.ends_with(&route.to_string()) { - return true; + if let Some(routes) = routes { + for route in routes { + if resource_path_str.ends_with(&route.to_string()) { + return true; + } } } false @@ -89,10 +93,13 @@ pub struct TransformFeatureOptions { pub(crate) fn transform<'a>( resource_path: &'a Path, - routes_config: &Vec, + routes_config: Option<&Vec>, feature_options: &TransformFeatureOptions, ) -> impl Fold + 'a { chain!( + either!(Some(&vec!["@uni/env".to_string(), "universal-env".to_string()]), |options: &Vec| { + env_replacement(options.clone()) + }), either!(feature_options.keep_export, |options: &Vec| { let mut exports_name = options.clone(); // Special case for app entry. diff --git a/crates/loader_compilation/tests/fixtures.rs b/crates/loader_compilation/tests/fixtures.rs index ae7386a..23ea4b3 100644 --- a/crates/loader_compilation/tests/fixtures.rs +++ b/crates/loader_compilation/tests/fixtures.rs @@ -3,8 +3,12 @@ use loader_compilation::{CompilationLoader, LoaderOptions}; use rspack_core::{ run_loaders, CompilerContext, CompilerOptions, Loader, LoaderRunnerContext, ResourceData, SideEffectOption, }; +use swc_core::ecma::ast::EsVersion; use swc_core::base::config::Config; +use rspack_ast::RspackAst; +use rspack_plugin_javascript::ast; + async fn loader_test(actual: impl AsRef, expected: impl AsRef) { let tests_path = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"))).join("tests"); let expected_path = tests_path.join(expected); @@ -12,6 +16,7 @@ async fn loader_test(actual: impl AsRef, expected: impl AsRef) { let parent_path = actual_path.parent().unwrap().to_path_buf(); let mut options = Config::default(); + options.jsc.target = Some(EsVersion::Es2020); let (result, _) = run_loaders( &[Arc::new(CompilationLoader::new(LoaderOptions { swc_options: options, @@ -92,17 +97,57 @@ async fn loader_test(actual: impl AsRef, expected: impl AsRef) { .await .expect("TODO:") .split_into_parts(); - - let result = result.content.try_into_string().expect("TODO:"); + let code: String; + let code_ast = result.additional_data.get::().unwrap(); + let code_gen_options = result.additional_data.get::().unwrap(); + if let RspackAst::JavaScript(code_ast) = code_ast { + code = ast::stringify(code_ast, code_gen_options.clone()).unwrap().code; + } else { + panic!("TODO:"); + } + if env::var("UPDATE").is_ok() { + let result = code.into_bytes(); fs::write(expected_path, result).expect("TODO:"); } else { let expected = fs::read_to_string(expected_path).expect("TODO:"); - assert_eq!(result, expected); + assert_eq!(code, expected); } } #[tokio::test] async fn basic() { loader_test("fixtures/basic/input.js", "fixtures/basic/output.js").await; +} +#[tokio::test] +async fn named() { + loader_test("fixtures/named/input.js", "fixtures/named/output.js").await; +} +#[tokio::test] +async fn multiple() { + loader_test("fixtures/multiple/input.js", "fixtures/multiple/output.js").await; +} +#[tokio::test] +async fn default() { + loader_test("fixtures/default/input.js", "fixtures/default/output.js").await; +} +#[tokio::test] +async fn require_basic() { + loader_test("fixtures/require_basic/input.js", "fixtures/require_basic/output.js").await; +} +#[tokio::test] +async fn require_named() { + loader_test("fixtures/require_named/input.js", "fixtures/require_named/output.js").await; +} +#[tokio::test] +async fn require_default() { + loader_test("fixtures/require_default/input.js", "fixtures/require_default/output.js").await; +} +#[tokio::test] +async fn require_rest() { + loader_test("fixtures/require_rest/input.js", "fixtures/require_rest/output.js").await; +} +#[tokio::test] +async fn require_scoped() { + loader_test("fixtures/require_scoped/input.js", "fixtures/require_scoped/output.js").await; } \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/basic/.ice/route-manifest.json b/crates/loader_compilation/tests/fixtures/basic/.ice/route-manifest.json deleted file mode 100644 index cfcf422..0000000 --- a/crates/loader_compilation/tests/fixtures/basic/.ice/route-manifest.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "path": "error", - "id": "error", - "file": "error.tsx", - "componentName": "error", - "layout": false, - "exports": [ - "default" - ] - }, - { - "index": true, - "id": "/", - "file": "index.tsx", - "componentName": "index", - "layout": false, - "exports": [ - "default" - ] - } -] \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/basic/input.js b/crates/loader_compilation/tests/fixtures/basic/input.js index f11cfe5..a5f980a 100644 --- a/crates/loader_compilation/tests/fixtures/basic/input.js +++ b/crates/loader_compilation/tests/fixtures/basic/input.js @@ -1,8 +1,5 @@ -const a = 1; -const b = 2; +import { isWeb } from "@uni/env"; -export const dataLoader = { - b, -}; - -export default a; \ No newline at end of file +if (isWeb) { + console.log("test"); +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/basic/output.js b/crates/loader_compilation/tests/fixtures/basic/output.js index 5442d74..71a9e11 100644 --- a/crates/loader_compilation/tests/fixtures/basic/output.js +++ b/crates/loader_compilation/tests/fixtures/basic/output.js @@ -1,3 +1,4 @@ -const a = 1; - -window.__custom_code__ = true; +var isWeb = import.meta.renderer === "client" && import.meta.target === "web"; +if (isWeb) { + console.log("test"); +} diff --git a/crates/loader_compilation/tests/fixtures/default/input.js b/crates/loader_compilation/tests/fixtures/default/input.js new file mode 100644 index 0000000..353670a --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/default/input.js @@ -0,0 +1,5 @@ +import env from "@uni/env"; + +if (env.isWeb) { + console.log("test"); +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/default/output.js b/crates/loader_compilation/tests/fixtures/default/output.js new file mode 100644 index 0000000..849bffa --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/default/output.js @@ -0,0 +1,19 @@ +const env = { + isWeb: import.meta.renderer === "client" && import.meta.target === "web", + isClient: import.meta.renderer === "client", + isNode: import.meta.renderer === "server", + isWeex: import.meta.renderer === "client" && import.meta.target === "weex", + isKraken: import.meta.renderer === "client" && import.meta.target === "kraken", + isMiniApp: false, + isByteDanceMicroApp: false, + isBaiduSmartProgram: false, + isKuaiShouMiniProgram: false, + isWeChatMiniProgram: false, + isQuickApp: false, + isPHA: import.meta.renderer === "client" && import.meta.target === "web" && typeof pha === "object", + isWindVane: import.meta.renderer === "client" && /.+AliApp\((\w+)\/((?:\d+\.)+\d+)\).* .*(WindVane)(?:\/((?:\d+\.)+\d+))?.*/.test(typeof navigator ? navigator.userAgent || navigator.swuserAgent : "") && typeof WindVane !== "undefined" && typeof WindVane.call !== "undefined", + isFRM: false +}; +if (env.isWeb) { + console.log("test"); +} diff --git a/crates/loader_compilation/tests/fixtures/multiple/input.js b/crates/loader_compilation/tests/fixtures/multiple/input.js new file mode 100644 index 0000000..e740f1e --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/multiple/input.js @@ -0,0 +1,5 @@ +import { isWeb, isPHA } from "@uni/env"; + +if (isWeb && isPHA) { + console.log("test"); +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/multiple/output.js b/crates/loader_compilation/tests/fixtures/multiple/output.js new file mode 100644 index 0000000..bd9c688 --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/multiple/output.js @@ -0,0 +1,5 @@ +var isWeb = import.meta.renderer === "client" && import.meta.target === "web"; +var isPHA = import.meta.renderer === "client" && import.meta.target === "web" && typeof pha === "object"; +if (isWeb && isPHA) { + console.log("test"); +} diff --git a/crates/loader_compilation/tests/fixtures/named/input.js b/crates/loader_compilation/tests/fixtures/named/input.js new file mode 100644 index 0000000..2b6908e --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/named/input.js @@ -0,0 +1,5 @@ +import { isWeb as web } from "@uni/env"; + +if (web) { + console.log("test"); +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/named/output.js b/crates/loader_compilation/tests/fixtures/named/output.js new file mode 100644 index 0000000..1ac586d --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/named/output.js @@ -0,0 +1,4 @@ +var web = import.meta.renderer === "client" && import.meta.target === "web"; +if (web) { + console.log("test"); +} diff --git a/crates/loader_compilation/tests/fixtures/require_basic/input.js b/crates/loader_compilation/tests/fixtures/require_basic/input.js new file mode 100644 index 0000000..cdd4e60 --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_basic/input.js @@ -0,0 +1,5 @@ +const { isWeb } = require("@uni/env"); + +if (isWeb) { + console.log("test"); +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/require_basic/output.js b/crates/loader_compilation/tests/fixtures/require_basic/output.js new file mode 100644 index 0000000..71a9e11 --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_basic/output.js @@ -0,0 +1,4 @@ +var isWeb = import.meta.renderer === "client" && import.meta.target === "web"; +if (isWeb) { + console.log("test"); +} diff --git a/crates/loader_compilation/tests/fixtures/require_default/input.js b/crates/loader_compilation/tests/fixtures/require_default/input.js new file mode 100644 index 0000000..02f68f4 --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_default/input.js @@ -0,0 +1,5 @@ +const env = require("@uni/env"); + +if (env.isWeb) { + console.log("test"); +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/require_default/output.js b/crates/loader_compilation/tests/fixtures/require_default/output.js new file mode 100644 index 0000000..849bffa --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_default/output.js @@ -0,0 +1,19 @@ +const env = { + isWeb: import.meta.renderer === "client" && import.meta.target === "web", + isClient: import.meta.renderer === "client", + isNode: import.meta.renderer === "server", + isWeex: import.meta.renderer === "client" && import.meta.target === "weex", + isKraken: import.meta.renderer === "client" && import.meta.target === "kraken", + isMiniApp: false, + isByteDanceMicroApp: false, + isBaiduSmartProgram: false, + isKuaiShouMiniProgram: false, + isWeChatMiniProgram: false, + isQuickApp: false, + isPHA: import.meta.renderer === "client" && import.meta.target === "web" && typeof pha === "object", + isWindVane: import.meta.renderer === "client" && /.+AliApp\((\w+)\/((?:\d+\.)+\d+)\).* .*(WindVane)(?:\/((?:\d+\.)+\d+))?.*/.test(typeof navigator ? navigator.userAgent || navigator.swuserAgent : "") && typeof WindVane !== "undefined" && typeof WindVane.call !== "undefined", + isFRM: false +}; +if (env.isWeb) { + console.log("test"); +} diff --git a/crates/loader_compilation/tests/fixtures/require_named/input.js b/crates/loader_compilation/tests/fixtures/require_named/input.js new file mode 100644 index 0000000..9368250 --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_named/input.js @@ -0,0 +1,5 @@ +const { isWeb: web } = require("@uni/env"); + +if (web) { + console.log("test"); +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/require_named/output.js b/crates/loader_compilation/tests/fixtures/require_named/output.js new file mode 100644 index 0000000..1ac586d --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_named/output.js @@ -0,0 +1,4 @@ +var web = import.meta.renderer === "client" && import.meta.target === "web"; +if (web) { + console.log("test"); +} diff --git a/crates/loader_compilation/tests/fixtures/require_rest/input.js b/crates/loader_compilation/tests/fixtures/require_rest/input.js new file mode 100644 index 0000000..3c9be22 --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_rest/input.js @@ -0,0 +1,5 @@ +const { isNode, ...rest } = require("@uni/env"); + +if (rest.isWeb || isNode) { + console.log("test"); +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/require_rest/output.js b/crates/loader_compilation/tests/fixtures/require_rest/output.js new file mode 100644 index 0000000..262d928 --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_rest/output.js @@ -0,0 +1,20 @@ +var isNode = import.meta.renderer === "server"; +const rest = { + isWeb: import.meta.renderer === "client" && import.meta.target === "web", + isClient: import.meta.renderer === "client", + isNode: import.meta.renderer === "server", + isWeex: import.meta.renderer === "client" && import.meta.target === "weex", + isKraken: import.meta.renderer === "client" && import.meta.target === "kraken", + isMiniApp: false, + isByteDanceMicroApp: false, + isBaiduSmartProgram: false, + isKuaiShouMiniProgram: false, + isWeChatMiniProgram: false, + isQuickApp: false, + isPHA: import.meta.renderer === "client" && import.meta.target === "web" && typeof pha === "object", + isWindVane: import.meta.renderer === "client" && /.+AliApp\((\w+)\/((?:\d+\.)+\d+)\).* .*(WindVane)(?:\/((?:\d+\.)+\d+))?.*/.test(typeof navigator ? navigator.userAgent || navigator.swuserAgent : "") && typeof WindVane !== "undefined" && typeof WindVane.call !== "undefined", + isFRM: false +}; +if (rest.isWeb || isNode) { + console.log("test"); +} diff --git a/crates/loader_compilation/tests/fixtures/require_scoped/input.js b/crates/loader_compilation/tests/fixtures/require_scoped/input.js new file mode 100644 index 0000000..369dd9c --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_scoped/input.js @@ -0,0 +1,8 @@ +const { isNode } = require("@uni/env"); +function check() { + const { isWeb } = require("@uni/env"); + if (isWeb) { + const { isServer, isClient } = require("@uni/env"); + console.log("test"); + } +} \ No newline at end of file diff --git a/crates/loader_compilation/tests/fixtures/require_scoped/output.js b/crates/loader_compilation/tests/fixtures/require_scoped/output.js new file mode 100644 index 0000000..84f6294 --- /dev/null +++ b/crates/loader_compilation/tests/fixtures/require_scoped/output.js @@ -0,0 +1,9 @@ +var isNode = import.meta.renderer === "server"; +function check() { + var isWeb = import.meta.renderer === "client" && import.meta.target === "web"; + if (isWeb) { + var isServer = import.meta.renderer === "server"; + var isClient = import.meta.renderer === "client"; + console.log("test"); + } +} From b6147aff73be0ad4fd4dc21eca712a84fbb18b32 Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Tue, 5 Dec 2023 13:47:13 +0800 Subject: [PATCH 2/2] 0.0.1 --- crates/loader_compilation/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/loader_compilation/src/lib.rs b/crates/loader_compilation/src/lib.rs index 197808d..5bfb2dc 100644 --- a/crates/loader_compilation/src/lib.rs +++ b/crates/loader_compilation/src/lib.rs @@ -168,7 +168,6 @@ impl Loader for CompilationLoader { if routes_content.is_ok() { *routes_config = Some(routes_content?); } - if file_accessed { // If file accessed, then we need to clear the map for the current compilation. file_access.clear();