@tarojs/helper 3.8.0-canary.0 → 4.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/LICENSE +14 -0
  2. package/README.md +25 -0
  3. package/dist/constants.d.ts +5 -3
  4. package/dist/constants.js +24 -22
  5. package/dist/constants.js.map +1 -1
  6. package/dist/dotenv.js.map +1 -1
  7. package/dist/esbuild/index.js +7 -5
  8. package/dist/esbuild/index.js.map +1 -1
  9. package/dist/npm.d.ts +2 -2
  10. package/dist/npm.js +6 -6
  11. package/dist/npm.js.map +1 -1
  12. package/dist/swcRegister.d.ts +0 -6
  13. package/dist/swcRegister.js +0 -15
  14. package/dist/swcRegister.js.map +1 -1
  15. package/dist/utils.d.ts +33 -1
  16. package/dist/utils.js +83 -33
  17. package/dist/utils.js.map +1 -1
  18. package/package.json +24 -18
  19. package/swc/.gitkeep +0 -0
  20. package/swc/swc_plugin_compile_mode.wasm +0 -0
  21. package/swc/swc_plugin_define_config.wasm +0 -0
  22. package/swc/plugin-compile-mode/Cargo.lock +0 -2086
  23. package/swc/plugin-compile-mode/Cargo.toml +0 -20
  24. package/swc/plugin-compile-mode/src/lib.rs +0 -52
  25. package/swc/plugin-compile-mode/src/tests/attributes.rs +0 -85
  26. package/swc/plugin-compile-mode/src/tests/condition.rs +0 -71
  27. package/swc/plugin-compile-mode/src/tests/entry.rs +0 -32
  28. package/swc/plugin-compile-mode/src/tests/looping.rs +0 -134
  29. package/swc/plugin-compile-mode/src/tests/mod.rs +0 -98
  30. package/swc/plugin-compile-mode/src/tests/shake.rs +0 -41
  31. package/swc/plugin-compile-mode/src/transform.rs +0 -466
  32. package/swc/plugin-compile-mode/src/utils/constants.rs +0 -11
  33. package/swc/plugin-compile-mode/src/utils/mod.rs +0 -236
  34. package/swc/plugin-compile-mode/target/wasm32-wasi/release/swc_plugin_compile_mode.wasm +0 -0
  35. package/swc/plugin-define-config/Cargo.lock +0 -2034
  36. package/swc/plugin-define-config/Cargo.toml +0 -27
  37. package/swc/plugin-define-config/src/lib.rs +0 -188
  38. package/swc/plugin-define-config/target/wasm32-wasi/release/swc_plugin_define_config.wasm +0 -0
