@variojs/core 0.1.0

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 (209) hide show
  1. package/__tests__/README.md +101 -0
  2. package/__tests__/errors.test.ts +139 -0
  3. package/__tests__/expression/cache.test.ts +118 -0
  4. package/__tests__/expression/compiler.test.ts +111 -0
  5. package/__tests__/expression/evaluate.test.ts +95 -0
  6. package/__tests__/expression/parser.test.ts +57 -0
  7. package/__tests__/expression/whitelist.test.ts +59 -0
  8. package/__tests__/performance.test.ts +379 -0
  9. package/__tests__/runtime/create-context.test.ts +78 -0
  10. package/__tests__/runtime/loop-context-pool.test.ts +74 -0
  11. package/__tests__/runtime/path.test.ts +128 -0
  12. package/__tests__/vm/executor-timeout.test.ts +117 -0
  13. package/__tests__/vm/executor.test.ts +173 -0
  14. package/__tests__/vm/handlers/array.test.ts +113 -0
  15. package/__tests__/vm/handlers/call.test.ts +93 -0
  16. package/dist/errors.d.ts +100 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +132 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/expression/cache.d.ts +53 -0
  21. package/dist/expression/cache.d.ts.map +1 -0
  22. package/dist/expression/cache.js +158 -0
  23. package/dist/expression/cache.js.map +1 -0
  24. package/dist/expression/compiler.d.ts +34 -0
  25. package/dist/expression/compiler.d.ts.map +1 -0
  26. package/dist/expression/compiler.js +123 -0
  27. package/dist/expression/compiler.js.map +1 -0
  28. package/dist/expression/dependencies.d.ts +17 -0
  29. package/dist/expression/dependencies.d.ts.map +1 -0
  30. package/dist/expression/dependencies.js +106 -0
  31. package/dist/expression/dependencies.js.map +1 -0
  32. package/dist/expression/evaluate.d.ts +22 -0
  33. package/dist/expression/evaluate.d.ts.map +1 -0
  34. package/dist/expression/evaluate.js +75 -0
  35. package/dist/expression/evaluate.js.map +1 -0
  36. package/dist/expression/evaluator.d.ts +22 -0
  37. package/dist/expression/evaluator.d.ts.map +1 -0
  38. package/dist/expression/evaluator.js +506 -0
  39. package/dist/expression/evaluator.js.map +1 -0
  40. package/dist/expression/index.d.ts +12 -0
  41. package/dist/expression/index.d.ts.map +1 -0
  42. package/dist/expression/index.js +12 -0
  43. package/dist/expression/index.js.map +1 -0
  44. package/dist/expression/parser.d.ts +15 -0
  45. package/dist/expression/parser.d.ts.map +1 -0
  46. package/dist/expression/parser.js +42 -0
  47. package/dist/expression/parser.js.map +1 -0
  48. package/dist/expression/utils.d.ts +46 -0
  49. package/dist/expression/utils.d.ts.map +1 -0
  50. package/dist/expression/utils.js +78 -0
  51. package/dist/expression/utils.js.map +1 -0
  52. package/dist/expression/whitelist.d.ts +24 -0
  53. package/dist/expression/whitelist.d.ts.map +1 -0
  54. package/dist/expression/whitelist.js +198 -0
  55. package/dist/expression/whitelist.js.map +1 -0
  56. package/dist/index.d.ts +19 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +21 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/runtime/context.d.ts +8 -0
  61. package/dist/runtime/context.d.ts.map +1 -0
  62. package/dist/runtime/context.js +7 -0
  63. package/dist/runtime/context.js.map +1 -0
  64. package/dist/runtime/create-context.d.ts +50 -0
  65. package/dist/runtime/create-context.d.ts.map +1 -0
  66. package/dist/runtime/create-context.js +73 -0
  67. package/dist/runtime/create-context.js.map +1 -0
  68. package/dist/runtime/index.d.ts +10 -0
  69. package/dist/runtime/index.d.ts.map +1 -0
  70. package/dist/runtime/index.js +10 -0
  71. package/dist/runtime/index.js.map +1 -0
  72. package/dist/runtime/loop-context-pool.d.ts +58 -0
  73. package/dist/runtime/loop-context-pool.d.ts.map +1 -0
  74. package/dist/runtime/loop-context-pool.js +114 -0
  75. package/dist/runtime/loop-context-pool.js.map +1 -0
  76. package/dist/runtime/path.d.ts +114 -0
  77. package/dist/runtime/path.d.ts.map +1 -0
  78. package/dist/runtime/path.js +302 -0
  79. package/dist/runtime/path.js.map +1 -0
  80. package/dist/runtime/proxy.d.ts +18 -0
  81. package/dist/runtime/proxy.d.ts.map +1 -0
  82. package/dist/runtime/proxy.js +53 -0
  83. package/dist/runtime/proxy.js.map +1 -0
  84. package/dist/runtime/sandbox.d.ts +20 -0
  85. package/dist/runtime/sandbox.d.ts.map +1 -0
  86. package/dist/runtime/sandbox.js +32 -0
  87. package/dist/runtime/sandbox.js.map +1 -0
  88. package/dist/types.d.ts +175 -0
  89. package/dist/types.d.ts.map +1 -0
  90. package/dist/types.js +22 -0
  91. package/dist/types.js.map +1 -0
  92. package/dist/vm/action.d.ts +11 -0
  93. package/dist/vm/action.d.ts.map +1 -0
  94. package/dist/vm/action.js +10 -0
  95. package/dist/vm/action.js.map +1 -0
  96. package/dist/vm/errors.d.ts +5 -0
  97. package/dist/vm/errors.d.ts.map +1 -0
  98. package/dist/vm/errors.js +5 -0
  99. package/dist/vm/errors.js.map +1 -0
  100. package/dist/vm/executor.d.ts +35 -0
  101. package/dist/vm/executor.d.ts.map +1 -0
  102. package/dist/vm/executor.js +137 -0
  103. package/dist/vm/executor.js.map +1 -0
  104. package/dist/vm/handlers/array/pop.d.ts +12 -0
  105. package/dist/vm/handlers/array/pop.d.ts.map +1 -0
  106. package/dist/vm/handlers/array/pop.js +28 -0
  107. package/dist/vm/handlers/array/pop.js.map +1 -0
  108. package/dist/vm/handlers/array/push.d.ts +13 -0
  109. package/dist/vm/handlers/array/push.d.ts.map +1 -0
  110. package/dist/vm/handlers/array/push.js +42 -0
  111. package/dist/vm/handlers/array/push.js.map +1 -0
  112. package/dist/vm/handlers/array/shift.d.ts +12 -0
  113. package/dist/vm/handlers/array/shift.d.ts.map +1 -0
  114. package/dist/vm/handlers/array/shift.js +28 -0
  115. package/dist/vm/handlers/array/shift.js.map +1 -0
  116. package/dist/vm/handlers/array/splice.d.ts +12 -0
  117. package/dist/vm/handlers/array/splice.d.ts.map +1 -0
  118. package/dist/vm/handlers/array/splice.js +59 -0
  119. package/dist/vm/handlers/array/splice.js.map +1 -0
  120. package/dist/vm/handlers/array/unshift.d.ts +13 -0
  121. package/dist/vm/handlers/array/unshift.d.ts.map +1 -0
  122. package/dist/vm/handlers/array/unshift.js +42 -0
  123. package/dist/vm/handlers/array/unshift.js.map +1 -0
  124. package/dist/vm/handlers/array/utils.d.ts +10 -0
  125. package/dist/vm/handlers/array/utils.d.ts.map +1 -0
  126. package/dist/vm/handlers/array/utils.js +33 -0
  127. package/dist/vm/handlers/array/utils.js.map +1 -0
  128. package/dist/vm/handlers/batch.d.ts +12 -0
  129. package/dist/vm/handlers/batch.d.ts.map +1 -0
  130. package/dist/vm/handlers/batch.js +40 -0
  131. package/dist/vm/handlers/batch.js.map +1 -0
  132. package/dist/vm/handlers/call.d.ts +14 -0
  133. package/dist/vm/handlers/call.d.ts.map +1 -0
  134. package/dist/vm/handlers/call.js +65 -0
  135. package/dist/vm/handlers/call.js.map +1 -0
  136. package/dist/vm/handlers/emit.d.ts +12 -0
  137. package/dist/vm/handlers/emit.d.ts.map +1 -0
  138. package/dist/vm/handlers/emit.js +26 -0
  139. package/dist/vm/handlers/emit.js.map +1 -0
  140. package/dist/vm/handlers/if.d.ts +13 -0
  141. package/dist/vm/handlers/if.d.ts.map +1 -0
  142. package/dist/vm/handlers/if.js +35 -0
  143. package/dist/vm/handlers/if.js.map +1 -0
  144. package/dist/vm/handlers/index.d.ts +11 -0
  145. package/dist/vm/handlers/index.d.ts.map +1 -0
  146. package/dist/vm/handlers/index.js +46 -0
  147. package/dist/vm/handlers/index.js.map +1 -0
  148. package/dist/vm/handlers/log.d.ts +12 -0
  149. package/dist/vm/handlers/log.d.ts.map +1 -0
  150. package/dist/vm/handlers/log.js +41 -0
  151. package/dist/vm/handlers/log.js.map +1 -0
  152. package/dist/vm/handlers/loop.d.ts +12 -0
  153. package/dist/vm/handlers/loop.d.ts.map +1 -0
  154. package/dist/vm/handlers/loop.js +71 -0
  155. package/dist/vm/handlers/loop.js.map +1 -0
  156. package/dist/vm/handlers/navigate.d.ts +12 -0
  157. package/dist/vm/handlers/navigate.d.ts.map +1 -0
  158. package/dist/vm/handlers/navigate.js +43 -0
  159. package/dist/vm/handlers/navigate.js.map +1 -0
  160. package/dist/vm/handlers/set.d.ts +15 -0
  161. package/dist/vm/handlers/set.d.ts.map +1 -0
  162. package/dist/vm/handlers/set.js +30 -0
  163. package/dist/vm/handlers/set.js.map +1 -0
  164. package/dist/vm/index.d.ts +8 -0
  165. package/dist/vm/index.d.ts.map +1 -0
  166. package/dist/vm/index.js +7 -0
  167. package/dist/vm/index.js.map +1 -0
  168. package/package.json +34 -0
  169. package/src/errors.ts +194 -0
  170. package/src/expression/README.md +192 -0
  171. package/src/expression/cache.ts +199 -0
  172. package/src/expression/compiler.ts +144 -0
  173. package/src/expression/dependencies.ts +116 -0
  174. package/src/expression/evaluate.ts +95 -0
  175. package/src/expression/evaluator.ts +640 -0
  176. package/src/expression/index.ts +27 -0
  177. package/src/expression/parser.ts +54 -0
  178. package/src/expression/utils.ts +89 -0
  179. package/src/expression/whitelist.ts +224 -0
  180. package/src/globals.d.ts +10 -0
  181. package/src/index.ts +72 -0
  182. package/src/runtime/context.ts +8 -0
  183. package/src/runtime/create-context.ts +133 -0
  184. package/src/runtime/index.ts +28 -0
  185. package/src/runtime/loop-context-pool.ts +134 -0
  186. package/src/runtime/path.ts +372 -0
  187. package/src/runtime/proxy.ts +66 -0
  188. package/src/runtime/sandbox.ts +43 -0
  189. package/src/types.ts +177 -0
  190. package/src/vm/errors.ts +10 -0
  191. package/src/vm/executor.ts +210 -0
  192. package/src/vm/handlers/array/pop.ts +47 -0
  193. package/src/vm/handlers/array/push.ts +68 -0
  194. package/src/vm/handlers/array/shift.ts +47 -0
  195. package/src/vm/handlers/array/splice.ts +78 -0
  196. package/src/vm/handlers/array/unshift.ts +68 -0
  197. package/src/vm/handlers/array/utils.ts +41 -0
  198. package/src/vm/handlers/batch.ts +57 -0
  199. package/src/vm/handlers/call.ts +92 -0
  200. package/src/vm/handlers/emit.ts +39 -0
  201. package/src/vm/handlers/if.ts +48 -0
  202. package/src/vm/handlers/index.ts +52 -0
  203. package/src/vm/handlers/log.ts +54 -0
  204. package/src/vm/handlers/loop.ts +102 -0
  205. package/src/vm/handlers/navigate.ts +64 -0
  206. package/src/vm/handlers/set.ts +43 -0
  207. package/src/vm/index.ts +8 -0
  208. package/tsconfig.json +17 -0
  209. package/vitest.config.ts +30 -0
