wevu 7.4.0 → 7.5.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 (227) hide show
  1. package/README.md +2 -0
  2. package/dist/dev/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/defineProperty.mjs +1 -1
  3. package/dist/dev/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/toPrimitive.mjs +1 -1
  4. package/dist/dev/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/toPropertyKey.mjs +1 -1
  5. package/dist/dev/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/typeof.mjs +1 -1
  6. package/dist/dev/package.mjs +1 -1
  7. package/dist/dev/reactivity/core.mjs +1 -1
  8. package/dist/dev/reactivity/ref.mjs +1 -1
  9. package/dist/dev/runtime/app/diagnostics.mjs +5 -1
  10. package/dist/dev/runtime/app/diagnostics.mjs.map +1 -1
  11. package/dist/dev/runtime/app/mount.mjs +8 -3
  12. package/dist/dev/runtime/app/mount.mjs.map +1 -1
  13. package/dist/dev/runtime/app/setData/commitTracker.mjs +39 -4
  14. package/dist/dev/runtime/app/setData/commitTracker.mjs.map +1 -1
  15. package/dist/dev/runtime/app/setData/observation.mjs +109 -0
  16. package/dist/dev/runtime/app/setData/observation.mjs.map +1 -0
  17. package/dist/dev/runtime/app/setData/scheduler.mjs +12 -1
  18. package/dist/dev/runtime/app/setData/scheduler.mjs.map +1 -1
  19. package/dist/dev/runtime/app/setDataOptions.mjs +1 -0
  20. package/dist/dev/runtime/app/setDataOptions.mjs.map +1 -1
  21. package/dist/dev/runtime/define/initialComputed.mjs +13 -12
  22. package/dist/dev/runtime/define/initialComputed.mjs.map +1 -1
  23. package/dist/dev/runtime/define/props.mjs +5 -1
  24. package/dist/dev/runtime/define/props.mjs.map +1 -1
  25. package/dist/dev/runtime/define/scopedSlotOptions.mjs +2 -1
  26. package/dist/dev/runtime/define/scopedSlotOptions.mjs.map +1 -1
  27. package/dist/dev/runtime/define.mjs +1 -1
  28. package/dist/dev/runtime/define.mjs.map +1 -1
  29. package/dist/dev/runtime/features/scopedSlots.mjs.map +1 -1
  30. package/dist/dev/runtime/register/component/props.mjs +14 -4
  31. package/dist/dev/runtime/register/component/props.mjs.map +1 -1
  32. package/dist/dev/runtime/register/component/registerDefinition.mjs +27 -17
  33. package/dist/dev/runtime/register/component/registerDefinition.mjs.map +1 -1
  34. package/dist/dev/runtime/register/component.mjs +2 -1
  35. package/dist/dev/runtime/register/component.mjs.map +1 -1
  36. package/dist/dev/runtime/register/runtimeInstance/methodBridge.mjs +14 -7
  37. package/dist/dev/runtime/register/runtimeInstance/methodBridge.mjs.map +1 -1
  38. package/dist/dev/runtime/register/runtimeInstance/nativeDeclaration.mjs +78 -0
  39. package/dist/dev/runtime/register/runtimeInstance/nativeDeclaration.mjs.map +1 -0
  40. package/dist/dev/runtime/register/runtimeInstance/provideContext.mjs +52 -8
  41. package/dist/dev/runtime/register/runtimeInstance/provideContext.mjs.map +1 -1
  42. package/dist/dev/runtime/register/runtimeInstance/utils.mjs.map +1 -1
  43. package/dist/dev/runtime/register/runtimeInstance.mjs +60 -19
  44. package/dist/dev/runtime/register/runtimeInstance.mjs.map +1 -1
  45. package/dist/fetch.mjs +1 -1
  46. package/dist/internal-template.mjs +1 -1
  47. package/dist/package.mjs +1 -1
  48. package/dist/reactivity/core.mjs +1 -1
  49. package/dist/reactivity/reactive/patch.mjs +1 -1
  50. package/dist/reactivity/reactive/patchState.mjs +1 -1
  51. package/dist/reactivity/ref.mjs +1 -1
  52. package/dist/reactivity/watch/helpers.mjs +1 -1
  53. package/dist/router/initialNavigation.mjs +1 -1
  54. package/dist/router/useRoute.mjs +1 -1
  55. package/dist/routerInternal/matching.mjs +1 -1
  56. package/dist/routerInternal/params.mjs +1 -1
  57. package/dist/routerInternal/path.mjs +1 -1
  58. package/dist/routerInternal/query.mjs +1 -1
  59. package/dist/routerInternal/records.mjs +1 -1
  60. package/dist/runtime/app/context.mjs +1 -1
  61. package/dist/runtime/app/diagnostics.mjs +1 -1
  62. package/dist/runtime/app/mount.mjs +1 -1
  63. package/dist/runtime/app/setData/commitTracker.d.mts +2 -1
  64. package/dist/runtime/app/setData/commitTracker.mjs +1 -1
  65. package/dist/runtime/app/setData/observation.d.mts +12 -0
  66. package/dist/runtime/app/setData/observation.mjs +1 -0
  67. package/dist/runtime/app/setData/scheduler.d.mts +1 -0
  68. package/dist/runtime/app/setData/scheduler.mjs +1 -1
  69. package/dist/runtime/app/setDataOptions.mjs +1 -1
  70. package/dist/runtime/define/initialComputed.mjs +1 -1
  71. package/dist/runtime/define/props.mjs +1 -1
  72. package/dist/runtime/define/scopedSlotOptions.mjs +1 -1
  73. package/dist/runtime/define.mjs +1 -1
  74. package/dist/runtime/diff.mjs +1 -1
  75. package/dist/runtime/features/publicLayout.mjs +1 -1
  76. package/dist/runtime/features/scopedSlots.d.mts +2 -1
  77. package/dist/runtime/jsxIsland.mjs +1 -1
  78. package/dist/runtime/pageLayout.mjs +1 -1
  79. package/dist/runtime/pageScroll.mjs +1 -1
  80. package/dist/runtime/register/component/alipayRegistration.mjs +1 -1
  81. package/dist/runtime/register/component/lifecycle.mjs +1 -1
  82. package/dist/runtime/register/component/props.mjs +1 -1
  83. package/dist/runtime/register/component/registerDefinition.mjs +1 -1
  84. package/dist/runtime/register/component/registerNativeDefinition.mjs +1 -1
  85. package/dist/runtime/register/component.mjs +1 -1
  86. package/dist/runtime/register/runtimeInstance/methodBridge.mjs +1 -1
  87. package/dist/runtime/register/runtimeInstance/nativeDeclaration.mjs +1 -0
  88. package/dist/runtime/register/runtimeInstance/provideContext.mjs +1 -1
  89. package/dist/runtime/register/runtimeInstance.d.mts +8 -4
  90. package/dist/runtime/register/runtimeInstance.mjs +1 -1
  91. package/dist/runtime/setupTracking.mjs +1 -1
  92. package/dist/runtime/templateRefs.mjs +1 -1
  93. package/dist/runtime/types/runtime.d.mts +1 -0
  94. package/dist/runtime/types/setData.d.mts +30 -0
  95. package/dist/scheduler.mjs +1 -1
  96. package/dist/web-apis.mjs +1 -1
  97. package/package.json +10 -9
  98. package/dist/dev/api/vitest/setup.d.mts +0 -1
  99. package/dist/dev/api/vitest.d.mts +0 -1
  100. package/dist/dev/api.d.mts +0 -1
  101. package/dist/dev/compiler.d.mts +0 -1
  102. package/dist/dev/fetch.d.mts +0 -9
  103. package/dist/dev/index.d.mts +0 -72
  104. package/dist/dev/internal-reactivity.d.mts +0 -18
  105. package/dist/dev/internal-runtime.d.mts +0 -45
  106. package/dist/dev/internal-template.d.mts +0 -2
  107. package/dist/dev/jsxTypes.d.mts +0 -9
  108. package/dist/dev/macros/shared.d.mts +0 -83
  109. package/dist/dev/macros.d.mts +0 -71
  110. package/dist/dev/reactivity/asyncDerivation.d.mts +0 -41
  111. package/dist/dev/reactivity/computed.d.mts +0 -25
  112. package/dist/dev/reactivity/core.d.mts +0 -35
  113. package/dist/dev/reactivity/index.d.mts +0 -16
  114. package/dist/dev/reactivity/reactive/mutation.d.mts +0 -21
  115. package/dist/dev/reactivity/reactive/patch.d.mts +0 -18
  116. package/dist/dev/reactivity/reactive/shallow.d.mts +0 -22
  117. package/dist/dev/reactivity/reactive/shared.d.mts +0 -4
  118. package/dist/dev/reactivity/reactive.d.mts +0 -42
  119. package/dist/dev/reactivity/readonly.d.mts +0 -27
  120. package/dist/dev/reactivity/ref.d.mts +0 -27
  121. package/dist/dev/reactivity/shallowRef.d.mts +0 -19
  122. package/dist/dev/reactivity/toRefs.d.mts +0 -43
  123. package/dist/dev/reactivity/traverse.d.mts +0 -8
  124. package/dist/dev/reactivity/watch/types.d.mts +0 -43
  125. package/dist/dev/reactivity/watch.d.mts +0 -22
  126. package/dist/dev/router/auto-routes.d.mts +0 -8
  127. package/dist/dev/router/createRouter.d.mts +0 -9
  128. package/dist/dev/router/navigationCore.d.mts +0 -7
  129. package/dist/dev/router/resolve.d.mts +0 -7
  130. package/dist/dev/router/routeSync.d.mts +0 -2
  131. package/dist/dev/router/scrollRestoration/adapters.d.mts +0 -8
  132. package/dist/dev/router/scrollRestoration/controller.d.mts +0 -8
  133. package/dist/dev/router/scrollRestoration/host.d.mts +0 -3
  134. package/dist/dev/router/scrollRestoration/index.d.mts +0 -9
  135. package/dist/dev/router/scrollRestoration/types.d.mts +0 -61
  136. package/dist/dev/router/types.d.mts +0 -267
  137. package/dist/dev/router/useRoute.d.mts +0 -20
  138. package/dist/dev/router/useRouter.d.mts +0 -9
  139. package/dist/dev/router.d.mts +0 -30
  140. package/dist/dev/routerInternal/location.d.mts +0 -2
  141. package/dist/dev/routerInternal/matching.d.mts +0 -2
  142. package/dist/dev/routerInternal/params.d.mts +0 -2
  143. package/dist/dev/routerInternal/query.d.mts +0 -7
  144. package/dist/dev/routerInternal/records.d.mts +0 -2
  145. package/dist/dev/routerInternal/recordsWarnings.d.mts +0 -2
  146. package/dist/dev/routerInternal/shared.d.mts +0 -9
  147. package/dist/dev/routerInternal/snapshots.d.mts +0 -2
  148. package/dist/dev/routerInternal/types.d.mts +0 -9
  149. package/dist/dev/runtime/app/pending.d.mts +0 -10
  150. package/dist/dev/runtime/app/setData/commitTracker.d.mts +0 -13
  151. package/dist/dev/runtime/app/setData/scheduler.d.mts +0 -51
  152. package/dist/dev/runtime/app.d.mts +0 -8
  153. package/dist/dev/runtime/capabilities.d.mts +0 -78
  154. package/dist/dev/runtime/css.d.mts +0 -14
  155. package/dist/dev/runtime/defaults.d.mts +0 -12
  156. package/dist/dev/runtime/define.d.mts +0 -118
  157. package/dist/dev/runtime/disposables.d.mts +0 -31
  158. package/dist/dev/runtime/elementIntersectionObserver.d.mts +0 -26
  159. package/dist/dev/runtime/features/inlineEvents.d.mts +0 -7
  160. package/dist/dev/runtime/features/jsxIslands.d.mts +0 -7
  161. package/dist/dev/runtime/features/layout.d.mts +0 -7
  162. package/dist/dev/runtime/features/patchStrategy.d.mts +0 -7
  163. package/dist/dev/runtime/features/publicLayout.d.mts +0 -24
  164. package/dist/dev/runtime/features/scopedSlots.d.mts +0 -23
  165. package/dist/dev/runtime/features/setDataHighFrequencyWarning.d.mts +0 -7
  166. package/dist/dev/runtime/features/templateRefs.d.mts +0 -7
  167. package/dist/dev/runtime/hooks/base.d.mts +0 -27
  168. package/dist/dev/runtime/hooks/register.d.mts +0 -30
  169. package/dist/dev/runtime/hooks/vue.d.mts +0 -52
  170. package/dist/dev/runtime/hooks.d.mts +0 -4
  171. package/dist/dev/runtime/index.d.mts +0 -46
  172. package/dist/dev/runtime/intersectionObserver.d.mts +0 -14
  173. package/dist/dev/runtime/jsxIsland.d.mts +0 -37
  174. package/dist/dev/runtime/layoutBridge.d.mts +0 -55
  175. package/dist/dev/runtime/noSetData.d.mts +0 -5
  176. package/dist/dev/runtime/pageEnvironment.d.mts +0 -50
  177. package/dist/dev/runtime/pageLayout.d.mts +0 -25
  178. package/dist/dev/runtime/pageScroll.d.mts +0 -29
  179. package/dist/dev/runtime/provide.d.mts +0 -60
  180. package/dist/dev/runtime/provideStore.d.mts +0 -7
  181. package/dist/dev/runtime/publicRuntime.d.mts +0 -22
  182. package/dist/dev/runtime/pullDownRefresh.d.mts +0 -12
  183. package/dist/dev/runtime/register/app.d.mts +0 -14
  184. package/dist/dev/runtime/register/component.d.mts +0 -17
  185. package/dist/dev/runtime/register/inline.d.mts +0 -15
  186. package/dist/dev/runtime/register/runtimeInstance.d.mts +0 -26
  187. package/dist/dev/runtime/register/setup.d.mts +0 -11
  188. package/dist/dev/runtime/register/watch.d.mts +0 -12
  189. package/dist/dev/runtime/register.d.mts +0 -5
  190. package/dist/dev/runtime/selectorQuery.d.mts +0 -54
  191. package/dist/dev/runtime/template.d.mts +0 -6
  192. package/dist/dev/runtime/templateRefTypes.d.mts +0 -12
  193. package/dist/dev/runtime/types/core.d.mts +0 -35
  194. package/dist/dev/runtime/types/miniprogram.d.mts +0 -84
  195. package/dist/dev/runtime/types/miniprogramHost.d.mts +0 -45
  196. package/dist/dev/runtime/types/miniprogramHostSources.d.mts +0 -112
  197. package/dist/dev/runtime/types/options.d.mts +0 -138
  198. package/dist/dev/runtime/types/props/propTypes.d.mts +0 -79
  199. package/dist/dev/runtime/types/props/router.d.mts +0 -51
  200. package/dist/dev/runtime/types/props/setup.d.mts +0 -96
  201. package/dist/dev/runtime/types/props.d.mts +0 -4
  202. package/dist/dev/runtime/types/runtime.d.mts +0 -59
  203. package/dist/dev/runtime/types/setData.d.mts +0 -237
  204. package/dist/dev/runtime/types.d.mts +0 -29
  205. package/dist/dev/runtime/uniAppHost.d.mts +0 -8
  206. package/dist/dev/runtime/updatePerformance.d.mts +0 -13
  207. package/dist/dev/runtime/use.d.mts +0 -13
  208. package/dist/dev/runtime/vueCompat/context.d.mts +0 -8
  209. package/dist/dev/runtime/vueCompat/model.d.mts +0 -30
  210. package/dist/dev/runtime/vueCompat/router.d.mts +0 -29
  211. package/dist/dev/runtime/vueCompat/templateRef.d.mts +0 -9
  212. package/dist/dev/runtime/vueCompat.d.mts +0 -5
  213. package/dist/dev/scheduler.d.mts +0 -4
  214. package/dist/dev/store/define.d.mts +0 -8
  215. package/dist/dev/store/manager.d.mts +0 -16
  216. package/dist/dev/store/storeToRefs.d.mts +0 -11
  217. package/dist/dev/store/types.d.mts +0 -106
  218. package/dist/dev/store.d.mts +0 -5
  219. package/dist/dev/version.d.mts +0 -4
  220. package/dist/dev/vue-augment.d.mts +0 -8
  221. package/dist/dev/vue-demi.d.mts +0 -87
  222. package/dist/dev/vue-types.d.mts +0 -19
  223. package/dist/dev/web-apis.d.mts +0 -3
  224. /package/dist/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/defineProperty.mjs +0 -0
  225. /package/dist/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/toPrimitive.mjs +0 -0
  226. /package/dist/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/toPropertyKey.mjs +0 -0
  227. /package/dist/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/typeof.mjs +0 -0