@@ -1,466 +0,0 @@
1
-
2
- use swc_core::{
3
- common::{
4
- iter::IdentifyLast,
5
- util::take::Take,
6
- DUMMY_SP as span
7
- },
8
- ecma::{
9
- self,
10
- ast::*,
11
- atoms::Atom,
12
- visit::{VisitMut, VisitMutWith},
13
- },
14
- };
15
- use std::collections::HashMap;
16
- use std::rc::Rc;
17
- use crate::PluginConfig;
18
- use crate::utils::{self, constants::*};
19
-
20
- struct PreVisitor {
21
- is_in_jsx_expr_container: Rc<bool>,
22
- is_in_and_expr: bool,
23
- }
24
- impl PreVisitor {
25
- fn new () -> Self {
26
- Self {
27
- is_in_jsx_expr_container: Rc::new(true),
28
- is_in_and_expr: false
29
- }
30
- }
31
- }
32
- impl VisitMut for PreVisitor {
33
- fn visit_mut_jsx_expr_container (&mut self, container: &mut JSXExprContainer) {
34
- let _counter = Rc::clone(&self.is_in_jsx_expr_container);
35
- // TODO 目前的判断可能误伤函数内的三元表达式、条件表达式
36
- container.visit_mut_children_with(self);
37
- }
38
- fn visit_mut_expr (&mut self, expr: &mut Expr) {
39
- if Rc::strong_count(&self.is_in_jsx_expr_container) == 1 { return };
40
- let mut is_first_and_expr = false;
41
-
42
- match expr {
43
- Expr::Bin(BinExpr { op, left, right, ..}) => {
44
- // C&&A 替换为 C?A:A',原因是为了无论显示还是隐藏都保留一个元素,从而不影响兄弟节点的变量路径
45
- if *op == op!("&&") && !self.is_in_and_expr {
46
- is_first_and_expr = true;
47
- fn inject_compile_if (el: &mut Box<JSXElement>, condition: &mut Box<Expr>) -> () {
48
- el.opening.attrs.push(utils::create_jsx_expr_attr(COMPILE_IF, condition.clone()));
49
- }
50
- fn get_element_double (element_name: JSXElementName, condition: &mut Box<Expr>, right: &mut Box<Expr>) -> Expr {
51
- Expr::Cond(CondExpr {
52
- span,
53
- test: condition.take(),
54
- cons: right.take(),
55
- alt: Box::new(utils::create_self_closing_jsx_element_expr(
56
- element_name, // element 替换为同类型的元素。在显示/隐藏切换时,让运行时 diff 只更新必要属性而不是整个节点刷新
57
- Some(vec![utils::create_jsx_bool_attr(COMPILE_IGNORE)]
58
- )))
59
- })
60
- }
61
- match &mut **right {
62
- Expr::JSXElement(el) => {
63
- let element_name = el.opening.name.clone();
64
- inject_compile_if(el, left);
65
- *expr = get_element_double(element_name, left, right);
66
- },
67
- Expr::Paren(ParenExpr { expr: paren_expr, .. }) => {
68
- if paren_expr.is_jsx_element() {
69
- let el: &mut Box<JSXElement> = paren_expr.as_mut_jsx_element().unwrap();
70
- let element_name = el.opening.name.clone();
71
- inject_compile_if(el, left);
72
- *expr = get_element_double(element_name, left, paren_expr);
73
- }
74
- },
75
- Expr::Lit(_) => {
76
- *expr = Expr::Cond(CondExpr {
77
- span,
78
- test: left.take(),
79
- cons: right.take(),
80
- alt: Box::new(Expr::Lit(Lit::Str(Str { span, value: COMPILE_IGNORE.into(), raw: None })))
81
- })
82
- },
83
- _ => {
84
- // TODO Unknown fallback to template
85
- println!("unknown expr: {right:?}");
86
- }
87
- }
88
- }
89
- },
90
- Expr::Cond(CondExpr { test, cons, alt, ..}) => {
91
- let compile_if = utils::create_jsx_expr_attr(COMPILE_IF, test.clone());
92
- let compile_else = utils::create_jsx_bool_attr(COMPILE_ELSE);
93
- let process_cond_arm = |arm: &mut Box<Expr>, attr: JSXAttrOrSpread| {
94
- match &mut **arm {
95
- Expr::JSXElement(el) => {
96
- el.opening.attrs.push(attr);
97
- },
98
- _ => {
99
- let temp = arm.take();
100
- let jsx_el_name = JSXElementName::Ident(Ident { span, sym: "block".into(), optional: false });
101
- **arm = Expr::JSXElement(Box::new(JSXElement {
102
- span,
103
- opening: JSXOpeningElement { name: jsx_el_name.clone(), span, attrs: vec![attr], self_closing: false, type_args: None },
104
- children: vec![JSXElementChild::JSXExprContainer(JSXExprContainer { span, expr: JSXExpr::Expr(temp)})],
105
- closing: Some(JSXClosingElement { span, name: jsx_el_name })
106
- }))
107
- }
108
- }
109
- };
110
- process_cond_arm(cons, compile_if);
111
- process_cond_arm(alt, compile_else);
112
- },
113
- _ => (),
114
- }
115
-
116
- if is_first_and_expr {
117
- self.is_in_and_expr = true;
118
- }
119
-
120
- expr.visit_mut_children_with(self);
121
-
122
- if is_first_and_expr {
123
- self.is_in_and_expr = false;
124
- }
125
- }
126
- }
127
-
128
- pub struct TransformVisitor {
129
- pub config: PluginConfig,
130
- pub is_compile_mode: bool,
131
- pub node_stack: Vec<i32>,
132
- pub templates: HashMap<String, String>,
133
- pub get_tmpl_name: Box<dyn FnMut() -> String>
134
- }
135
-
136
- impl TransformVisitor {
137
- pub fn new (config: PluginConfig) -> Self {
138
- let get_tmpl_name = Box::new(utils::named_iter(
139
- format!("{}t", config.tmpl_prefix)
140
- ));
141
- Self {
142
- config,
143
- is_compile_mode: false,
144
- node_stack: vec![],
145
- templates: HashMap::new(),
146
- get_tmpl_name
147
- }
148
- }
149
-
150
- fn build_xml_element (&mut self, el: &mut JSXElement) -> String {
151
- let opening_element = &mut el.opening;
152
- match &opening_element.name {
153
- JSXElementName::Ident(ident) => {
154
- let name = utils::to_kebab_case(&ident.sym);
155
- match self.config.components.get(&name) {
156
- // 内置组件
157
- Some(attrs_map) => {
158
- let attrs = self.build_xml_attrs(opening_element, attrs_map);
159
- if attrs.is_none() { return String::new() };
160
- let children = self.build_xml_children(el);
161
- format!("<{}{}>{}</{}>", name, attrs.unwrap(), children, name)
162
- },
163
- None => {
164
- // React 组件
165
- // 原生自定义组件
166
- let node_path = self.get_current_node_path();
167
- format!(r#"<template is="{{{{xs.a(c, {}.nn, l)}}}}" data="{{{{i:{},c:c+1,l:xs.f(l,{}.nn)}}}}" />"#, node_path, node_path, node_path)
168
- }
169
- }
170
- }
171
- _ => String::new()
172
- }
173
- }
174
-
175
- fn build_xml_attrs (&self, opening_element: &mut JSXOpeningElement, attrs_map: &HashMap<String, String>) -> Option<String> {
176
- let mut props = HashMap::new();
177
- let mut attrs_string = String::new();
178
-
179
- opening_element.attrs.retain_mut(|attr| {
180
- if let JSXAttrOrSpread::JSXAttr(jsx_attr) = attr {
181
- if let JSXAttrName::Ident(Ident { sym: name, .. }) = &jsx_attr.name {
182
- let jsx_attr_name = name.to_string();
183
-
184
- if jsx_attr_name == "key" {
185
- return true;
186
- }
187
-
188
- let miniapp_attr_name = utils::convert_jsx_attr_key(&jsx_attr_name, &self.config.adapter);
189
- let event_name = utils::identify_jsx_event_key(&jsx_attr_name);
190
- let is_event = event_name.is_some();
191
- match &jsx_attr.value {
192
- Some(jsx_attr_value) => {
193
- match jsx_attr_value {
194
- JSXAttrValue::Lit(Lit::Str(Str { value, .. })) => {
195
- // 静态属性在 xml 中保留即可,jsx 中可以删除
196
- if jsx_attr_name != COMPILE_MODE {
197
- props.insert(miniapp_attr_name, value.to_string());
198
- return false
199
- }
200
- },
201
- JSXAttrValue::JSXExprContainer(..) => {
202
- let mut node_path = self.get_current_node_path();
203
- if is_event {
204
- props.insert(event_name.unwrap(), String::from(EVENT_HANDLER));
205
- if props.get(DATA_SID).is_none() {
206
- props.insert(String::from(DATA_SID), format!("{{{{{}.sid}}}}", node_path));
207
- }
208
- return true
209
- }
210
-
211
- // 小程序组件标准属性 -> 取 @tarojs/shared 传递过来的属性值;非标准属性 -> 取属性名
212
- let value: &str = attrs_map.get(&miniapp_attr_name).unwrap_or(&jsx_attr_name);
213
- // 按当前节点在节点树中的位置换算路径
214
- node_path.push('.');
215
- let value = if value.contains(TMPL_DATA_ROOT) {
216
- value.replace(TMPL_DATA_ROOT, &node_path)
217
- } else {
218
- format!("{}{}", node_path, value)
219
- };
220
- // 得出最终的模板属性值
221
- let miniapp_attr_value = format!("{{{{{}}}}}", value);
222
-
223
- props.insert(miniapp_attr_name, miniapp_attr_value);
224
- },
225
- _ => ()
226
- }
227
- },
228
- None => {
229
- if
230
- jsx_attr_name == COMPILE_ELSE ||
231
- jsx_attr_name == COMPILE_IGNORE
232
- {
233
- props.insert(miniapp_attr_name, String::from(jsx_attr_name));
234
- } else if jsx_attr_name == COMPILE_FOR {
235
- let current_path = self.get_current_loop_path();
236
- let miniapp_attr_value = format!("{{{{{}}}}}", current_path);
237
- props.insert(miniapp_attr_name, miniapp_attr_value);
238
- } else {
239
- props.insert(miniapp_attr_name, String::from("true"));
240
- }
241
- // 布尔值在 jsx 中也可以删除了
242
- return false
243
- }
244
- }
245
- }
246
- }
247
- return true
248
- });
249
-
250
- // 组件包含事件,但没有设置自定义 id 的话,把 id 设为 sid
251
- if props.get(DATA_SID).is_some() && props.get(ID).is_none() {
252
- props.insert(String::from(ID), props.get(DATA_SID).unwrap().clone());
253
- }
254
-
255
- // 生成的 template 需要幂等
256
- let mut keys: Vec<&String> = props.keys().collect();
257
- keys.sort();
258
- for key in keys {
259
- let value = props.get(key).unwrap();
260
- if value == COMPILE_IGNORE {
261
- return None
262
- } else if value == COMPILE_ELSE {
263
- attrs_string.push_str(&format!(" {}", key));
264
- } else {
265
- attrs_string.push_str(&format!(r#" {}="{}""#, key, value));
266
- }
267
- }
268
-
269
- Some(attrs_string)
270
- }
271
-
272
- fn build_xml_children (&mut self, el: &mut JSXElement) -> String {
273
- let mut children_string = String::new();
274
- let mut retain_child_counter = 0;
275
-
276
- el.children
277
- .iter_mut()
278
- .for_each(|child| {
279
- self.node_stack.push(retain_child_counter);
280
- match child {
281
- JSXElementChild::JSXElement(child_el) => {
282
- let child_string = self.build_xml_element(&mut **child_el);
283
- children_string.push_str(&child_string);
284
-
285
- let is_pure = utils::is_static_jsx(child_el);
286
- if is_pure {
287
- let raw: Atom = "To be removed".into();
288
- *child = JSXElementChild::JSXText(JSXText { span, value: raw.clone(), raw });
289
- } else {
290
- retain_child_counter = retain_child_counter + 1;
291
- }
292
- },
293
- JSXElementChild::JSXExprContainer(JSXExprContainer {
294
- expr: JSXExpr::Expr(jsx_expr),
295
- ..
296
- }) => {
297
- if let Expr::Paren(ParenExpr { expr, .. }) = &mut **jsx_expr {
298
- *jsx_expr = expr.take();
299
- }
300
- match &mut **jsx_expr {
301
- Expr::Cond(CondExpr { cons, alt, ..}) => {
302
- let mut process_condition_expr = |arm: &mut Box<Expr>| {
303
- match &mut **arm {
304
- Expr::JSXElement(el) => {
305
- let child_string = self.build_xml_element(el);
306
- children_string.push_str(&child_string);
307
- },
308
- Expr::Lit(lit) => {
309
- if let Lit::Str(Str { value, .. }) = lit {
310
- if &*value == COMPILE_IGNORE {
311
- return ();
312
- }
313
- }
314
- let current_path = self.get_current_node_path();
315
- let str = format!(r#"{{{{{}.v==="{}"?"":{}.v}}}}"#, current_path, COMPILE_IGNORE, current_path);
316
- children_string.push_str(&str);
317
- },
318
- _ => ()
319
- }
320
- };
321
- process_condition_expr(cons);
322
- process_condition_expr(alt);
323
- },
324
- Expr::Call(CallExpr {
325
- callee: Callee::Expr(callee_expr),
326
- args,
327
- ..
328
- }) => {
329
- // 处理循环
330
- if let Some(return_value) = utils::extract_jsx_loop(callee_expr, args) {
331
- self.node_stack.pop();
332
- self.node_stack.push(LOOP_WRAPPER_ID);
333
- let child_string = self.build_xml_element(&mut *return_value);
334
- children_string.push_str(&child_string);
335
- }
336
- },
337
- // TODO 只支持 render 开头的函数调用返回 JSX
338
- // Expr::Call(_)
339
- _ => {
340
- // println!("_ expr: {:?} ", jsx_expr);
341
- let node_path = self.get_current_node_path();
342
- let code = format!("{{{{{}.v}}}}", node_path);
343
- children_string.push_str(&code);
344
- }
345
- }
346
- retain_child_counter = retain_child_counter + 1
347
- },
348
- JSXElementChild::JSXText(jsx_text) => {
349
- let content = utils::jsx_text_to_string(&jsx_text.value);
350
- if !content.is_empty() {
351
- children_string.push_str(&content);
352
- }
353
- },
354
- _ => ()
355
- }
356
- self.node_stack.pop();
357
- });
358
-
359
- el.children.retain_mut(|item| {
360
- // JSX 过滤掉静态文本节点,只在模板中保留
361
- match item {
362
- JSXElementChild::JSXText(jsx_text) => {
363
- utils::is_empty_jsx_text_line(&jsx_text.value)
364
- },
365
- _ => true
366
- }
367
- });
368
-
369
- children_string
370
- }
371
-
372
- fn get_current_node_path (&self) -> String {
373
- // return: i.cn[0].cn[0]....
374
- self.node_stack
375
- .iter()
376
- .fold(String::from("i"), |mut acc, item| {
377
- if item == &LOOP_WRAPPER_ID {
378
- return String::from("item")
379
- }
380
- acc.push_str(&format!(".cn[{}]", item));
381
- return acc;
382
- })
383
- }
384
-
385
- fn get_current_loop_path (&self) -> String {
386
- // return: i.cn[0]...cn
387
- self.node_stack
388
- .iter()
389
- .identify_last()
390
- .fold(String::from("i"), |mut acc, (is_last, item)| {
391
- let str = if is_last {
392
- String::from(".cn")
393
- } else {
394
- if item == &LOOP_WRAPPER_ID {
395
- return String::from("item")
396
- }
397
- format!(".cn[{}]", item)
398
- };
399
- acc.push_str(&str);
400
- return acc;
401
- })
402
- }
403
- }
404
-
405
- impl VisitMut for TransformVisitor {
406
- // Implement necessary visit_mut_* methods for actual custom transform.
407
- // A comprehensive list of possible visitor methods can be found here:
408
- // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html
409
- fn visit_mut_jsx_element (&mut self, el: &mut JSXElement) {
410
- let mut tmpl_name = String::new();
411
- for attr in &mut el.opening.attrs {
412
- if let JSXAttrOrSpread::JSXAttr(jsx_attr) = attr {
413
- if let JSXAttrName::Ident(jsx_attr_name) = &jsx_attr.name {
414
- if &*jsx_attr_name.sym == COMPILE_MODE {
415
- self.is_compile_mode = true;
416
- tmpl_name = (self.get_tmpl_name)();
417
- jsx_attr.value = Some(JSXAttrValue::Lit(Lit::Str(Str {
418
- span,
419
- value: tmpl_name.clone().into(),
420
- raw: None,
421
- })));
422
- break;
423
- }
424
- }
425
- }
426
- }
427
- if self.is_compile_mode {
428
- el.visit_mut_children_with(&mut PreVisitor::new());
429
- let tmpl_contents = format!(r#"<template name="tmpl_0_{}">{}</template>"#,
430
- &tmpl_name,
431
- self.build_xml_element(el)
432
- );
433
- self.templates.insert(tmpl_name, tmpl_contents);
434
- self.is_compile_mode = false;
435
- } else {
436
- el.visit_mut_children_with(self)
437
- }
438
- }
439
-
440
- fn visit_mut_module_items (&mut self, body_stmts: &mut Vec<ModuleItem>) {
441
- body_stmts.visit_mut_children_with(self);
442
-
443
- let mut keys: Vec<&String> = self.templates.keys().collect();
444
- keys.sort();
445
- let stmts_being_inserted = keys.into_iter()
446
- .map(|key| {
447
- let value = self.templates.get(key).unwrap();
448
- ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new(VarDecl {
449
- span,
450
- kind: VarDeclKind::Const,
451
- declare: false,
452
- decls: vec![VarDeclarator {
453
- span,
454
- name: Pat::Ident(Ident::new(format!("TARO_TEMPLATES_{}", key).as_str().into(), span).into()),
455
- init: Some(Box::new(Expr::Lit(Lit::Str(Str {
456
- span,
457
- value: value.as_str().into(),
458
- raw: None
459
- })))),
460
- definite: false,
461
- }],
462
- }))))
463
- });
464
- ecma::utils::prepend_stmts(body_stmts, stmts_being_inserted);
465
- }
466
- }
@@ -1,11 +0,0 @@
1
- pub const COMPILE_MODE: &str = "compileMode";
2
- pub const COMPILE_IF: &str = "compileIf";
3
- pub const COMPILE_ELSE: &str = "compileElse";
4
- pub const COMPILE_IGNORE: &str = "compileIgnore";
5
- pub const COMPILE_FOR: &str = "compileFor";
6
- pub const COMPILE_FOR_KEY: &str = "compileForKey";
7
- pub const EVENT_HANDLER: &str = "eh";
8
- pub const DATA_SID: &str = "data-sid";
9
- pub const TMPL_DATA_ROOT: &str = "i.";
10
- pub const ID: &str = "id";
11
- pub const LOOP_WRAPPER_ID: i32 = -1;