Skip to content

Commit 3f08e33

Browse files
authored
Merge branch 'main' into main
2 parents 02a61a2 + 8ae3f2d commit 3f08e33

File tree

128 files changed

+4168
-3421
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+4168
-3421
lines changed

.github/workflows/nodejs.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
name: Build Rust WASM
2929
uses: ./.github/workflows/build-rust-wasm.yml
3030

31-
nodejs-tesing:
31+
nodejs-testing:
3232
name: Testing on Node.js ${{ matrix.node-version }} (${{ matrix.host }})
3333
needs:
3434
- build-rust-binding
@@ -118,31 +118,27 @@ jobs:
118118
uses: codecov/codecov-action@v4
119119
if: ${{ matrix.host == 'ubuntu-latest' }}
120120
with:
121-
move_coverage_to_trash: true
122121
flags: taro-cli
123122
files: ./packages/taro-cli/coverage/clover.xml
124123
token: ${{ secrets.CODECOV_TOKEN }}
125124
- name: Upload runner coverage to Codecov
126125
uses: codecov/codecov-action@v4
127126
if: ${{ matrix.host == 'ubuntu-latest' }}
128127
with:
129-
move_coverage_to_trash: true
130128
flags: taro-runner
131129
files: ./packages/taro-webpack5-runner/coverage/clover.xml
132130
token: ${{ secrets.CODECOV_TOKEN }}
133131
- name: Upload [taro-runtime] coverage to Codecov
134132
uses: codecov/codecov-action@v4
135133
if: ${{ matrix.host == 'ubuntu-latest' }}
136134
with:
137-
move_coverage_to_trash: true
138135
flags: taro-runtime
139136
files: ./packages/taro-runtime/coverage/clover.xml
140137
token: ${{ secrets.CODECOV_TOKEN }}
141138
- name: Upload [taro-web] coverage to Codecov
142139
uses: codecov/codecov-action@v4
143140
if: ${{ matrix.host == 'ubuntu-latest' }}
144141
with:
145-
move_coverage_to_trash: true
146142
flags: taro-web
147143
files: ./packages/taro-components/coverage/clover.xml,./packages/taro-h5/coverage/clover.xml,./packages/taro-router/coverage/clover.xml
148144
token: ${{ secrets.CODECOV_TOKEN }}

.npmrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ public-hoist-pattern[]=@types/*
99
public-hoist-pattern[]=*eslint*
1010
public-hoist-pattern[]=*jest*
1111
public-hoist-pattern[]=*prettier*
12-
registry="https://registry.yarnpkg.com/"
1312
strict-peer-dependencies=false
1413

1514
{SCOPE}:registry=https://npm.pkg.github.com

crates/native_binding/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tarojs/binding",
3-
"version": "4.0.10-beta.1",
3+
"version": "4.0.10-alpha.5",
44
"description": "Node binding for taro",
55
"main": "binding.js",
66
"typings": "binding.d.ts",

crates/swc_plugin_compile_mode/src/tests/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use swc_core::ecma::{
33
parser,
44
visit::{as_folder, Fold},
55
};
6+
use std::env;
67

78
mod attributes;
89
mod children;
@@ -12,6 +13,7 @@ mod harmony;
1213
mod looping;
1314
mod shake;
1415
mod wxs;
16+
mod skyline;
1517

1618
pub fn tr() -> impl Fold {
1719
let config = serde_json::from_str::<PluginConfig>(
@@ -92,6 +94,10 @@ pub fn tr() -> impl Fold {
9294
}
9395

9496
pub fn get_syntax_config() -> parser::Syntax {
97+
// 获取当前工作目录
98+
let manifest_dir = env::current_dir().expect("Failed to get current directory");
99+
// 设置 CARGO_MANIFEST_DIR 环境变量
100+
env::set_var("CARGO_MANIFEST_DIR", manifest_dir.to_str().unwrap());
95101
parser::Syntax::Es(parser::EsConfig {
96102
jsx: true,
97103
..Default::default()
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use super::{get_syntax_config, tr};
2+
use swc_core::ecma::transforms::testing::test;
3+
4+
test!(
5+
get_syntax_config(),
6+
|_| tr(),
7+
should_support_list,
8+
r#"
9+
import { List as TaroList, ListItem as TaroListItem } from '@tarojs/components'
10+
const list = [1,2,3]
11+
function Index () {
12+
return (
13+
<TaroList
14+
compileMode
15+
scrollY
16+
onScroll={() => {
17+
console.log("scroll");
18+
}}
19+
onItemDispose={(ev) => {
20+
console.log(`${ev.detail.index} disposed`);
21+
}}
22+
list={list}
23+
childCount={list.length}
24+
childHeight={100}
25+
style={{ height: "100vh" }}
26+
type="static"
27+
>
28+
{
29+
list.map(x => (
30+
<TaroListItem key={x} style={{height: 100}}>
31+
<View>{x}</View>
32+
</TaroListItem>
33+
)
34+
)
35+
}
36+
</TaroList>
37+
)
38+
}
39+
"#
40+
);

crates/swc_plugin_compile_mode/src/transform.rs

Lines changed: 129 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use crate::utils::{self, constants::*};
1+
use crate::utils::{self, constants::*, transform_taro_components};
22
use crate::{utils::as_xscript_expr_string, PluginConfig};
33
use std::collections::HashMap;
4+
use std::vec;
45
use swc_core::{
56
atoms::Atom,
67
common::{iter::IdentifyLast, util::take::Take, Spanned, DUMMY_SP as span},
@@ -13,10 +14,23 @@ use swc_core::{
1314
plugin::errors::HANDLER,
1415
};
1516

16-
struct PreVisitor;
17+
struct PreVisitor {
18+
// HashMap<导出名, 模块标识符>
19+
pub import_specifiers: HashMap<String, String>,
20+
// HashMap<导出名, 别名>
21+
// import { x as y } from 'pkg'; import_aliases: [[x -> y]]
22+
pub import_aliases: HashMap<String, String>,
23+
}
24+
1725
impl PreVisitor {
18-
fn new() -> Self {
19-
Self {}
26+
fn new(
27+
import_specifiers: HashMap<String, String>,
28+
import_aliases: HashMap<String, String>,
29+
) -> Self {
30+
Self {
31+
import_specifiers,
32+
import_aliases,
33+
}
2034
}
2135
}
2236
impl VisitMut for PreVisitor {
@@ -232,6 +246,12 @@ impl VisitMut for PreVisitor {
232246
child.visit_mut_children_with(self);
233247
}
234248
}
249+
250+
fn visit_mut_jsx_element(&mut self, el: &mut JSXElement) {
251+
// 处理 @tarojs/components 的 List,ListItem 组件
252+
transform_taro_components(el, &self.import_specifiers, &self.import_aliases);
253+
el.visit_mut_children_with(self);
254+
}
235255
}
236256

237257
pub struct TransformVisitor {
@@ -242,6 +262,11 @@ pub struct TransformVisitor {
242262
pub get_tmpl_name: Box<dyn FnMut() -> String>,
243263
pub xs_module_names: Vec<String>,
244264
pub xs_sources: Vec<String>,
265+
// HashMap<导出名, 模块标识符>
266+
pub import_specifiers: HashMap<String, String>,
267+
// HashMap<导出名, 别名>
268+
// import { x as y } from 'pkg'; import_aliases: [[x -> y]]
269+
pub import_aliases: HashMap<String, String>,
245270
}
246271

247272
impl TransformVisitor {
@@ -255,15 +280,72 @@ impl TransformVisitor {
255280
get_tmpl_name,
256281
xs_module_names: vec![],
257282
xs_sources: vec![],
283+
import_specifiers: HashMap::new(),
284+
import_aliases: HashMap::new(),
258285
}
259286
}
260287

288+
fn collect_import_info(&mut self, body_stmts: &mut Vec<ModuleItem>) {
289+
body_stmts.iter().for_each(|item| match item {
290+
ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) => {
291+
import_decl.specifiers.iter().for_each(|import_specifier| {
292+
let src = import_decl.src.value.to_string();
293+
match import_specifier {
294+
ImportSpecifier::Named(import_named_specifier) => {
295+
let specifier = import_named_specifier.local.sym.to_string();
296+
// origin: 原始导出名
297+
// import { X as Y } from 'pkg', origin = X;
298+
// import { X } from 'pkg', origin = X;
299+
let mut origin = specifier.clone();
300+
self.import_specifiers.insert(specifier.clone(), src);
301+
302+
if let Some(ModuleExportName::Ident(imported)) =
303+
import_named_specifier.clone().imported
304+
{
305+
origin = imported.sym.to_string();
306+
}
307+
self
308+
.import_aliases
309+
.insert(origin.clone(), specifier.clone());
310+
}
311+
ImportSpecifier::Default(import_default_specifier) => {
312+
let specifier = import_default_specifier.local.sym.to_string();
313+
self.import_specifiers.insert(specifier, src);
314+
}
315+
ImportSpecifier::Namespace(import_star_as_specifier) => {
316+
let specifier = import_star_as_specifier.local.sym.to_string();
317+
self.import_specifiers.insert(specifier, src);
318+
}
319+
}
320+
});
321+
}
322+
_ => (),
323+
});
324+
}
325+
261326
fn build_xml_element(&mut self, el: &mut JSXElement) -> String {
262327
let is_inner_component = utils::is_inner_component(&el, &self.config);
263328
let opening_element = &mut el.opening;
264329

330+
let has_slot_item_attr = opening_element.clone().attrs.iter().any(|attr| {
331+
if let JSXAttrOrSpread::JSXAttr(attr) = attr {
332+
if let JSXAttrName::Ident(Ident { sym: name, .. }) = &attr.name {
333+
return name.to_string() == SLOT_ITEM;
334+
}
335+
}
336+
false
337+
});
265338
match &opening_element.name {
266339
JSXElementName::Ident(ident) => {
340+
// 先特殊处理有 slotItem 属性的组件,避免进入回退逻辑添加 wx:for 造成干扰
341+
if has_slot_item_attr {
342+
let node_path = self.get_current_node_path();
343+
return format!(
344+
"<block slot:item slot:index>{}</block>",
345+
self.generate_template(node_path, "".to_string())
346+
);
347+
}
348+
267349
if is_inner_component {
268350
// 内置组件
269351
let mut name = utils::to_kebab_case(ident.as_ref());
@@ -295,8 +377,23 @@ impl TransformVisitor {
295377
)
296378
} else {
297379
// 回退到旧的渲染模式(React 组件、原生自定义组件)
380+
// 如果是 map React组件,那么组件经过 extract_jsx_loop 的处理后会有 compileFor 属性,可以检测这个属性判断当前组件是否是循环里的组件
381+
let is_loop = el.opening.attrs.iter().any(|attr| {
382+
if let JSXAttrOrSpread::JSXAttr(attr) = attr {
383+
if let JSXAttrName::Ident(attr) = &attr.name {
384+
return attr.sym == COMPILE_FOR;
385+
}
386+
}
387+
false
388+
});
298389
let node_path = self.get_current_node_path();
299-
self.generate_template(node_path)
390+
// 循环的组件需要添加 wx:for 指令,否则生成的 template 里的 item 找不到
391+
let attrs = if is_loop {
392+
"wx:for=\"{{i.cn}}\" wx:key=\"{{sid}}\""
393+
} else {
394+
""
395+
};
396+
self.generate_template(node_path, attrs.to_string())
300397
}
301398
}
302399
JSXElementName::JSXMemberExpr(JSXMemberExpr { prop, .. }) => {
@@ -307,7 +404,7 @@ impl TransformVisitor {
307404
} else {
308405
// 回退到旧的渲染模式
309406
let node_path = self.get_current_node_path();
310-
self.generate_template(node_path)
407+
self.generate_template(node_path, "".to_string())
311408
}
312409
}
313410
_ => String::new(),
@@ -325,7 +422,6 @@ impl TransformVisitor {
325422
let is_xscript = utils::is_xscript(element_name);
326423
let mut attrs_wait_for_inserting: Vec<JSXAttrOrSpread> = vec![];
327424
let mut get_xs_attrs_name = utils::named_iter("xs".into());
328-
329425
opening_element.attrs.retain_mut(|attr| {
330426
if let JSXAttrOrSpread::JSXAttr(jsx_attr) = attr {
331427
if let JSXAttrName::Ident(Ident { sym: name, .. }) = &jsx_attr.name {
@@ -471,7 +567,16 @@ impl TransformVisitor {
471567
// 小程序组件标准属性 -> 取 @tarojs/shared 传递过来的属性值;非标准属性 -> 取属性名
472568
let value: &str = attrs_map
473569
.get(&miniapp_attr_name)
474-
.map(|res| res.as_str())
570+
.map(|res| {
571+
// list-builder这种场景下需要把原 list 换成 taro vdom 的 list
572+
if utils::to_kebab_case(element_name) == "list-builder"
573+
&& miniapp_attr_name == "list"
574+
{
575+
"cn"
576+
} else {
577+
res.as_str()
578+
}
579+
})
475580
.unwrap_or(if miniapp_attr_name == "id" {
476581
"uid"
477582
} else {
@@ -496,6 +601,7 @@ impl TransformVisitor {
496601
if jsx_attr_name == COMPILE_ELSE || jsx_attr_name == COMPILE_IGNORE {
497602
props.insert(miniapp_attr_name, String::from(jsx_attr_name));
498603
} else if jsx_attr_name == COMPILE_FOR {
604+
// 构造 wx:for 表达式
499605
let current_path = self.get_current_loop_path();
500606
let miniapp_attr_value = format!("{{{{{}}}}}", current_path);
501607
props.insert(miniapp_attr_name, miniapp_attr_value);
@@ -643,7 +749,7 @@ impl TransformVisitor {
643749
let child_string = self.build_xml_element(&mut *return_value);
644750
children_string.push_str(&child_string);
645751
} else if utils::is_render_fn(callee_expr) {
646-
let tmpl = self.generate_template(node_path);
752+
let tmpl = self.generate_template(node_path, "".to_string());
647753
children_string.push_str(&tmpl)
648754
} else {
649755
let mut xscript_expr_string: Option<String> = None;
@@ -786,19 +892,20 @@ impl TransformVisitor {
786892
(children_string, retain_child_counter - start)
787893
}
788894

789-
fn generate_template(&mut self, node_path: String) -> String {
895+
fn generate_template(&mut self, node_path: String, attrs: String) -> String {
790896
if self.config.is_use_xs {
791897
format!(
792-
r#"<template is="{{{{xs.a(c, {}.nn, l)}}}}" data="{{{{i:{},c:c+1,l:xs.f(l,{}.nn)}}}}" />"#,
793-
node_path, node_path, node_path
898+
r#"<template is="{{{{xs.a(c, {}.nn, l)}}}}" data="{{{{i:{},c:c+1,l:xs.f(l,{}.nn)}}}}" {}/>"#,
899+
node_path, node_path, node_path, attrs
794900
)
795901
} else {
796902
format!(
797-
r#"<template is="{{{{'tmpl_' + ({}.nn[0] === '{}' ? 0 : c) + '_' + {}.nn }}}}" data="{{{{i:{},c:c+1}}}}" />"#,
903+
r#"<template is="{{{{'tmpl_' + ({}.nn[0] === '{}' ? 0 : c) + '_' + {}.nn }}}}" data="{{{{i:{},c:c+1}}}}" {}/>"#,
798904
node_path,
799905
self.config.tmpl_prefix.chars().next().unwrap(),
800906
node_path,
801-
node_path
907+
node_path,
908+
attrs
802909
)
803910
}
804911
}
@@ -864,9 +971,14 @@ impl VisitMut for TransformVisitor {
864971
}
865972
}
866973
}
974+
867975
if self.is_compile_mode {
868976
self.reset_states();
869-
el.visit_mut_children_with(&mut PreVisitor::new());
977+
transform_taro_components(el, &self.import_specifiers, &self.import_aliases);
978+
el.visit_mut_children_with(&mut PreVisitor::new(
979+
self.import_specifiers.clone(),
980+
self.import_aliases.clone(),
981+
));
870982

871983
let tmpl_contents = format!(
872984
r#"{}<template name="tmpl_0_{}">{}</template>{}"#,
@@ -883,6 +995,8 @@ impl VisitMut for TransformVisitor {
883995
}
884996

885997
fn visit_mut_module_items(&mut self, body_stmts: &mut Vec<ModuleItem>) {
998+
// 收集模块导入信息
999+
self.collect_import_info(body_stmts);
8861000
body_stmts.visit_mut_children_with(self);
8871001

8881002
let mut keys: Vec<&String> = self.templates.keys().collect();

crates/swc_plugin_compile_mode/src/utils/constants.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub const COMPILE_ELSE: &str = "compileElse";
44
pub const COMPILE_IGNORE: &str = "compileIgnore";
55
pub const COMPILE_FOR: &str = "compileFor";
66
pub const COMPILE_FOR_KEY: &str = "compileForKey";
7+
pub const SLOT_ITEM: &str = "slotItem";
78
pub const EVENT_HANDLER: &str = "eh";
89
pub const DATA_SID: &str = "data-sid";
910
pub const TMPL_DATA_ROOT: &str = "i.";

0 commit comments

Comments
 (0)