package/dist/errors.js ADDED
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Vario 错误处理体系
3
+ *
4
+ * 统一的错误基类和错误码系统
5
+ */
6
+ /**
7
+ * Vario 错误基类
8
+ *
9
+ * 所有 Vario 相关错误都应继承此类
10
+ */
11
+ export class VarioError extends Error {
12
+ /** 错误码 */
13
+ code;
14
+ /** 错误上下文 */
15
+ context;
16
+ constructor(message, code, context = {}) {
17
+ super(message);
18
+ this.name = 'VarioError';
19
+ this.code = code;
20
+ this.context = context;
21
+ // 确保 stack 属性存在
22
+ if (Error.captureStackTrace) {
23
+ Error.captureStackTrace(this, VarioError);
24
+ }
25
+ }
26
+ /**
27
+ * 获取友好的错误消息
28
+ */
29
+ getFriendlyMessage() {
30
+ const parts = [this.message];
31
+ if (this.context.schemaPath) {
32
+ parts.push(`\n Schema 路径: ${this.context.schemaPath}`);
33
+ }
34
+ if (this.context.expression) {
35
+ parts.push(`\n 表达式: ${this.context.expression}`);
36
+ }
37
+ if (this.context.action) {
38
+ parts.push(`\n 动作类型: ${this.context.action.type}`);
39
+ }
40
+ return parts.join('');
41
+ }
42
+ /**
43
+ * 转换为 JSON(用于序列化)
44
+ */
45
+ toJSON() {
46
+ return {
47
+ name: this.name,
48
+ message: this.message,
49
+ code: this.code,
50
+ context: this.context,
51
+ stack: this.stack
52
+ };
53
+ }
54
+ }
55
+ /**
56
+ * 动作执行错误
57
+ */
58
+ export class ActionError extends VarioError {
59
+ constructor(action, message, code = 'ACTION_ERROR', context = {}) {
60
+ super(message, code, {
61
+ ...context,
62
+ action
63
+ });
64
+ this.name = 'ActionError';
65
+ }
66
+ }
67
+ /**
68
+ * 表达式求值错误
69
+ */
70
+ export class ExpressionError extends VarioError {
71
+ constructor(expression, message, code = 'EXPRESSION_ERROR', context = {}) {
72
+ super(message, code, {
73
+ ...context,
74
+ expression
75
+ });
76
+ this.name = 'ExpressionError';
77
+ }
78
+ }
79
+ /**
80
+ * 服务调用错误
81
+ */
82
+ export class ServiceError extends VarioError {
83
+ service;
84
+ originalError;
85
+ constructor(service, message, originalError, context = {}) {
86
+ super(message, 'SERVICE_ERROR', context);
87
+ this.name = 'ServiceError';
88
+ this.service = service;
89
+ this.originalError = originalError;
90
+ }
91
+ }
92
+ /**
93
+ * 批量执行错误
94
+ */
95
+ export class BatchError extends VarioError {
96
+ failedActions;
97
+ constructor(failedActions, message, context = {}) {
98
+ super(message, 'BATCH_ERROR', context);
99
+ this.name = 'BatchError';
100
+ this.failedActions = failedActions;
101
+ }
102
+ }
103
+ /**
104
+ * 错误码定义
105
+ */
106
+ export const ErrorCodes = {
107
+ // 动作相关错误
108
+ ACTION_UNKNOWN_TYPE: 'ACTION_UNKNOWN_TYPE',
109
+ ACTION_EXECUTION_ERROR: 'ACTION_EXECUTION_ERROR',
110
+ ACTION_ABORTED: 'ACTION_ABORTED',
111
+ ACTION_TIMEOUT: 'ACTION_TIMEOUT',
112
+ ACTION_MAX_STEPS_EXCEEDED: 'ACTION_MAX_STEPS_EXCEEDED',
113
+ ACTION_MISSING_PARAM: 'ACTION_MISSING_PARAM',
114
+ ACTION_INVALID_PARAM: 'ACTION_INVALID_PARAM',
115
+ // 表达式相关错误
116
+ EXPRESSION_PARSE_ERROR: 'EXPRESSION_PARSE_ERROR',
117
+ EXPRESSION_VALIDATION_ERROR: 'EXPRESSION_VALIDATION_ERROR',
118
+ EXPRESSION_EVALUATION_ERROR: 'EXPRESSION_EVALUATION_ERROR',
119
+ EXPRESSION_TIMEOUT: 'EXPRESSION_TIMEOUT',
120
+ EXPRESSION_MAX_STEPS_EXCEEDED: 'EXPRESSION_MAX_STEPS_EXCEEDED',
121
+ EXPRESSION_UNSAFE_ACCESS: 'EXPRESSION_UNSAFE_ACCESS',
122
+ EXPRESSION_FUNCTION_NOT_WHITELISTED: 'EXPRESSION_FUNCTION_NOT_WHITELISTED',
123
+ // 服务相关错误
124
+ SERVICE_NOT_FOUND: 'SERVICE_NOT_FOUND',
125
+ SERVICE_CALL_ERROR: 'SERVICE_CALL_ERROR',
126
+ // 批量执行错误
127
+ BATCH_ERROR: 'BATCH_ERROR',
128
+ // Schema 相关错误
129
+ SCHEMA_VALIDATION_ERROR: 'SCHEMA_VALIDATION_ERROR',
130
+ SCHEMA_INVALID_ACTION: 'SCHEMA_INVALID_ACTION',
131
+ };
132
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH;;;;GAIG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,UAAU;IACM,IAAI,CAAQ;IAC5B,YAAY;IACI,OAAO,CAAc;IAErC,YACE,OAAe,EACf,IAAY,EACZ,UAAwB,EAAE;QAE1B,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,YAAY,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QAEtB,gBAAgB;QAChB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QAC3C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAEtC,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;QACzD,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;QACnD,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QACrD,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAA;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,UAAU;IACzC,YACE,MAAc,EACd,OAAe,EACf,OAAe,cAAc,EAC7B,UAAwC,EAAE;QAE1C,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACnB,GAAG,OAAO;YACV,MAAM;SACP,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,GAAG,aAAa,CAAA;IAC3B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,UAAU;IAC7C,YACE,UAAkB,EAClB,OAAe,EACf,OAAe,kBAAkB,EACjC,UAA4C,EAAE;QAE9C,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACnB,GAAG,OAAO;YACV,UAAU;SACX,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,UAAU;IAC1B,OAAO,CAAQ;IACf,aAAa,CAAQ;IAErC,YACE,OAAe,EACf,OAAe,EACf,aAAqB,EACrB,UAAwB,EAAE;QAE1B,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;IACpC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,UAAU;IACxB,aAAa,CAAyC;IAEtE,YACE,aAAsD,EACtD,OAAe,EACf,UAAwB,EAAE;QAE1B,KAAK,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAA;QACxB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;IACpC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS;IACT,mBAAmB,EAAE,qBAAqB;IAC1C,sBAAsB,EAAE,wBAAwB;IAChD,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAChC,yBAAyB,EAAE,2BAA2B;IACtD,oBAAoB,EAAE,sBAAsB;IAC5C,oBAAoB,EAAE,sBAAsB;IAE5C,UAAU;IACV,sBAAsB,EAAE,wBAAwB;IAChD,2BAA2B,EAAE,6BAA6B;IAC1D,2BAA2B,EAAE,6BAA6B;IAC1D,kBAAkB,EAAE,oBAAoB;IACxC,6BAA6B,EAAE,+BAA+B;IAC9D,wBAAwB,EAAE,0BAA0B;IACpD,mCAAmC,EAAE,qCAAqC;IAE1E,SAAS;IACT,iBAAiB,EAAE,mBAAmB;IACtC,kBAAkB,EAAE,oBAAoB;IAExC,SAAS;IACT,WAAW,EAAE,aAAa;IAE1B,cAAc;IACd,uBAAuB,EAAE,yBAAyB;IAClD,qBAAqB,EAAE,uBAAuB;CACtC,CAAA"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 表达式缓存系统
3
+ *
4
+ * 功能:
5
+ * - 每个 RuntimeContext 独立缓存(WeakMap 关联)
6
+ * - LRU 淘汰策略
7
+ * - 通配符依赖匹配
8
+ * - 缓存失效机制
9
+ *
10
+ * 设计原则:
11
+ * - 惰性求值:只在需要时计算
12
+ * - 依赖追踪:精确的缓存失效
13
+ * - 内存友好:WeakMap + LRU 淘汰
14
+ */
15
+ import type { RuntimeContext } from '../types.js';
16
+ /**
17
+ * 获取缓存的表达式结果
18
+ *
19
+ * @param expr 表达式字符串
20
+ * @param ctx 运行时上下文
21
+ * @returns 缓存的结果,无缓存或已失效返回 null
22
+ */
23
+ export declare function getCachedExpression(expr: string, ctx: RuntimeContext): unknown | null;
24
+ /**
25
+ * 设置表达式缓存
26
+ *
27
+ * @param expr 表达式字符串
28
+ * @param result 求值结果
29
+ * @param dependencies 依赖的状态路径
30
+ * @param ctx 运行时上下文
31
+ */
32
+ export declare function setCachedExpression(expr: string, result: unknown, dependencies: string[], ctx: RuntimeContext): void;
33
+ /**
34
+ * 使缓存失效
35
+ *
36
+ * 当状态变化时调用,精确删除依赖该状态的缓存
37
+ *
38
+ * @param changedPath 变化的状态路径
39
+ * @param ctx 运行时上下文
40
+ */
41
+ export declare function invalidateCache(changedPath: string, ctx: RuntimeContext): void;
42
+ /**
43
+ * 清除指定上下文的所有缓存
44
+ */
45
+ export declare function clearCache(ctx: RuntimeContext): void;
46
+ /**
47
+ * 获取缓存统计信息(调试用)
48
+ */
49
+ export declare function getCacheStats(ctx: RuntimeContext): {
50
+ size: number;
51
+ expressions: string[];
52
+ };
53
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/expression/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAA;AA0ElE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,cAAc,GAClB,OAAO,GAAG,IAAI,CAgBhB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,GAAG,EAAE,cAAc,GAClB,IAAI,CAcN;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,cAAc,GAClB,IAAI,CAmBN;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAGpD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB,CAMA"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * 表达式缓存系统
3
+ *
4
+ * 功能:
5
+ * - 每个 RuntimeContext 独立缓存(WeakMap 关联)
6
+ * - LRU 淘汰策略
7
+ * - 通配符依赖匹配
8
+ * - 缓存失效机制
9
+ *
10
+ * 设计原则:
11
+ * - 惰性求值:只在需要时计算
12
+ * - 依赖追踪:精确的缓存失效
13
+ * - 内存友好:WeakMap + LRU 淘汰
14
+ */
15
+ import { matchPath } from '../runtime/path.js';
16
+ /**
17
+ * 每个上下文独立缓存
18
+ * 使用 RuntimeContext 作为键(WeakMap 自动回收)
19
+ */
20
+ const cacheMap = new WeakMap();
21
+ /**
22
+ * 缓存配置
23
+ */
24
+ const CACHE_CONFIG = {
25
+ /** 最大缓存条目数 */
26
+ maxSize: 100,
27
+ /** 缓存有效期(毫秒),0 表示不过期 */
28
+ ttl: 0
29
+ };
30
+ /**
31
+ * 获取上下文的缓存 Map
32
+ */
33
+ function getCache(ctx) {
34
+ let cache = cacheMap.get(ctx);
35
+ if (!cache) {
36
+ cache = new Map();
37
+ cacheMap.set(ctx, cache);
38
+ }
39
+ return cache;
40
+ }
41
+ /**
42
+ * 检查缓存条目是否有效
43
+ */
44
+ function isCacheValid(entry, ctx) {
45
+ // TTL 检查
46
+ if (CACHE_CONFIG.ttl > 0 && Date.now() - entry.timestamp > CACHE_CONFIG.ttl) {
47
+ return false;
48
+ }
49
+ // 依赖检查:所有依赖的值必须存在
50
+ return entry.dependencies.every(dep => {
51
+ if (dep.includes('*')) {
52
+ // 通配符依赖:检查父路径是否存在
53
+ const parentPath = dep.split('.*')[0];
54
+ return ctx._get(parentPath) != null;
55
+ }
56
+ // 具体路径:检查值是否存在
57
+ return ctx._get(dep) !== undefined;
58
+ });
59
+ }
60
+ /**
61
+ * LRU 淘汰:删除最旧的缓存条目
62
+ */
63
+ function evictOldest(cache) {
64
+ let oldestKey = null;
65
+ let oldestTime = Infinity;
66
+ for (const [key, entry] of cache.entries()) {
67
+ if (entry.timestamp < oldestTime) {
68
+ oldestTime = entry.timestamp;
69
+ oldestKey = key;
70
+ }
71
+ }
72
+ if (oldestKey) {
73
+ cache.delete(oldestKey);
74
+ }
75
+ }
76
+ /**
77
+ * 获取缓存的表达式结果
78
+ *
79
+ * @param expr 表达式字符串
80
+ * @param ctx 运行时上下文
81
+ * @returns 缓存的结果,无缓存或已失效返回 null
82
+ */
83
+ export function getCachedExpression(expr, ctx) {
84
+ const cache = getCache(ctx);
85
+ const entry = cache.get(expr);
86
+ if (!entry) {
87
+ return null;
88
+ }
89
+ if (!isCacheValid(entry, ctx)) {
90
+ cache.delete(expr);
91
+ return null;
92
+ }
93
+ // 更新时间戳(LRU)
94
+ entry.timestamp = Date.now();
95
+ return entry.result;
96
+ }
97
+ /**
98
+ * 设置表达式缓存
99
+ *
100
+ * @param expr 表达式字符串
101
+ * @param result 求值结果
102
+ * @param dependencies 依赖的状态路径
103
+ * @param ctx 运行时上下文
104
+ */
105
+ export function setCachedExpression(expr, result, dependencies, ctx) {
106
+ const cache = getCache(ctx);
107
+ // LRU 淘汰
108
+ if (cache.size >= CACHE_CONFIG.maxSize) {
109
+ evictOldest(cache);
110
+ }
111
+ cache.set(expr, {
112
+ expr,
113
+ result,
114
+ dependencies,
115
+ timestamp: Date.now()
116
+ });
117
+ }
118
+ /**
119
+ * 使缓存失效
120
+ *
121
+ * 当状态变化时调用,精确删除依赖该状态的缓存
122
+ *
123
+ * @param changedPath 变化的状态路径
124
+ * @param ctx 运行时上下文
125
+ */
126
+ export function invalidateCache(changedPath, ctx) {
127
+ const cache = getCache(ctx);
128
+ const toDelete = [];
129
+ for (const [expr, entry] of cache.entries()) {
130
+ // 检查是否有依赖被影响
131
+ const isAffected = entry.dependencies.some(dep => matchPath(dep, changedPath) || matchPath(changedPath, dep));
132
+ if (isAffected) {
133
+ toDelete.push(expr);
134
+ }
135
+ }
136
+ // 批量删除
137
+ for (const expr of toDelete) {
138
+ cache.delete(expr);
139
+ }
140
+ }
141
+ /**
142
+ * 清除指定上下文的所有缓存
143
+ */
144
+ export function clearCache(ctx) {
145
+ const cache = getCache(ctx);
146
+ cache.clear();
147
+ }
148
+ /**
149
+ * 获取缓存统计信息(调试用)
150
+ */
151
+ export function getCacheStats(ctx) {
152
+ const cache = getCache(ctx);
153
+ return {
154
+ size: cache.size,
155
+ expressions: Array.from(cache.keys())
156
+ };
157
+ }
158
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/expression/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 表达式编译器
3
+ *
4
+ * 功能:
5
+ * - 将简单表达式编译为直接访问函数
6
+ * - 提升简单表达式的执行性能
7
+ * - 复杂表达式回退到解释执行
8
+ */
9
+ import type * as ESTree from '@babel/types';
10
+ import type { RuntimeContext } from '../types.js';
11
+ /**
12
+ * 编译后的表达式函数类型
13
+ */
14
+ export type CompiledExpression = (ctx: RuntimeContext) => unknown;
15
+ /**
16
+ * 编译简单表达式为直接访问函数
17
+ *
18
+ * @param ast AST 节点
19
+ * @returns 编译后的函数,如果无法编译则返回 null
20
+ */
21
+ export declare function compileSimpleExpression(ast: ESTree.Node): CompiledExpression | null;
22
+ /**
23
+ * 获取或编译表达式
24
+ *
25
+ * @param expr 表达式字符串
26
+ * @param ast AST 节点(已解析)
27
+ * @returns 编译后的函数,如果无法编译则返回 null
28
+ */
29
+ export declare function getCompiledExpression(expr: string, ast: ESTree.Node): CompiledExpression | null;
30
+ /**
31
+ * 清除编译缓存
32
+ */
33
+ export declare function clearCompiledCache(): void;
34
+ //# sourceMappingURL=compiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/expression/compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,MAAM,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAA;AA8CjE;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,GAAG,kBAAkB,GAAG,IAAI,CA8CnF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,CAAC,IAAI,GACf,kBAAkB,GAAG,IAAI,CAW3B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * 表达式编译器
3
+ *
4
+ * 功能:
5
+ * - 将简单表达式编译为直接访问函数
6
+ * - 提升简单表达式的执行性能
7
+ * - 复杂表达式回退到解释执行
8
+ */
9
+ /**
10
+ * 编译缓存(全局,表达式字符串 → 编译函数)
11
+ */
12
+ const compiledCache = new Map();
13
+ /**
14
+ * 提取静态路径(从 MemberExpression)
15
+ *
16
+ * 例如:user.name → "user.name"
17
+ * 例如:items.0.text → "items.0.text"
18
+ */
19
+ function extractStaticPath(node) {
20
+ if (node.type === 'Identifier') {
21
+ return node.name;
22
+ }
23
+ if (node.type === 'MemberExpression') {
24
+ const object = extractStaticPath(node.object);
25
+ if (!object)
26
+ return null;
27
+ if (node.computed) {
28
+ // 计算属性:obj[key],需要检查 key 是否为字面量
29
+ if (node.property.type === 'NumericLiteral') {
30
+ const prop = node.property.value;
31
+ return `${object}.${String(prop)}`;
32
+ }
33
+ if (node.property.type === 'StringLiteral') {
34
+ const prop = node.property.value;
35
+ return `${object}.${String(prop)}`;
36
+ }
37
+ // 处理其他字面量类型(已由上面的具体类型处理,这里不需要)
38
+ return null;
39
+ }
40
+ else {
41
+ // 静态属性:obj.prop
42
+ if (node.property.type === 'Identifier') {
43
+ return `${object}.${node.property.name}`;
44
+ }
45
+ return null;
46
+ }
47
+ }
48
+ return null;
49
+ }
50
+ /**
51
+ * 编译简单表达式为直接访问函数
52
+ *
53
+ * @param ast AST 节点
54
+ * @returns 编译后的函数,如果无法编译则返回 null
55
+ */
56
+ export function compileSimpleExpression(ast) {
57
+ // 字面量:{{ 42 }} → () => 42
58
+ if (ast.type === 'NumericLiteral') {
59
+ const value = ast.value;
60
+ return () => value;
61
+ }
62
+ if (ast.type === 'StringLiteral') {
63
+ const value = ast.value;
64
+ return () => value;
65
+ }
66
+ if (ast.type === 'BooleanLiteral') {
67
+ const value = ast.value;
68
+ return () => value;
69
+ }
70
+ if (ast.type === 'NullLiteral') {
71
+ return () => null;
72
+ }
73
+ // 注意:Literal 类型已被更具体的类型(NumericLiteral, StringLiteral等)替代
74
+ // 如果遇到其他字面量类型,回退到解释执行
75
+ // 标识符:{{ user }} → (ctx) => ctx._get('user')
76
+ // 注意:全局对象名称(window, document等)不应该被编译,应该回退到解释执行以进行安全检查
77
+ if (ast.type === 'Identifier') {
78
+ const name = ast.name;
79
+ // 全局对象名称不应该被编译(需要安全检查)
80
+ const globalObjectNames = ['window', 'document', 'global', 'globalThis', 'self'];
81
+ if (globalObjectNames.includes(name)) {
82
+ return null; // 回退到解释执行
83
+ }
84
+ return (ctx) => ctx._get(name);
85
+ }
86
+ // 静态成员访问:{{ user.name }} → (ctx) => ctx._get('user.name')
87
+ // 注意:如果路径以全局对象名称开头,不应该被编译
88
+ const path = extractStaticPath(ast);
89
+ if (path) {
90
+ // 检查路径是否以全局对象名称开头
91
+ const globalObjectNames = ['window', 'document', 'global', 'globalThis', 'self'];
92
+ const firstSegment = path.split('.')[0];
93
+ if (globalObjectNames.includes(firstSegment)) {
94
+ return null; // 回退到解释执行以进行安全检查
95
+ }
96
+ return (ctx) => ctx._get(path);
97
+ }
98
+ return null; // 复杂表达式,无法编译
99
+ }
100
+ /**
101
+ * 获取或编译表达式
102
+ *
103
+ * @param expr 表达式字符串
104
+ * @param ast AST 节点(已解析)
105
+ * @returns 编译后的函数,如果无法编译则返回 null
106
+ */
107
+ export function getCompiledExpression(expr, ast) {
108
+ // 检查缓存
109
+ if (compiledCache.has(expr)) {
110
+ return compiledCache.get(expr) || null;
111
+ }
112
+ // 尝试编译
113
+ const compiled = compileSimpleExpression(ast);
114
+ compiledCache.set(expr, compiled);
115
+ return compiled;
116
+ }
117
+ /**
118
+ * 清除编译缓存
119
+ */
120
+ export function clearCompiledCache() {
121
+ compiledCache.clear();
122
+ }
123
+ //# sourceMappingURL=compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../src/expression/compiler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 依赖提取算法
3
+ *
4
+ * 功能:
5
+ * - 从 AST 中提取状态依赖
6
+ * - 支持通配符依赖(items.*)
7
+ * - 保守策略:标记整个对象
8
+ */
9
+ import type * as ESTree from '@babel/types';
10
+ /**
11
+ * 从 AST 中提取依赖的状态路径
12
+ *
13
+ * @param ast AST 节点
14
+ * @returns 依赖路径数组(支持通配符)
15
+ */
16
+ export declare function extractDependencies(ast: ESTree.Node): string[];
17
+ //# sourceMappingURL=dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/expression/dependencies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,MAAM,MAAM,cAAc,CAAA;AAE3C;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,GAAG,MAAM,EAAE,CAqF9D"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * 依赖提取算法
3
+ *
4
+ * 功能:
5
+ * - 从 AST 中提取状态依赖
6
+ * - 支持通配符依赖(items.*)
7
+ * - 保守策略:标记整个对象
8
+ */
9
+ /**
10
+ * 从 AST 中提取依赖的状态路径
11
+ *
12
+ * @param ast AST 节点
13
+ * @returns 依赖路径数组(支持通配符)
14
+ */
15
+ export function extractDependencies(ast) {
16
+ const dependencies = new Set();
17
+ function traverse(node, path = '') {
18
+ switch (node.type) {
19
+ case 'Identifier': {
20
+ const id = node;
21
+ // 标识符可能是状态依赖(排除全局函数)
22
+ if (!isGlobalFunction(id.name)) {
23
+ dependencies.add(id.name);
24
+ }
25
+ break;
26
+ }
27
+ case 'MemberExpression': {
28
+ const member = node;
29
+ const object = member.object;
30
+ if (object.type === 'Identifier') {
31
+ const basePath = object.name;
32
+ if (member.computed) {
33
+ // 计算属性:items[0] -> 保守策略:标记 items.*
34
+ dependencies.add(`${basePath}.*`);
35
+ traverse(member.property, path);
36
+ }
37
+ else {
38
+ // 静态属性:user.name
39
+ const prop = member.property.name;
40
+ dependencies.add(`${basePath}.${prop}`);
41
+ // 同时添加通配符依赖(保守策略)
42
+ dependencies.add(`${basePath}.*`);
43
+ }
44
+ }
45
+ else {
46
+ // 嵌套成员访问:user.profile.name
47
+ traverse(object, path);
48
+ }
49
+ break;
50
+ }
51
+ case 'OptionalMemberExpression': {
52
+ const member = node;
53
+ const object = member.object;
54
+ if (object.type === 'Identifier') {
55
+ const basePath = object.name;
56
+ if (member.computed) {
57
+ dependencies.add(`${basePath}.*`);
58
+ traverse(member.property, path);
59
+ }
60
+ else {
61
+ const prop = member.property.name;
62
+ dependencies.add(`${basePath}.${prop}`);
63
+ dependencies.add(`${basePath}.*`);
64
+ }
65
+ }
66
+ else {
67
+ traverse(object, path);
68
+ }
69
+ break;
70
+ }
71
+ default: {
72
+ // 递归遍历所有子节点
73
+ for (const key in node) {
74
+ const value = node[key];
75
+ if (value == null)
76
+ continue;
77
+ if (Array.isArray(value)) {
78
+ value.forEach(child => {
79
+ if (child && typeof child === 'object' && 'type' in child) {
80
+ traverse(child, path);
81
+ }
82
+ });
83
+ }
84
+ else if (value && typeof value === 'object' && 'type' in value) {
85
+ traverse(value, path);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ traverse(ast);
92
+ return Array.from(dependencies);
93
+ }
94
+ /**
95
+ * 检查是否为全局函数(不应作为依赖)
96
+ */
97
+ function isGlobalFunction(name) {
98
+ const globals = new Set([
99
+ 'String', 'Number', 'Boolean', 'BigInt', 'Symbol',
100
+ 'Array', 'Object', 'Math', 'Date',
101
+ 'console', 'JSON', 'parseInt', 'parseFloat',
102
+ 'isNaN', 'isFinite',
103
+ ]);
104
+ return globals.has(name);
105
+ }
106
+ //# sourceMappingURL=dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/expression/dependencies.ts"],"names":[],"mappings":"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"}