package/README.md CHANGED
@@ -180,6 +180,8 @@ const onActiveChange = bindModel.model<boolean>('isActive').onChange
180
180
 
181
181
  - 更新被批量加入微任务队列;`nextTick` 只等待当前 JavaScript/响应式任务队列排空,不等待小程序 `setData` 回调或视图提交。
182
182
  - 对状态做快照 diff,只把变更路径传给 `setData`;宿主提交失败时,下一次响应式更新会发送完整恢复快照。
183
+ - 可用 `setData.debugPhases: true` 在现有 `debug` 回调中关联 prepare、物理 dispatch 与 commit。合并调用按 ID 去重;callback/Promise/同步返回不等于可见视图完成,未观测边界保持 `null`。参见 [阶段观测与测量示例](../../docs/wevu/setdata-observation.md)。
184
+ - `weapp.wevu.preset: 'performance'` 默认开启 patch、隐藏时暂停和 `diagnostics: 'fallback'`。首次快照收集也会记录 `needsFullSnapshot`;启用阶段观测后,同一 revision 可有多条日志,不能将 warning 条数视为失败或回退次数。配置覆盖见 [预设说明](https://vite.weapp.dev/config/wevu#weapp-wevu-preset)。
183
185
  - 提供 `batch`/`startBatch`/`endBatch` 用于同步更新合并触发;以及 `effectScope`/`getCurrentScope`/`onScopeDispose` 统一管理 effect/watch 的销毁,`setup()` 同步阶段内创建的副作用会自动归属到实例级 scope,便于避免泄漏。
184
186
 
185
187
  ## 开发产物与源码调试
@@ -1,6 +1,6 @@
1
1
  import toPropertyKey from "./toPropertyKey.mjs";
2
2
 
3
- //#region \0@oxc-project+runtime@0.151.0/helpers/esm/defineProperty.js
3
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/defineProperty.js
4
4
  function _defineProperty(e, r, t) {
5
5
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
6
6
  value: t,
@@ -1,6 +1,6 @@
1
1
  import _typeof from "./typeof.mjs";
2
2
 
3
- //#region \0@oxc-project+runtime@0.151.0/helpers/esm/toPrimitive.js
3
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/toPrimitive.js
4
4
  function toPrimitive(t, r) {
5
5
  if ("object" != _typeof(t) || !t) return t;
6
6
  var e = t[Symbol.toPrimitive];
@@ -1,7 +1,7 @@
1
1
  import _typeof from "./typeof.mjs";
2
2
  import toPrimitive from "./toPrimitive.mjs";
3
3
 
4
- //#region \0@oxc-project+runtime@0.151.0/helpers/esm/toPropertyKey.js
4
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/toPropertyKey.js
5
5
  function toPropertyKey(t) {
6
6
  var i = toPrimitive(t, "string");
7
7
  return "symbol" == _typeof(i) ? i : i + "";
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.151.0/helpers/esm/typeof.js
1
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/typeof.js
2
2
  function _typeof(o) {
3
3
  "@babel/helpers - typeof";
4
4
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "7.4.0";
2
+ var version = "7.5.0";
3
3
 
4
4
  //#endregion
5
5
  export { version };
@@ -1,5 +1,5 @@
1
1
  import { queueJob } from "../scheduler.mjs";
2
- import _defineProperty from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/defineProperty.mjs";
2
+ import _defineProperty from "../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/defineProperty.mjs";
3
3
 
4
4
  //#region src/reactivity/core.ts
5
5
  const targetMap = /* @__PURE__ */ new WeakMap();
@@ -1,4 +1,4 @@
1
- import _defineProperty from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/defineProperty.mjs";
1
+ import _defineProperty from "../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/defineProperty.mjs";
2
2
  import { trackEffects, triggerEffects } from "./core.mjs";
3
3
  import { convertToReactive, markRaw } from "./reactive.mjs";
4
4
 
@@ -6,7 +6,7 @@ function createDiagnosticsLogger(mode) {
6
6
  if (mode === "off") return;
7
7
  return (info) => {
8
8
  if (mode === "fallback" && !isFallbackReason(info.reason)) return;
9
- const bytes = typeof info.bytes === "number" ? info.bytes : info.estimatedBytes;
9
+ const bytes = info.phase ? info.phase.dispatch?.payloadBytes : typeof info.bytes === "number" ? info.bytes : info.estimatedBytes;
10
10
  const bytesText = typeof bytes === "number" ? `${bytes}B` : "unknown";
11
11
  const parts = [
12
12
  `mode=${info.mode}`,
@@ -17,6 +17,10 @@ function createDiagnosticsLogger(mode) {
17
17
  ];
18
18
  if (typeof info.revision === "number") parts.push(`revision=${info.revision}`);
19
19
  if (typeof info.committedRevision === "number") parts.push(`committedRevision=${info.committedRevision}`);
20
+ if (info.phase) {
21
+ const phase = info.phase;
22
+ parts.push(`phase=${phase.name}`, `observer=${phase.observerId}`, `result=${phase.result}`, `completion=${phase.completion}`, `dispatch=${phase.dispatch?.id ?? "unknown"}`, `prepareMs=${phase.prepareDurationMs ?? "unknown"}`, `dispatchMs=${phase.dispatch?.durationMs ?? "unknown"}`, `commitMs=${phase.commitDurationMs ?? "unknown"}`, "visibleAt=unknown");
23
+ }
20
24
  if (typeof info.mergedSiblingParents === "number") parts.push(`mergedParents=${info.mergedSiblingParents}`);
21
25
  if (typeof info.computedDirtyKeys === "number") parts.push(`computedDirty=${info.computedDirtyKeys}`);
22
26
  if (typeof info.flushCount === "number") parts.push(`flushes=${info.flushCount}`);
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.mjs","names":[],"sources":["../../../../src/runtime/app/diagnostics.ts"],"sourcesContent":["import type { SetDataDebugInfo } from '../types'\n\nfunction isFallbackReason(reason: SetDataDebugInfo['reason']) {\n return reason !== 'patch' && reason !== 'diff'\n}\n\nexport function createDiagnosticsLogger(mode: 'off' | 'fallback' | 'always') {\n if (mode === 'off') {\n return undefined\n }\n return (info: SetDataDebugInfo) => {\n if (mode === 'fallback' && !isFallbackReason(info.reason)) {\n return\n }\n const bytes = typeof info.bytes === 'number' ? info.bytes : info.estimatedBytes\n const bytesText = typeof bytes === 'number' ? `${bytes}B` : 'unknown'\n const parts = [\n `mode=${info.mode}`,\n `reason=${info.reason}`,\n `pending=${info.pendingPatchKeys}`,\n `keys=${info.payloadKeys}`,\n `bytes=${bytesText}`,\n ]\n if (typeof info.revision === 'number') {\n parts.push(`revision=${info.revision}`)\n }\n if (typeof info.committedRevision === 'number') {\n parts.push(`committedRevision=${info.committedRevision}`)\n }\n if (typeof info.mergedSiblingParents === 'number') {\n parts.push(`mergedParents=${info.mergedSiblingParents}`)\n }\n if (typeof info.computedDirtyKeys === 'number') {\n parts.push(`computedDirty=${info.computedDirtyKeys}`)\n }\n if (typeof info.flushCount === 'number') {\n parts.push(`flushes=${info.flushCount}`)\n }\n if (typeof info.windowMs === 'number') {\n parts.push(`window=${info.windowMs}ms`)\n }\n if (info.targetLabel) {\n parts.push(`target=${info.targetLabel}`)\n }\n if (info.bindings?.length) {\n const bindings = info.bindings.map((binding) => {\n const start = binding.sourceLocation?.start\n return start\n ? `${binding.id}@${binding.sourceFile}:${start.line}:${start.column}`\n : `${binding.id}@${binding.sourceFile}`\n })\n parts.push(`bindings=${bindings.join(',')}`)\n }\n if (info.message) {\n parts.push(`message=${info.message}`)\n }\n const message = `[wevu:setData] ${parts.join(' ')}`\n if (isFallbackReason(info.reason)) {\n // eslint-disable-next-line no-console\n console.warn(message)\n return\n }\n // eslint-disable-next-line no-console\n console.info(message)\n }\n}\n"],"mappings":";AAEA,SAAS,iBAAiB,QAAoC;CAC5D,OAAO,WAAW,WAAW,WAAW;AAC1C;AAEA,SAAgB,wBAAwB,MAAqC;CAC3E,IAAI,SAAS,OACX;CAEF,QAAQ,SAA2B;EACjC,IAAI,SAAS,cAAc,CAAC,iBAAiB,KAAK,MAAM,GACtD;EAEF,MAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAK;EACjE,MAAM,YAAY,OAAO,UAAU,WAAW,GAAG,MAAM,KAAK;EAC5D,MAAM,QAAQ;GACZ,QAAQ,KAAK;GACb,UAAU,KAAK;GACf,WAAW,KAAK;GAChB,QAAQ,KAAK;GACb,SAAS;EACX;EACA,IAAI,OAAO,KAAK,aAAa,UAC3B,MAAM,KAAK,YAAY,KAAK,UAAU;EAExC,IAAI,OAAO,KAAK,sBAAsB,UACpC,MAAM,KAAK,qBAAqB,KAAK,mBAAmB;EAE1D,IAAI,OAAO,KAAK,yBAAyB,UACvC,MAAM,KAAK,iBAAiB,KAAK,sBAAsB;EAEzD,IAAI,OAAO,KAAK,sBAAsB,UACpC,MAAM,KAAK,iBAAiB,KAAK,mBAAmB;EAEtD,IAAI,OAAO,KAAK,eAAe,UAC7B,MAAM,KAAK,WAAW,KAAK,YAAY;EAEzC,IAAI,OAAO,KAAK,aAAa,UAC3B,MAAM,KAAK,UAAU,KAAK,SAAS,GAAG;EAExC,IAAI,KAAK,aACP,MAAM,KAAK,UAAU,KAAK,aAAa;EAEzC,IAAI,KAAK,UAAU,QAAQ;GACzB,MAAM,WAAW,KAAK,SAAS,KAAK,YAAY;IAC9C,MAAM,QAAQ,QAAQ,gBAAgB;IACtC,OAAO,QACH,GAAG,QAAQ,GAAG,GAAG,QAAQ,WAAW,GAAG,MAAM,KAAK,GAAG,MAAM,WAC3D,GAAG,QAAQ,GAAG,GAAG,QAAQ;GAC/B,CAAC;GACD,MAAM,KAAK,YAAY,SAAS,KAAK,GAAG,GAAG;EAC7C;EACA,IAAI,KAAK,SACP,MAAM,KAAK,WAAW,KAAK,SAAS;EAEtC,MAAM,UAAU,kBAAkB,MAAM,KAAK,GAAG;EAChD,IAAI,iBAAiB,KAAK,MAAM,GAAG;GAEjC,QAAQ,KAAK,OAAO;GACpB;EACF;EAEA,QAAQ,KAAK,OAAO;CACtB;AACF"}
1
+ {"version":3,"file":"diagnostics.mjs","names":[],"sources":["../../../../src/runtime/app/diagnostics.ts"],"sourcesContent":["import type { SetDataDebugInfo } from '../types'\n\nfunction isFallbackReason(reason: SetDataDebugInfo['reason']) {\n return reason !== 'patch' && reason !== 'diff'\n}\n\nexport function createDiagnosticsLogger(mode: 'off' | 'fallback' | 'always') {\n if (mode === 'off') {\n return undefined\n }\n return (info: SetDataDebugInfo) => {\n if (mode === 'fallback' && !isFallbackReason(info.reason)) {\n return\n }\n const bytes = info.phase\n ? info.phase.dispatch?.payloadBytes\n : typeof info.bytes === 'number' ? info.bytes : info.estimatedBytes\n const bytesText = typeof bytes === 'number' ? `${bytes}B` : 'unknown'\n const parts = [\n `mode=${info.mode}`,\n `reason=${info.reason}`,\n `pending=${info.pendingPatchKeys}`,\n `keys=${info.payloadKeys}`,\n `bytes=${bytesText}`,\n ]\n if (typeof info.revision === 'number') {\n parts.push(`revision=${info.revision}`)\n }\n if (typeof info.committedRevision === 'number') {\n parts.push(`committedRevision=${info.committedRevision}`)\n }\n if (info.phase) {\n const phase = info.phase\n parts.push(\n `phase=${phase.name}`,\n `observer=${phase.observerId}`,\n `result=${phase.result}`,\n `completion=${phase.completion}`,\n `dispatch=${phase.dispatch?.id ?? 'unknown'}`,\n `prepareMs=${phase.prepareDurationMs ?? 'unknown'}`,\n `dispatchMs=${phase.dispatch?.durationMs ?? 'unknown'}`,\n `commitMs=${phase.commitDurationMs ?? 'unknown'}`,\n 'visibleAt=unknown',\n )\n }\n if (typeof info.mergedSiblingParents === 'number') {\n parts.push(`mergedParents=${info.mergedSiblingParents}`)\n }\n if (typeof info.computedDirtyKeys === 'number') {\n parts.push(`computedDirty=${info.computedDirtyKeys}`)\n }\n if (typeof info.flushCount === 'number') {\n parts.push(`flushes=${info.flushCount}`)\n }\n if (typeof info.windowMs === 'number') {\n parts.push(`window=${info.windowMs}ms`)\n }\n if (info.targetLabel) {\n parts.push(`target=${info.targetLabel}`)\n }\n if (info.bindings?.length) {\n const bindings = info.bindings.map((binding) => {\n const start = binding.sourceLocation?.start\n return start\n ? `${binding.id}@${binding.sourceFile}:${start.line}:${start.column}`\n : `${binding.id}@${binding.sourceFile}`\n })\n parts.push(`bindings=${bindings.join(',')}`)\n }\n if (info.message) {\n parts.push(`message=${info.message}`)\n }\n const message = `[wevu:setData] ${parts.join(' ')}`\n if (isFallbackReason(info.reason)) {\n // eslint-disable-next-line no-console\n console.warn(message)\n return\n }\n // eslint-disable-next-line no-console\n console.info(message)\n }\n}\n"],"mappings":";AAEA,SAAS,iBAAiB,QAAoC;CAC5D,OAAO,WAAW,WAAW,WAAW;AAC1C;AAEA,SAAgB,wBAAwB,MAAqC;CAC3E,IAAI,SAAS,OACX;CAEF,QAAQ,SAA2B;EACjC,IAAI,SAAS,cAAc,CAAC,iBAAiB,KAAK,MAAM,GACtD;EAEF,MAAM,QAAQ,KAAK,QACf,KAAK,MAAM,UAAU,eACrB,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAK;EACvD,MAAM,YAAY,OAAO,UAAU,WAAW,GAAG,MAAM,KAAK;EAC5D,MAAM,QAAQ;GACZ,QAAQ,KAAK;GACb,UAAU,KAAK;GACf,WAAW,KAAK;GAChB,QAAQ,KAAK;GACb,SAAS;EACX;EACA,IAAI,OAAO,KAAK,aAAa,UAC3B,MAAM,KAAK,YAAY,KAAK,UAAU;EAExC,IAAI,OAAO,KAAK,sBAAsB,UACpC,MAAM,KAAK,qBAAqB,KAAK,mBAAmB;EAE1D,IAAI,KAAK,OAAO;GACd,MAAM,QAAQ,KAAK;GACnB,MAAM,KACJ,SAAS,MAAM,QACf,YAAY,MAAM,cAClB,UAAU,MAAM,UAChB,cAAc,MAAM,cACpB,YAAY,MAAM,UAAU,MAAM,aAClC,aAAa,MAAM,qBAAqB,aACxC,cAAc,MAAM,UAAU,cAAc,aAC5C,YAAY,MAAM,oBAAoB,aACtC,mBACF;EACF;EACA,IAAI,OAAO,KAAK,yBAAyB,UACvC,MAAM,KAAK,iBAAiB,KAAK,sBAAsB;EAEzD,IAAI,OAAO,KAAK,sBAAsB,UACpC,MAAM,KAAK,iBAAiB,KAAK,mBAAmB;EAEtD,IAAI,OAAO,KAAK,eAAe,UAC7B,MAAM,KAAK,WAAW,KAAK,YAAY;EAEzC,IAAI,OAAO,KAAK,aAAa,UAC3B,MAAM,KAAK,UAAU,KAAK,SAAS,GAAG;EAExC,IAAI,KAAK,aACP,MAAM,KAAK,UAAU,KAAK,aAAa;EAEzC,IAAI,KAAK,UAAU,QAAQ;GACzB,MAAM,WAAW,KAAK,SAAS,KAAK,YAAY;IAC9C,MAAM,QAAQ,QAAQ,gBAAgB;IACtC,OAAO,QACH,GAAG,QAAQ,GAAG,GAAG,QAAQ,WAAW,GAAG,MAAM,KAAK,GAAG,MAAM,WAC3D,GAAG,QAAQ,GAAG,GAAG,QAAQ;GAC/B,CAAC;GACD,MAAM,KAAK,YAAY,SAAS,KAAK,GAAG,GAAG;EAC7C;EACA,IAAI,KAAK,SACP,MAAM,KAAK,WAAW,KAAK,SAAS;EAEtC,MAAM,UAAU,kBAAkB,MAAM,KAAK,GAAG;EAChD,IAAI,iBAAiB,KAAK,MAAM,GAAG;GAEjC,QAAQ,KAAK,OAAO;GACpB;EACF;EAEA,QAAQ,KAAK,OAAO;CACtB;AACF"}
@@ -76,7 +76,7 @@ function createRuntimeMount(options) {
76
76
  const value = state[key];
77
77
  if (hasTrackableSetupBinding(value)) trackedSetupReactiveKeys.add(key);
78
78
  });
79
- const { includeComputed, setDataStrategy, maxPatchKeys, maxPayloadBytes, mergeSiblingThreshold, mergeSiblingMaxInflationRatio, mergeSiblingMaxParentBytes, mergeSiblingSkipArray, computedCompare, computedCompareMaxDepth, computedCompareMaxKeys, prelinkMaxDepth, prelinkMaxKeys, debug, diagnostics, loopWarning, debugWhen, debugSampleRate, elevateTopKeyThreshold, toPlainMaxDepth, toPlainMaxKeys, includeFunctions, functionPaths, shouldIncludeKey } = resolveSetDataOptions(setDataOptions);
79
+ const { includeComputed, setDataStrategy, maxPatchKeys, maxPayloadBytes, mergeSiblingThreshold, mergeSiblingMaxInflationRatio, mergeSiblingMaxParentBytes, mergeSiblingSkipArray, computedCompare, computedCompareMaxDepth, computedCompareMaxKeys, prelinkMaxDepth, prelinkMaxKeys, debug, diagnostics, loopWarning, debugWhen, debugSampleRate, debugPhases, elevateTopKeyThreshold, toPlainMaxDepth, toPlainMaxKeys, includeFunctions, functionPaths, shouldIncludeKey } = resolveSetDataOptions(setDataOptions);
80
80
  const diagnosticsLogger = createDiagnosticsLogger(diagnostics);
81
81
  const loopWarningLogger = diagnostics === "off" && loopWarning ? createDiagnosticsLogger("fallback") : void 0;
82
82
  const mergedDebug = debug || diagnosticsLogger || loopWarningLogger ? (info) => {
@@ -128,6 +128,7 @@ function createRuntimeMount(options) {
128
128
  debug: mergedDebug,
129
129
  debugWhen: mergedDebugWhen,
130
130
  debugSampleRate,
131
+ debugPhases,
131
132
  bindingManifest,
132
133
  loopWarning,
133
134
  targetLabel,
@@ -138,6 +139,10 @@ function createRuntimeMount(options) {
138
139
  };
139
140
  const scheduler = setDataStrategy === "patch" ? requireRuntimeCapability("patchStrategy", "createRuntimeMount(setData.strategy=\"patch\")").createScheduler(schedulerOptions) : createSetDataScheduler(schedulerOptions);
140
141
  const job = () => scheduler.job();
142
+ const flushSetupSnapshotSync = () => {
143
+ tracker?.();
144
+ scheduler.job();
145
+ };
141
146
  tracker = effect(() => {
142
147
  touchReactive(state);
143
148
  const runtimeProps = state[WEVU_PROPS_KEY];
@@ -216,13 +221,13 @@ function createRuntimeMount(options) {
216
221
  }
217
222
  try {
218
223
  Object.defineProperty(runtimeInstance, "__wevu_flushSetupSnapshotSync", {
219
- value: job,
224
+ value: flushSetupSnapshotSync,
220
225
  configurable: true,
221
226
  enumerable: false,
222
227
  writable: false
223
228
  });
224
229
  } catch {
225
- runtimeInstance.__wevu_flushSetupSnapshotSync = job;
230
+ runtimeInstance.__wevu_flushSetupSnapshotSync = flushSetupSnapshotSync;
226
231
  }
227
232
  try {
228
233
  Object.defineProperty(runtimeInstance, "__wevu_cloneDispatchedSnapshot", {
@@ -1 +1 @@
1
- {"version":3,"file":"mount.mjs","names":[],"sources":["../../../../src/runtime/app/mount.ts"],"sourcesContent":["import type { WevuRuntimeBindingManifestV1 } from '@weapp-core/constants'\nimport type { WatchOptions, WatchStopHandle } from '../../reactivity'\nimport type {\n AppConfig,\n ComputedDefinitions,\n CreateAppOptions,\n ExtractComputed,\n MethodDefinitions,\n MiniProgramAdapter,\n RuntimeInstance,\n SetDataDebugInfo,\n} from '../types'\nimport type { CommitAwareSetDataAdapter } from './setData/commitTracker'\nimport {\n WEVU_ATTRS_KEY,\n WEVU_PROPS_DERIVED_KEYS_KEY,\n WEVU_PROPS_KEY,\n WEVU_SETUP_STATE_KEY,\n} from '@weapp-core/constants'\nimport { effect, isReactive, reactive, shallowReactive, stop, touchReactive, watch } from '../../reactivity'\nimport { queueJob } from '../../scheduler'\nimport { hasOwn } from '../../utils'\nimport { createBindModel } from '../bindModel'\nimport { requireRuntimeCapability } from '../capabilities'\nimport { hasTrackableSetupBinding, touchSetupBinding } from '../setupTracking'\nimport { createRuntimeContext } from './context'\nimport { createDiagnosticsLogger } from './diagnostics'\nimport { createSetDataScheduler } from './setData/scheduler'\nimport { resolveSetDataOptions } from './setDataOptions'\n\nfunction createWatchStopHandle(cleanup: () => void, baseHandle?: WatchStopHandle): WatchStopHandle {\n const stopHandle = (() => {\n cleanup()\n }) as WatchStopHandle\n stopHandle.stop = () => stopHandle()\n stopHandle.pause = () => {\n baseHandle?.pause?.()\n }\n stopHandle.resume = () => {\n baseHandle?.resume?.()\n }\n return stopHandle\n}\n\ntype RuntimeInstanceWithSetupMethodsVersion<\n D extends object,\n C extends ComputedDefinitions,\n M extends MethodDefinitions,\n> = RuntimeInstance<D, C, M> & {\n __wevu_touchSetupMethodsVersion?: () => void\n __wevu_flushSetupSnapshotSync?: () => void\n __wevu_cloneDispatchedSnapshot?: () => Record<string, any>\n __wevu_trackSetupReactiveKey?: (key: string) => void\n}\n\nfunction resolveDataOption<D extends object>(data: CreateAppOptions<D, any, any>['data']): D {\n if (typeof data === 'function') {\n return data()\n }\n return (data ?? {}) as D\n}\n\nexport function createRuntimeMount<D extends object, C extends ComputedDefinitions, M extends MethodDefinitions>(options: {\n data: CreateAppOptions<D, C, M>['data']\n resolvedComputed: C\n resolvedMethods: M\n appConfig: AppConfig\n setDataOptions: CreateAppOptions<D, C, M>['setData']\n bindingManifest?: WevuRuntimeBindingManifestV1\n}) {\n const {\n data,\n resolvedComputed,\n resolvedMethods,\n appConfig,\n setDataOptions,\n bindingManifest,\n } = options\n\n return (adapter?: MiniProgramAdapter): RuntimeInstance<D, C, M> => {\n if (setDataOptions?.strategy === 'patch') {\n requireRuntimeCapability('patchStrategy', 'createRuntimeMount(setData.strategy=\"patch\")')\n }\n const rawState = resolveDataOption(data)\n const adapterInitialProps = (adapter as any)?.__wevu_initialProps\n // 预置 props 容器,确保编译器生成的 this.__wevuProps 回退表达式\n // 在 computed 首次求值阶段即可建立响应式依赖。\n if (rawState && typeof rawState === 'object' && !hasOwn(rawState as object, WEVU_PROPS_KEY)) {\n try {\n Object.defineProperty(rawState as object, WEVU_PROPS_KEY, {\n value: shallowReactive(Object.create(null)),\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n // 若 data 返回对象不可扩展,则跳过预置,后续由 mount 阶段兜底注入。\n }\n }\n const rawProps = rawState && typeof rawState === 'object'\n ? (rawState as any)[WEVU_PROPS_KEY]\n : undefined\n if (rawProps && typeof rawProps === 'object' && adapterInitialProps && typeof adapterInitialProps === 'object') {\n Object.assign(rawProps, adapterInitialProps)\n }\n const state = reactive(rawState)\n const setupState = reactive(Object.create(null))\n const adapterSnapshotOmitKeys = (adapter as any)?.__wevu_snapshotOmitKeys\n const deferInitialSnapshot = Boolean((adapter as any)?.__wevu_deferInitialSnapshot)\n const adapterInitialSnapshot = (adapter as any)?.__wevu_initialSnapshot\n const adapterInitialState = (adapter as any)?.__wevu_initialState\n const snapshotOmitKeys = new Set<string>(\n adapterSnapshotOmitKeys instanceof Set\n ? adapterSnapshotOmitKeys\n : Array.isArray(adapterSnapshotOmitKeys)\n ? adapterSnapshotOmitKeys\n : [],\n )\n if (rawState && typeof rawState === 'object' && !hasOwn(rawState as object, WEVU_SETUP_STATE_KEY)) {\n try {\n Object.defineProperty(rawState as object, WEVU_SETUP_STATE_KEY, {\n value: setupState,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n // 若 data 返回对象不可扩展,则跳过预置,后续由注册阶段兜底注入。\n }\n }\n if (rawState && typeof rawState === 'object' && adapterInitialState && typeof adapterInitialState === 'object') {\n for (const [key, value] of Object.entries(adapterInitialState as Record<string, unknown>)) {\n if (snapshotOmitKeys.has(key)) {\n continue\n }\n ;(rawState as Record<string, unknown>)[key] = value\n }\n }\n const computedDefs = resolvedComputed\n const methodDefs = resolvedMethods\n\n let mounted = true\n const stopHandles: WatchStopHandle[] = []\n const trackedSetupReactiveKeys = new Set<string>()\n Object.keys(state as any).forEach((key) => {\n const value = (state as any)[key]\n if (hasTrackableSetupBinding(value)) {\n trackedSetupReactiveKeys.add(key)\n }\n })\n\n const {\n includeComputed,\n setDataStrategy,\n maxPatchKeys,\n maxPayloadBytes,\n mergeSiblingThreshold,\n mergeSiblingMaxInflationRatio,\n mergeSiblingMaxParentBytes,\n mergeSiblingSkipArray,\n computedCompare,\n computedCompareMaxDepth,\n computedCompareMaxKeys,\n prelinkMaxDepth,\n prelinkMaxKeys,\n debug,\n diagnostics,\n loopWarning,\n debugWhen,\n debugSampleRate,\n elevateTopKeyThreshold,\n toPlainMaxDepth,\n toPlainMaxKeys,\n includeFunctions,\n functionPaths,\n shouldIncludeKey,\n } = resolveSetDataOptions(setDataOptions)\n const diagnosticsLogger = createDiagnosticsLogger(diagnostics)\n const loopWarningLogger = diagnostics === 'off' && loopWarning\n ? createDiagnosticsLogger('fallback')\n : undefined\n const mergedDebug = (debug || diagnosticsLogger || loopWarningLogger)\n ? (info: SetDataDebugInfo) => {\n if (typeof debug === 'function') {\n try {\n debug(info)\n }\n catch {\n // 用户调试回调不得阻止默认诊断。\n }\n }\n diagnosticsLogger?.(info)\n if (info.reason === 'loopWarning') {\n loopWarningLogger?.(info)\n }\n }\n : undefined\n const mergedDebugWhen = diagnostics === 'always'\n ? 'always'\n : debugWhen\n\n const {\n boundMethods,\n computedRefs,\n computedSetters,\n dirtyComputedKeys,\n computedProxy,\n publicInstance,\n touchSetupMethodsVersion,\n } = createRuntimeContext({\n state,\n setupState: setupState as Record<string, any>,\n computedDefs,\n methodDefs,\n appConfig,\n includeComputed,\n setDataStrategy,\n })\n\n const currentAdapter: CommitAwareSetDataAdapter = adapter ?? { setData: () => {} }\n const targetLabel = (currentAdapter as any).__wevu_targetLabel as string | undefined\n let tracker: ReturnType<typeof effect> | undefined\n const schedulerOptions = {\n state: state as any,\n setupState: setupState as any,\n snapshotOmitKeys,\n computedRefs,\n dirtyComputedKeys,\n includeComputed,\n setDataStrategy,\n computedCompare,\n computedCompareMaxDepth,\n computedCompareMaxKeys,\n currentAdapter,\n shouldIncludeKey,\n maxPatchKeys,\n maxPayloadBytes,\n mergeSiblingThreshold,\n mergeSiblingMaxInflationRatio,\n mergeSiblingMaxParentBytes,\n mergeSiblingSkipArray,\n elevateTopKeyThreshold,\n prelinkMaxDepth,\n prelinkMaxKeys,\n toPlainMaxDepth,\n toPlainMaxKeys,\n includeFunctions,\n functionPaths,\n debug: mergedDebug,\n debugWhen: mergedDebugWhen,\n debugSampleRate,\n bindingManifest,\n loopWarning,\n targetLabel,\n runTracker: () => tracker?.(),\n isMounted: () => mounted,\n initialSnapshot: adapterInitialSnapshot && typeof adapterInitialSnapshot === 'object'\n ? adapterInitialSnapshot\n : undefined,\n initialState: adapterInitialState && typeof adapterInitialState === 'object'\n ? adapterInitialState\n : undefined,\n }\n const scheduler = setDataStrategy === 'patch'\n ? requireRuntimeCapability('patchStrategy', 'createRuntimeMount(setData.strategy=\"patch\")')\n .createScheduler(schedulerOptions)\n : createSetDataScheduler(schedulerOptions)\n const job = () => scheduler.job()\n\n tracker = effect(\n () => {\n // 通过根版本信号跟踪任意状态变化\n touchReactive(state as any)\n // __wevuProps / __wevuAttrs 是非枚举属性,需显式跟踪,\n // 否则 props/attrs 更新不会触发 setData 调度。\n const runtimeProps = (state as any)[WEVU_PROPS_KEY]\n if (isReactive(runtimeProps)) {\n touchReactive(runtimeProps as any)\n }\n const runtimeAttrs = (state as any)[WEVU_ATTRS_KEY]\n if (isReactive(runtimeAttrs)) {\n touchReactive(runtimeAttrs as any)\n }\n // 在 setup 返回的 ref/computedRef 变更不会提升 reactive 根版本:\n // 仅跟踪这些明确注册过的键,避免每轮 flush 扫描整份 state。\n trackedSetupReactiveKeys.forEach((key) => {\n const v = (setupState as any)[key] ?? (state as any)[key]\n // setup 返回的组合式对象常常是“普通对象 + 内含 refs/reactive”,\n // 这里递归触达内部响应式源,确保异步更新也能继续驱动 setData。\n touchSetupBinding(v)\n })\n },\n {\n lazy: true,\n scheduler: () => queueJob(job),\n },\n )\n\n if (!deferInitialSnapshot) {\n job()\n }\n\n stopHandles.push(createWatchStopHandle(() => stop(tracker)))\n scheduler.start?.()\n if (scheduler.dispose) {\n stopHandles.push(createWatchStopHandle(scheduler.dispose))\n }\n\n function registerWatch<T>(\n source: (() => T) | Record<string, any>,\n cb: (value: T, oldValue: T) => void,\n watchOptions?: WatchOptions,\n ): WatchStopHandle {\n const stopHandle = watch(source as any, (value: T, oldValue: T) => cb(value, oldValue), watchOptions)\n stopHandles.push(stopHandle)\n return createWatchStopHandle(() => {\n stopHandle()\n const index = stopHandles.indexOf(stopHandle)\n if (index >= 0) {\n stopHandles.splice(index, 1)\n }\n }, stopHandle)\n }\n\n const bindModel = createBindModel(\n publicInstance as any,\n state as any,\n computedRefs,\n computedSetters,\n setupState as Record<string, any>,\n )\n\n const unmount = () => {\n if (!mounted) {\n return\n }\n mounted = false\n scheduler.dispose?.()\n try {\n currentAdapter.__wevu_disposeSetData?.()\n }\n catch {\n // 卸载阶段继续清理其余运行时资源。\n }\n stopHandles.forEach((handle) => {\n try {\n handle()\n }\n catch {\n // 卸载阶段忽略 stop 抛错,确保其余清理继续\n }\n })\n stopHandles.length = 0\n }\n\n const runtimeInstance: RuntimeInstance<D, C, M> = {\n get state() {\n return state\n },\n get setupState() {\n return setupState as Record<string, any>\n },\n get proxy() {\n return publicInstance\n },\n get methods() {\n return boundMethods\n },\n get computed() {\n return computedProxy as Readonly<ExtractComputed<C>>\n },\n get adapter() {\n return currentAdapter\n },\n bindModel,\n watch: registerWatch,\n snapshot: () => scheduler.snapshot(),\n unmount,\n }\n\n try {\n Object.defineProperty(runtimeInstance, '__wevu_touchSetupMethodsVersion', {\n value: touchSetupMethodsVersion,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as RuntimeInstanceWithSetupMethodsVersion<D, C, M>).__wevu_touchSetupMethodsVersion = touchSetupMethodsVersion\n }\n\n try {\n Object.defineProperty(runtimeInstance, '__wevu_flushSetupSnapshotSync', {\n value: job,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as RuntimeInstanceWithSetupMethodsVersion<D, C, M>).__wevu_flushSetupSnapshotSync = job\n }\n\n try {\n Object.defineProperty(runtimeInstance, '__wevu_cloneDispatchedSnapshot', {\n value: scheduler.cloneLatestSnapshot,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as RuntimeInstanceWithSetupMethodsVersion<D, C, M>).__wevu_cloneDispatchedSnapshot = scheduler.cloneLatestSnapshot\n }\n\n try {\n Object.defineProperty(runtimeInstance, '__wevu_trackSetupReactiveKey', {\n value: (key: string) => {\n trackedSetupReactiveKeys.add(key)\n },\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as RuntimeInstanceWithSetupMethodsVersion<D, C, M>).__wevu_trackSetupReactiveKey = (key: string) => {\n trackedSetupReactiveKeys.add(key)\n }\n }\n\n try {\n Object.defineProperty(runtimeInstance, WEVU_PROPS_DERIVED_KEYS_KEY, {\n value: snapshotOmitKeys,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as any)[WEVU_PROPS_DERIVED_KEYS_KEY] = snapshotOmitKeys\n }\n\n return runtimeInstance\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mount.mjs","names":[],"sources":["../../../../src/runtime/app/mount.ts"],"sourcesContent":["import type { WevuRuntimeBindingManifestV1 } from '@weapp-core/constants'\nimport type { WatchOptions, WatchStopHandle } from '../../reactivity'\nimport type {\n AppConfig,\n ComputedDefinitions,\n CreateAppOptions,\n ExtractComputed,\n MethodDefinitions,\n MiniProgramAdapter,\n RuntimeInstance,\n SetDataDebugInfo,\n} from '../types'\nimport type { CommitAwareSetDataAdapter } from './setData/commitTracker'\nimport {\n WEVU_ATTRS_KEY,\n WEVU_PROPS_DERIVED_KEYS_KEY,\n WEVU_PROPS_KEY,\n WEVU_SETUP_STATE_KEY,\n} from '@weapp-core/constants'\nimport { effect, isReactive, reactive, shallowReactive, stop, touchReactive, watch } from '../../reactivity'\nimport { queueJob } from '../../scheduler'\nimport { hasOwn } from '../../utils'\nimport { createBindModel } from '../bindModel'\nimport { requireRuntimeCapability } from '../capabilities'\nimport { hasTrackableSetupBinding, touchSetupBinding } from '../setupTracking'\nimport { createRuntimeContext } from './context'\nimport { createDiagnosticsLogger } from './diagnostics'\nimport { createSetDataScheduler } from './setData/scheduler'\nimport { resolveSetDataOptions } from './setDataOptions'\n\nfunction createWatchStopHandle(cleanup: () => void, baseHandle?: WatchStopHandle): WatchStopHandle {\n const stopHandle = (() => {\n cleanup()\n }) as WatchStopHandle\n stopHandle.stop = () => stopHandle()\n stopHandle.pause = () => {\n baseHandle?.pause?.()\n }\n stopHandle.resume = () => {\n baseHandle?.resume?.()\n }\n return stopHandle\n}\n\ntype RuntimeInstanceWithSetupMethodsVersion<\n D extends object,\n C extends ComputedDefinitions,\n M extends MethodDefinitions,\n> = RuntimeInstance<D, C, M> & {\n __wevu_touchSetupMethodsVersion?: () => void\n __wevu_flushSetupSnapshotSync?: () => void\n __wevu_cloneDispatchedSnapshot?: () => Record<string, any>\n __wevu_trackSetupReactiveKey?: (key: string) => void\n}\n\nfunction resolveDataOption<D extends object>(data: CreateAppOptions<D, any, any>['data']): D {\n if (typeof data === 'function') {\n return data()\n }\n return (data ?? {}) as D\n}\n\nexport function createRuntimeMount<D extends object, C extends ComputedDefinitions, M extends MethodDefinitions>(options: {\n data: CreateAppOptions<D, C, M>['data']\n resolvedComputed: C\n resolvedMethods: M\n appConfig: AppConfig\n setDataOptions: CreateAppOptions<D, C, M>['setData']\n bindingManifest?: WevuRuntimeBindingManifestV1\n}) {\n const {\n data,\n resolvedComputed,\n resolvedMethods,\n appConfig,\n setDataOptions,\n bindingManifest,\n } = options\n\n return (adapter?: MiniProgramAdapter): RuntimeInstance<D, C, M> => {\n if (setDataOptions?.strategy === 'patch') {\n requireRuntimeCapability('patchStrategy', 'createRuntimeMount(setData.strategy=\"patch\")')\n }\n const rawState = resolveDataOption(data)\n const adapterInitialProps = (adapter as any)?.__wevu_initialProps\n // 预置 props 容器,确保编译器生成的 this.__wevuProps 回退表达式\n // 在 computed 首次求值阶段即可建立响应式依赖。\n if (rawState && typeof rawState === 'object' && !hasOwn(rawState as object, WEVU_PROPS_KEY)) {\n try {\n Object.defineProperty(rawState as object, WEVU_PROPS_KEY, {\n value: shallowReactive(Object.create(null)),\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n // 若 data 返回对象不可扩展,则跳过预置,后续由 mount 阶段兜底注入。\n }\n }\n const rawProps = rawState && typeof rawState === 'object'\n ? (rawState as any)[WEVU_PROPS_KEY]\n : undefined\n if (rawProps && typeof rawProps === 'object' && adapterInitialProps && typeof adapterInitialProps === 'object') {\n Object.assign(rawProps, adapterInitialProps)\n }\n const state = reactive(rawState)\n const setupState = reactive(Object.create(null))\n const adapterSnapshotOmitKeys = (adapter as any)?.__wevu_snapshotOmitKeys\n const deferInitialSnapshot = Boolean((adapter as any)?.__wevu_deferInitialSnapshot)\n const adapterInitialSnapshot = (adapter as any)?.__wevu_initialSnapshot\n const adapterInitialState = (adapter as any)?.__wevu_initialState\n const snapshotOmitKeys = new Set<string>(\n adapterSnapshotOmitKeys instanceof Set\n ? adapterSnapshotOmitKeys\n : Array.isArray(adapterSnapshotOmitKeys)\n ? adapterSnapshotOmitKeys\n : [],\n )\n if (rawState && typeof rawState === 'object' && !hasOwn(rawState as object, WEVU_SETUP_STATE_KEY)) {\n try {\n Object.defineProperty(rawState as object, WEVU_SETUP_STATE_KEY, {\n value: setupState,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n // 若 data 返回对象不可扩展,则跳过预置,后续由注册阶段兜底注入。\n }\n }\n if (rawState && typeof rawState === 'object' && adapterInitialState && typeof adapterInitialState === 'object') {\n for (const [key, value] of Object.entries(adapterInitialState as Record<string, unknown>)) {\n if (snapshotOmitKeys.has(key)) {\n continue\n }\n ;(rawState as Record<string, unknown>)[key] = value\n }\n }\n const computedDefs = resolvedComputed\n const methodDefs = resolvedMethods\n\n let mounted = true\n const stopHandles: WatchStopHandle[] = []\n const trackedSetupReactiveKeys = new Set<string>()\n Object.keys(state as any).forEach((key) => {\n const value = (state as any)[key]\n if (hasTrackableSetupBinding(value)) {\n trackedSetupReactiveKeys.add(key)\n }\n })\n\n const {\n includeComputed,\n setDataStrategy,\n maxPatchKeys,\n maxPayloadBytes,\n mergeSiblingThreshold,\n mergeSiblingMaxInflationRatio,\n mergeSiblingMaxParentBytes,\n mergeSiblingSkipArray,\n computedCompare,\n computedCompareMaxDepth,\n computedCompareMaxKeys,\n prelinkMaxDepth,\n prelinkMaxKeys,\n debug,\n diagnostics,\n loopWarning,\n debugWhen,\n debugSampleRate,\n debugPhases,\n elevateTopKeyThreshold,\n toPlainMaxDepth,\n toPlainMaxKeys,\n includeFunctions,\n functionPaths,\n shouldIncludeKey,\n } = resolveSetDataOptions(setDataOptions)\n const diagnosticsLogger = createDiagnosticsLogger(diagnostics)\n const loopWarningLogger = diagnostics === 'off' && loopWarning\n ? createDiagnosticsLogger('fallback')\n : undefined\n const mergedDebug = (debug || diagnosticsLogger || loopWarningLogger)\n ? (info: SetDataDebugInfo) => {\n if (typeof debug === 'function') {\n try {\n debug(info)\n }\n catch {\n // 用户调试回调不得阻止默认诊断。\n }\n }\n diagnosticsLogger?.(info)\n if (info.reason === 'loopWarning') {\n loopWarningLogger?.(info)\n }\n }\n : undefined\n const mergedDebugWhen = diagnostics === 'always'\n ? 'always'\n : debugWhen\n\n const {\n boundMethods,\n computedRefs,\n computedSetters,\n dirtyComputedKeys,\n computedProxy,\n publicInstance,\n touchSetupMethodsVersion,\n } = createRuntimeContext({\n state,\n setupState: setupState as Record<string, any>,\n computedDefs,\n methodDefs,\n appConfig,\n includeComputed,\n setDataStrategy,\n })\n\n const currentAdapter: CommitAwareSetDataAdapter = adapter ?? { setData: () => {} }\n const targetLabel = (currentAdapter as any).__wevu_targetLabel as string | undefined\n let tracker: ReturnType<typeof effect> | undefined\n const schedulerOptions = {\n state: state as any,\n setupState: setupState as any,\n snapshotOmitKeys,\n computedRefs,\n dirtyComputedKeys,\n includeComputed,\n setDataStrategy,\n computedCompare,\n computedCompareMaxDepth,\n computedCompareMaxKeys,\n currentAdapter,\n shouldIncludeKey,\n maxPatchKeys,\n maxPayloadBytes,\n mergeSiblingThreshold,\n mergeSiblingMaxInflationRatio,\n mergeSiblingMaxParentBytes,\n mergeSiblingSkipArray,\n elevateTopKeyThreshold,\n prelinkMaxDepth,\n prelinkMaxKeys,\n toPlainMaxDepth,\n toPlainMaxKeys,\n includeFunctions,\n functionPaths,\n debug: mergedDebug,\n debugWhen: mergedDebugWhen,\n debugSampleRate,\n debugPhases,\n bindingManifest,\n loopWarning,\n targetLabel,\n runTracker: () => tracker?.(),\n isMounted: () => mounted,\n initialSnapshot: adapterInitialSnapshot && typeof adapterInitialSnapshot === 'object'\n ? adapterInitialSnapshot\n : undefined,\n initialState: adapterInitialState && typeof adapterInitialState === 'object'\n ? adapterInitialState\n : undefined,\n }\n const scheduler = setDataStrategy === 'patch'\n ? requireRuntimeCapability('patchStrategy', 'createRuntimeMount(setData.strategy=\"patch\")')\n .createScheduler(schedulerOptions)\n : createSetDataScheduler(schedulerOptions)\n const job = () => scheduler.job()\n // HMR 延迟快照可能把 setup 状态恢复为与宿主相同的值;此时调度器不会因值变化重新运行\n // tracker。先主动触达一次新 setup 的响应式依赖,确保后续 ref/computed 更新仍能进入调度器。\n const flushSetupSnapshotSync = () => {\n tracker?.()\n scheduler.job()\n }\n\n tracker = effect(\n () => {\n // 通过根版本信号跟踪任意状态变化\n touchReactive(state as any)\n // __wevuProps / __wevuAttrs 是非枚举属性,需显式跟踪,\n // 否则 props/attrs 更新不会触发 setData 调度。\n const runtimeProps = (state as any)[WEVU_PROPS_KEY]\n if (isReactive(runtimeProps)) {\n touchReactive(runtimeProps as any)\n }\n const runtimeAttrs = (state as any)[WEVU_ATTRS_KEY]\n if (isReactive(runtimeAttrs)) {\n touchReactive(runtimeAttrs as any)\n }\n // 在 setup 返回的 ref/computedRef 变更不会提升 reactive 根版本:\n // 仅跟踪这些明确注册过的键,避免每轮 flush 扫描整份 state。\n trackedSetupReactiveKeys.forEach((key) => {\n const v = (setupState as any)[key] ?? (state as any)[key]\n // setup 返回的组合式对象常常是“普通对象 + 内含 refs/reactive”,\n // 这里递归触达内部响应式源,确保异步更新也能继续驱动 setData。\n touchSetupBinding(v)\n })\n },\n {\n lazy: true,\n scheduler: () => queueJob(job),\n },\n )\n\n if (!deferInitialSnapshot) {\n job()\n }\n\n stopHandles.push(createWatchStopHandle(() => stop(tracker)))\n scheduler.start?.()\n if (scheduler.dispose) {\n stopHandles.push(createWatchStopHandle(scheduler.dispose))\n }\n\n function registerWatch<T>(\n source: (() => T) | Record<string, any>,\n cb: (value: T, oldValue: T) => void,\n watchOptions?: WatchOptions,\n ): WatchStopHandle {\n const stopHandle = watch(source as any, (value: T, oldValue: T) => cb(value, oldValue), watchOptions)\n stopHandles.push(stopHandle)\n return createWatchStopHandle(() => {\n stopHandle()\n const index = stopHandles.indexOf(stopHandle)\n if (index >= 0) {\n stopHandles.splice(index, 1)\n }\n }, stopHandle)\n }\n\n const bindModel = createBindModel(\n publicInstance as any,\n state as any,\n computedRefs,\n computedSetters,\n setupState as Record<string, any>,\n )\n\n const unmount = () => {\n if (!mounted) {\n return\n }\n mounted = false\n scheduler.dispose?.()\n try {\n currentAdapter.__wevu_disposeSetData?.()\n }\n catch {\n // 卸载阶段继续清理其余运行时资源。\n }\n stopHandles.forEach((handle) => {\n try {\n handle()\n }\n catch {\n // 卸载阶段忽略 stop 抛错,确保其余清理继续\n }\n })\n stopHandles.length = 0\n }\n\n const runtimeInstance: RuntimeInstance<D, C, M> = {\n get state() {\n return state\n },\n get setupState() {\n return setupState as Record<string, any>\n },\n get proxy() {\n return publicInstance\n },\n get methods() {\n return boundMethods\n },\n get computed() {\n return computedProxy as Readonly<ExtractComputed<C>>\n },\n get adapter() {\n return currentAdapter\n },\n bindModel,\n watch: registerWatch,\n snapshot: () => scheduler.snapshot(),\n unmount,\n }\n\n try {\n Object.defineProperty(runtimeInstance, '__wevu_touchSetupMethodsVersion', {\n value: touchSetupMethodsVersion,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as RuntimeInstanceWithSetupMethodsVersion<D, C, M>).__wevu_touchSetupMethodsVersion = touchSetupMethodsVersion\n }\n\n try {\n Object.defineProperty(runtimeInstance, '__wevu_flushSetupSnapshotSync', {\n value: flushSetupSnapshotSync,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as RuntimeInstanceWithSetupMethodsVersion<D, C, M>).__wevu_flushSetupSnapshotSync = flushSetupSnapshotSync\n }\n\n try {\n Object.defineProperty(runtimeInstance, '__wevu_cloneDispatchedSnapshot', {\n value: scheduler.cloneLatestSnapshot,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as RuntimeInstanceWithSetupMethodsVersion<D, C, M>).__wevu_cloneDispatchedSnapshot = scheduler.cloneLatestSnapshot\n }\n\n try {\n Object.defineProperty(runtimeInstance, '__wevu_trackSetupReactiveKey', {\n value: (key: string) => {\n trackedSetupReactiveKeys.add(key)\n },\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as RuntimeInstanceWithSetupMethodsVersion<D, C, M>).__wevu_trackSetupReactiveKey = (key: string) => {\n trackedSetupReactiveKeys.add(key)\n }\n }\n\n try {\n Object.defineProperty(runtimeInstance, WEVU_PROPS_DERIVED_KEYS_KEY, {\n value: snapshotOmitKeys,\n configurable: true,\n enumerable: false,\n writable: false,\n })\n }\n catch {\n ;(runtimeInstance as any)[WEVU_PROPS_DERIVED_KEYS_KEY] = snapshotOmitKeys\n }\n\n return runtimeInstance\n }\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { observePhysicalDispatch } from "./observation.mjs";
1
2
  import { cloneSnapshotValue } from "./snapshot.mjs";
2
3
 
3
4
  //#region src/runtime/app/setData/commitTracker.ts
@@ -22,10 +23,13 @@ function observeSetDataCompletion(options) {
22
23
  let settled = false;
23
24
  let invoking = true;
24
25
  let callbackCalled = false;
26
+ let observedReturn = false;
25
27
  let returnIsAuthoritative = false;
28
+ let boundary = options.completion;
26
29
  const settleOnce = (settlement, cause) => {
27
30
  if (settled) return;
28
31
  settled = true;
32
+ options.observer?.complete(boundary);
29
33
  options.settle(settlement, cause);
30
34
  };
31
35
  const callback = () => {
@@ -37,17 +41,28 @@ function observeSetDataCompletion(options) {
37
41
  if (options.completion === "callback") settleOnce("committed");
38
42
  };
39
43
  try {
44
+ if (options.observer && options.payload) observePhysicalDispatch(options.observer, options.payload);
40
45
  const result = options.invoke(callback);
41
46
  const resultIsThenable = isThenable(result);
42
47
  returnIsAuthoritative = resultIsThenable;
43
48
  invoking = false;
49
+ if (options.observer && !observedReturn) {
50
+ observedReturn = true;
51
+ options.observer.returned(Date.now());
52
+ }
44
53
  if (resultIsThenable) {
54
+ boundary = "promise";
45
55
  result.then(() => settleOnce("committed"), (cause) => settleOnce("failed", cause));
46
56
  return;
47
57
  }
48
58
  if (options.completion === "return" || callbackCalled) settleOnce("committed");
49
59
  } catch (cause) {
60
+ boundary = "throw";
50
61
  invoking = false;
62
+ if (options.observer && !observedReturn) {
63
+ observedReturn = true;
64
+ options.observer.returned(Date.now());
65
+ }
51
66
  settleOnce("failed", cause);
52
67
  }
53
68
  }
@@ -113,12 +128,17 @@ function createSetDataCommitTracker(options) {
113
128
  }
114
129
  };
115
130
  const invalidateLedger = () => {
131
+ let abandonedObservations;
132
+ const result = state.disposed ? "disposed" : "abandoned";
116
133
  let current = head;
117
134
  while (current) {
118
135
  const next = current.next;
119
136
  current.inLedger = false;
120
137
  current.next = void 0;
121
- if (!current.physicalSettled) current.status = "abandoned";
138
+ if (!current.physicalSettled) {
139
+ current.status = "abandoned";
140
+ if (current.observation) (abandonedObservations ?? (abandonedObservations = [])).push(current.observation);
141
+ }
122
142
  resolveRecord(current);
123
143
  current = next;
124
144
  }
@@ -126,6 +146,7 @@ function createSetDataCommitTracker(options) {
126
146
  tail = void 0;
127
147
  epoch += 1;
128
148
  highestCompletedRevision = state.committedRevision;
149
+ abandonedObservations?.forEach((observation) => observation.finish(result));
129
150
  };
130
151
  const armRecovery = () => {
131
152
  state.needsFullSnapshot = true;
@@ -168,7 +189,7 @@ function createSetDataCommitTracker(options) {
168
189
  reportFailure("out-of-order", record, `revision ${record.revision} completed after committed revision ${state.committedRevision}`);
169
190
  }
170
191
  };
171
- const settleRecord = (record, settlement, cause) => {
192
+ const applySettlement = (record, settlement, cause) => {
172
193
  if (state.disposed || record.physicalSettled) return;
173
194
  record.physicalSettled = true;
174
195
  if (!record.inLedger || record.epoch !== epoch) {
@@ -197,6 +218,17 @@ function createSetDataCommitTracker(options) {
197
218
  }
198
219
  drainSucceededPrefix();
199
220
  };
221
+ const settleRecord = (record, settlement, cause) => {
222
+ if (state.disposed || record.physicalSettled) return;
223
+ if (!record.observation) {
224
+ applySettlement(record, settlement, cause);
225
+ return;
226
+ }
227
+ const late = !record.inLedger || record.epoch !== epoch;
228
+ const outOfOrder = settlement === "committed" && (late ? state.committedRevision > record.revision : highestCompletedRevision > record.revision);
229
+ applySettlement(record, settlement, cause);
230
+ record.observation?.finish(outOfOrder ? "out-of-order" : late ? settlement === "failed" ? "late-failed" : settlement === "committed" ? "late-committed" : "abandoned" : settlement);
231
+ };
200
232
  const createFullPayload = (snapshot) => {
201
233
  const payload = {};
202
234
  const snapshotKeys = new Set(Object.keys(snapshot));
@@ -227,19 +259,22 @@ function createSetDataCommitTracker(options) {
227
259
  tail = record;
228
260
  state.dispatchedSnapshot = update.snapshot;
229
261
  for (const key of Object.keys(update.payload)) knownHostTopKeys.add(key.split(".", 1)[0]);
262
+ record.observation = options.observe?.(update, revision);
230
263
  const settle = (settlement, cause) => {
231
264
  settleRecord(record, settlement, cause);
232
265
  };
233
266
  const hostPayload = cloneSnapshotValue(update.payload);
234
267
  if (typeof options.adapter.__wevu_dispatchSetData === "function") try {
235
- options.adapter.__wevu_dispatchSetData(hostPayload, settle);
268
+ options.adapter.__wevu_dispatchSetData(hostPayload, settle, record.observation?.physical);
236
269
  } catch (cause) {
237
270
  settle("failed", cause);
238
271
  }
239
272
  else observeSetDataCompletion({
240
273
  invoke: () => options.adapter.setData?.(hostPayload),
241
274
  completion: "return",
242
- settle
275
+ settle,
276
+ payload: hostPayload,
277
+ observer: options.adapter.setData ? record.observation?.physical : void 0
243
278
  });
244
279
  return revision;
245
280
  };
@@ -1 +1 @@
1
- {"version":3,"file":"commitTracker.mjs","names":[],"sources":["../../../../../src/runtime/app/setData/commitTracker.ts"],"sourcesContent":["import type { MiniProgramAdapter, SetDataDebugInfo } from '../../types'\nimport { cloneSnapshotValue } from './snapshot'\n\nexport type SetDataSnapshot = Record<string, unknown>\nexport type SetDataPayload = Record<string, unknown>\nexport type SetDataMode = 'diff' | 'patch'\nexport type SetDataRevisionKind = 'delta' | 'full'\nexport type SetDataAdapterSettlement = 'committed' | 'failed' | 'abandoned'\n\nexport type SetDataAdapterSettler = (\n settlement: SetDataAdapterSettlement,\n cause?: unknown,\n) => void\n\nexport interface CommitAwareSetDataAdapter extends MiniProgramAdapter {\n __wevu_dispatchSetData?: (\n payload: SetDataPayload,\n settle: SetDataAdapterSettler,\n ) => void\n __wevu_reportSetDataError?: (error: Error) => void\n __wevu_disposeSetData?: () => void\n}\n\nexport interface PreparedSetDataUpdate {\n mode: SetDataMode\n kind: SetDataRevisionKind\n reason: SetDataDebugInfo['reason']\n snapshot: SetDataSnapshot\n payload: SetDataPayload\n pendingPatchKeys: number\n}\n\nexport interface SetDataCommitFailure {\n kind: 'adapter' | 'out-of-order'\n revision: number\n committedRevision: number\n mode: SetDataMode\n cause: unknown\n error: Error\n payloadKeys: number\n pendingPatchKeys: number\n}\n\nexport interface SetDataCommitState {\n preparedSnapshot: SetDataSnapshot\n dispatchedSnapshot: SetDataSnapshot\n committedSnapshot: SetDataSnapshot\n revision: number\n committedRevision: number\n failedRevision: number | undefined\n needsFullSnapshot: boolean\n commitPromise: Promise<void>\n disposed: boolean\n}\n\nexport interface SetDataCommitTracker {\n readonly state: SetDataCommitState\n dispatch: (update: PreparedSetDataUpdate) => number\n createFullPayload: (snapshot: SetDataSnapshot) => SetDataPayload\n dispose: () => void\n}\n\ntype RevisionStatus = 'dispatched' | 'succeeded' | 'failed' | 'abandoned'\n\ninterface RevisionRecord {\n revision: number\n epoch: number\n mode: SetDataMode\n kind: SetDataRevisionKind\n snapshot: SetDataSnapshot\n payloadKeys: number\n pendingPatchKeys: number\n status: RevisionStatus\n physicalSettled: boolean\n inLedger: boolean\n next: RevisionRecord | undefined\n commitPromise?: Promise<void>\n resolveCommit?: () => void\n}\n\nconst resolvedCommitPromise = Promise.resolve()\n\nfunction isThenable(value: unknown): value is PromiseLike<unknown> {\n return Boolean(\n value\n && (typeof value === 'object' || typeof value === 'function')\n && typeof (value as PromiseLike<unknown>).then === 'function',\n )\n}\n\nfunction formatCommitFailureCause(cause: unknown): string {\n try {\n return cause instanceof Error ? cause.message : String(cause)\n }\n catch {\n return '<unprintable cause>'\n }\n}\n\nfunction createCommitError(\n kind: SetDataCommitFailure['kind'],\n record: RevisionRecord,\n cause: unknown,\n) {\n const causeMessage = formatCommitFailureCause(cause)\n const label = kind === 'adapter' ? 'adapter failure' : 'out-of-order completion'\n const error = new Error(\n `[wevu] setData commit failed (${label}, revision=${record.revision}, mode=${record.mode}, kind=${record.kind}): ${causeMessage}`,\n )\n ;(error as Error & { cause?: unknown }).cause = cause\n return error\n}\n\nexport function observeSetDataCompletion(options: {\n invoke: (callback: () => void) => unknown\n completion: 'return' | 'callback'\n settle: SetDataAdapterSettler\n}): void {\n let settled = false\n let invoking = true\n let callbackCalled = false\n let returnIsAuthoritative = false\n const settleOnce: SetDataAdapterSettler = (settlement, cause) => {\n if (settled) {\n return\n }\n settled = true\n options.settle(settlement, cause)\n }\n const callback = () => {\n if (invoking) {\n callbackCalled = true\n return\n }\n if (returnIsAuthoritative) {\n return\n }\n if (options.completion === 'callback') {\n settleOnce('committed')\n }\n }\n\n try {\n const result = options.invoke(callback)\n const resultIsThenable = isThenable(result)\n returnIsAuthoritative = resultIsThenable\n invoking = false\n if (resultIsThenable) {\n result.then(\n () => settleOnce('committed'),\n cause => settleOnce('failed', cause),\n )\n return\n }\n if (options.completion === 'return' || callbackCalled) {\n settleOnce('committed')\n }\n }\n catch (cause) {\n invoking = false\n settleOnce('failed', cause)\n }\n}\n\nexport function createSetDataCommitTracker(options: {\n initialSnapshot?: SetDataSnapshot\n adapter: CommitAwareSetDataAdapter\n onFailure: (failure: SetDataCommitFailure) => void\n}): SetDataCommitTracker {\n const initialSnapshot = options.initialSnapshot ? cloneSnapshotValue(options.initialSnapshot) : {}\n const knownHostTopKeys = new Set(Object.keys(initialSnapshot))\n let epoch = 0\n let highestCompletedRevision = 0\n let head: RevisionRecord | undefined\n let tail: RevisionRecord | undefined\n\n function ensureCommitBarrier(record: RevisionRecord) {\n if (!record.inLedger) {\n return resolvedCommitPromise\n }\n if (!record.commitPromise) {\n record.commitPromise = new Promise<void>((resolve) => {\n record.resolveCommit = resolve\n })\n }\n return record.commitPromise\n }\n\n const state: SetDataCommitState = {\n preparedSnapshot: initialSnapshot,\n dispatchedSnapshot: initialSnapshot,\n committedSnapshot: initialSnapshot,\n revision: 0,\n committedRevision: 0,\n failedRevision: undefined,\n needsFullSnapshot: false,\n get commitPromise() {\n return tail ? ensureCommitBarrier(tail) : resolvedCommitPromise\n },\n disposed: false,\n }\n\n const reportFailure = (\n kind: SetDataCommitFailure['kind'],\n record: RevisionRecord,\n cause: unknown,\n ) => {\n const error = createCommitError(kind, record, cause)\n try {\n options.onFailure({\n kind,\n revision: record.revision,\n committedRevision: state.committedRevision,\n mode: record.mode,\n cause,\n error,\n payloadKeys: record.payloadKeys,\n pendingPatchKeys: record.pendingPatchKeys,\n })\n }\n catch {\n // 错误上报不得反向破坏提交状态机。\n }\n }\n\n const resolveRecord = (record: RevisionRecord) => {\n record.resolveCommit?.()\n record.resolveCommit = undefined\n }\n\n const removePrefixThrough = (last: RevisionRecord) => {\n let current = head\n while (current) {\n const next = current.next\n current.inLedger = false\n current.next = undefined\n resolveRecord(current)\n if (current === last) {\n head = next\n if (!head) {\n tail = undefined\n }\n return\n }\n current = next\n }\n }\n\n const invalidateLedger = () => {\n let current = head\n while (current) {\n const next = current.next\n current.inLedger = false\n current.next = undefined\n if (!current.physicalSettled) {\n current.status = 'abandoned'\n }\n resolveRecord(current)\n current = next\n }\n head = undefined\n tail = undefined\n epoch += 1\n highestCompletedRevision = state.committedRevision\n }\n\n const armRecovery = () => {\n state.needsFullSnapshot = true\n }\n\n const failLineage = (\n kind: SetDataCommitFailure['kind'],\n record: RevisionRecord,\n cause: unknown,\n ) => {\n record.status = 'failed'\n state.failedRevision = record.revision\n armRecovery()\n invalidateLedger()\n reportFailure(kind, record, cause)\n }\n\n const drainSucceededPrefix = () => {\n while (head?.status === 'succeeded') {\n const record = head\n state.committedSnapshot = record.snapshot\n state.committedRevision = record.revision\n head = record.next\n record.inLedger = false\n record.next = undefined\n resolveRecord(record)\n }\n if (!head) {\n tail = undefined\n }\n }\n\n const commitFullCheckpoint = (record: RevisionRecord) => {\n state.committedSnapshot = record.snapshot\n state.committedRevision = record.revision\n state.failedRevision = undefined\n state.needsFullSnapshot = false\n removePrefixThrough(record)\n drainSucceededPrefix()\n }\n\n const handleLateSettlement = (\n record: RevisionRecord,\n settlement: SetDataAdapterSettlement,\n cause: unknown,\n ) => {\n if (settlement === 'failed') {\n reportFailure('adapter', record, cause)\n return\n }\n if (settlement === 'committed' && state.committedRevision > record.revision) {\n if (head) {\n invalidateLedger()\n }\n armRecovery()\n reportFailure(\n 'out-of-order',\n record,\n `revision ${record.revision} completed after committed revision ${state.committedRevision}`,\n )\n }\n }\n\n const settleRecord = (\n record: RevisionRecord,\n settlement: SetDataAdapterSettlement,\n cause?: unknown,\n ) => {\n if (state.disposed || record.physicalSettled) {\n return\n }\n record.physicalSettled = true\n\n if (!record.inLedger || record.epoch !== epoch) {\n handleLateSettlement(record, settlement, cause)\n return\n }\n\n if (settlement === 'abandoned') {\n record.status = 'abandoned'\n armRecovery()\n invalidateLedger()\n return\n }\n if (settlement === 'failed') {\n failLineage('adapter', record, cause)\n return\n }\n\n record.status = 'succeeded'\n if (highestCompletedRevision > record.revision) {\n failLineage(\n 'out-of-order',\n record,\n `revision ${record.revision} completed after revision ${highestCompletedRevision}`,\n )\n return\n }\n highestCompletedRevision = record.revision\n\n if (record.kind === 'full') {\n commitFullCheckpoint(record)\n return\n }\n drainSucceededPrefix()\n }\n\n const createFullPayload = (snapshot: SetDataSnapshot): SetDataPayload => {\n const payload: SetDataPayload = {}\n const snapshotKeys = new Set(Object.keys(snapshot))\n for (const [key, value] of Object.entries(snapshot)) {\n payload[key] = value === undefined ? null : value\n }\n for (const key of knownHostTopKeys) {\n if (!snapshotKeys.has(key)) {\n payload[key] = null\n }\n }\n return payload\n }\n\n const dispatch = (update: PreparedSetDataUpdate) => {\n if (state.disposed) {\n return state.revision\n }\n\n const revision = state.revision + 1\n state.revision = revision\n state.preparedSnapshot = update.snapshot\n const record: RevisionRecord = {\n revision,\n epoch,\n mode: update.mode,\n kind: update.kind,\n snapshot: update.snapshot,\n payloadKeys: Object.keys(update.payload).length,\n pendingPatchKeys: update.pendingPatchKeys,\n status: 'dispatched',\n physicalSettled: false,\n inLedger: true,\n next: undefined,\n }\n if (tail) {\n tail.next = record\n }\n else {\n head = record\n }\n tail = record\n state.dispatchedSnapshot = update.snapshot\n for (const key of Object.keys(update.payload)) {\n knownHostTopKeys.add(key.split('.', 1)[0]!)\n }\n\n const settle: SetDataAdapterSettler = (settlement, cause) => {\n settleRecord(record, settlement, cause)\n }\n // 宿主会保留对象并在后续路径更新时原地修改,载荷不能与序列化缓存及快照共享引用。\n const hostPayload = cloneSnapshotValue(update.payload)\n if (typeof options.adapter.__wevu_dispatchSetData === 'function') {\n try {\n options.adapter.__wevu_dispatchSetData(hostPayload, settle)\n }\n catch (cause) {\n settle('failed', cause)\n }\n }\n else {\n observeSetDataCompletion({\n invoke: () => options.adapter.setData?.(hostPayload),\n completion: 'return',\n settle,\n })\n }\n return revision\n }\n\n const dispose = () => {\n if (state.disposed) {\n return\n }\n state.disposed = true\n invalidateLedger()\n }\n\n return {\n state,\n dispatch,\n createFullPayload,\n dispose,\n }\n}\n"],"mappings":";;;AAgFA,MAAM,wBAAwB,QAAQ,QAAQ;AAE9C,SAAS,WAAW,OAA+C;CACjE,OAAO,QACL,UACI,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,OAAQ,MAA+B,SAAS,UACrD;AACF;AAEA,SAAS,yBAAyB,OAAwB;CACxD,IAAI;EACF,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CAC9D,QACM;EACJ,OAAO;CACT;AACF;AAEA,SAAS,kBACP,MACA,QACA,OACA;CACA,MAAM,eAAe,yBAAyB,KAAK;CAEnD,MAAM,wBAAQ,IAAI,MAChB,iCAFY,SAAS,YAAY,oBAAoB,0BAEd,aAAa,OAAO,SAAS,SAAS,OAAO,KAAK,SAAS,OAAO,KAAK,KAAK,cACrH;CACC,AAAC,MAAsC,QAAQ;CAChD,OAAO;AACT;AAEA,SAAgB,yBAAyB,SAIhC;CACP,IAAI,UAAU;CACd,IAAI,WAAW;CACf,IAAI,iBAAiB;CACrB,IAAI,wBAAwB;CAC5B,MAAM,cAAqC,YAAY,UAAU;EAC/D,IAAI,SACF;EAEF,UAAU;EACV,QAAQ,OAAO,YAAY,KAAK;CAClC;CACA,MAAM,iBAAiB;EACrB,IAAI,UAAU;GACZ,iBAAiB;GACjB;EACF;EACA,IAAI,uBACF;EAEF,IAAI,QAAQ,eAAe,YACzB,WAAW,WAAW;CAE1B;CAEA,IAAI;EACF,MAAM,SAAS,QAAQ,OAAO,QAAQ;EACtC,MAAM,mBAAmB,WAAW,MAAM;EAC1C,wBAAwB;EACxB,WAAW;EACX,IAAI,kBAAkB;GACpB,OAAO,WACC,WAAW,WAAW,IAC5B,UAAS,WAAW,UAAU,KAAK,CACrC;GACA;EACF;EACA,IAAI,QAAQ,eAAe,YAAY,gBACrC,WAAW,WAAW;CAE1B,SACO,OAAO;EACZ,WAAW;EACX,WAAW,UAAU,KAAK;CAC5B;AACF;AAEA,SAAgB,2BAA2B,SAIlB;CACvB,MAAM,kBAAkB,QAAQ,kBAAkB,mBAAmB,QAAQ,eAAe,IAAI,CAAC;CACjG,MAAM,mBAAmB,IAAI,IAAI,OAAO,KAAK,eAAe,CAAC;CAC7D,IAAI,QAAQ;CACZ,IAAI,2BAA2B;CAC/B,IAAI;CACJ,IAAI;CAEJ,SAAS,oBAAoB,QAAwB;EACnD,IAAI,CAAC,OAAO,UACV,OAAO;EAET,IAAI,CAAC,OAAO,eACV,OAAO,gBAAgB,IAAI,SAAe,YAAY;GACpD,OAAO,gBAAgB;EACzB,CAAC;EAEH,OAAO,OAAO;CAChB;CAEA,MAAM,QAA4B;EAChC,kBAAkB;EAClB,oBAAoB;EACpB,mBAAmB;EACnB,UAAU;EACV,mBAAmB;EACnB,gBAAgB;EAChB,mBAAmB;EACnB,IAAI,gBAAgB;GAClB,OAAO,OAAO,oBAAoB,IAAI,IAAI;EAC5C;EACA,UAAU;CACZ;CAEA,MAAM,iBACJ,MACA,QACA,UACG;EACH,MAAM,QAAQ,kBAAkB,MAAM,QAAQ,KAAK;EACnD,IAAI;GACF,QAAQ,UAAU;IAChB;IACA,UAAU,OAAO;IACjB,mBAAmB,MAAM;IACzB,MAAM,OAAO;IACb;IACA;IACA,aAAa,OAAO;IACpB,kBAAkB,OAAO;GAC3B,CAAC;EACH,QACM,CAEN;CACF;CAEA,MAAM,iBAAiB,WAA2B;EAChD,OAAO,gBAAgB;EACvB,OAAO,gBAAgB;CACzB;CAEA,MAAM,uBAAuB,SAAyB;EACpD,IAAI,UAAU;EACd,OAAO,SAAS;GACd,MAAM,OAAO,QAAQ;GACrB,QAAQ,WAAW;GACnB,QAAQ,OAAO;GACf,cAAc,OAAO;GACrB,IAAI,YAAY,MAAM;IACpB,OAAO;IACP,IAAI,CAAC,MACH,OAAO;IAET;GACF;GACA,UAAU;EACZ;CACF;CAEA,MAAM,yBAAyB;EAC7B,IAAI,UAAU;EACd,OAAO,SAAS;GACd,MAAM,OAAO,QAAQ;GACrB,QAAQ,WAAW;GACnB,QAAQ,OAAO;GACf,IAAI,CAAC,QAAQ,iBACX,QAAQ,SAAS;GAEnB,cAAc,OAAO;GACrB,UAAU;EACZ;EACA,OAAO;EACP,OAAO;EACP,SAAS;EACT,2BAA2B,MAAM;CACnC;CAEA,MAAM,oBAAoB;EACxB,MAAM,oBAAoB;CAC5B;CAEA,MAAM,eACJ,MACA,QACA,UACG;EACH,OAAO,SAAS;EAChB,MAAM,iBAAiB,OAAO;EAC9B,YAAY;EACZ,iBAAiB;EACjB,cAAc,MAAM,QAAQ,KAAK;CACnC;CAEA,MAAM,6BAA6B;EACjC,OAAO,MAAM,WAAW,aAAa;GACnC,MAAM,SAAS;GACf,MAAM,oBAAoB,OAAO;GACjC,MAAM,oBAAoB,OAAO;GACjC,OAAO,OAAO;GACd,OAAO,WAAW;GAClB,OAAO,OAAO;GACd,cAAc,MAAM;EACtB;EACA,IAAI,CAAC,MACH,OAAO;CAEX;CAEA,MAAM,wBAAwB,WAA2B;EACvD,MAAM,oBAAoB,OAAO;EACjC,MAAM,oBAAoB,OAAO;EACjC,MAAM,iBAAiB;EACvB,MAAM,oBAAoB;EAC1B,oBAAoB,MAAM;EAC1B,qBAAqB;CACvB;CAEA,MAAM,wBACJ,QACA,YACA,UACG;EACH,IAAI,eAAe,UAAU;GAC3B,cAAc,WAAW,QAAQ,KAAK;GACtC;EACF;EACA,IAAI,eAAe,eAAe,MAAM,oBAAoB,OAAO,UAAU;GAC3E,IAAI,MACF,iBAAiB;GAEnB,YAAY;GACZ,cACE,gBACA,QACA,YAAY,OAAO,SAAS,sCAAsC,MAAM,mBAC1E;EACF;CACF;CAEA,MAAM,gBACJ,QACA,YACA,UACG;EACH,IAAI,MAAM,YAAY,OAAO,iBAC3B;EAEF,OAAO,kBAAkB;EAEzB,IAAI,CAAC,OAAO,YAAY,OAAO,UAAU,OAAO;GAC9C,qBAAqB,QAAQ,YAAY,KAAK;GAC9C;EACF;EAEA,IAAI,eAAe,aAAa;GAC9B,OAAO,SAAS;GAChB,YAAY;GACZ,iBAAiB;GACjB;EACF;EACA,IAAI,eAAe,UAAU;GAC3B,YAAY,WAAW,QAAQ,KAAK;GACpC;EACF;EAEA,OAAO,SAAS;EAChB,IAAI,2BAA2B,OAAO,UAAU;GAC9C,YACE,gBACA,QACA,YAAY,OAAO,SAAS,4BAA4B,0BAC1D;GACA;EACF;EACA,2BAA2B,OAAO;EAElC,IAAI,OAAO,SAAS,QAAQ;GAC1B,qBAAqB,MAAM;GAC3B;EACF;EACA,qBAAqB;CACvB;CAEA,MAAM,qBAAqB,aAA8C;EACvE,MAAM,UAA0B,CAAC;EACjC,MAAM,eAAe,IAAI,IAAI,OAAO,KAAK,QAAQ,CAAC;EAClD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,GAChD,QAAQ,OAAO,UAAU,SAAY,OAAO;EAE9C,KAAK,MAAM,OAAO,kBAChB,IAAI,CAAC,aAAa,IAAI,GAAG,GACvB,QAAQ,OAAO;EAGnB,OAAO;CACT;CAEA,MAAM,YAAY,WAAkC;EAClD,IAAI,MAAM,UACR,OAAO,MAAM;EAGf,MAAM,WAAW,MAAM,WAAW;EAClC,MAAM,WAAW;EACjB,MAAM,mBAAmB,OAAO;EAChC,MAAM,SAAyB;GAC7B;GACA;GACA,MAAM,OAAO;GACb,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,aAAa,OAAO,KAAK,OAAO,OAAO,CAAC,CAAC;GACzC,kBAAkB,OAAO;GACzB,QAAQ;GACR,iBAAiB;GACjB,UAAU;GACV,MAAM;EACR;EACA,IAAI,MACF,KAAK,OAAO;OAGZ,OAAO;EAET,OAAO;EACP,MAAM,qBAAqB,OAAO;EAClC,KAAK,MAAM,OAAO,OAAO,KAAK,OAAO,OAAO,GAC1C,iBAAiB,IAAI,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC,EAAG;EAG5C,MAAM,UAAiC,YAAY,UAAU;GAC3D,aAAa,QAAQ,YAAY,KAAK;EACxC;EAEA,MAAM,cAAc,mBAAmB,OAAO,OAAO;EACrD,IAAI,OAAO,QAAQ,QAAQ,2BAA2B,YACpD,IAAI;GACF,QAAQ,QAAQ,uBAAuB,aAAa,MAAM;EAC5D,SACO,OAAO;GACZ,OAAO,UAAU,KAAK;EACxB;OAGA,yBAAyB;GACvB,cAAc,QAAQ,QAAQ,UAAU,WAAW;GACnD,YAAY;GACZ;EACF,CAAC;EAEH,OAAO;CACT;CAEA,MAAM,gBAAgB;EACpB,IAAI,MAAM,UACR;EAEF,MAAM,WAAW;EACjB,iBAAiB;CACnB;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}
1
+ {"version":3,"file":"commitTracker.mjs","names":[],"sources":["../../../../../src/runtime/app/setData/commitTracker.ts"],"sourcesContent":["import type { MiniProgramAdapter, SetDataDebugInfo } from '../../types'\nimport type { PhysicalSetDataObserver, SetDataRevisionObservation } from './observation'\nimport { observePhysicalDispatch } from './observation'\nimport { cloneSnapshotValue } from './snapshot'\n\nexport type SetDataSnapshot = Record<string, unknown>\nexport type SetDataPayload = Record<string, unknown>\nexport type SetDataMode = 'diff' | 'patch'\nexport type SetDataRevisionKind = 'delta' | 'full'\nexport type SetDataAdapterSettlement = 'committed' | 'failed' | 'abandoned'\n\nexport type SetDataAdapterSettler = (\n settlement: SetDataAdapterSettlement,\n cause?: unknown,\n) => void\n\nexport interface CommitAwareSetDataAdapter extends MiniProgramAdapter {\n __wevu_dispatchSetData?: (\n payload: SetDataPayload,\n settle: SetDataAdapterSettler,\n observer?: PhysicalSetDataObserver,\n ) => void\n __wevu_reportSetDataError?: (error: Error) => void\n __wevu_disposeSetData?: () => void\n}\n\nexport interface PreparedSetDataUpdate {\n mode: SetDataMode\n kind: SetDataRevisionKind\n reason: SetDataDebugInfo['reason']\n snapshot: SetDataSnapshot\n payload: SetDataPayload\n pendingPatchKeys: number\n}\n\nexport interface SetDataCommitFailure {\n kind: 'adapter' | 'out-of-order'\n revision: number\n committedRevision: number\n mode: SetDataMode\n cause: unknown\n error: Error\n payloadKeys: number\n pendingPatchKeys: number\n}\n\nexport interface SetDataCommitState {\n preparedSnapshot: SetDataSnapshot\n dispatchedSnapshot: SetDataSnapshot\n committedSnapshot: SetDataSnapshot\n revision: number\n committedRevision: number\n failedRevision: number | undefined\n needsFullSnapshot: boolean\n commitPromise: Promise<void>\n disposed: boolean\n}\n\nexport interface SetDataCommitTracker {\n readonly state: SetDataCommitState\n dispatch: (update: PreparedSetDataUpdate) => number\n createFullPayload: (snapshot: SetDataSnapshot) => SetDataPayload\n dispose: () => void\n}\n\ntype RevisionStatus = 'dispatched' | 'succeeded' | 'failed' | 'abandoned'\n\ninterface RevisionRecord {\n revision: number\n epoch: number\n mode: SetDataMode\n kind: SetDataRevisionKind\n snapshot: SetDataSnapshot\n payloadKeys: number\n pendingPatchKeys: number\n status: RevisionStatus\n physicalSettled: boolean\n inLedger: boolean\n next: RevisionRecord | undefined\n commitPromise?: Promise<void>\n observation?: SetDataRevisionObservation\n resolveCommit?: () => void\n}\n\nconst resolvedCommitPromise = Promise.resolve()\n\nfunction isThenable(value: unknown): value is PromiseLike<unknown> {\n return Boolean(\n value\n && (typeof value === 'object' || typeof value === 'function')\n && typeof (value as PromiseLike<unknown>).then === 'function',\n )\n}\n\nfunction formatCommitFailureCause(cause: unknown): string {\n try {\n return cause instanceof Error ? cause.message : String(cause)\n }\n catch {\n return '<unprintable cause>'\n }\n}\n\nfunction createCommitError(\n kind: SetDataCommitFailure['kind'],\n record: RevisionRecord,\n cause: unknown,\n) {\n const causeMessage = formatCommitFailureCause(cause)\n const label = kind === 'adapter' ? 'adapter failure' : 'out-of-order completion'\n const error = new Error(\n `[wevu] setData commit failed (${label}, revision=${record.revision}, mode=${record.mode}, kind=${record.kind}): ${causeMessage}`,\n )\n ;(error as Error & { cause?: unknown }).cause = cause\n return error\n}\n\nexport function observeSetDataCompletion(options: {\n invoke: (callback: () => void) => unknown\n completion: 'return' | 'callback'\n settle: SetDataAdapterSettler\n observer?: PhysicalSetDataObserver\n payload?: SetDataPayload\n}): void {\n let settled = false\n let invoking = true\n let callbackCalled = false\n let observedReturn = false\n let returnIsAuthoritative = false\n let boundary: Parameters<PhysicalSetDataObserver['complete']>[0] = options.completion\n const settleOnce: SetDataAdapterSettler = (settlement, cause) => {\n if (settled) {\n return\n }\n settled = true\n options.observer?.complete(boundary)\n options.settle(settlement, cause)\n }\n const callback = () => {\n if (invoking) {\n callbackCalled = true\n return\n }\n if (returnIsAuthoritative) {\n return\n }\n if (options.completion === 'callback') {\n settleOnce('committed')\n }\n }\n\n try {\n if (options.observer && options.payload) {\n observePhysicalDispatch(options.observer, options.payload)\n }\n const result = options.invoke(callback)\n const resultIsThenable = isThenable(result)\n returnIsAuthoritative = resultIsThenable\n invoking = false\n if (options.observer && !observedReturn) {\n observedReturn = true\n options.observer.returned(Date.now())\n }\n if (resultIsThenable) {\n boundary = 'promise'\n result.then(\n () => settleOnce('committed'),\n cause => settleOnce('failed', cause),\n )\n return\n }\n if (options.completion === 'return' || callbackCalled) {\n settleOnce('committed')\n }\n }\n catch (cause) {\n boundary = 'throw'\n invoking = false\n if (options.observer && !observedReturn) {\n observedReturn = true\n options.observer.returned(Date.now())\n }\n settleOnce('failed', cause)\n }\n}\n\nexport function createSetDataCommitTracker(options: {\n initialSnapshot?: SetDataSnapshot\n adapter: CommitAwareSetDataAdapter\n onFailure: (failure: SetDataCommitFailure) => void\n observe?: (update: PreparedSetDataUpdate, revision: number) => SetDataRevisionObservation | undefined\n}): SetDataCommitTracker {\n const initialSnapshot = options.initialSnapshot ? cloneSnapshotValue(options.initialSnapshot) : {}\n const knownHostTopKeys = new Set(Object.keys(initialSnapshot))\n let epoch = 0\n let highestCompletedRevision = 0\n let head: RevisionRecord | undefined\n let tail: RevisionRecord | undefined\n\n function ensureCommitBarrier(record: RevisionRecord) {\n if (!record.inLedger) {\n return resolvedCommitPromise\n }\n if (!record.commitPromise) {\n record.commitPromise = new Promise<void>((resolve) => {\n record.resolveCommit = resolve\n })\n }\n return record.commitPromise\n }\n\n const state: SetDataCommitState = {\n preparedSnapshot: initialSnapshot,\n dispatchedSnapshot: initialSnapshot,\n committedSnapshot: initialSnapshot,\n revision: 0,\n committedRevision: 0,\n failedRevision: undefined,\n needsFullSnapshot: false,\n get commitPromise() {\n return tail ? ensureCommitBarrier(tail) : resolvedCommitPromise\n },\n disposed: false,\n }\n\n const reportFailure = (\n kind: SetDataCommitFailure['kind'],\n record: RevisionRecord,\n cause: unknown,\n ) => {\n const error = createCommitError(kind, record, cause)\n try {\n options.onFailure({\n kind,\n revision: record.revision,\n committedRevision: state.committedRevision,\n mode: record.mode,\n cause,\n error,\n payloadKeys: record.payloadKeys,\n pendingPatchKeys: record.pendingPatchKeys,\n })\n }\n catch {\n // 错误上报不得反向破坏提交状态机。\n }\n }\n\n const resolveRecord = (record: RevisionRecord) => {\n record.resolveCommit?.()\n record.resolveCommit = undefined\n }\n\n const removePrefixThrough = (last: RevisionRecord) => {\n let current = head\n while (current) {\n const next = current.next\n current.inLedger = false\n current.next = undefined\n resolveRecord(current)\n if (current === last) {\n head = next\n if (!head) {\n tail = undefined\n }\n return\n }\n current = next\n }\n }\n\n const invalidateLedger = () => {\n let abandonedObservations: SetDataRevisionObservation[] | undefined\n const result = state.disposed ? 'disposed' : 'abandoned'\n let current = head\n while (current) {\n const next = current.next\n current.inLedger = false\n current.next = undefined\n if (!current.physicalSettled) {\n current.status = 'abandoned'\n if (current.observation) {\n (abandonedObservations ??= []).push(current.observation)\n }\n }\n resolveRecord(current)\n current = next\n }\n head = undefined\n tail = undefined\n epoch += 1\n highestCompletedRevision = state.committedRevision\n // 先清空旧账本,再交付诊断,避免回调重入时误删新 revision。\n abandonedObservations?.forEach(observation => observation.finish(result))\n }\n\n const armRecovery = () => {\n state.needsFullSnapshot = true\n }\n\n const failLineage = (\n kind: SetDataCommitFailure['kind'],\n record: RevisionRecord,\n cause: unknown,\n ) => {\n record.status = 'failed'\n state.failedRevision = record.revision\n armRecovery()\n invalidateLedger()\n reportFailure(kind, record, cause)\n }\n\n const drainSucceededPrefix = () => {\n while (head?.status === 'succeeded') {\n const record = head\n state.committedSnapshot = record.snapshot\n state.committedRevision = record.revision\n head = record.next\n record.inLedger = false\n record.next = undefined\n resolveRecord(record)\n }\n if (!head) {\n tail = undefined\n }\n }\n\n const commitFullCheckpoint = (record: RevisionRecord) => {\n state.committedSnapshot = record.snapshot\n state.committedRevision = record.revision\n state.failedRevision = undefined\n state.needsFullSnapshot = false\n removePrefixThrough(record)\n drainSucceededPrefix()\n }\n\n const handleLateSettlement = (\n record: RevisionRecord,\n settlement: SetDataAdapterSettlement,\n cause: unknown,\n ) => {\n if (settlement === 'failed') {\n reportFailure('adapter', record, cause)\n return\n }\n if (settlement === 'committed' && state.committedRevision > record.revision) {\n if (head) {\n invalidateLedger()\n }\n armRecovery()\n reportFailure(\n 'out-of-order',\n record,\n `revision ${record.revision} completed after committed revision ${state.committedRevision}`,\n )\n }\n }\n\n const applySettlement = (\n record: RevisionRecord,\n settlement: SetDataAdapterSettlement,\n cause?: unknown,\n ) => {\n if (state.disposed || record.physicalSettled) {\n return\n }\n record.physicalSettled = true\n\n if (!record.inLedger || record.epoch !== epoch) {\n handleLateSettlement(record, settlement, cause)\n return\n }\n\n if (settlement === 'abandoned') {\n record.status = 'abandoned'\n armRecovery()\n invalidateLedger()\n return\n }\n if (settlement === 'failed') {\n failLineage('adapter', record, cause)\n return\n }\n\n record.status = 'succeeded'\n if (highestCompletedRevision > record.revision) {\n failLineage(\n 'out-of-order',\n record,\n `revision ${record.revision} completed after revision ${highestCompletedRevision}`,\n )\n return\n }\n highestCompletedRevision = record.revision\n\n if (record.kind === 'full') {\n commitFullCheckpoint(record)\n return\n }\n drainSucceededPrefix()\n }\n\n const settleRecord = (record: RevisionRecord, settlement: SetDataAdapterSettlement, cause?: unknown) => {\n if (state.disposed || record.physicalSettled) {\n return\n }\n if (!record.observation) {\n applySettlement(record, settlement, cause)\n return\n }\n const late = !record.inLedger || record.epoch !== epoch\n const outOfOrder = settlement === 'committed' && (late\n ? state.committedRevision > record.revision\n : highestCompletedRevision > record.revision)\n applySettlement(record, settlement, cause)\n record.observation?.finish(outOfOrder\n ? 'out-of-order'\n : late\n ? settlement === 'failed' ? 'late-failed' : settlement === 'committed' ? 'late-committed' : 'abandoned'\n : settlement)\n }\n\n const createFullPayload = (snapshot: SetDataSnapshot): SetDataPayload => {\n const payload: SetDataPayload = {}\n const snapshotKeys = new Set(Object.keys(snapshot))\n for (const [key, value] of Object.entries(snapshot)) {\n payload[key] = value === undefined ? null : value\n }\n for (const key of knownHostTopKeys) {\n if (!snapshotKeys.has(key)) {\n payload[key] = null\n }\n }\n return payload\n }\n\n const dispatch = (update: PreparedSetDataUpdate) => {\n if (state.disposed) {\n return state.revision\n }\n\n const revision = state.revision + 1\n state.revision = revision\n state.preparedSnapshot = update.snapshot\n const record: RevisionRecord = {\n revision,\n epoch,\n mode: update.mode,\n kind: update.kind,\n snapshot: update.snapshot,\n payloadKeys: Object.keys(update.payload).length,\n pendingPatchKeys: update.pendingPatchKeys,\n status: 'dispatched',\n physicalSettled: false,\n inLedger: true,\n next: undefined,\n }\n if (tail) {\n tail.next = record\n }\n else {\n head = record\n }\n tail = record\n state.dispatchedSnapshot = update.snapshot\n for (const key of Object.keys(update.payload)) {\n knownHostTopKeys.add(key.split('.', 1)[0]!)\n }\n\n record.observation = options.observe?.(update, revision)\n const settle: SetDataAdapterSettler = (settlement, cause) => {\n settleRecord(record, settlement, cause)\n }\n // 宿主会保留对象并在后续路径更新时原地修改,载荷不能与序列化缓存及快照共享引用。\n const hostPayload = cloneSnapshotValue(update.payload)\n if (typeof options.adapter.__wevu_dispatchSetData === 'function') {\n try {\n options.adapter.__wevu_dispatchSetData(hostPayload, settle, record.observation?.physical)\n }\n catch (cause) {\n settle('failed', cause)\n }\n }\n else {\n observeSetDataCompletion({\n invoke: () => options.adapter.setData?.(hostPayload),\n completion: 'return',\n settle,\n payload: hostPayload,\n observer: options.adapter.setData ? record.observation?.physical : undefined,\n })\n }\n return revision\n }\n\n const dispose = () => {\n if (state.disposed) {\n return\n }\n state.disposed = true\n invalidateLedger()\n }\n\n return {\n state,\n dispatch,\n createFullPayload,\n dispose,\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ //#region src/runtime/app/setData/observation.ts
2
+ let nextObserverId = 0;
3
+ let nextDispatchId = 0;
4
+ function duration(start, end) {
5
+ return start !== null && end >= start ? end - start : null;
6
+ }
7
+ function payloadBytes(payload) {
8
+ try {
9
+ const json = JSON.stringify(payload);
10
+ let bytes = 0;
11
+ for (let index = 0; index < json.length; index++) {
12
+ const code = json.charCodeAt(index);
13
+ if (code < 128) bytes += 1;
14
+ else if (code < 2048) bytes += 2;
15
+ else if (code >= 55296 && code <= 56319 && json.charCodeAt(index + 1) >= 56320 && json.charCodeAt(index + 1) <= 57343) {
16
+ bytes += 4;
17
+ index += 1;
18
+ } else bytes += 3;
19
+ }
20
+ return bytes;
21
+ } catch {
22
+ return null;
23
+ }
24
+ }
25
+ function observePhysicalDispatch(observer, payload) {
26
+ const bytes = payloadBytes(payload);
27
+ observer.dispatch({
28
+ id: ++nextDispatchId,
29
+ startedAt: Date.now(),
30
+ payloadBytes: bytes,
31
+ returnedAt: null,
32
+ durationMs: null
33
+ });
34
+ }
35
+ function createSetDataObservation(options) {
36
+ const observerId = ++nextObserverId;
37
+ let prepareStartedAt = null;
38
+ return {
39
+ prepare() {
40
+ prepareStartedAt = Date.now();
41
+ },
42
+ revision(update, revision) {
43
+ const startedAt = prepareStartedAt;
44
+ prepareStartedAt = null;
45
+ if (options.debugWhen === "fallback" && (update.reason === "patch" || update.reason === "diff")) return;
46
+ if (options.debugSampleRate <= 0 || options.debugSampleRate < 1 && Math.random() >= options.debugSampleRate) return;
47
+ const preparedAt = Date.now();
48
+ let dispatch = null;
49
+ let completion = "unknown";
50
+ const base = {
51
+ mode: update.mode,
52
+ reason: update.reason,
53
+ pendingPatchKeys: update.pendingPatchKeys,
54
+ payloadKeys: Object.keys(update.payload).length,
55
+ revision,
56
+ targetLabel: options.targetLabel
57
+ };
58
+ const emit = (name, result, settledAt = null) => {
59
+ try {
60
+ options.debug({
61
+ ...base,
62
+ committedRevision: options.committedRevision(),
63
+ phase: {
64
+ version: 1,
65
+ observerId,
66
+ name,
67
+ result,
68
+ completion,
69
+ prepareStartedAt: startedAt,
70
+ preparedAt,
71
+ prepareDurationMs: duration(startedAt, preparedAt),
72
+ settledAt,
73
+ commitDurationMs: settledAt === null ? null : duration(dispatch?.startedAt ?? null, settledAt),
74
+ visibleAt: null,
75
+ dispatch: dispatch ? { ...dispatch } : null
76
+ }
77
+ });
78
+ } catch {}
79
+ };
80
+ emit("prepare", "prepared");
81
+ return {
82
+ physical: {
83
+ dispatch(info) {
84
+ dispatch = info;
85
+ },
86
+ returned(returnedAt) {
87
+ if (!dispatch) return;
88
+ dispatch = {
89
+ ...dispatch,
90
+ returnedAt,
91
+ durationMs: duration(dispatch.startedAt, returnedAt)
92
+ };
93
+ emit("dispatch", "pending");
94
+ },
95
+ complete(boundary) {
96
+ if (dispatch || boundary === "throw") completion = boundary;
97
+ }
98
+ },
99
+ finish(result) {
100
+ emit("commit", result, Date.now());
101
+ }
102
+ };
103
+ }
104
+ };
105
+ }
106
+
107
+ //#endregion
108
+ export { createSetDataObservation, observePhysicalDispatch };
109
+ //# sourceMappingURL=observation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation.mjs","names":[],"sources":["../../../../../src/runtime/app/setData/observation.ts"],"sourcesContent":["import type { SetDataDebugInfo } from '../../types'\nimport type { PreparedSetDataUpdate } from './commitTracker'\n\ntype Phase = NonNullable<SetDataDebugInfo['phase']>\nexport type SetDataCompletionBoundary = Phase['completion']\n\nexport interface PhysicalSetDataObserver {\n dispatch: (dispatch: NonNullable<Phase['dispatch']>) => void\n returned: (returnedAt: number) => void\n complete: (boundary: SetDataCompletionBoundary) => void\n}\n\nexport interface SetDataRevisionObservation {\n physical: PhysicalSetDataObserver\n finish: (result: Phase['result']) => void\n}\n\nlet nextObserverId = 0\nlet nextDispatchId = 0\n\nfunction duration(start: number | null, end: number): number | null {\n return start !== null && end >= start ? end - start : null\n}\n\nfunction payloadBytes(payload: Record<string, unknown>): number | null {\n try {\n const json = JSON.stringify(payload)\n let bytes = 0\n for (let index = 0; index < json.length; index++) {\n const code = json.charCodeAt(index)\n if (code < 0x80) {\n bytes += 1\n }\n else if (code < 0x800) {\n bytes += 2\n }\n else if (code >= 0xD800 && code <= 0xDBFF && json.charCodeAt(index + 1) >= 0xDC00 && json.charCodeAt(index + 1) <= 0xDFFF) {\n bytes += 4\n index += 1\n }\n else {\n bytes += 3\n }\n }\n return bytes\n }\n catch {\n return null\n }\n}\n\nexport function observePhysicalDispatch(observer: PhysicalSetDataObserver, payload: Record<string, unknown>) {\n // 只在观测启用时序列化;耗时从字节测量之后开始,避免将测量成本计入宿主提交。\n const bytes = payloadBytes(payload)\n observer.dispatch({ id: ++nextDispatchId, startedAt: Date.now(), payloadBytes: bytes, returnedAt: null, durationMs: null })\n}\n\nexport function createSetDataObservation(options: {\n debug: (info: SetDataDebugInfo) => void\n debugWhen: 'fallback' | 'always'\n debugSampleRate: number\n targetLabel?: string\n committedRevision: () => number\n}) {\n const observerId = ++nextObserverId\n let prepareStartedAt: number | null = null\n return {\n prepare() {\n prepareStartedAt = Date.now()\n },\n revision(update: PreparedSetDataUpdate, revision: number): SetDataRevisionObservation | undefined {\n const startedAt = prepareStartedAt\n prepareStartedAt = null\n if (options.debugWhen === 'fallback' && (update.reason === 'patch' || update.reason === 'diff')) {\n return\n }\n if (options.debugSampleRate <= 0 || (options.debugSampleRate < 1 && Math.random() >= options.debugSampleRate)) {\n return\n }\n const preparedAt = Date.now()\n let dispatch: Phase['dispatch'] = null\n let completion: SetDataCompletionBoundary = 'unknown'\n const base = {\n mode: update.mode,\n reason: update.reason,\n pendingPatchKeys: update.pendingPatchKeys,\n payloadKeys: Object.keys(update.payload).length,\n revision,\n targetLabel: options.targetLabel,\n }\n const emit = (name: Phase['name'], result: Phase['result'], settledAt: number | null = null) => {\n try {\n options.debug({\n ...base,\n committedRevision: options.committedRevision(),\n phase: {\n version: 1,\n observerId,\n name,\n result,\n completion,\n prepareStartedAt: startedAt,\n preparedAt,\n prepareDurationMs: duration(startedAt, preparedAt),\n settledAt,\n commitDurationMs: settledAt === null ? null : duration(dispatch?.startedAt ?? null, settledAt),\n visibleAt: null,\n dispatch: dispatch ? { ...dispatch } : null,\n },\n })\n }\n catch {\n // 消费者诊断异常不能影响调度或宿主提交。\n }\n }\n emit('prepare', 'prepared')\n return {\n physical: {\n dispatch(info) {\n dispatch = info\n },\n returned(returnedAt) {\n if (!dispatch) {\n return\n }\n dispatch = { ...dispatch, returnedAt, durationMs: duration(dispatch.startedAt, returnedAt) }\n emit('dispatch', 'pending')\n },\n complete(boundary) {\n if (dispatch || boundary === 'throw') {\n completion = boundary\n }\n },\n },\n finish(result) { emit('commit', result, Date.now()) },\n }\n },\n }\n}\n"],"mappings":";AAiBA,IAAI,iBAAiB;AACrB,IAAI,iBAAiB;AAErB,SAAS,SAAS,OAAsB,KAA4B;CAClE,OAAO,UAAU,QAAQ,OAAO,QAAQ,MAAM,QAAQ;AACxD;AAEA,SAAS,aAAa,SAAiD;CACrE,IAAI;EACF,MAAM,OAAO,KAAK,UAAU,OAAO;EACnC,IAAI,QAAQ;EACZ,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;GAChD,MAAM,OAAO,KAAK,WAAW,KAAK;GAClC,IAAI,OAAO,KACT,SAAS;QAEN,IAAI,OAAO,MACd,SAAS;QAEN,IAAI,QAAQ,SAAU,QAAQ,SAAU,KAAK,WAAW,QAAQ,CAAC,KAAK,SAAU,KAAK,WAAW,QAAQ,CAAC,KAAK,OAAQ;IACzH,SAAS;IACT,SAAS;GACX,OAEE,SAAS;EAEb;EACA,OAAO;CACT,QACM;EACJ,OAAO;CACT;AACF;AAEA,SAAgB,wBAAwB,UAAmC,SAAkC;CAE3G,MAAM,QAAQ,aAAa,OAAO;CAClC,SAAS,SAAS;EAAE,IAAI,EAAE;EAAgB,WAAW,KAAK,IAAI;EAAG,cAAc;EAAO,YAAY;EAAM,YAAY;CAAK,CAAC;AAC5H;AAEA,SAAgB,yBAAyB,SAMtC;CACD,MAAM,aAAa,EAAE;CACrB,IAAI,mBAAkC;CACtC,OAAO;EACL,UAAU;GACR,mBAAmB,KAAK,IAAI;EAC9B;EACA,SAAS,QAA+B,UAA0D;GAChG,MAAM,YAAY;GAClB,mBAAmB;GACnB,IAAI,QAAQ,cAAc,eAAe,OAAO,WAAW,WAAW,OAAO,WAAW,SACtF;GAEF,IAAI,QAAQ,mBAAmB,KAAM,QAAQ,kBAAkB,KAAK,KAAK,OAAO,KAAK,QAAQ,iBAC3F;GAEF,MAAM,aAAa,KAAK,IAAI;GAC5B,IAAI,WAA8B;GAClC,IAAI,aAAwC;GAC5C,MAAM,OAAO;IACX,MAAM,OAAO;IACb,QAAQ,OAAO;IACf,kBAAkB,OAAO;IACzB,aAAa,OAAO,KAAK,OAAO,OAAO,CAAC,CAAC;IACzC;IACA,aAAa,QAAQ;GACvB;GACA,MAAM,QAAQ,MAAqB,QAAyB,YAA2B,SAAS;IAC9F,IAAI;KACF,QAAQ,MAAM;MACZ,GAAG;MACH,mBAAmB,QAAQ,kBAAkB;MAC7C,OAAO;OACL,SAAS;OACT;OACA;OACA;OACA;OACA,kBAAkB;OAClB;OACA,mBAAmB,SAAS,WAAW,UAAU;OACjD;OACA,kBAAkB,cAAc,OAAO,OAAO,SAAS,UAAU,aAAa,MAAM,SAAS;OAC7F,WAAW;OACX,UAAU,WAAW,EAAE,GAAG,SAAS,IAAI;MACzC;KACF,CAAC;IACH,QACM,CAEN;GACF;GACA,KAAK,WAAW,UAAU;GAC1B,OAAO;IACL,UAAU;KACR,SAAS,MAAM;MACb,WAAW;KACb;KACA,SAAS,YAAY;MACnB,IAAI,CAAC,UACH;MAEF,WAAW;OAAE,GAAG;OAAU;OAAY,YAAY,SAAS,SAAS,WAAW,UAAU;MAAE;MAC3F,KAAK,YAAY,SAAS;KAC5B;KACA,SAAS,UAAU;MACjB,IAAI,YAAY,aAAa,SAC3B,aAAa;KAEjB;IACF;IACA,OAAO,QAAQ;KAAE,KAAK,UAAU,QAAQ,KAAK,IAAI,CAAC;IAAE;GACtD;EACF;CACF;AACF"}