@dongmingzhixiu/vuexir-compiler 0.3.1 → 0.3.3

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.
@@ -265,6 +265,8 @@ export interface IrScreen {
265
265
  init: number | string | boolean;
266
266
  list?: boolean;
267
267
  obj?: boolean;
268
+ /** R96 computed 表达式(JS 运行时求值后写回该状态) */
269
+ computed?: string;
268
270
  }[];
269
271
  /** M3 <script setup> 提取的 handler 函数(@click="fn()" 引用;body 已做 .value → stateStore 重写)
270
272
  * R72:async:true 表示 `async function`(JS 侧保留 async 关键字;Android 侧按协程形状生成) */
@@ -8,6 +8,8 @@ export interface ScreenStateInfo {
8
8
  init: number | string | boolean;
9
9
  list?: boolean;
10
10
  obj?: boolean;
11
+ /** R96 computed 表达式(JS 运行时求值后写回该状态) */
12
+ computed?: string;
11
13
  }[];
12
14
  /** setter 函数名 → { target: 状态变量名, param: 形参名, expr: 无参函数体的赋值表达式 } */
13
15
  setters: Record<string, {
@@ -46,6 +48,7 @@ export declare function generateRuntimeSource(states: {
46
48
  name: string;
47
49
  init: number | string | boolean;
48
50
  list?: boolean;
51
+ computed?: string;
49
52
  }[], handlers: {
50
53
  name: string;
51
54
  params: string;
@@ -285,6 +285,19 @@ export function rewriteStateRefs(body, names) {
285
285
  }
286
286
  /** 生成 runtime.js 完整内容(M3:stateStore Proxy + handlers + onMounted + localStorage shim) */
287
287
  export function generateRuntimeSource(states, handlers, onMounted, onMountedAsync = false) {
288
+ // R96 computed:JS 运行时按表达式求值并写回 stateStore(写回经 Proxy → pushState 直达原生)
289
+ const computedStates = states.filter((st) => st.computed);
290
+ const computedBlock = computedStates.length === 0
291
+ ? ''
292
+ : `
293
+ // R96 computed 求值:页面里的 computed(() => expr) 原样在 JS 里算,结果写回状态
294
+ function __vrnRecompute() {
295
+ ${computedStates
296
+ .map((st) => ` try { stateStore.${st.name} = String(${st.computed}); } catch (e) { /* 求值失败保持初值 */ }`)
297
+ .join('\n')}
298
+ }
299
+ __vrnRecompute();
300
+ `;
288
301
  const initPairs = states.map((s) => {
289
302
  // M4b 动态列表态:list → JS 真数组('[]' 或 '["a","b"]' JSON 字面量,Swift JSONSerialization 可解码)
290
303
  const v = s.list
@@ -424,7 +437,7 @@ var router = {
424
437
  };
425
438
  // handlers(<script setup> 函数体:ref.value → stateStore 重写)
426
439
  ${handlerSrc}
427
- // onMounted(Swift onAppear → invoke("__onMounted"))
440
+ ${computedBlock}// onMounted(Swift onAppear → invoke("__onMounted"))
428
441
  ${onMounted !== undefined ? `${onMountedAsync ? 'async ' : ''}function __onMounted() {\n${indentBody(onMounted)}\n}` : ''}`;
429
442
  }
430
443
  /** 简单缩进(handler 体统一 2 空格缩进) */
@@ -994,6 +1007,26 @@ export function vueToIr(source, opts = {}) {
994
1007
  derivedNames.set(cm[1], flat);
995
1008
  }
996
1009
  }
1010
+ // R96 computed 求值:`const X = computed(() => expr)` 状态自足时注册为「运行时求值状态」
1011
+ // expr 里的 ref.value 会被重写成 stateStore.X;含未知标识符(外部函数/未声明变量)则跳过,
1012
+ // 留给后续 P2 打包阶段(需要 utils 进 bundle 才能算)
1013
+ {
1014
+ const stateNames = stateInfo.states.map((st) => st.name);
1015
+ const SAFE = new Set([
1016
+ 'Math', 'String', 'Number', 'Boolean', 'Date', 'JSON', 'parseInt', 'parseFloat',
1017
+ 'undefined', 'null', 'true', 'false', 'Array', 'Object', 'stateStore',
1018
+ ]);
1019
+ for (const cm of src.matchAll(/const\s+([A-Za-z_$][\w$]*)\s*=\s*computed\s*\(\s*\(\s*\)\s*=>\s*([^\n]+?)\s*\)\s*$/gm)) {
1020
+ const name = cm[1];
1021
+ const rawExpr = cm[2].trim();
1022
+ if (stateInfo.states.some((st) => st.name === name))
1023
+ continue;
1024
+ const jsExpr = rawExpr.replace(/\b([A-Za-z_$][\w$]*)\.value\b/g, (all, id) => stateNames.includes(id) ? `stateStore.${id}` : all);
1025
+ // R97:不再要求「标识符全部已知」——外部函数由 utils bundle(esbuild)提供,
1026
+ // 运行时找不到时由 try/catch 兜住(保持 init 空串),不静默也不阻断编译
1027
+ stateInfo.states.push({ name, init: '', computed: jsExpr });
1028
+ }
1029
+ }
997
1030
  // R89 常量折叠:模块级纯常量(含可静态求值的模板字面量)注入为状态
998
1031
  for (const km of src.matchAll(/const\s+([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=\s*(`[^`]*`|'[^']*'|"[^"]*"|-?\d+(?:\.\d+)?)\s*$/gm)) {
999
1032
  const raw = km[2];
@@ -1068,7 +1101,8 @@ export function vueToIr(source, opts = {}) {
1068
1101
  if (onMountedBody !== undefined)
1069
1102
  onMountedBody = renameSrc(onMountedBody);
1070
1103
  }
1071
- if (handlers.length > 0 || onMountedBody !== undefined) {
1104
+ const hasComputed = (stateInfo?.states ?? []).some((st) => st.computed);
1105
+ if (handlers.length > 0 || onMountedBody !== undefined || hasComputed) {
1072
1106
  runtime = generateRuntimeSource(stateInfo?.states ?? [], handlers, onMountedBody, onMountedAsync);
1073
1107
  }
1074
1108
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dongmingzhixiu/vuexir-compiler",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Vue SFC → IR → 原生源码(SwiftUI / Compose)编译器核心:纯函数、零 IO",
5
5
  "type": "module",
6
6
  "license": "MIT",