@dongmingzhixiu/vuexir-compiler 0.4.1 → 0.4.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.
- package/dist/codegen/swiftui.js +1 -1
- package/dist/transform/vue2ir.js +20 -6
- package/package.json +1 -1
package/dist/codegen/swiftui.js
CHANGED
|
@@ -810,7 +810,7 @@ function emitNodeInner(node, ctx) {
|
|
|
810
810
|
let line = isRef
|
|
811
811
|
? pad(`Text(${props.ref})`)
|
|
812
812
|
: props.bindExpr !== undefined
|
|
813
|
-
? pad(`Text(${props.bindExpr})`)
|
|
813
|
+
? pad(`Text(${String(props.bindExpr).includes('.') ? '""' : props.bindExpr})`)
|
|
814
814
|
: props.fieldOf !== undefined
|
|
815
815
|
? pad(`Text(vrnField(${props.fieldOf.obj}, "${props.fieldOf.field}"${props.fieldOf.fallback !== undefined ? `, "${swiftStringEscape(props.fieldOf.fallback)}"` : ''}))`)
|
|
816
816
|
: props.dynField !== undefined
|
package/dist/transform/vue2ir.js
CHANGED
|
@@ -41,6 +41,8 @@ function addJsExprState(expr) {
|
|
|
41
41
|
jsExprStates.push({ name, init: '', computed: js });
|
|
42
42
|
return name;
|
|
43
43
|
}
|
|
44
|
+
/** R125 当前生效的 v-for 作用域栈(绕开 loopScope 透传不一致的问题) */
|
|
45
|
+
let activeLoops = [];
|
|
44
46
|
/** R115 是否允许未注册组件降级(由 vueToIr 选项设置) */
|
|
45
47
|
let allowUnknownComponentsFlag = false;
|
|
46
48
|
/** R104 脚本里声明过的名字(const/let/function)——未登记为 state 时走运行时求值 */
|
|
@@ -979,6 +981,7 @@ export function vueToIr(source, opts = {}) {
|
|
|
979
981
|
jsExprSeq = 0;
|
|
980
982
|
jsExprStates = [];
|
|
981
983
|
allowUnknownComponentsFlag = opts.allowUnknownComponents === true;
|
|
984
|
+
activeLoops = [];
|
|
982
985
|
const warnings = [];
|
|
983
986
|
const { descriptor, errors } = parse(source, { filename: 'Screen.vue' });
|
|
984
987
|
if (errors.length > 0) {
|
|
@@ -1417,12 +1420,18 @@ function walk(node, classProps, comboRules, scopedRules, pseudoRules, warnings,
|
|
|
1417
1420
|
if (tri)
|
|
1418
1421
|
return [{ type: 'text', props: { bindExpr: tri } }];
|
|
1419
1422
|
// M2:v-for 循环变量(item/index)优先于状态表
|
|
1420
|
-
const loopVar = loopScope.find((l) => l.itemKey === name || l.indexKey === name)
|
|
1423
|
+
const loopVar = loopScope.find((l) => l.itemKey === name || l.indexKey === name) ??
|
|
1424
|
+
[...activeLoops].reverse().find((l) => l.itemKey === name.split('.')[0] || l.indexKey === name.split('.')[0]);
|
|
1421
1425
|
if (loopVar) {
|
|
1422
|
-
// M4b 动态列表项属性访问 {{ item.field }} → dynField
|
|
1426
|
+
// M4b 动态列表项属性访问 {{ item.field }} / item.a.b → dynField(点路径拍平键)
|
|
1423
1427
|
const dot = name.split('.');
|
|
1424
|
-
if (dot.length
|
|
1425
|
-
return [{ type: 'text', props: { dynField: { var: dot[0], field: dot
|
|
1428
|
+
if (dot.length >= 2 && dot[0] === loopVar.itemKey && dot.slice(1).every((seg) => /^\w+$/.test(seg))) {
|
|
1429
|
+
return [{ type: 'text', props: { dynField: { var: dot[0], field: dot.slice(1).join('.') } } }];
|
|
1430
|
+
}
|
|
1431
|
+
// R126:循环体内出现复杂表达式(三元等)→ 原生端无法静态求值,置空避免非法代码
|
|
1432
|
+
if (!/^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$/.test(name)) {
|
|
1433
|
+
warnings.push(`v-for 项内复杂表达式「${name.slice(0, 30)}」暂不支持 → 已置空(R126)`);
|
|
1434
|
+
return [{ type: 'text', props: { text: ' ' } }];
|
|
1426
1435
|
}
|
|
1427
1436
|
return [{ type: 'text', bind: { key: name } }];
|
|
1428
1437
|
}
|
|
@@ -1707,10 +1716,12 @@ function walkElement(node, classProps, comboRules, scopedRules, pseudoRules, war
|
|
|
1707
1716
|
...node,
|
|
1708
1717
|
props: node.props.filter((p) => !(p.type === NodeTypes.DIRECTIVE && p.name === 'for')),
|
|
1709
1718
|
};
|
|
1719
|
+
activeLoops.push({ itemKey: vfSunk.itemKey, indexKey: vfSunk.indexKey });
|
|
1710
1720
|
const itemSunk = walkElement(innerNodeSunk, classProps, comboRules, scopedRules, pseudoRules, warnings, state, compTable, propRefs, [
|
|
1711
1721
|
...loopScope,
|
|
1712
1722
|
{ itemKey: vfSunk.itemKey, indexKey: vfSunk.indexKey },
|
|
1713
1723
|
], ancestorClasses);
|
|
1724
|
+
activeLoops.pop();
|
|
1714
1725
|
return { type: 'for', vfor: vfSunk, children: [itemSunk] };
|
|
1715
1726
|
}
|
|
1716
1727
|
}
|
|
@@ -1746,10 +1757,12 @@ function walkElement(node, classProps, comboRules, scopedRules, pseudoRules, war
|
|
|
1746
1757
|
throw new VueCompileError(`v-for 动态数据源「${vf.listState}」未在 <script setup> 中声明为 ref 数组(M4b)`);
|
|
1747
1758
|
}
|
|
1748
1759
|
const innerNode = { ...node, props: node.props.filter((p) => !(p.type === NodeTypes.DIRECTIVE && p.name === 'for')) };
|
|
1760
|
+
activeLoops.push({ itemKey: vf.itemKey, indexKey: vf.indexKey });
|
|
1749
1761
|
const item = walkElement(innerNode, classProps, comboRules, scopedRules, pseudoRules, warnings, state, compTable, propRefs, [
|
|
1750
1762
|
...loopScope,
|
|
1751
1763
|
{ itemKey: vf.itemKey, indexKey: vf.indexKey },
|
|
1752
1764
|
], ancestorClasses);
|
|
1765
|
+
activeLoops.pop();
|
|
1753
1766
|
return { type: 'for', vfor: vf, children: [item] };
|
|
1754
1767
|
}
|
|
1755
1768
|
// R76 Vue 内置容器组件(Transition/KeepAlive/Teleport/Suspense/Fragment)→ 透明展开:
|
|
@@ -2000,7 +2013,8 @@ function walkElement(node, classProps, comboRules, scopedRules, pseudoRules, war
|
|
|
2000
2013
|
// 动态列表项属性 {{ item.field }}:基名(dot[0])命中循环变量才成立
|
|
2001
2014
|
const dot = name.split('.');
|
|
2002
2015
|
const base = dot[0];
|
|
2003
|
-
const loopVar = loopScope.find((l) => l.itemKey === base || l.indexKey === base)
|
|
2016
|
+
const loopVar = loopScope.find((l) => l.itemKey === base || l.indexKey === base) ??
|
|
2017
|
+
[...activeLoops].reverse().find((l) => l.itemKey === base || l.indexKey === base);
|
|
2004
2018
|
const dyn = loopVar && dot.length >= 2 && dot[0] === loopVar.itemKey && dot.slice(1).every((seg) => /^\w+$/.test(seg));
|
|
2005
2019
|
if (!text && !parts.some((p) => 'bind' in p || 'dynField' in p || 'fieldOf' in p)) {
|
|
2006
2020
|
// M2 模板内三元(D1 小范围):cond ? 'a' : 'b' → Swift 三元字符串表达式(Text(expr))
|
|
@@ -2069,7 +2083,7 @@ function walkElement(node, classProps, comboRules, scopedRules, pseudoRules, war
|
|
|
2069
2083
|
}
|
|
2070
2084
|
// 混合段:静态文本之后的插值
|
|
2071
2085
|
if (dyn)
|
|
2072
|
-
parts.push({ dynField: { var: dot[0], field: dot
|
|
2086
|
+
parts.push({ dynField: { var: dot[0], field: dot.slice(1).join('.') } });
|
|
2073
2087
|
else if (/^\w+$/.test(name) && (loopVar || (state && state.states.some((s) => s.name === name))))
|
|
2074
2088
|
parts.push({ bind: name });
|
|
2075
2089
|
else if (propRefs)
|