@graphrefly/ts 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -0
- package/dist/actions-types-CSC3NMDl.d.ts +657 -0
- package/dist/actions-types-wl9Mgkmr.d.cts +657 -0
- package/dist/adapters/index.cjs +5219 -2974
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +204 -192
- package/dist/adapters/index.d.ts +204 -192
- package/dist/adapters/index.js +3685 -1833
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/nestjs/microservices.cjs +841 -0
- package/dist/adapters/nestjs/microservices.cjs.map +1 -0
- package/dist/adapters/nestjs/microservices.d.cts +45 -0
- package/dist/adapters/nestjs/microservices.d.ts +45 -0
- package/dist/adapters/nestjs/microservices.js +206 -0
- package/dist/adapters/nestjs/microservices.js.map +1 -0
- package/dist/adapters/nestjs/native.cjs +1391 -0
- package/dist/adapters/nestjs/native.cjs.map +1 -0
- package/dist/adapters/nestjs/native.d.cts +111 -0
- package/dist/adapters/nestjs/native.d.ts +111 -0
- package/dist/adapters/nestjs/native.js +577 -0
- package/dist/adapters/nestjs/native.js.map +1 -0
- package/dist/adapters/nestjs/websockets.cjs +924 -0
- package/dist/adapters/nestjs/websockets.cjs.map +1 -0
- package/dist/adapters/nestjs/websockets.d.cts +47 -0
- package/dist/adapters/nestjs/websockets.d.ts +47 -0
- package/dist/adapters/nestjs/websockets.js +286 -0
- package/dist/adapters/nestjs/websockets.js.map +1 -0
- package/dist/adapters/nestjs.cjs +1085 -0
- package/dist/adapters/nestjs.cjs.map +1 -0
- package/dist/adapters/nestjs.d.cts +385 -0
- package/dist/adapters/nestjs.d.ts +385 -0
- package/dist/adapters/nestjs.js +112 -0
- package/dist/adapters/nestjs.js.map +1 -0
- package/dist/adapters/observe-storage.d.cts +4 -4
- package/dist/adapters/observe-storage.d.ts +4 -4
- package/dist/adapters/observe-storage.js +5 -4
- package/dist/adapters/observe-storage.js.map +1 -1
- package/dist/adapters/react.cjs +166 -0
- package/dist/adapters/react.cjs.map +1 -0
- package/dist/adapters/react.d.cts +31 -0
- package/dist/adapters/react.d.ts +31 -0
- package/dist/adapters/react.js +51 -0
- package/dist/adapters/react.js.map +1 -0
- package/dist/adapters/solid.cjs +157 -0
- package/dist/adapters/solid.cjs.map +1 -0
- package/dist/adapters/solid.d.cts +26 -0
- package/dist/adapters/solid.d.ts +26 -0
- package/dist/adapters/solid.js +48 -0
- package/dist/adapters/solid.js.map +1 -0
- package/dist/adapters/svelte.cjs +148 -0
- package/dist/adapters/svelte.cjs.map +1 -0
- package/dist/adapters/svelte.d.cts +31 -0
- package/dist/adapters/svelte.d.ts +31 -0
- package/dist/adapters/svelte.js +46 -0
- package/dist/adapters/svelte.js.map +1 -0
- package/dist/adapters/vue.cjs +155 -0
- package/dist/adapters/vue.cjs.map +1 -0
- package/dist/adapters/vue.d.cts +26 -0
- package/dist/adapters/vue.d.ts +26 -0
- package/dist/adapters/vue.js +46 -0
- package/dist/adapters/vue.js.map +1 -0
- package/dist/agent-runtime-types-core-CaXfKNtY.d.cts +406 -0
- package/dist/agent-runtime-types-core-hU299uIC.d.ts +406 -0
- package/dist/agent-runtime-types-tool-BEpSINol.d.ts +695 -0
- package/dist/agent-runtime-types-tool-DninPEzk.d.cts +695 -0
- package/dist/agentic-memory-retention-BmGX368S.d.ts +14 -0
- package/dist/agentic-memory-retention-Ih1qhX9Z.d.cts +14 -0
- package/dist/agentic-memory-types-CVSUS6XR.d.ts +473 -0
- package/dist/agentic-memory-types-FnnYlVUs.d.cts +473 -0
- package/dist/capability-admission-BW2CziT6.d.ts +102 -0
- package/dist/capability-admission-lwSecxXs.d.cts +102 -0
- package/dist/chunk-2KUAG2GZ.js +9693 -0
- package/dist/chunk-2KUAG2GZ.js.map +1 -0
- package/dist/chunk-2NJP6GO4.js +1320 -0
- package/dist/chunk-2NJP6GO4.js.map +1 -0
- package/dist/{chunk-GDL26N2T.js → chunk-3KN7NJDR.js} +2 -2
- package/dist/{chunk-COHO25CZ.js → chunk-4NWSNI4K.js} +2232 -1672
- package/dist/chunk-4NWSNI4K.js.map +1 -0
- package/dist/{chunk-Z2ANQ6JW.js → chunk-4Q77MMJY.js} +2 -2
- package/dist/chunk-6E76H4OU.js +132 -0
- package/dist/chunk-6E76H4OU.js.map +1 -0
- package/dist/chunk-7GOTIIQ7.js +819 -0
- package/dist/chunk-7GOTIIQ7.js.map +1 -0
- package/dist/{chunk-D6BG7U6A.js → chunk-7HZRJMN6.js} +3 -3
- package/dist/{chunk-SCRFRCGR.js → chunk-BSQGE5PS.js} +1 -1
- package/dist/{chunk-PKVBHGBM.js → chunk-CJIFGJQG.js} +7 -7
- package/dist/{chunk-G4M3NHRJ.js → chunk-CX6B6PO2.js} +93 -10
- package/dist/chunk-CX6B6PO2.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/{chunk-JIMUDQN3.js → chunk-E4QCH32M.js} +449 -447
- package/dist/chunk-E4QCH32M.js.map +1 -0
- package/dist/{chunk-RIIOUTGM.js → chunk-ECURQ3HD.js} +19 -129
- package/dist/chunk-ECURQ3HD.js.map +1 -0
- package/dist/{chunk-2ILL7HQI.js → chunk-EOKT4QFF.js} +134 -128
- package/dist/chunk-EOKT4QFF.js.map +1 -0
- package/dist/{chunk-K3FXTC3I.js → chunk-HJACH5PU.js} +3 -3
- package/dist/{chunk-GTPCOEOZ.js → chunk-IDMLXLLG.js} +3 -3
- package/dist/{chunk-DKP56CSW.js → chunk-JKAYLDQV.js} +2 -2
- package/dist/{chunk-4VLAQHZI.js → chunk-K7FB3JTD.js} +17 -1
- package/dist/chunk-K7FB3JTD.js.map +1 -0
- package/dist/chunk-L6LDXRWE.js +219 -0
- package/dist/chunk-L6LDXRWE.js.map +1 -0
- package/dist/chunk-M7J6Z4IJ.js +1930 -0
- package/dist/chunk-M7J6Z4IJ.js.map +1 -0
- package/dist/chunk-MQEQMS7B.js +1009 -0
- package/dist/chunk-MQEQMS7B.js.map +1 -0
- package/dist/chunk-MTELVIYR.js +1421 -0
- package/dist/chunk-MTELVIYR.js.map +1 -0
- package/dist/chunk-PVC7WDKI.js +885 -0
- package/dist/chunk-PVC7WDKI.js.map +1 -0
- package/dist/chunk-RAHNUYA5.js +368 -0
- package/dist/chunk-RAHNUYA5.js.map +1 -0
- package/dist/{chunk-DK554R7P.js → chunk-S6HXABGL.js} +2 -1
- package/dist/chunk-S6HXABGL.js.map +1 -0
- package/dist/{chunk-I3IHOHCJ.js → chunk-SHZDP2MQ.js} +1181 -1001
- package/dist/chunk-SHZDP2MQ.js.map +1 -0
- package/dist/{chunk-Y3ZLRGHC.js → chunk-SIDJO2T4.js} +16 -16
- package/dist/chunk-STXRMPW4.js +4131 -0
- package/dist/chunk-STXRMPW4.js.map +1 -0
- package/dist/{chunk-JR4IKCR2.js → chunk-TPND5MJS.js} +5 -5
- package/dist/chunk-TQPCAIQI.js +612 -0
- package/dist/chunk-TQPCAIQI.js.map +1 -0
- package/dist/chunk-UT3MHJCW.js +49 -0
- package/dist/chunk-UT3MHJCW.js.map +1 -0
- package/dist/{chunk-TEW47IVR.js → chunk-VPEFSDME.js} +2 -2
- package/dist/{chunk-SWTLEQL6.js → chunk-WQIA3GFB.js} +2 -2
- package/dist/chunk-WQIA3GFB.js.map +1 -0
- package/dist/{chunk-DJC4CHLQ.js → chunk-YDWBXXQZ.js} +5 -5
- package/dist/{chunk-6PHB5CJS.js → chunk-ZLFRB6FI.js} +2 -2
- package/dist/composition/index.cjs +1256 -1059
- package/dist/composition/index.cjs.map +1 -1
- package/dist/composition/index.d.cts +4 -4
- package/dist/composition/index.d.ts +4 -4
- package/dist/composition/index.js +7 -6
- package/dist/core/index.cjs +1218 -1021
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +5 -4
- package/dist/cqrs/index.cjs.map +1 -1
- package/dist/cqrs/index.d.cts +4 -4
- package/dist/cqrs/index.d.ts +4 -4
- package/dist/cqrs/index.js +3 -2
- package/dist/cqrs/index.js.map +1 -1
- package/dist/cqrs/messaging.cjs +312 -0
- package/dist/cqrs/messaging.cjs.map +1 -0
- package/dist/cqrs/messaging.d.cts +57 -0
- package/dist/cqrs/messaging.d.ts +57 -0
- package/dist/cqrs/messaging.js +274 -0
- package/dist/cqrs/messaging.js.map +1 -0
- package/dist/cqrs/work-queue.cjs +329 -0
- package/dist/cqrs/work-queue.cjs.map +1 -0
- package/dist/cqrs/work-queue.d.cts +90 -0
- package/dist/cqrs/work-queue.d.ts +90 -0
- package/dist/cqrs/work-queue.js +292 -0
- package/dist/cqrs/work-queue.js.map +1 -0
- package/dist/data/index.cjs +19 -0
- package/dist/data/index.cjs.map +1 -0
- package/dist/data/index.d.cts +36 -0
- package/dist/data/index.d.ts +36 -0
- package/dist/data/index.js +1 -0
- package/dist/data/index.js.map +1 -0
- package/dist/data-structures/index.cjs +1252 -1052
- package/dist/data-structures/index.cjs.map +1 -1
- package/dist/data-structures/index.d.cts +9 -8
- package/dist/data-structures/index.d.ts +9 -8
- package/dist/data-structures/index.js +9 -7
- package/dist/{describe-BZb7AS2y.d.ts → describe-B_A5fbXH.d.ts} +1 -1
- package/dist/{describe-Ciu8SUnN.d.cts → describe-CQRrkv-Q.d.cts} +1 -1
- package/dist/executors/tool-provider-adapters.cjs +3091 -0
- package/dist/executors/tool-provider-adapters.cjs.map +1 -0
- package/dist/executors/tool-provider-adapters.d.cts +174 -0
- package/dist/executors/tool-provider-adapters.d.ts +174 -0
- package/dist/executors/tool-provider-adapters.js +1336 -0
- package/dist/executors/tool-provider-adapters.js.map +1 -0
- package/dist/executors/tool-provider-runtime.cjs +5178 -0
- package/dist/executors/tool-provider-runtime.cjs.map +1 -0
- package/dist/executors/tool-provider-runtime.d.cts +17 -0
- package/dist/executors/tool-provider-runtime.d.ts +17 -0
- package/dist/executors/tool-provider-runtime.js +15 -0
- package/dist/executors/tool-provider-runtime.js.map +1 -0
- package/dist/executors/tool-provider.cjs +6392 -0
- package/dist/executors/tool-provider.cjs.map +1 -0
- package/dist/executors/tool-provider.d.cts +60 -0
- package/dist/executors/tool-provider.d.ts +60 -0
- package/dist/executors/tool-provider.js +89 -0
- package/dist/executors/tool-provider.js.map +1 -0
- package/dist/executors/work-queue.cjs +342 -0
- package/dist/executors/work-queue.cjs.map +1 -0
- package/dist/executors/work-queue.d.cts +90 -0
- package/dist/executors/work-queue.d.ts +90 -0
- package/dist/executors/work-queue.js +306 -0
- package/dist/executors/work-queue.js.map +1 -0
- package/dist/graph/index.cjs +1536 -1324
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +10 -9
- package/dist/graph/index.d.ts +10 -9
- package/dist/graph/index.js +22 -20
- package/dist/{graph-s23RbbFO.d.cts → graph-CWK3HLPB.d.cts} +134 -132
- package/dist/{graph-DfdF9zy4.d.ts → graph-ho5sotHP.d.ts} +134 -132
- package/dist/{index-SnzZu3x7.d.ts → index-CQWcE0Dw.d.ts} +18 -4
- package/dist/{index-CAEmLCYF.d.cts → index-DHA1i67c.d.cts} +18 -4
- package/dist/index.cjs +3331 -3020
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -10
- package/dist/index.d.ts +14 -10
- package/dist/index.js +114 -108
- package/dist/inspection/boundary.cjs +98 -0
- package/dist/inspection/boundary.cjs.map +1 -0
- package/dist/inspection/boundary.d.cts +61 -0
- package/dist/inspection/boundary.d.ts +61 -0
- package/dist/inspection/boundary.js +75 -0
- package/dist/inspection/boundary.js.map +1 -0
- package/dist/measurements-C0mAvWU1.d.cts +164 -0
- package/dist/measurements-OMpCeBwh.d.ts +164 -0
- package/dist/{messages-BZqrGGm1.d.ts → messages-CAzUPPJM.d.cts} +10 -5
- package/dist/{messages-BZqrGGm1.d.cts → messages-CAzUPPJM.d.ts} +10 -5
- package/dist/messaging/index.cjs +756 -619
- package/dist/messaging/index.cjs.map +1 -1
- package/dist/messaging/index.d.cts +17 -226
- package/dist/messaging/index.d.ts +17 -226
- package/dist/messaging/index.js +19 -749
- package/dist/messaging/index.js.map +1 -1
- package/dist/operators/index.cjs +1256 -1059
- package/dist/operators/index.cjs.map +1 -1
- package/dist/operators/index.d.cts +6 -6
- package/dist/operators/index.d.ts +6 -6
- package/dist/operators/index.js +9 -8
- package/dist/orchestration/index.cjs +8664 -2617
- package/dist/orchestration/index.cjs.map +1 -1
- package/dist/orchestration/index.d.cts +171 -221
- package/dist/orchestration/index.d.ts +171 -221
- package/dist/orchestration/index.js +74 -982
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/messaging.cjs +314 -0
- package/dist/orchestration/messaging.cjs.map +1 -0
- package/dist/orchestration/messaging.d.cts +56 -0
- package/dist/orchestration/messaging.d.ts +56 -0
- package/dist/orchestration/messaging.js +276 -0
- package/dist/orchestration/messaging.js.map +1 -0
- package/dist/orchestration/work-queue.cjs +1500 -0
- package/dist/orchestration/work-queue.cjs.map +1 -0
- package/dist/orchestration/work-queue.d.cts +196 -0
- package/dist/orchestration/work-queue.d.ts +196 -0
- package/dist/orchestration/work-queue.js +1289 -0
- package/dist/orchestration/work-queue.js.map +1 -0
- package/dist/patterns/event-flow.cjs +433 -0
- package/dist/patterns/event-flow.cjs.map +1 -0
- package/dist/patterns/event-flow.d.cts +115 -0
- package/dist/patterns/event-flow.d.ts +115 -0
- package/dist/patterns/event-flow.js +14 -0
- package/dist/patterns/event-flow.js.map +1 -0
- package/dist/patterns/index.cjs +748 -355
- package/dist/patterns/index.cjs.map +1 -1
- package/dist/patterns/index.d.cts +9 -5
- package/dist/patterns/index.d.ts +9 -5
- package/dist/patterns/index.js +13 -4
- package/dist/process-types-C9uMYz3i.d.ts +200 -0
- package/dist/process-types-h3uRlzDc.d.cts +200 -0
- package/dist/{reactive-collection-BxBqtIOE.d.cts → reactive-collection-B9R0Bl1P.d.cts} +11 -41
- package/dist/{reactive-collection-Cb1II1Fi.d.ts → reactive-collection-BXFrH0U2.d.ts} +11 -41
- package/dist/{reactive-collection-storage-D-KmjE0J.d.cts → reactive-collection-storage-BLGv8Xp8.d.cts} +5 -5
- package/dist/{reactive-collection-storage-BNiEc-Gd.d.ts → reactive-collection-storage-a4zD3665.d.ts} +5 -5
- package/dist/{reactive-map-BcB4KsQR.d.ts → reactive-map-C_8sOfdS.d.cts} +7 -6
- package/dist/{reactive-map-D-g3dv8I.d.cts → reactive-map-jle5dnok.d.ts} +7 -6
- package/dist/render/index.d.cts +3 -3
- package/dist/render/index.d.ts +3 -3
- package/dist/render/index.js +1 -0
- package/dist/scheduled-readiness-5rwQlyjV.d.ts +91 -0
- package/dist/scheduled-readiness-DpRY8jI0.d.cts +91 -0
- package/dist/semantic-memory-graph-C2ZUwIlq.d.ts +30 -0
- package/dist/semantic-memory-graph-DlZBD_Eu.d.cts +30 -0
- package/dist/{semantic-memory-graph-BYoIlP35.d.cts → semantic-memory-graph-types-BvzdqmkY.d.cts} +2 -28
- package/dist/{semantic-memory-graph-CxyXLms3.d.ts → semantic-memory-graph-types-Ci-OtahO.d.ts} +2 -28
- package/dist/solutions/index.cjs +6788 -2128
- package/dist/solutions/index.cjs.map +1 -1
- package/dist/solutions/index.d.cts +15 -519
- package/dist/solutions/index.d.ts +15 -519
- package/dist/solutions/index.js +91 -7
- package/dist/solutions/reactive-layout/browser/index.cjs +457 -0
- package/dist/solutions/reactive-layout/browser/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/browser/index.d.cts +44 -0
- package/dist/solutions/reactive-layout/browser/index.d.ts +44 -0
- package/dist/solutions/reactive-layout/browser/index.js +69 -0
- package/dist/solutions/reactive-layout/browser/index.js.map +1 -0
- package/dist/solutions/reactive-layout/index.cjs +4494 -0
- package/dist/solutions/reactive-layout/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/index.d.cts +37 -0
- package/dist/solutions/reactive-layout/index.d.ts +37 -0
- package/dist/solutions/reactive-layout/index.js +146 -0
- package/dist/solutions/reactive-layout/index.js.map +1 -0
- package/dist/solutions/reactive-layout/node-canvas/index.cjs +555 -0
- package/dist/solutions/reactive-layout/node-canvas/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/node-canvas/index.d.cts +54 -0
- package/dist/solutions/reactive-layout/node-canvas/index.d.ts +54 -0
- package/dist/solutions/reactive-layout/node-canvas/index.js +131 -0
- package/dist/solutions/reactive-layout/node-canvas/index.js.map +1 -0
- package/dist/solutions/reactive-layout/react-native/index.cjs +504 -0
- package/dist/solutions/reactive-layout/react-native/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/react-native/index.d.cts +51 -0
- package/dist/solutions/reactive-layout/react-native/index.d.ts +51 -0
- package/dist/solutions/reactive-layout/react-native/index.js +77 -0
- package/dist/solutions/reactive-layout/react-native/index.js.map +1 -0
- package/dist/solutions/reactive-layout/skia/index.cjs +557 -0
- package/dist/solutions/reactive-layout/skia/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/skia/index.d.cts +64 -0
- package/dist/solutions/reactive-layout/skia/index.d.ts +64 -0
- package/dist/solutions/reactive-layout/skia/index.js +70 -0
- package/dist/solutions/reactive-layout/skia/index.js.map +1 -0
- package/dist/solutions/work-item/actions.cjs +2345 -0
- package/dist/solutions/work-item/actions.cjs.map +1 -0
- package/dist/solutions/work-item/actions.d.cts +40 -0
- package/dist/solutions/work-item/actions.d.ts +40 -0
- package/dist/solutions/work-item/actions.js +2078 -0
- package/dist/solutions/work-item/actions.js.map +1 -0
- package/dist/solutions/work-item/scheduling.cjs +9797 -0
- package/dist/solutions/work-item/scheduling.cjs.map +1 -0
- package/dist/solutions/work-item/scheduling.d.cts +1868 -0
- package/dist/solutions/work-item/scheduling.d.ts +1868 -0
- package/dist/solutions/work-item/scheduling.js +146 -0
- package/dist/solutions/work-item/scheduling.js.map +1 -0
- package/dist/solutions/work-item/work-queue.cjs +306 -0
- package/dist/solutions/work-item/work-queue.cjs.map +1 -0
- package/dist/solutions/work-item/work-queue.d.cts +71 -0
- package/dist/solutions/work-item/work-queue.d.ts +71 -0
- package/dist/solutions/work-item/work-queue.js +270 -0
- package/dist/solutions/work-item/work-queue.js.map +1 -0
- package/dist/sources/browser.cjs +1399 -1052
- package/dist/sources/browser.cjs.map +1 -1
- package/dist/sources/browser.d.cts +33 -6
- package/dist/sources/browser.d.ts +33 -6
- package/dist/sources/browser.js +73 -6
- package/dist/sources/browser.js.map +1 -1
- package/dist/sources/index.cjs +1345 -1065
- package/dist/sources/index.cjs.map +1 -1
- package/dist/sources/index.d.cts +5 -5
- package/dist/sources/index.d.ts +5 -5
- package/dist/sources/index.js +7 -6
- package/dist/sources/node.cjs.map +1 -1
- package/dist/sources/node.d.cts +4 -4
- package/dist/sources/node.d.ts +4 -4
- package/dist/sources/node.js +2 -1
- package/dist/sources/node.js.map +1 -1
- package/dist/storage/browser.cjs +16 -0
- package/dist/storage/browser.cjs.map +1 -1
- package/dist/storage/browser.js +4 -3
- package/dist/storage/browser.js.map +1 -1
- package/dist/storage/index.cjs +16 -0
- package/dist/storage/index.cjs.map +1 -1
- package/dist/storage/index.d.cts +6 -5
- package/dist/storage/index.d.ts +6 -5
- package/dist/storage/index.js +10 -9
- package/dist/storage/node.cjs +16 -0
- package/dist/storage/node.cjs.map +1 -1
- package/dist/storage/node.js +4 -3
- package/dist/storage/node.js.map +1 -1
- package/dist/store-BmtEs9mG.d.ts +123 -0
- package/dist/store-PAAsYvML.d.cts +123 -0
- package/dist/testing/index.cjs +1 -0
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +3 -2
- package/dist/types-BRNKoFHj.d.ts +357 -0
- package/dist/{types-h12mNYbq.d.ts → types-BS6CyR-x.d.cts} +49 -130
- package/dist/types-BWK2ay3e.d.cts +457 -0
- package/dist/types-BXKSAoE1.d.cts +357 -0
- package/dist/types-BaPpZItj.d.ts +457 -0
- package/dist/types-BhveCMg5.d.cts +274 -0
- package/dist/{types-bNMSWKqF.d.cts → types-C9NOgNJw.d.ts} +49 -130
- package/dist/types-CTsQ8Ww4.d.ts +274 -0
- package/dist/types-DL_05n2M.d.ts +34 -0
- package/dist/types-XDoqxYO9.d.cts +34 -0
- package/dist/work-item-runtime-types-BqtWnSCS.d.ts +138 -0
- package/dist/work-item-runtime-types-CHO03AKh.d.cts +138 -0
- package/dist/work-queue/index.cjs +1136 -0
- package/dist/work-queue/index.cjs.map +1 -0
- package/dist/work-queue/index.d.cts +21 -0
- package/dist/work-queue/index.d.ts +21 -0
- package/dist/work-queue/index.js +1082 -0
- package/dist/work-queue/index.js.map +1 -0
- package/package.json +603 -249
- package/dist/chunk-2ILL7HQI.js.map +0 -1
- package/dist/chunk-4VLAQHZI.js.map +0 -1
- package/dist/chunk-COHO25CZ.js.map +0 -1
- package/dist/chunk-DK554R7P.js.map +0 -1
- package/dist/chunk-G4M3NHRJ.js.map +0 -1
- package/dist/chunk-I3IHOHCJ.js.map +0 -1
- package/dist/chunk-JIMUDQN3.js.map +0 -1
- package/dist/chunk-RIIOUTGM.js.map +0 -1
- package/dist/chunk-SWTLEQL6.js.map +0 -1
- /package/dist/{chunk-GDL26N2T.js.map → chunk-3KN7NJDR.js.map} +0 -0
- /package/dist/{chunk-Z2ANQ6JW.js.map → chunk-4Q77MMJY.js.map} +0 -0
- /package/dist/{chunk-D6BG7U6A.js.map → chunk-7HZRJMN6.js.map} +0 -0
- /package/dist/{chunk-SCRFRCGR.js.map → chunk-BSQGE5PS.js.map} +0 -0
- /package/dist/{chunk-PKVBHGBM.js.map → chunk-CJIFGJQG.js.map} +0 -0
- /package/dist/{chunk-K3FXTC3I.js.map → chunk-HJACH5PU.js.map} +0 -0
- /package/dist/{chunk-GTPCOEOZ.js.map → chunk-IDMLXLLG.js.map} +0 -0
- /package/dist/{chunk-DKP56CSW.js.map → chunk-JKAYLDQV.js.map} +0 -0
- /package/dist/{chunk-Y3ZLRGHC.js.map → chunk-SIDJO2T4.js.map} +0 -0
- /package/dist/{chunk-JR4IKCR2.js.map → chunk-TPND5MJS.js.map} +0 -0
- /package/dist/{chunk-TEW47IVR.js.map → chunk-VPEFSDME.js.map} +0 -0
- /package/dist/{chunk-DJC4CHLQ.js.map → chunk-YDWBXXQZ.js.map} +0 -0
- /package/dist/{chunk-6PHB5CJS.js.map → chunk-ZLFRB6FI.js.map} +0 -0
package/dist/graph/index.cjs
CHANGED
|
@@ -94,6 +94,7 @@ var TIER = {
|
|
|
94
94
|
START: TIER_START,
|
|
95
95
|
PAUSE: TIER_CONTROL,
|
|
96
96
|
RESUME: TIER_CONTROL,
|
|
97
|
+
PULL: TIER_CONTROL,
|
|
97
98
|
DIRTY: TIER_NOTIFICATION,
|
|
98
99
|
DATA: TIER_VALUE,
|
|
99
100
|
RESOLVED: TIER_VALUE,
|
|
@@ -214,86 +215,6 @@ function drain() {
|
|
|
214
215
|
if (escaped !== null) throw escaped.e;
|
|
215
216
|
}
|
|
216
217
|
|
|
217
|
-
// src/batch/batch.ts
|
|
218
|
-
var active = null;
|
|
219
|
-
var boundaryOwner = null;
|
|
220
|
-
function currentBatch() {
|
|
221
|
-
return active !== null;
|
|
222
|
-
}
|
|
223
|
-
function currentBoundaryBatchToken() {
|
|
224
|
-
return active ?? boundaryOwner ?? void 0;
|
|
225
|
-
}
|
|
226
|
-
function deferToBatch(target, tier3Wave) {
|
|
227
|
-
if (active === null) return false;
|
|
228
|
-
if (!active.deferred.has(target)) active.order.push(target);
|
|
229
|
-
active.deferred.set(target, tier3Wave);
|
|
230
|
-
return true;
|
|
231
|
-
}
|
|
232
|
-
function deferAfterBatchForTarget(target, fn) {
|
|
233
|
-
if (active === null || !active.deferred.has(target)) return false;
|
|
234
|
-
const owner = active;
|
|
235
|
-
target.__deferBoundary(() => {
|
|
236
|
-
if (owner.committed) fn();
|
|
237
|
-
}, owner);
|
|
238
|
-
return true;
|
|
239
|
-
}
|
|
240
|
-
function commit(b) {
|
|
241
|
-
const prev = boundaryOwner;
|
|
242
|
-
boundaryOwner = b;
|
|
243
|
-
try {
|
|
244
|
-
for (const target of b.order) {
|
|
245
|
-
const wave = b.deferred.get(target);
|
|
246
|
-
if (wave) target.__commitBatchedWave(wave);
|
|
247
|
-
}
|
|
248
|
-
b.committed = true;
|
|
249
|
-
} catch (e) {
|
|
250
|
-
dropBoundaryTasksForBatch(b);
|
|
251
|
-
throw e;
|
|
252
|
-
} finally {
|
|
253
|
-
boundaryOwner = prev;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
function rollback(b) {
|
|
257
|
-
dropBoundaryTasksForBatch(b);
|
|
258
|
-
for (const target of b.order) target.__rollbackBatched();
|
|
259
|
-
}
|
|
260
|
-
function batch(fn) {
|
|
261
|
-
enterWave();
|
|
262
|
-
try {
|
|
263
|
-
if (active !== null) {
|
|
264
|
-
const outer = active;
|
|
265
|
-
return fn({
|
|
266
|
-
rollback: () => {
|
|
267
|
-
outer.rolledBack = true;
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
const b = { order: [], deferred: /* @__PURE__ */ new Map(), committed: false, rolledBack: false };
|
|
272
|
-
active = b;
|
|
273
|
-
const bctx = {
|
|
274
|
-
rollback: () => {
|
|
275
|
-
b.rolledBack = true;
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
let result;
|
|
279
|
-
try {
|
|
280
|
-
result = fn(bctx);
|
|
281
|
-
} catch (e) {
|
|
282
|
-
active = null;
|
|
283
|
-
rollback(b);
|
|
284
|
-
throw e;
|
|
285
|
-
}
|
|
286
|
-
active = null;
|
|
287
|
-
if (b.rolledBack) rollback(b);
|
|
288
|
-
else {
|
|
289
|
-
commit(b);
|
|
290
|
-
}
|
|
291
|
-
return result;
|
|
292
|
-
} finally {
|
|
293
|
-
exitWave();
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
218
|
// src/dispatcher/index.ts
|
|
298
219
|
var PoolTable = class {
|
|
299
220
|
constructor(kind) {
|
|
@@ -757,109 +678,792 @@ function makeDepBookkeeping(depCount2) {
|
|
|
757
678
|
};
|
|
758
679
|
}
|
|
759
680
|
|
|
760
|
-
// src/
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
if (!Number.isFinite(value)) {
|
|
764
|
-
throw new TypeError(`stableJsonString: non-finite number at ${path}`);
|
|
765
|
-
}
|
|
681
|
+
// src/node/protocol-guards.ts
|
|
682
|
+
function terminalView(t) {
|
|
683
|
+
return t === void 0 ? false : t;
|
|
766
684
|
}
|
|
767
|
-
function
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
throw new TypeError(`stableJsonString: non-canonical number at ${path}`);
|
|
771
|
-
}
|
|
772
|
-
const abs = Math.abs(value);
|
|
773
|
-
if (abs > 0 && abs < JS_MIN_NORMAL_NUMBER) {
|
|
774
|
-
throw new TypeError(`stableJsonString: subnormal number at ${path}`);
|
|
685
|
+
function normalizePullDemand(demand) {
|
|
686
|
+
if (typeof demand !== "object" || demand === null || Array.isArray(demand)) {
|
|
687
|
+
throw new Error("ctx.up: PULL requires { pullId, params? } demand payload (D269)");
|
|
775
688
|
}
|
|
776
|
-
|
|
777
|
-
|
|
689
|
+
const pullId = demand.pullId;
|
|
690
|
+
if (typeof pullId !== "string" && typeof pullId !== "symbol") {
|
|
691
|
+
throw new Error("ctx.up: PULL demand requires a string or symbol pullId (D269)");
|
|
778
692
|
}
|
|
693
|
+
const params = demand.params;
|
|
694
|
+
return params === void 0 ? { pullId } : { pullId, params };
|
|
779
695
|
}
|
|
780
|
-
function
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
if (typeof value !== "object") {
|
|
789
|
-
throw new TypeError(`stableJsonString: value at ${path} is not JSON-encodable`);
|
|
696
|
+
function validateDownPayloads(msgs) {
|
|
697
|
+
for (const m of msgs) {
|
|
698
|
+
if (m[0] === "DATA" && m[1] === void 0) {
|
|
699
|
+
throw new Error("down: DATA requires a non-SENTINEL payload (R-data-payload)");
|
|
700
|
+
}
|
|
701
|
+
if (m[0] === "ERROR" && isInvalidErrorPayload(m[1])) {
|
|
702
|
+
throw new Error("down: ERROR requires a non-SENTINEL, non-boolean payload (R-data-payload)");
|
|
703
|
+
}
|
|
790
704
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// src/node/runtime-accessors.ts
|
|
708
|
+
var constructingCore;
|
|
709
|
+
var constructingEnvironment;
|
|
710
|
+
var ownerTokens = /* @__PURE__ */ new WeakMap();
|
|
711
|
+
var topologyDepsChangedObservers = /* @__PURE__ */ new WeakMap();
|
|
712
|
+
var checkpointReaders = /* @__PURE__ */ new WeakMap();
|
|
713
|
+
var restoreWriters = /* @__PURE__ */ new WeakMap();
|
|
714
|
+
var runtimeReleasers = /* @__PURE__ */ new WeakMap();
|
|
715
|
+
var runtimeQuiescenceReaders = /* @__PURE__ */ new WeakMap();
|
|
716
|
+
var subscriberCountReaders = /* @__PURE__ */ new WeakMap();
|
|
717
|
+
var activationReaders = /* @__PURE__ */ new WeakMap();
|
|
718
|
+
var releasedNodes = /* @__PURE__ */ new WeakSet();
|
|
719
|
+
function withNodeCore(core, create) {
|
|
720
|
+
const prev = constructingCore;
|
|
721
|
+
constructingCore = core;
|
|
722
|
+
try {
|
|
723
|
+
return create();
|
|
724
|
+
} finally {
|
|
725
|
+
constructingCore = prev;
|
|
795
726
|
}
|
|
796
|
-
|
|
727
|
+
}
|
|
728
|
+
function takeConstructingNodeCore() {
|
|
729
|
+
const core = constructingCore;
|
|
730
|
+
constructingCore = void 0;
|
|
731
|
+
return core;
|
|
732
|
+
}
|
|
733
|
+
function withEnvironmentDrivers(environment, create) {
|
|
734
|
+
const prev = constructingEnvironment;
|
|
735
|
+
constructingEnvironment = environment;
|
|
797
736
|
try {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
737
|
+
return create();
|
|
738
|
+
} finally {
|
|
739
|
+
constructingEnvironment = prev;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
function takeConstructingEnvironmentDrivers() {
|
|
743
|
+
const environment = constructingEnvironment;
|
|
744
|
+
constructingEnvironment = void 0;
|
|
745
|
+
return environment;
|
|
746
|
+
}
|
|
747
|
+
function getNodeOwner(n) {
|
|
748
|
+
return ownerTokens.get(n);
|
|
749
|
+
}
|
|
750
|
+
function setNodeOwner(n, owner) {
|
|
751
|
+
ownerTokens.set(n, owner);
|
|
752
|
+
}
|
|
753
|
+
function setNodeTopologyDepsChangedObserver(n, observer) {
|
|
754
|
+
topologyDepsChangedObservers.set(n, observer);
|
|
755
|
+
}
|
|
756
|
+
function notifyTopologyDepsChanged(node2, prevDeps, deps) {
|
|
757
|
+
topologyDepsChangedObservers.get(node2)?.(node2, prevDeps, deps);
|
|
758
|
+
}
|
|
759
|
+
function checkpointStateOfNode(n) {
|
|
760
|
+
const read = checkpointReaders.get(n);
|
|
761
|
+
if (read === void 0) throw new Error("checkpoint: unknown node state");
|
|
762
|
+
return read();
|
|
763
|
+
}
|
|
764
|
+
function restoreStateOfNode(n, state) {
|
|
765
|
+
const write = restoreWriters.get(n);
|
|
766
|
+
if (write === void 0) throw new Error("restoreGraph: unknown node state");
|
|
767
|
+
write(state);
|
|
768
|
+
}
|
|
769
|
+
function releaseRuntimeOfNode(n) {
|
|
770
|
+
runtimeReleasers.get(n)?.();
|
|
771
|
+
}
|
|
772
|
+
function isNodeRuntimeQuiescentForRelease(n) {
|
|
773
|
+
return runtimeQuiescenceReaders.get(n)?.() ?? false;
|
|
774
|
+
}
|
|
775
|
+
function subscriberCountOfNode(n) {
|
|
776
|
+
return subscriberCountReaders.get(n)?.() ?? 0;
|
|
777
|
+
}
|
|
778
|
+
function isNodeActiveForRelease(n) {
|
|
779
|
+
return activationReaders.get(n)?.() ?? false;
|
|
780
|
+
}
|
|
781
|
+
function isNodeRuntimeReleased(n) {
|
|
782
|
+
return releasedNodes.has(n);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// src/node/node-context-runtime.ts
|
|
786
|
+
function nodeBuildCtx(self) {
|
|
787
|
+
const kind = self._slot.handle ? self._slot.dispatcher.poolKind(self._slot.handle.poolId) : "sync";
|
|
788
|
+
if (kind === "sync") {
|
|
789
|
+
if (self._syncCtx === null) self._syncCtx = self._makeCtx();
|
|
790
|
+
self._refreshCtx(self._syncCtx);
|
|
791
|
+
return self._syncCtx;
|
|
792
|
+
}
|
|
793
|
+
return self._makeCtx({
|
|
794
|
+
waveData: self._dep.waveData.map((waves) => waves.map((w) => [...w])),
|
|
795
|
+
terminal: self._dep.terminalInput.map(terminalView),
|
|
796
|
+
latest: [...self._dep.prev]
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
function nodeMakeCtx(self, snapshot) {
|
|
800
|
+
const ctx = {
|
|
801
|
+
// Wave-owner boundary (D47): a SYNC fn's emit nests under the public entry that drove
|
|
802
|
+
// it (cheap inc/dec, no early drain); an ASYNC-pool fn re-enters here from its stashed
|
|
803
|
+
// ctx at depth 0, so this is the boundary that drains any rewireNext it issued.
|
|
804
|
+
up: (msgs, towardDep) => {
|
|
805
|
+
if (self._released) return;
|
|
806
|
+
enterWave();
|
|
807
|
+
try {
|
|
808
|
+
self._up(msgs, towardDep);
|
|
809
|
+
} finally {
|
|
810
|
+
exitWave();
|
|
807
811
|
}
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
812
|
+
},
|
|
813
|
+
down: (msgs) => {
|
|
814
|
+
if (self._released) return;
|
|
815
|
+
enterWave();
|
|
816
|
+
try {
|
|
817
|
+
self._down(msgs);
|
|
818
|
+
} finally {
|
|
819
|
+
exitWave();
|
|
814
820
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
821
|
+
},
|
|
822
|
+
waveData: snapshot?.waveData ?? self._dep.waveData,
|
|
823
|
+
terminal: snapshot?.terminal ?? self._dep.terminalInput.map(terminalView),
|
|
824
|
+
state: self._makeState(),
|
|
825
|
+
onDeactivation: (fn) => {
|
|
826
|
+
if (self._released) return;
|
|
827
|
+
self._hooks.onDeactivation.push(fn);
|
|
828
|
+
},
|
|
829
|
+
onInvalidate: (fn) => {
|
|
830
|
+
if (self._released) return;
|
|
831
|
+
self._hooks.onInvalidate.push(fn);
|
|
832
|
+
},
|
|
833
|
+
environment: () => self._slot.environment,
|
|
834
|
+
// R-rewire-deferred (D47): defer a self-dep-set mutation to the committed boundary.
|
|
835
|
+
rewireNext: {
|
|
836
|
+
subscribeDep: (dep, fn) => self._requestRewireNext({ kind: "add", dep, fn }),
|
|
837
|
+
unsubscribeDep: (dep, fn) => self._requestRewireNext({ kind: "remove", dep, fn }),
|
|
838
|
+
replaceDeps: (deps, fn) => self._requestRewireNext({ kind: "set", deps, fn })
|
|
839
|
+
},
|
|
840
|
+
// R-up-routing / R-pull (D269): deferred up — route a control/demand wave (e.g. PULL)
|
|
841
|
+
// up the declared cone at the committed boundary. The SELF-demand path: an
|
|
842
|
+
// immediate ctx.up whose delivery loops back re-enters this fn (D37 / R-reentrancy).
|
|
843
|
+
upNext: (msgs, towardDep) => self._requestUpNext(msgs, towardDep),
|
|
844
|
+
...self._control.activePull === void 0 ? {} : { pull: self._control.activePull },
|
|
845
|
+
[CTX_DEP_CACHE]: { latest: snapshot?.latest ?? self._dep.prev },
|
|
846
|
+
[CTX_NODE_BINDING]: {
|
|
847
|
+
dispatcher: self._slot.dispatcher,
|
|
848
|
+
create: (factory) => withEnvironmentDrivers(self._slot.environment, () => withNodeCore(self._core, factory))
|
|
828
849
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
850
|
+
};
|
|
851
|
+
if (self._slot.dynamic) {
|
|
852
|
+
ctx.track = (i) => ctx[CTX_DEP_CACHE]?.latest[i];
|
|
832
853
|
}
|
|
854
|
+
return ctx;
|
|
833
855
|
}
|
|
834
|
-
function
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
856
|
+
function nodeRefreshCtx(self, ctx) {
|
|
857
|
+
ctx.waveData = self._dep.waveData;
|
|
858
|
+
ctx.terminal = self._dep.terminalInput.map(terminalView);
|
|
859
|
+
if (self._control.activePull === void 0) {
|
|
860
|
+
delete ctx.pull;
|
|
861
|
+
} else {
|
|
862
|
+
ctx.pull = self._control.activePull;
|
|
863
|
+
}
|
|
864
|
+
ctx[CTX_DEP_CACHE] = { latest: self._dep.prev };
|
|
839
865
|
}
|
|
840
|
-
function
|
|
841
|
-
const encoder = new TextEncoder();
|
|
842
|
-
const decoder = new TextDecoder();
|
|
866
|
+
function nodeMakeState(self) {
|
|
843
867
|
return {
|
|
844
|
-
|
|
845
|
-
|
|
868
|
+
get: () => self._privateState.value,
|
|
869
|
+
set: (v) => {
|
|
870
|
+
self._privateState.value = v;
|
|
846
871
|
},
|
|
847
|
-
|
|
848
|
-
|
|
872
|
+
persist: (on = true) => {
|
|
873
|
+
self._privateState.persist = on;
|
|
849
874
|
}
|
|
850
875
|
};
|
|
851
876
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
877
|
+
|
|
878
|
+
// src/node/node-input-runtime.ts
|
|
879
|
+
function nodeRecordDepProjection(self, idx, delivery) {
|
|
880
|
+
const token = delivery?.wave ?? {};
|
|
881
|
+
if (self._dep.waveTokens[idx] !== token) {
|
|
882
|
+
self._dep.waveData[idx].push([]);
|
|
883
|
+
self._dep.waveTokens[idx] = token;
|
|
884
|
+
}
|
|
885
|
+
return self._dep.waveData[idx][self._dep.waveData[idx].length - 1];
|
|
886
|
+
}
|
|
887
|
+
function nodeDepProjectionHasData(self, idx) {
|
|
888
|
+
const projection = self._dep.waveData[idx][self._dep.waveData[idx].length - 1];
|
|
889
|
+
return projection?.some((v) => v !== SENTINEL) ?? false;
|
|
890
|
+
}
|
|
891
|
+
function nodeReceiveFromDep(self, idx, msg, delivery) {
|
|
892
|
+
if (self._released) return;
|
|
893
|
+
const t = msg[0];
|
|
894
|
+
if (t === "START") return;
|
|
895
|
+
const isLastInDeliveredWave = delivery?.last ?? true;
|
|
896
|
+
if (self._value.terminal !== void 0) {
|
|
897
|
+
if (t === "TEARDOWN") self._down([["TEARDOWN"]]);
|
|
898
|
+
return;
|
|
857
899
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
900
|
+
if (t === "INVALIDATE") {
|
|
901
|
+
const projection = self._recordDepProjection(idx, delivery);
|
|
902
|
+
projection.push(SENTINEL);
|
|
903
|
+
if (projection.some((v) => v !== SENTINEL) && isLastInDeliveredWave) self._maybeRun();
|
|
904
|
+
self._dep.prev[idx] = SENTINEL;
|
|
905
|
+
self._dep.hasData[idx] = false;
|
|
906
|
+
self._dep.batch[idx] = null;
|
|
907
|
+
if (self._dep.dirty[idx]) {
|
|
908
|
+
self._dep.dirty[idx] = false;
|
|
909
|
+
self._wave.pending--;
|
|
910
|
+
}
|
|
911
|
+
if (self._control.pausedDepWaveOccurred && self._dep.batch.every((b) => b === null)) {
|
|
912
|
+
self._control.pausedDepWaveOccurred = false;
|
|
913
|
+
}
|
|
914
|
+
const hadData = self._value.hasData;
|
|
915
|
+
self._invalidate();
|
|
916
|
+
if (self._wave.pending === 0 && self._wave.emittedDirtyThisWave) {
|
|
917
|
+
if (!hadData) self._down([["RESOLVED"]]);
|
|
918
|
+
else self._wave.emittedDirtyThisWave = false;
|
|
919
|
+
}
|
|
920
|
+
self._fireOwedDemandIfReady();
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
if (isTerminal(t)) {
|
|
924
|
+
const isError = t === "ERROR";
|
|
925
|
+
const errPayload = isError ? msg[1] : void 0;
|
|
926
|
+
self._dep.terminal[idx] = isError ? errPayload : true;
|
|
927
|
+
self._dep.terminalInput[idx] = isError ? errPayload : true;
|
|
928
|
+
self._releaseDepDirty(idx);
|
|
929
|
+
const ranValueBeforeTerminal = self._depProjectionHasData(idx) && isLastInDeliveredWave;
|
|
930
|
+
if (ranValueBeforeTerminal) self._maybeRun();
|
|
931
|
+
if (isError && self._slot.errorWhenDepsError) {
|
|
932
|
+
self._down([["ERROR", errPayload]]);
|
|
933
|
+
} else if (self._slot.terminalAsRealInput) {
|
|
934
|
+
if (ranValueBeforeTerminal) {
|
|
935
|
+
self._fireOwedDemandIfReady();
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
self._maybeRun();
|
|
939
|
+
} else if (self._slot.completeWhenDepsComplete && self._allDepsTerminal()) {
|
|
940
|
+
self._down([["COMPLETE"]]);
|
|
941
|
+
} else {
|
|
942
|
+
self._settleAfterAbsorbedTerminal();
|
|
943
|
+
}
|
|
944
|
+
self._fireOwedDemandIfReady();
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
if (t === "TEARDOWN") {
|
|
948
|
+
self._down([["TEARDOWN"]]);
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
if (t === "DIRTY") {
|
|
952
|
+
if (!self._dep.dirty[idx]) {
|
|
953
|
+
self._dep.dirty[idx] = true;
|
|
954
|
+
self._wave.pending++;
|
|
955
|
+
self._dep.tier[idx] = 2;
|
|
956
|
+
self._markDirty();
|
|
957
|
+
}
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
if (t === "DATA") {
|
|
961
|
+
const v = msg[1];
|
|
962
|
+
self._recordDepProjection(idx, delivery).push(v);
|
|
963
|
+
const b = self._dep.batch[idx];
|
|
964
|
+
if (b === null) self._dep.batch[idx] = [v];
|
|
965
|
+
else b.push(v);
|
|
966
|
+
self._dep.prev[idx] = v;
|
|
967
|
+
self._dep.hasData[idx] = true;
|
|
968
|
+
self._dep.tier[idx] = 3;
|
|
969
|
+
if (self._dep.dirty[idx]) {
|
|
970
|
+
self._dep.dirty[idx] = false;
|
|
971
|
+
self._wave.pending--;
|
|
972
|
+
}
|
|
973
|
+
if (isLastInDeliveredWave) self._maybeRun();
|
|
974
|
+
self._fireOwedDemandIfReady();
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
if (t === "RESOLVED") {
|
|
978
|
+
self._recordDepProjection(idx, delivery);
|
|
979
|
+
self._dep.tier[idx] = 3;
|
|
980
|
+
if (self._dep.dirty[idx]) {
|
|
981
|
+
self._dep.dirty[idx] = false;
|
|
982
|
+
self._wave.pending--;
|
|
983
|
+
}
|
|
984
|
+
if (isLastInDeliveredWave) self._maybeRun();
|
|
985
|
+
self._fireOwedDemandIfReady();
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
function nodeReleaseDepDirty(self, idx) {
|
|
990
|
+
if (self._dep.dirty[idx]) {
|
|
991
|
+
self._dep.dirty[idx] = false;
|
|
992
|
+
self._wave.pending--;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
function nodeSettleAfterAbsorbedTerminal(self) {
|
|
996
|
+
if (self._wave.pending !== 0 || !self._wave.emittedDirtyThisWave) return;
|
|
997
|
+
const sawData = self._dep.batch.some((b) => b !== null && b.length > 0);
|
|
998
|
+
if (sawData) self._maybeRun();
|
|
999
|
+
if (self._wave.emittedDirtyThisWave) self._down([["RESOLVED"]]);
|
|
1000
|
+
}
|
|
1001
|
+
function nodeMarkDirty(self) {
|
|
1002
|
+
self._value.status = "dirty";
|
|
1003
|
+
if (self._isPullQuiet()) return;
|
|
1004
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1005
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1006
|
+
self._emitToSubs(["DIRTY"]);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
function nodeMaybeRun(self) {
|
|
1010
|
+
if (self._wave.inDepMutation) {
|
|
1011
|
+
self._wave.rewireRunPending = true;
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
if (self._slot.pausable === true && (self._isPaused() || self._isPullQuiet())) {
|
|
1015
|
+
self._control.pausedDepWaveOccurred = true;
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
self._tryRun();
|
|
1019
|
+
}
|
|
1020
|
+
function nodeSettleRewire(self) {
|
|
1021
|
+
if (self._slot.pausable === true && self._isPaused()) {
|
|
1022
|
+
self._control.pausedDepWaveOccurred = true;
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
if (self._wave.pending > 0) return;
|
|
1026
|
+
if (self._slot.handle === null) {
|
|
1027
|
+
self._passthroughEmit();
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
if (!self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled())) return;
|
|
1031
|
+
self._markDirty();
|
|
1032
|
+
self._runWave();
|
|
1033
|
+
}
|
|
1034
|
+
function nodeTryRun(self) {
|
|
1035
|
+
if (self._wave.pending > 0) return;
|
|
1036
|
+
if (self._slot.handle === null) {
|
|
1037
|
+
self._passthroughEmit();
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
if (!self._wave.hasCalledFnOnce) {
|
|
1041
|
+
if (self._slot.partial || self._allDepsSettled()) self._runWave();
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
self._runWave();
|
|
1045
|
+
}
|
|
1046
|
+
function nodeAllDepsSettled(self) {
|
|
1047
|
+
for (let i = 0; i < self._slot.deps.length; i++) {
|
|
1048
|
+
if (self._dep.hasData[i]) continue;
|
|
1049
|
+
if (self._slot.terminalAsRealInput && self._dep.terminal[i] !== void 0) continue;
|
|
1050
|
+
return false;
|
|
1051
|
+
}
|
|
1052
|
+
return true;
|
|
1053
|
+
}
|
|
1054
|
+
function nodePassthroughEmit(self) {
|
|
1055
|
+
const b = self._dep.batch[0];
|
|
1056
|
+
if (b !== null && b.length > 0) {
|
|
1057
|
+
self._down([["DATA", b[b.length - 1]]]);
|
|
1058
|
+
} else if (self._wave.emittedDirtyThisWave) {
|
|
1059
|
+
self._down([["RESOLVED"]]);
|
|
1060
|
+
}
|
|
1061
|
+
self._dep.batch[0] = null;
|
|
1062
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1063
|
+
}
|
|
1064
|
+
function nodeRunWave(self) {
|
|
1065
|
+
if (self._wave.insideRunWave)
|
|
1066
|
+
throw new Error(
|
|
1067
|
+
"synchronous feedback cycle: node fn re-entered its own wave (R-reentrancy / D37)"
|
|
1068
|
+
);
|
|
1069
|
+
self._wave.hasCalledFnOnce = true;
|
|
1070
|
+
self._hooks.onInvalidate = [];
|
|
1071
|
+
self._hooks.onDeactivation = [];
|
|
1072
|
+
const ctx = self._buildCtx();
|
|
1073
|
+
const wasDirty = self._wave.emittedDirtyThisWave;
|
|
1074
|
+
self._wave.emittedSettleThisWave = false;
|
|
1075
|
+
self._wave.insideRunWave = true;
|
|
1076
|
+
try {
|
|
1077
|
+
self._slot.dispatcher.invoke(self._slot.handle, ctx);
|
|
1078
|
+
} finally {
|
|
1079
|
+
self._wave.insideRunWave = false;
|
|
1080
|
+
}
|
|
1081
|
+
if (wasDirty && !self._wave.emittedSettleThisWave && self._value.terminal === void 0 && !self._isAsyncPool()) {
|
|
1082
|
+
self._down([["RESOLVED"]]);
|
|
1083
|
+
}
|
|
1084
|
+
for (let i = 0; i < self._dep.batch.length; i++) {
|
|
1085
|
+
self._dep.batch[i] = null;
|
|
1086
|
+
self._dep.waveData[i] = [];
|
|
1087
|
+
self._dep.waveTokens[i] = void 0;
|
|
1088
|
+
self._dep.terminalInput[i] = void 0;
|
|
1089
|
+
}
|
|
1090
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// src/node/node-runtime-host.ts
|
|
1094
|
+
function nodeRuntimeHost(node2) {
|
|
1095
|
+
return node2;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
// src/node/node-lifecycle-runtime.ts
|
|
1099
|
+
function nodeActivate(self) {
|
|
1100
|
+
self._lifecycle.activated = true;
|
|
1101
|
+
const seedRestoredDeps = self._restoredActivationPending;
|
|
1102
|
+
self._restoredActivationPending = false;
|
|
1103
|
+
self._dep.unsubs = new Array(self._slot.deps.length);
|
|
1104
|
+
self._dep.idxBoxes = new Array(self._slot.deps.length);
|
|
1105
|
+
for (const dep of self._slot.deps) self._subscribeDepAt(dep, { seedRestored: seedRestoredDeps });
|
|
1106
|
+
if (self._slot.deps.length === 0 && self._slot.handle !== null && !self._wave.hasCalledFnOnce) {
|
|
1107
|
+
self._runWave();
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
function nodeSubscribeDepAt(self, depNode, opts = {}) {
|
|
1111
|
+
const idx0 = self._slot.deps.indexOf(depNode);
|
|
1112
|
+
const box = { v: idx0 };
|
|
1113
|
+
let ignoreInitialPush = opts.seedRestored === true;
|
|
1114
|
+
if (ignoreInitialPush && idx0 !== -1) {
|
|
1115
|
+
self._seedRestoredDepAt(idx0, depNode);
|
|
1116
|
+
const dep = nodeRuntimeHost(depNode);
|
|
1117
|
+
if (dep._value.terminal !== void 0 && !dep._slot.resubscribable) {
|
|
1118
|
+
self._dep.unsubs[idx0] = () => {
|
|
1119
|
+
};
|
|
1120
|
+
self._dep.idxBoxes[idx0] = box;
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
const unsub = depNode.subscribe((msg, delivery) => {
|
|
1125
|
+
if (ignoreInitialPush && delivery === void 0) return;
|
|
1126
|
+
if (ignoreInitialPush) ignoreInitialPush = false;
|
|
1127
|
+
if (box.v === -1) return;
|
|
1128
|
+
self._receiveFromDep(box.v, msg, delivery);
|
|
1129
|
+
});
|
|
1130
|
+
if (ignoreInitialPush && idx0 !== -1 && box.v !== -1) self._seedRestoredDepAt(idx0, depNode);
|
|
1131
|
+
ignoreInitialPush = false;
|
|
1132
|
+
if (idx0 !== -1) {
|
|
1133
|
+
self._dep.unsubs[idx0] = unsub;
|
|
1134
|
+
self._dep.idxBoxes[idx0] = box;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
function nodeSeedRestoredDepAt(self, idx, depNode) {
|
|
1138
|
+
const dep = nodeRuntimeHost(depNode);
|
|
1139
|
+
const seedData = dep._value.hasData && !dep._slot.pull;
|
|
1140
|
+
self._dep.batch[idx] = null;
|
|
1141
|
+
self._dep.waveData[idx] = [];
|
|
1142
|
+
self._dep.waveTokens[idx] = void 0;
|
|
1143
|
+
self._dep.prev[idx] = seedData ? dep._value.cache : SENTINEL;
|
|
1144
|
+
self._dep.hasData[idx] = seedData;
|
|
1145
|
+
self._dep.dirty[idx] = false;
|
|
1146
|
+
self._dep.tier[idx] = seedData ? 3 : 0;
|
|
1147
|
+
self._dep.terminal[idx] = dep._value.terminal;
|
|
1148
|
+
self._dep.terminalInput[idx] = void 0;
|
|
1149
|
+
}
|
|
1150
|
+
function nodeDeactivate(self) {
|
|
1151
|
+
self._lifecycle.activated = false;
|
|
1152
|
+
for (const u of self._dep.unsubs) if (u) u();
|
|
1153
|
+
self._dep.unsubs = [];
|
|
1154
|
+
self._dep.idxBoxes = [];
|
|
1155
|
+
for (const fn of self._hooks.onDeactivation) fn();
|
|
1156
|
+
self._hooks.onDeactivation = [];
|
|
1157
|
+
self._hooks.onInvalidate = [];
|
|
1158
|
+
const isCompute = self._slot.handle !== null || self._slot.deps.length > 0;
|
|
1159
|
+
if (isCompute) {
|
|
1160
|
+
self._value.cache = SENTINEL;
|
|
1161
|
+
self._value.hasData = false;
|
|
1162
|
+
self._value.status = "sentinel";
|
|
1163
|
+
}
|
|
1164
|
+
self._resetDepState();
|
|
1165
|
+
self._wave.hasCalledFnOnce = false;
|
|
1166
|
+
self._control.pauseLockset.clear();
|
|
1167
|
+
self._control.pauseBuffer = [];
|
|
1168
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1169
|
+
self._control.demandOwed = void 0;
|
|
1170
|
+
self._control.activePull = void 0;
|
|
1171
|
+
self._control.pullDirtyOwed = false;
|
|
1172
|
+
self._value.replayRing = [];
|
|
1173
|
+
if (!self._privateState.persist) self._privateState.value = SENTINEL;
|
|
1174
|
+
}
|
|
1175
|
+
function nodeSubscriberCount(self) {
|
|
1176
|
+
return self._lifecycle.subscribers.size;
|
|
1177
|
+
}
|
|
1178
|
+
function nodeIsRuntimeQuiescentForRelease(self) {
|
|
1179
|
+
return !self._released && self._value.status !== "dirty" && self._value.status !== "pending" && self._wave.pending === 0 && !self._wave.insideRunWave && !self._wave.inDepMutation && !self._wave.rewireRunPending && !self._wave.batchDirtyOwed && self._dep.dirty.every((dirty) => !dirty) && self._control.pauseBuffer.length === 0 && !self._control.pausedDepWaveOccurred && self._control.demandOwed === void 0 && self._control.activePull === void 0 && !self._control.inDeliverDemand && self._control.pauseLockset.size === 0;
|
|
1180
|
+
}
|
|
1181
|
+
function nodeReleaseRuntime(self) {
|
|
1182
|
+
if (self._released) return;
|
|
1183
|
+
self._released = true;
|
|
1184
|
+
const node2 = self;
|
|
1185
|
+
releasedNodes.add(node2);
|
|
1186
|
+
let releaseError;
|
|
1187
|
+
const recordReleaseError = (error) => {
|
|
1188
|
+
if (releaseError === void 0) releaseError = error;
|
|
1189
|
+
};
|
|
1190
|
+
self._lifecycle.activated = false;
|
|
1191
|
+
for (const u of self._dep.unsubs) {
|
|
1192
|
+
try {
|
|
1193
|
+
u();
|
|
1194
|
+
} catch (error) {
|
|
1195
|
+
recordReleaseError(error);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
for (const fn of self._hooks.onDeactivation) {
|
|
1199
|
+
try {
|
|
1200
|
+
fn();
|
|
1201
|
+
} catch (error) {
|
|
1202
|
+
recordReleaseError(error);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
self._dep.unsubs = [];
|
|
1206
|
+
self._dep.idxBoxes = [];
|
|
1207
|
+
self._lifecycle.subscribers.clear();
|
|
1208
|
+
if (self._slot.handle !== null) {
|
|
1209
|
+
self._slot.dispatcher.unregister(self._slot.handle);
|
|
1210
|
+
self._slot.handle = null;
|
|
1211
|
+
}
|
|
1212
|
+
self._slot.deps = [];
|
|
1213
|
+
self._dep.batch = [];
|
|
1214
|
+
self._dep.waveData = [];
|
|
1215
|
+
self._dep.waveTokens = [];
|
|
1216
|
+
self._dep.prev = [];
|
|
1217
|
+
self._dep.hasData = [];
|
|
1218
|
+
self._dep.dirty = [];
|
|
1219
|
+
self._dep.tier = [];
|
|
1220
|
+
self._dep.terminal = [];
|
|
1221
|
+
self._dep.terminalInput = [];
|
|
1222
|
+
self._value.cache = SENTINEL;
|
|
1223
|
+
self._value.hasData = false;
|
|
1224
|
+
self._value.status = "sentinel";
|
|
1225
|
+
self._value.terminal = void 0;
|
|
1226
|
+
self._value.replayRing = [];
|
|
1227
|
+
self._privateState.value = SENTINEL;
|
|
1228
|
+
self._privateState.persist = false;
|
|
1229
|
+
self._syncCtx = null;
|
|
1230
|
+
self._resetDepState();
|
|
1231
|
+
self._hooks.onDeactivation = [];
|
|
1232
|
+
self._hooks.onInvalidate = [];
|
|
1233
|
+
self._control.pauseLockset.clear();
|
|
1234
|
+
self._control.pauseBuffer = [];
|
|
1235
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1236
|
+
self._control.demandOwed = void 0;
|
|
1237
|
+
self._control.activePull = void 0;
|
|
1238
|
+
self._control.pullDirtyOwed = false;
|
|
1239
|
+
self._restoredActivationPending = false;
|
|
1240
|
+
checkpointReaders.delete(node2);
|
|
1241
|
+
restoreWriters.delete(node2);
|
|
1242
|
+
runtimeReleasers.delete(node2);
|
|
1243
|
+
runtimeQuiescenceReaders.delete(node2);
|
|
1244
|
+
subscriberCountReaders.delete(node2);
|
|
1245
|
+
activationReaders.delete(node2);
|
|
1246
|
+
ownerTokens.delete(node2);
|
|
1247
|
+
topologyDepsChangedObservers.delete(node2);
|
|
1248
|
+
self._core.releaseSlot(self._id);
|
|
1249
|
+
if (releaseError !== void 0) throw releaseError;
|
|
1250
|
+
}
|
|
1251
|
+
function nodeResetDepState(self) {
|
|
1252
|
+
const n = self._slot.deps.length;
|
|
1253
|
+
for (let i = 0; i < n; i++) {
|
|
1254
|
+
self._dep.batch[i] = null;
|
|
1255
|
+
self._dep.waveData[i] = [];
|
|
1256
|
+
self._dep.waveTokens[i] = void 0;
|
|
1257
|
+
self._dep.prev[i] = SENTINEL;
|
|
1258
|
+
self._dep.hasData[i] = false;
|
|
1259
|
+
self._dep.dirty[i] = false;
|
|
1260
|
+
self._dep.tier[i] = 0;
|
|
1261
|
+
self._dep.terminal[i] = void 0;
|
|
1262
|
+
self._dep.terminalInput[i] = void 0;
|
|
1263
|
+
}
|
|
1264
|
+
self._wave.pending = 0;
|
|
1265
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// src/batch/batch.ts
|
|
1269
|
+
var active = null;
|
|
1270
|
+
var boundaryOwner = null;
|
|
1271
|
+
function currentBatch() {
|
|
1272
|
+
return active !== null;
|
|
1273
|
+
}
|
|
1274
|
+
function currentBoundaryBatchToken() {
|
|
1275
|
+
return active ?? boundaryOwner ?? void 0;
|
|
1276
|
+
}
|
|
1277
|
+
function deferToBatch(target, tier3Wave) {
|
|
1278
|
+
if (active === null) return false;
|
|
1279
|
+
if (!active.deferred.has(target)) active.order.push(target);
|
|
1280
|
+
active.deferred.set(target, tier3Wave);
|
|
1281
|
+
return true;
|
|
1282
|
+
}
|
|
1283
|
+
function deferAfterBatchForTarget(target, fn) {
|
|
1284
|
+
if (active === null || !active.deferred.has(target)) return false;
|
|
1285
|
+
const owner = active;
|
|
1286
|
+
target.__deferBoundary(() => {
|
|
1287
|
+
if (owner.committed) fn();
|
|
1288
|
+
}, owner);
|
|
1289
|
+
return true;
|
|
1290
|
+
}
|
|
1291
|
+
function commit(b) {
|
|
1292
|
+
const prev = boundaryOwner;
|
|
1293
|
+
boundaryOwner = b;
|
|
1294
|
+
try {
|
|
1295
|
+
for (const target of b.order) {
|
|
1296
|
+
const wave = b.deferred.get(target);
|
|
1297
|
+
if (wave) target.__commitBatchedWave(wave);
|
|
1298
|
+
}
|
|
1299
|
+
b.committed = true;
|
|
1300
|
+
} catch (e) {
|
|
1301
|
+
dropBoundaryTasksForBatch(b);
|
|
1302
|
+
throw e;
|
|
1303
|
+
} finally {
|
|
1304
|
+
boundaryOwner = prev;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
function rollback(b) {
|
|
1308
|
+
dropBoundaryTasksForBatch(b);
|
|
1309
|
+
for (const target of b.order) target.__rollbackBatched();
|
|
1310
|
+
}
|
|
1311
|
+
function batch(fn) {
|
|
1312
|
+
enterWave();
|
|
1313
|
+
try {
|
|
1314
|
+
if (active !== null) {
|
|
1315
|
+
const outer = active;
|
|
1316
|
+
return fn({
|
|
1317
|
+
rollback: () => {
|
|
1318
|
+
outer.rolledBack = true;
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
const b = { order: [], deferred: /* @__PURE__ */ new Map(), committed: false, rolledBack: false };
|
|
1323
|
+
active = b;
|
|
1324
|
+
const bctx = {
|
|
1325
|
+
rollback: () => {
|
|
1326
|
+
b.rolledBack = true;
|
|
1327
|
+
}
|
|
1328
|
+
};
|
|
1329
|
+
let result;
|
|
1330
|
+
try {
|
|
1331
|
+
result = fn(bctx);
|
|
1332
|
+
} catch (e) {
|
|
1333
|
+
active = null;
|
|
1334
|
+
rollback(b);
|
|
1335
|
+
throw e;
|
|
1336
|
+
}
|
|
1337
|
+
active = null;
|
|
1338
|
+
if (b.rolledBack) rollback(b);
|
|
1339
|
+
else {
|
|
1340
|
+
commit(b);
|
|
1341
|
+
}
|
|
1342
|
+
return result;
|
|
1343
|
+
} finally {
|
|
1344
|
+
exitWave();
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
// src/json/codec.ts
|
|
1349
|
+
var JS_MIN_NORMAL_NUMBER = 2 ** -1022;
|
|
1350
|
+
function assertStableJsonNumber(value, path) {
|
|
1351
|
+
if (!Number.isFinite(value)) {
|
|
1352
|
+
throw new TypeError(`stableJsonString: non-finite number at ${path}`);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
function assertStrictJsonNumber(value, path) {
|
|
1356
|
+
assertStableJsonNumber(value, path);
|
|
1357
|
+
if (Object.is(value, -0)) {
|
|
1358
|
+
throw new TypeError(`stableJsonString: non-canonical number at ${path}`);
|
|
1359
|
+
}
|
|
1360
|
+
const abs = Math.abs(value);
|
|
1361
|
+
if (abs > 0 && abs < JS_MIN_NORMAL_NUMBER) {
|
|
1362
|
+
throw new TypeError(`stableJsonString: subnormal number at ${path}`);
|
|
1363
|
+
}
|
|
1364
|
+
if (Number.isInteger(value) && !Number.isSafeInteger(value)) {
|
|
1365
|
+
throw new TypeError(`stableJsonString: integer outside safe range at ${path}`);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
function sortedJsonValue(value, seen = /* @__PURE__ */ new Set(), path = "$", strictNumbers = false) {
|
|
1369
|
+
if (value === null) return null;
|
|
1370
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
1371
|
+
if (typeof value === "number") {
|
|
1372
|
+
if (strictNumbers) assertStrictJsonNumber(value, path);
|
|
1373
|
+
else assertStableJsonNumber(value, path);
|
|
1374
|
+
return value;
|
|
1375
|
+
}
|
|
1376
|
+
if (typeof value !== "object") {
|
|
1377
|
+
throw new TypeError(`stableJsonString: value at ${path} is not JSON-encodable`);
|
|
1378
|
+
}
|
|
1379
|
+
if (seen.has(value)) throw new TypeError(`stableJsonString: circular reference at ${path}`);
|
|
1380
|
+
const proto = Object.getPrototypeOf(value);
|
|
1381
|
+
if (!Array.isArray(value) && proto !== Object.prototype && proto !== null) {
|
|
1382
|
+
throw new TypeError(`stableJsonString: non-plain object at ${path}`);
|
|
1383
|
+
}
|
|
1384
|
+
seen.add(value);
|
|
1385
|
+
try {
|
|
1386
|
+
if (Array.isArray(value)) {
|
|
1387
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
1388
|
+
throw new TypeError(`stableJsonString: symbol-keyed properties at ${path}`);
|
|
1389
|
+
}
|
|
1390
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
1391
|
+
const isIndex = /^(0|[1-9]\d*)$/.test(key) && Number.isSafeInteger(Number(key)) && Number(key) < value.length;
|
|
1392
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1393
|
+
if (descriptor !== void 0 && ("get" in descriptor || "set" in descriptor)) {
|
|
1394
|
+
throw new TypeError(`stableJsonString: accessor property at ${path}.${key}`);
|
|
1395
|
+
}
|
|
1396
|
+
if (key !== "length" && !isIndex) {
|
|
1397
|
+
throw new TypeError(`stableJsonString: non-index array property at ${path}.${key}`);
|
|
1398
|
+
}
|
|
1399
|
+
if (key !== "length" && descriptor !== void 0 && !descriptor.enumerable) {
|
|
1400
|
+
throw new TypeError(`stableJsonString: non-enumerable array property at ${path}.${key}`);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
const out2 = [];
|
|
1404
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
1405
|
+
if (!(i in value)) {
|
|
1406
|
+
throw new TypeError(`stableJsonString: sparse array hole at ${path}[${i}]`);
|
|
1407
|
+
}
|
|
1408
|
+
out2.push(sortedJsonValue(value[i], seen, `${path}[${i}]`, strictNumbers));
|
|
1409
|
+
}
|
|
1410
|
+
return out2;
|
|
1411
|
+
}
|
|
1412
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
1413
|
+
throw new TypeError(`stableJsonString: symbol-keyed properties at ${path}`);
|
|
1414
|
+
}
|
|
1415
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
1416
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1417
|
+
if (descriptor !== void 0 && ("get" in descriptor || "set" in descriptor)) {
|
|
1418
|
+
throw new TypeError(`stableJsonString: accessor property at ${path}.${key}`);
|
|
1419
|
+
}
|
|
1420
|
+
if (descriptor !== void 0 && !descriptor.enumerable) {
|
|
1421
|
+
throw new TypeError(`stableJsonString: non-enumerable property at ${path}.${key}`);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
1425
|
+
for (const key of Object.keys(value).sort()) {
|
|
1426
|
+
out[key] = sortedJsonValue(
|
|
1427
|
+
value[key],
|
|
1428
|
+
seen,
|
|
1429
|
+
`${path}.${key}`,
|
|
1430
|
+
strictNumbers
|
|
1431
|
+
);
|
|
1432
|
+
}
|
|
1433
|
+
return out;
|
|
1434
|
+
} finally {
|
|
1435
|
+
seen.delete(value);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
function stableJsonString(value) {
|
|
1439
|
+
return JSON.stringify(sortedJsonValue(value));
|
|
1440
|
+
}
|
|
1441
|
+
function strictStableJsonString(value) {
|
|
1442
|
+
return JSON.stringify(sortedJsonValue(value, /* @__PURE__ */ new Set(), "$", true));
|
|
1443
|
+
}
|
|
1444
|
+
function jsonCodecFor() {
|
|
1445
|
+
const encoder = new TextEncoder();
|
|
1446
|
+
const decoder = new TextDecoder();
|
|
1447
|
+
return {
|
|
1448
|
+
encode(value) {
|
|
1449
|
+
return encoder.encode(stableJsonString(value));
|
|
1450
|
+
},
|
|
1451
|
+
decode(bytes) {
|
|
1452
|
+
return JSON.parse(decoder.decode(bytes));
|
|
1453
|
+
}
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
var jsonCodec = jsonCodecFor();
|
|
1457
|
+
function bytesEqual(a, b) {
|
|
1458
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
1459
|
+
for (let i = 0; i < a.byteLength; i += 1) {
|
|
1460
|
+
if (a[i] !== b[i]) return false;
|
|
1461
|
+
}
|
|
1462
|
+
return true;
|
|
1463
|
+
}
|
|
1464
|
+
function hasUnpairedSurrogate(value) {
|
|
1465
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
1466
|
+
const code = value.charCodeAt(i);
|
|
863
1467
|
if (code >= 55296 && code <= 56319) {
|
|
864
1468
|
const next = value.charCodeAt(i + 1);
|
|
865
1469
|
if (next >= 56320 && next <= 57343) {
|
|
@@ -1190,87 +1794,532 @@ function validateNodeVersionJson(value, path) {
|
|
|
1190
1794
|
throw new Error(`restoreGraph: ${path}.level must be 0 or 1`);
|
|
1191
1795
|
}
|
|
1192
1796
|
|
|
1193
|
-
// src/node/node.ts
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1797
|
+
// src/node/node-output-runtime.ts
|
|
1798
|
+
function nodeDown(self, msgs) {
|
|
1799
|
+
if (self._released) return;
|
|
1800
|
+
validateDownPayloads(msgs);
|
|
1801
|
+
const deliveryWave = {};
|
|
1802
|
+
const assertVersionDataCompatible = (wave) => {
|
|
1803
|
+
for (const m of wave) {
|
|
1804
|
+
if (m[0] === "DATA") assertNodeVersionDataCompatible(self._version.policy, m[1]);
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
const snapshotVersionData = (wave) => wave.map(
|
|
1808
|
+
(m) => m[0] === "DATA" ? ["DATA", snapshotNodeVersionData(self._version.policy, m[1])] : m
|
|
1809
|
+
);
|
|
1810
|
+
assertVersionDataCompatible(msgs);
|
|
1811
|
+
if (self._value.terminal !== void 0) {
|
|
1812
|
+
if (!msgs.some((m) => m[0] === "TEARDOWN")) return;
|
|
1813
|
+
self._value.hasTorndown = true;
|
|
1814
|
+
if (self._slot.resetOnTeardown) {
|
|
1815
|
+
self._value.cache = SENTINEL;
|
|
1816
|
+
self._value.hasData = false;
|
|
1817
|
+
}
|
|
1818
|
+
self._emitToSubs(["TEARDOWN"], { wave: deliveryWave, last: true });
|
|
1819
|
+
return;
|
|
1212
1820
|
}
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1821
|
+
let sorted = [...msgs].sort((a, b) => messageTier(a[0]) - messageTier(b[0]));
|
|
1822
|
+
const firstInvalidate = sorted.findIndex((m) => m[0] === "INVALIDATE");
|
|
1823
|
+
if (firstInvalidate !== -1) {
|
|
1824
|
+
sorted = sorted.filter((m, i) => m[0] !== "INVALIDATE" || i === firstInvalidate);
|
|
1825
|
+
}
|
|
1826
|
+
const hasTeardown = sorted.some((m) => m[0] === "TEARDOWN");
|
|
1827
|
+
const hasTerminal = sorted.some((m) => m[0] === "COMPLETE" || m[0] === "ERROR");
|
|
1828
|
+
if (hasTeardown && !hasTerminal && self._value.terminal === void 0 && !self._value.hasTorndown) {
|
|
1829
|
+
sorted = [["COMPLETE"], ...sorted];
|
|
1830
|
+
}
|
|
1831
|
+
if (!self._wave.insideRunWave && currentBatch()) {
|
|
1832
|
+
const deferred = snapshotVersionData(sorted.filter((m) => isDeferredTier(m[0])));
|
|
1833
|
+
if (deferred.length > 0) {
|
|
1834
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1835
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1836
|
+
self._value.status = "dirty";
|
|
1837
|
+
self._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1838
|
+
}
|
|
1839
|
+
self._wave.batchDirtyOwed = true;
|
|
1840
|
+
deferToBatch(self, deferred);
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1221
1843
|
}
|
|
1844
|
+
if (self._shouldBufferOnPause()) {
|
|
1845
|
+
const buffered = snapshotVersionData(sorted.filter((m) => isPauseBufferedTier(m[0])));
|
|
1846
|
+
if (buffered.length > 0) {
|
|
1847
|
+
self._wave.emittedSettleThisWave = true;
|
|
1848
|
+
self._control.pauseBuffer.push(buffered);
|
|
1849
|
+
}
|
|
1850
|
+
sorted = sorted.filter((m) => !isPauseBufferedTier(m[0]));
|
|
1851
|
+
if (sorted.length === 0) return;
|
|
1852
|
+
}
|
|
1853
|
+
let dataCount = 0;
|
|
1854
|
+
let hasTier3 = false;
|
|
1855
|
+
let hasResolved = false;
|
|
1856
|
+
for (const m of sorted) {
|
|
1857
|
+
if (m[0] === "DATA") dataCount++;
|
|
1858
|
+
if (m[0] === "RESOLVED") hasResolved = true;
|
|
1859
|
+
if (isValueTier(m[0])) hasTier3 = true;
|
|
1860
|
+
}
|
|
1861
|
+
if (dataCount >= 1 && hasResolved) {
|
|
1862
|
+
throw new Error(
|
|
1863
|
+
"down: a wave cannot mix DATA and RESOLVED (tier-3 exclusivity, R-resolved-undirty)"
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
const plannedVersions = new Array(sorted.length);
|
|
1867
|
+
if (dataCount > 0) {
|
|
1868
|
+
let plannedVersion = self._version.value;
|
|
1869
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1870
|
+
const m = sorted[i];
|
|
1871
|
+
if (m[0] !== "DATA") continue;
|
|
1872
|
+
plannedVersion = advanceNodeVersion(plannedVersion, self._version.policy, m[1]);
|
|
1873
|
+
plannedVersions[i] = plannedVersion;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
if (hasTier3 && (!self._wave.insideRunWave || self._control.pullDirtyOwed) && !self._wave.emittedDirtyThisWave) {
|
|
1877
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1878
|
+
self._value.status = "dirty";
|
|
1879
|
+
self._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1880
|
+
}
|
|
1881
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1882
|
+
const m = sorted[i];
|
|
1883
|
+
const delivery = { wave: deliveryWave, last: i === sorted.length - 1 };
|
|
1884
|
+
if (isDeferredTier(m[0])) self._wave.emittedSettleThisWave = true;
|
|
1885
|
+
if (m[0] === "DIRTY") {
|
|
1886
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1887
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1888
|
+
self._value.status = "dirty";
|
|
1889
|
+
self._emitToSubs(["DIRTY"], delivery);
|
|
1890
|
+
}
|
|
1891
|
+
continue;
|
|
1892
|
+
}
|
|
1893
|
+
if (m[0] === "DATA") {
|
|
1894
|
+
const v = m[1];
|
|
1895
|
+
self._value.cache = v;
|
|
1896
|
+
self._value.hasData = true;
|
|
1897
|
+
self._value.status = "settled";
|
|
1898
|
+
self._version.value = plannedVersions[i];
|
|
1899
|
+
if (self._slot.replayN > 0) {
|
|
1900
|
+
self._value.replayRing.push(v);
|
|
1901
|
+
if (self._value.replayRing.length > self._slot.replayN) self._value.replayRing.shift();
|
|
1902
|
+
}
|
|
1903
|
+
self._emitToSubs(["DATA", v], delivery);
|
|
1904
|
+
continue;
|
|
1905
|
+
}
|
|
1906
|
+
if (m[0] === "RESOLVED") {
|
|
1907
|
+
self._value.status = self._value.hasData ? "resolved" : "sentinel";
|
|
1908
|
+
self._emitToSubs(["RESOLVED"], delivery);
|
|
1909
|
+
continue;
|
|
1910
|
+
}
|
|
1911
|
+
if (m[0] === "INVALIDATE") {
|
|
1912
|
+
self._invalidate(delivery);
|
|
1913
|
+
continue;
|
|
1914
|
+
}
|
|
1915
|
+
if (m[0] === "COMPLETE") {
|
|
1916
|
+
if (self._value.terminal !== void 0) continue;
|
|
1917
|
+
self._value.terminal = true;
|
|
1918
|
+
self._control.pauseBuffer = [];
|
|
1919
|
+
self._value.status = "completed";
|
|
1920
|
+
self._emitToSubs(["COMPLETE"], delivery);
|
|
1921
|
+
continue;
|
|
1922
|
+
}
|
|
1923
|
+
if (m[0] === "ERROR") {
|
|
1924
|
+
if (self._value.terminal !== void 0) continue;
|
|
1925
|
+
self._value.terminal = m[1];
|
|
1926
|
+
self._control.pauseBuffer = [];
|
|
1927
|
+
self._value.status = "errored";
|
|
1928
|
+
self._emitToSubs(["ERROR", m[1]], delivery);
|
|
1929
|
+
continue;
|
|
1930
|
+
}
|
|
1931
|
+
if (m[0] === "TEARDOWN") {
|
|
1932
|
+
self._value.hasTorndown = true;
|
|
1933
|
+
if (self._slot.resetOnTeardown) {
|
|
1934
|
+
self._value.cache = SENTINEL;
|
|
1935
|
+
self._value.hasData = false;
|
|
1936
|
+
}
|
|
1937
|
+
self._emitToSubs(["TEARDOWN"], delivery);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
if (!self._wave.insideRunWave) self._wave.emittedDirtyThisWave = false;
|
|
1222
1941
|
}
|
|
1223
|
-
function
|
|
1224
|
-
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
|
|
1942
|
+
function nodeUp(self, msgs, towardDep, route) {
|
|
1943
|
+
if (self._released) return;
|
|
1944
|
+
const routeState = route ?? { demandFired: /* @__PURE__ */ new Map() };
|
|
1945
|
+
for (const m of msgs) {
|
|
1946
|
+
if (!isUpAllowed(m[0])) {
|
|
1947
|
+
throw new Error(
|
|
1948
|
+
`ctx.up: ${m[0]} is down-only (tier ${messageTier(m[0])}); up carries control tiers only (R-ctx-up)`
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
for (const m of msgs) {
|
|
1953
|
+
if (m[0] === "PAUSE") {
|
|
1954
|
+
self._pauseAcquire(m[1]);
|
|
1955
|
+
} else if (m[0] === "RESUME") {
|
|
1956
|
+
if (self._control.pauseLockset.has(m[1])) {
|
|
1957
|
+
self._pauseRelease(m[1]);
|
|
1958
|
+
} else {
|
|
1959
|
+
self._forwardUp(m, towardDep, routeState);
|
|
1960
|
+
}
|
|
1961
|
+
} else if (m[0] === "PULL") {
|
|
1962
|
+
const demand = normalizePullDemand(m[1]);
|
|
1963
|
+
if (self._slot.pull && demand.pullId === self._slot.pullLock) {
|
|
1964
|
+
if (!self._markDemandRouted(demand.pullId, routeState)) self._onDemand(demand);
|
|
1965
|
+
} else {
|
|
1966
|
+
self._forwardUp(["PULL", demand], towardDep, routeState);
|
|
1967
|
+
}
|
|
1968
|
+
} else if (self._slot.deps.length === 0) {
|
|
1969
|
+
if (m[0] === "INVALIDATE") self._down([["INVALIDATE"]]);
|
|
1970
|
+
} else {
|
|
1971
|
+
self._forwardUp(m, towardDep, routeState);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1228
1974
|
}
|
|
1229
|
-
function
|
|
1230
|
-
|
|
1975
|
+
function nodeMarkDemandRouted(self, lockId, route) {
|
|
1976
|
+
let holders = route.demandFired.get(lockId);
|
|
1977
|
+
if (holders === void 0) {
|
|
1978
|
+
holders = /* @__PURE__ */ new Set();
|
|
1979
|
+
route.demandFired.set(lockId, holders);
|
|
1980
|
+
}
|
|
1981
|
+
const node2 = self;
|
|
1982
|
+
if (holders.has(node2)) return true;
|
|
1983
|
+
holders.add(node2);
|
|
1984
|
+
return false;
|
|
1231
1985
|
}
|
|
1232
|
-
function
|
|
1233
|
-
|
|
1986
|
+
function nodeForwardUp(self, m, towardDep, route) {
|
|
1987
|
+
if (self._slot.deps.length === 0) return;
|
|
1988
|
+
if (towardDep !== void 0) {
|
|
1989
|
+
const d = self._slot.deps[towardDep];
|
|
1990
|
+
if (d !== void 0) nodeRuntimeHost(d)._up([m], void 0, route);
|
|
1991
|
+
} else {
|
|
1992
|
+
for (const dep of self._slot.deps) nodeRuntimeHost(dep)._up([m], void 0, route);
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
function nodeIsPaused(self) {
|
|
1996
|
+
return self._control.pauseLockset.size > 0;
|
|
1997
|
+
}
|
|
1998
|
+
function nodeHasBoundaryPauseLock(self) {
|
|
1999
|
+
if (self._slot.pausable === false) return false;
|
|
2000
|
+
return self._control.pauseLockset.size > 0;
|
|
2001
|
+
}
|
|
2002
|
+
function nodeIsAsyncPool(self) {
|
|
2003
|
+
return self._slot.handle !== null && self._slot.dispatcher.poolKind(self._slot.handle.poolId) === "async";
|
|
2004
|
+
}
|
|
2005
|
+
function nodePauseAcquire(self, lockId) {
|
|
2006
|
+
self._control.pauseLockset.add(lockId);
|
|
2007
|
+
}
|
|
2008
|
+
function nodePauseRelease(self, lockId) {
|
|
2009
|
+
if (!self._control.pauseLockset.has(lockId)) return;
|
|
2010
|
+
self._control.pauseLockset.delete(lockId);
|
|
2011
|
+
if (self._slot.pull && self._control.demandOwed !== void 0) self._fireOwedDemandIfReady();
|
|
2012
|
+
if (self._hasBoundaryPauseLock()) return;
|
|
2013
|
+
scheduleBoundaryDrain(self._core);
|
|
2014
|
+
if (self._slot.pull) return;
|
|
2015
|
+
self._onResume();
|
|
2016
|
+
}
|
|
2017
|
+
function nodeOnResume(self) {
|
|
2018
|
+
if (self._value.terminal !== void 0) {
|
|
2019
|
+
self._control.pauseBuffer = [];
|
|
2020
|
+
self._control.pausedDepWaveOccurred = false;
|
|
2021
|
+
self._control.demandOwed = void 0;
|
|
2022
|
+
self._control.activePull = void 0;
|
|
2023
|
+
self._control.pullDirtyOwed = false;
|
|
2024
|
+
return;
|
|
2025
|
+
}
|
|
2026
|
+
if (self._control.pauseBuffer.length > 0) {
|
|
2027
|
+
const buf = self._control.pauseBuffer;
|
|
2028
|
+
self._control.pauseBuffer = [];
|
|
2029
|
+
for (const wave of buf) self._down(wave);
|
|
2030
|
+
}
|
|
2031
|
+
if (self._control.pausedDepWaveOccurred) {
|
|
2032
|
+
self._control.pausedDepWaveOccurred = false;
|
|
2033
|
+
self._tryRun();
|
|
2034
|
+
}
|
|
1234
2035
|
}
|
|
1235
|
-
function
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
return read();
|
|
2036
|
+
function nodeCanFireDemand(self) {
|
|
2037
|
+
if (self._value.terminal !== void 0 || self._wave.pending > 0) return false;
|
|
2038
|
+
return self._control.pauseLockset.size === 0;
|
|
1239
2039
|
}
|
|
1240
|
-
function
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
2040
|
+
function nodeDeliverPullDemand(self, demand) {
|
|
2041
|
+
self._control.demandOwed = void 0;
|
|
2042
|
+
self._control.activePull = demand;
|
|
2043
|
+
self._control.inDeliverDemand = true;
|
|
2044
|
+
try {
|
|
2045
|
+
self._firePullDemand();
|
|
2046
|
+
} finally {
|
|
2047
|
+
self._control.activePull = void 0;
|
|
2048
|
+
self._control.inDeliverDemand = false;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
function nodeOnDemand(self, demand) {
|
|
2052
|
+
if (self._control.inDeliverDemand) return;
|
|
2053
|
+
if (self._canFireDemand()) self._deliverPullDemand(demand);
|
|
2054
|
+
else self._control.demandOwed = demand;
|
|
2055
|
+
}
|
|
2056
|
+
function nodeFirePullDemand(self) {
|
|
2057
|
+
let drainedBuffer = false;
|
|
2058
|
+
if (self._control.pauseBuffer.length > 0) {
|
|
2059
|
+
const buf = self._control.pauseBuffer;
|
|
2060
|
+
self._control.pauseBuffer = [];
|
|
2061
|
+
for (const wave of buf) self._down(wave);
|
|
2062
|
+
drainedBuffer = true;
|
|
2063
|
+
}
|
|
2064
|
+
if (drainedBuffer) return;
|
|
2065
|
+
if (self._control.pausedDepWaveOccurred) {
|
|
2066
|
+
const gated = self._slot.handle !== null && !self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled());
|
|
2067
|
+
if (self._wave.pending > 0 || gated) return;
|
|
2068
|
+
self._control.pausedDepWaveOccurred = false;
|
|
2069
|
+
self._wave.emittedDirtyThisWave = false;
|
|
2070
|
+
self._control.pullDirtyOwed = true;
|
|
2071
|
+
try {
|
|
2072
|
+
self._tryRun();
|
|
2073
|
+
} finally {
|
|
2074
|
+
self._control.pullDirtyOwed = false;
|
|
2075
|
+
}
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
if (self._slot.handle !== null) {
|
|
2079
|
+
if (!self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled())) return;
|
|
2080
|
+
self._wave.emittedDirtyThisWave = false;
|
|
2081
|
+
self._control.pullDirtyOwed = true;
|
|
2082
|
+
try {
|
|
2083
|
+
self._runWave();
|
|
2084
|
+
} finally {
|
|
2085
|
+
self._control.pullDirtyOwed = false;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
1244
2088
|
}
|
|
1245
|
-
function
|
|
1246
|
-
|
|
2089
|
+
function nodeFireOwedDemandIfReady(self) {
|
|
2090
|
+
if (self._control.inDeliverDemand) return;
|
|
2091
|
+
if (self._slot.pull && self._control.demandOwed !== void 0 && self._canFireDemand()) {
|
|
2092
|
+
self._deliverPullDemand(self._control.demandOwed);
|
|
2093
|
+
}
|
|
1247
2094
|
}
|
|
1248
|
-
function
|
|
1249
|
-
|
|
2095
|
+
function nodeShouldBufferOnPause(self) {
|
|
2096
|
+
if (self._slot.pausable === false) return false;
|
|
2097
|
+
if (!self._isPaused() && !self._isPullQuiet()) return false;
|
|
2098
|
+
if (self._slot.pausable === "resumeAll") return true;
|
|
2099
|
+
if (!self._wave.insideRunWave && self._isAsyncPool() && self._slot.deps.length > 0) return true;
|
|
2100
|
+
return false;
|
|
1250
2101
|
}
|
|
1251
|
-
function
|
|
1252
|
-
|
|
2102
|
+
function nodeInvalidate(self, delivery) {
|
|
2103
|
+
if (!self._value.hasData) return;
|
|
2104
|
+
self._value.cache = SENTINEL;
|
|
2105
|
+
self._value.hasData = false;
|
|
2106
|
+
self._value.status = "sentinel";
|
|
2107
|
+
self._value.replayRing = [];
|
|
2108
|
+
for (const fn of self._hooks.onInvalidate) fn();
|
|
2109
|
+
self._emitToSubs(["INVALIDATE"], delivery);
|
|
2110
|
+
}
|
|
2111
|
+
function nodeAllDepsTerminal(self) {
|
|
2112
|
+
if (self._slot.deps.length === 0) return false;
|
|
2113
|
+
for (const tm of self._dep.terminal) if (tm === void 0) return false;
|
|
2114
|
+
return true;
|
|
1253
2115
|
}
|
|
1254
|
-
function
|
|
1255
|
-
|
|
2116
|
+
function nodeResetLifecycle(self) {
|
|
2117
|
+
for (const u of self._dep.unsubs) if (u) u();
|
|
2118
|
+
self._dep.unsubs = [];
|
|
2119
|
+
self._dep.idxBoxes = [];
|
|
2120
|
+
self._lifecycle.subscribers.clear();
|
|
2121
|
+
self._lifecycle.activated = false;
|
|
2122
|
+
self._value.terminal = void 0;
|
|
2123
|
+
self._value.hasTorndown = false;
|
|
2124
|
+
self._wave.hasCalledFnOnce = false;
|
|
2125
|
+
self._resetDepState();
|
|
2126
|
+
self._control.pauseLockset.clear();
|
|
2127
|
+
self._control.pauseBuffer = [];
|
|
2128
|
+
self._control.pausedDepWaveOccurred = false;
|
|
2129
|
+
self._control.demandOwed = void 0;
|
|
2130
|
+
self._control.activePull = void 0;
|
|
2131
|
+
self._control.pullDirtyOwed = false;
|
|
2132
|
+
self._value.replayRing = [];
|
|
2133
|
+
const isCompute = self._slot.handle !== null || self._slot.deps.length > 0;
|
|
2134
|
+
if (isCompute) {
|
|
2135
|
+
self._value.cache = SENTINEL;
|
|
2136
|
+
self._value.hasData = false;
|
|
2137
|
+
self._value.status = "sentinel";
|
|
2138
|
+
} else {
|
|
2139
|
+
self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
2140
|
+
}
|
|
2141
|
+
if (!self._privateState.persist) self._privateState.value = SENTINEL;
|
|
2142
|
+
}
|
|
2143
|
+
function nodeEmitToSubs(self, msg, delivery) {
|
|
2144
|
+
if (self._released) return;
|
|
2145
|
+
const subs = [...self._lifecycle.subscribers];
|
|
2146
|
+
for (const sink of subs) sink(msg, delivery);
|
|
2147
|
+
}
|
|
2148
|
+
function nodeCommitBatchedWave(self, wave) {
|
|
2149
|
+
self._wave.batchDirtyOwed = false;
|
|
2150
|
+
self._down(wave);
|
|
2151
|
+
}
|
|
2152
|
+
function nodeRollbackBatched(self) {
|
|
2153
|
+
if (self._wave.batchDirtyOwed) {
|
|
2154
|
+
self._wave.batchDirtyOwed = false;
|
|
2155
|
+
self._wave.emittedDirtyThisWave = false;
|
|
2156
|
+
self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
2157
|
+
self._emitToSubs(["RESOLVED"]);
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
function nodeDeferBoundary(self, fn, batchToken) {
|
|
2161
|
+
deferRewire(self._core, fn, {
|
|
2162
|
+
batchToken,
|
|
2163
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
2164
|
+
});
|
|
1256
2165
|
}
|
|
1257
|
-
|
|
1258
|
-
|
|
2166
|
+
|
|
2167
|
+
// src/node/node-rewire-runtime.ts
|
|
2168
|
+
function nodeRequestRewireNext(self, op) {
|
|
2169
|
+
deferRewire(self._core, () => self._applyRewireNext(op), {
|
|
2170
|
+
batchToken: currentBoundaryBatchToken(),
|
|
2171
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
2172
|
+
});
|
|
1259
2173
|
}
|
|
1260
|
-
function
|
|
1261
|
-
|
|
2174
|
+
function nodeRequestUpNext(self, msgs, towardDep) {
|
|
2175
|
+
deferRewire(
|
|
2176
|
+
self._core,
|
|
2177
|
+
() => {
|
|
2178
|
+
if (!self._released) self._up(msgs, towardDep);
|
|
2179
|
+
},
|
|
2180
|
+
{
|
|
2181
|
+
batchToken: currentBoundaryBatchToken(),
|
|
2182
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
2183
|
+
}
|
|
2184
|
+
);
|
|
1262
2185
|
}
|
|
1263
|
-
function
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
2186
|
+
function nodeApplyRewireNext(self, op) {
|
|
2187
|
+
if (self._released) return;
|
|
2188
|
+
try {
|
|
2189
|
+
if (op.kind === "add") {
|
|
2190
|
+
const next = self._slot.deps.includes(op.dep) ? [...self._slot.deps] : [...self._slot.deps, op.dep];
|
|
2191
|
+
self._rewire(next, op.fn, { allowTerminalOwner: true });
|
|
2192
|
+
} else if (op.kind === "remove") {
|
|
2193
|
+
self._rewire(
|
|
2194
|
+
self._slot.deps.filter((d) => d !== op.dep),
|
|
2195
|
+
op.fn,
|
|
2196
|
+
{ allowTerminalOwner: true }
|
|
2197
|
+
);
|
|
2198
|
+
} else {
|
|
2199
|
+
self._rewire(self._dedupDeps(op.deps), op.fn, { allowTerminalOwner: true });
|
|
1267
2200
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
2201
|
+
} catch (e) {
|
|
2202
|
+
self._down([["ERROR", errorPayload(e, "rewireNext op failed")]]);
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
function nodeRewire(self, newDeps, fn, opts = {}) {
|
|
2206
|
+
const node2 = self;
|
|
2207
|
+
if (self._value.terminal !== void 0 && !opts.allowTerminalOwner)
|
|
2208
|
+
throw new Error(
|
|
2209
|
+
"rewire: node is terminal (completed/errored) \u2014 cannot rewire (R-rewire / D42)"
|
|
2210
|
+
);
|
|
2211
|
+
if (self._wave.insideRunWave)
|
|
2212
|
+
throw new Error(
|
|
2213
|
+
"rewire: mid-fn topology mutation \u2014 a fn mutating its own deps mid-wave is the feedback cycle (R-rewire / D37)"
|
|
2214
|
+
);
|
|
2215
|
+
if (self._wave.inDepMutation)
|
|
2216
|
+
throw new Error(
|
|
2217
|
+
"rewire: reentrant dep mutation \u2014 another replaceDeps/subscribeDep/unsubscribeDep is in flight (R-rewire)"
|
|
2218
|
+
);
|
|
2219
|
+
if (newDeps.includes(node2)) throw new Error("rewire: self-dependency rejected (R-rewire / D42)");
|
|
2220
|
+
const oldDeps = self._slot.deps;
|
|
2221
|
+
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
2222
|
+
for (const d of added) {
|
|
2223
|
+
if (self._reachableUpstream(d, node2))
|
|
2224
|
+
throw new Error(
|
|
2225
|
+
"rewire: would create a cycle \u2014 dep already transitively depends on this node (R-rewire / D42)"
|
|
2226
|
+
);
|
|
2227
|
+
const dep = nodeRuntimeHost(d);
|
|
2228
|
+
if (dep._value.terminal !== void 0 && !dep._slot.resubscribable)
|
|
2229
|
+
throw new Error(
|
|
2230
|
+
"rewire: cannot add a non-resubscribable terminal dep \u2014 would wedge (R-rewire / D42)"
|
|
2231
|
+
);
|
|
2232
|
+
self._assertRewireDepOwner(d);
|
|
2233
|
+
}
|
|
2234
|
+
if (deferAfterBatchForTarget(node2, () => {
|
|
2235
|
+
self._rewire(newDeps, fn, { ...opts, allowTerminalOwner: true });
|
|
2236
|
+
})) {
|
|
2237
|
+
return true;
|
|
2238
|
+
}
|
|
2239
|
+
if (!self._lifecycle.activated) self._restoredActivationPending = false;
|
|
2240
|
+
self._wave.inDepMutation = true;
|
|
2241
|
+
self._wave.rewireRunPending = false;
|
|
2242
|
+
let zeroDepUnDirty = false;
|
|
2243
|
+
try {
|
|
2244
|
+
const oldHandle = self._slot.handle;
|
|
2245
|
+
self._slot.handle = self._slot.dispatcher.register(fn, self._slot.pool);
|
|
2246
|
+
if (oldHandle !== null) self._slot.dispatcher.unregister(oldHandle);
|
|
2247
|
+
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
2248
|
+
let removedDirtyContributor = false;
|
|
2249
|
+
for (const d of removed) {
|
|
2250
|
+
const oldIdx = oldDeps.indexOf(d);
|
|
2251
|
+
if (self._dep.dirty[oldIdx]) {
|
|
2252
|
+
removedDirtyContributor = true;
|
|
2253
|
+
self._wave.pending--;
|
|
2254
|
+
}
|
|
2255
|
+
if (self._lifecycle.activated) {
|
|
2256
|
+
const box = self._dep.idxBoxes[oldIdx];
|
|
2257
|
+
if (box) box.v = -1;
|
|
2258
|
+
const unsub = self._dep.unsubs[oldIdx];
|
|
2259
|
+
if (unsub) unsub();
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
const n = newDeps.length;
|
|
2263
|
+
const newBatch = new Array(n).fill(null);
|
|
2264
|
+
const newPrev = new Array(n).fill(SENTINEL);
|
|
2265
|
+
const newHasData = new Array(n).fill(false);
|
|
2266
|
+
const newDirty = new Array(n).fill(false);
|
|
2267
|
+
const newTier = new Array(n).fill(0);
|
|
2268
|
+
const newTerminal = new Array(n).fill(void 0);
|
|
2269
|
+
const newTerminalInput = new Array(n).fill(void 0);
|
|
2270
|
+
const newUnsubs = new Array(n);
|
|
2271
|
+
const newBoxes = new Array(n);
|
|
2272
|
+
for (let j = 0; j < n; j++) {
|
|
2273
|
+
const oldIdx = oldDeps.indexOf(newDeps[j]);
|
|
2274
|
+
if (oldIdx !== -1) {
|
|
2275
|
+
newBatch[j] = self._dep.batch[oldIdx];
|
|
2276
|
+
newPrev[j] = self._dep.prev[oldIdx];
|
|
2277
|
+
newHasData[j] = self._dep.hasData[oldIdx];
|
|
2278
|
+
newDirty[j] = self._dep.dirty[oldIdx];
|
|
2279
|
+
newTier[j] = self._dep.tier[oldIdx];
|
|
2280
|
+
newTerminal[j] = self._dep.terminal[oldIdx];
|
|
2281
|
+
newUnsubs[j] = self._dep.unsubs[oldIdx];
|
|
2282
|
+
const box = self._dep.idxBoxes[oldIdx];
|
|
2283
|
+
if (box) box.v = j;
|
|
2284
|
+
newBoxes[j] = box;
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
self._slot.deps = newDeps;
|
|
2288
|
+
self._dep.batch = newBatch;
|
|
2289
|
+
self._dep.prev = newPrev;
|
|
2290
|
+
self._dep.hasData = newHasData;
|
|
2291
|
+
self._dep.dirty = newDirty;
|
|
2292
|
+
self._dep.tier = newTier;
|
|
2293
|
+
self._dep.terminal = newTerminal;
|
|
2294
|
+
self._dep.terminalInput = newTerminalInput;
|
|
2295
|
+
self._dep.unsubs = newUnsubs;
|
|
2296
|
+
self._dep.idxBoxes = newBoxes;
|
|
2297
|
+
self._dep.waveData = newDeps.map(() => []);
|
|
2298
|
+
self._dep.waveTokens = new Array(newDeps.length).fill(void 0);
|
|
2299
|
+
self._syncCtx = null;
|
|
2300
|
+
if (self._lifecycle.activated) {
|
|
2301
|
+
for (const d of added) self._subscribeDepAt(d);
|
|
2302
|
+
}
|
|
2303
|
+
notifyTopologyDepsChanged(node2, oldDeps, newDeps);
|
|
2304
|
+
if (removedDirtyContributor && self._wave.pending === 0 && self._value.status === "dirty") {
|
|
2305
|
+
if (newDeps.length > 0) self._wave.rewireRunPending = true;
|
|
2306
|
+
else zeroDepUnDirty = true;
|
|
1270
2307
|
}
|
|
2308
|
+
} finally {
|
|
2309
|
+
self._wave.inDepMutation = false;
|
|
1271
2310
|
}
|
|
2311
|
+
if (self._wave.rewireRunPending) {
|
|
2312
|
+
self._wave.rewireRunPending = false;
|
|
2313
|
+
self._settleRewire();
|
|
2314
|
+
} else if (zeroDepUnDirty) {
|
|
2315
|
+
if (self._wave.emittedDirtyThisWave) self._down([["RESOLVED"]]);
|
|
2316
|
+
else self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
2317
|
+
}
|
|
2318
|
+
return false;
|
|
1272
2319
|
}
|
|
1273
|
-
|
|
2320
|
+
|
|
2321
|
+
// src/node/node.ts
|
|
2322
|
+
var Node = class _Node {
|
|
1274
2323
|
_core;
|
|
1275
2324
|
_id;
|
|
1276
2325
|
_slot;
|
|
@@ -1291,19 +2340,63 @@ var Node = class {
|
|
|
1291
2340
|
set _syncCtx(ctx) {
|
|
1292
2341
|
this._syncCtxState.value = ctx;
|
|
1293
2342
|
}
|
|
2343
|
+
static _retainIndirectRuntimeMethods(node2) {
|
|
2344
|
+
void node2._dep;
|
|
2345
|
+
void node2._hooks;
|
|
2346
|
+
void node2._restoredActivationPending;
|
|
2347
|
+
void node2._requestRewireNext;
|
|
2348
|
+
void node2._requestUpNext;
|
|
2349
|
+
void node2._applyRewireNext;
|
|
2350
|
+
void node2._reachableUpstream;
|
|
2351
|
+
void node2._assertRewireDepOwner;
|
|
2352
|
+
void node2._subscribeDepAt;
|
|
2353
|
+
void node2._seedRestoredDepAt;
|
|
2354
|
+
void node2._recordDepProjection;
|
|
2355
|
+
void node2._depProjectionHasData;
|
|
2356
|
+
void node2._receiveFromDep;
|
|
2357
|
+
void node2._releaseDepDirty;
|
|
2358
|
+
void node2._settleAfterAbsorbedTerminal;
|
|
2359
|
+
void node2._markDirty;
|
|
2360
|
+
void node2._maybeRun;
|
|
2361
|
+
void node2._settleRewire;
|
|
2362
|
+
void node2._tryRun;
|
|
2363
|
+
void node2._allDepsSettled;
|
|
2364
|
+
void node2._passthroughEmit;
|
|
2365
|
+
void node2._runWave;
|
|
2366
|
+
void node2._buildCtx;
|
|
2367
|
+
void node2._makeCtx;
|
|
2368
|
+
void node2._refreshCtx;
|
|
2369
|
+
void node2._makeState;
|
|
2370
|
+
void node2._markDemandRouted;
|
|
2371
|
+
void node2._forwardUp;
|
|
2372
|
+
void node2._isPullQuiet;
|
|
2373
|
+
void node2._isPaused;
|
|
2374
|
+
void node2._hasBoundaryPauseLock;
|
|
2375
|
+
void node2._isAsyncPool;
|
|
2376
|
+
void node2._pauseAcquire;
|
|
2377
|
+
void node2._pauseRelease;
|
|
2378
|
+
void node2._onResume;
|
|
2379
|
+
void node2._canFireDemand;
|
|
2380
|
+
void node2._deliverPullDemand;
|
|
2381
|
+
void node2._onDemand;
|
|
2382
|
+
void node2._firePullDemand;
|
|
2383
|
+
void node2._fireOwedDemandIfReady;
|
|
2384
|
+
void node2._shouldBufferOnPause;
|
|
2385
|
+
void node2._invalidate;
|
|
2386
|
+
void node2._allDepsTerminal;
|
|
2387
|
+
void node2._emitToSubs;
|
|
2388
|
+
}
|
|
1294
2389
|
constructor(deps, handleOrFn, opts = {}) {
|
|
1295
|
-
const core =
|
|
1296
|
-
constructingCore = void 0;
|
|
2390
|
+
const core = takeConstructingNodeCore();
|
|
1297
2391
|
const dispatcher = opts.dispatcher ?? defaultDispatcher;
|
|
1298
|
-
const environment =
|
|
1299
|
-
constructingEnvironment = void 0;
|
|
2392
|
+
const environment = takeConstructingEnvironmentDrivers() ?? EnvironmentDrivers.empty();
|
|
1300
2393
|
const pool = opts.pool ?? "sync";
|
|
1301
2394
|
const pausable = opts.pausable ?? true;
|
|
1302
2395
|
const pullLock = opts.pullId;
|
|
1303
2396
|
const pull = opts.pullId !== void 0;
|
|
1304
2397
|
if (pull && pausable === false)
|
|
1305
2398
|
throw new Error(
|
|
1306
|
-
"node: pullId is incompatible with pausable:false \u2014 a pull node
|
|
2399
|
+
"node: pullId is incompatible with pausable:false \u2014 a pull node uses the pausable delivery-content axis (R-pull / R-pause-modes / D55,D269)"
|
|
1307
2400
|
);
|
|
1308
2401
|
let handle;
|
|
1309
2402
|
if (handleOrFn === null) handle = null;
|
|
@@ -1326,7 +2419,6 @@ var Node = class {
|
|
|
1326
2419
|
value.status = "settled";
|
|
1327
2420
|
}
|
|
1328
2421
|
const pauseLockset = /* @__PURE__ */ new Set();
|
|
1329
|
-
if (pull) pauseLockset.add(pullLock);
|
|
1330
2422
|
this._core = core ?? new NodeCore();
|
|
1331
2423
|
const created = this._core.createSlot(
|
|
1332
2424
|
{
|
|
@@ -1367,7 +2459,9 @@ var Node = class {
|
|
|
1367
2459
|
pauseLockset,
|
|
1368
2460
|
pausedDepWaveOccurred: false,
|
|
1369
2461
|
pauseBuffer: [],
|
|
1370
|
-
demandOwed:
|
|
2462
|
+
demandOwed: void 0,
|
|
2463
|
+
activePull: void 0,
|
|
2464
|
+
pullDirtyOwed: false,
|
|
1371
2465
|
inDeliverDemand: false
|
|
1372
2466
|
},
|
|
1373
2467
|
privateState: { value: SENTINEL, persist: false },
|
|
@@ -1424,10 +2518,11 @@ var Node = class {
|
|
|
1424
2518
|
this._wave.batchDirtyOwed = false;
|
|
1425
2519
|
this._control.pauseBuffer = [];
|
|
1426
2520
|
this._control.pausedDepWaveOccurred = false;
|
|
1427
|
-
this._control.demandOwed =
|
|
2521
|
+
this._control.demandOwed = void 0;
|
|
2522
|
+
this._control.activePull = void 0;
|
|
2523
|
+
this._control.pullDirtyOwed = false;
|
|
1428
2524
|
this._control.inDeliverDemand = false;
|
|
1429
2525
|
this._control.pauseLockset.clear();
|
|
1430
|
-
if (this._slot.pull) this._control.pauseLockset.add(this._slot.pullLock);
|
|
1431
2526
|
this._privateState.value = state.ctxState.value;
|
|
1432
2527
|
this._privateState.persist = state.ctxState.persist;
|
|
1433
2528
|
if (state.version === false) {
|
|
@@ -1465,18 +2560,18 @@ var Node = class {
|
|
|
1465
2560
|
runtimeQuiescenceReaders.set(this, () => this._isRuntimeQuiescentForRelease());
|
|
1466
2561
|
subscriberCountReaders.set(this, () => this._subscriberCount());
|
|
1467
2562
|
activationReaders.set(this, () => this._lifecycle.activated);
|
|
2563
|
+
_Node._retainIndirectRuntimeMethods(this);
|
|
1468
2564
|
}
|
|
1469
|
-
/** R-pull (D55): true while a pull node is
|
|
2565
|
+
/** R-pull (D55/D272): true while a pull node is not serving a PULL demand pulse. */
|
|
1470
2566
|
_isPullQuiet() {
|
|
1471
|
-
return this._slot.pull && this._control.
|
|
2567
|
+
return this._slot.pull && this._control.activePull === void 0;
|
|
1472
2568
|
}
|
|
1473
2569
|
/**
|
|
1474
|
-
* R-pull (
|
|
1475
|
-
* triggers computation). A consumer demands one delivery by cone-routing
|
|
1476
|
-
* reference): `ctx.up([["
|
|
1477
|
-
* `ctx.upNext([["
|
|
1478
|
-
*
|
|
1479
|
-
* for inspection/describe; routing matches by the pullId value carried in the RESUME, by identity.
|
|
2570
|
+
* R-pull (D269/D272): this pull node's pullId (pure data, like {@link cache}/{@link handle} —
|
|
2571
|
+
* never triggers computation). A consumer demands one delivery by cone-routing PULL of it (no
|
|
2572
|
+
* node reference): `ctx.up([["PULL", { pullId }]])` (immediate; loops back → D37 for a self-read
|
|
2573
|
+
* dep) or `ctx.upNext([["PULL", { pullId }]])` (boundary-deferred self-demand). Undefined for a
|
|
2574
|
+
* non-pull node. The author writes the pullId verbatim; routing matches by identity.
|
|
1480
2575
|
*/
|
|
1481
2576
|
get pullId() {
|
|
1482
2577
|
return this._slot.pullLock;
|
|
@@ -1570,58 +2665,6 @@ var Node = class {
|
|
|
1570
2665
|
exitWave();
|
|
1571
2666
|
}
|
|
1572
2667
|
}
|
|
1573
|
-
// ── deferred self-rewire (R-rewire-deferred / D47): ctx.rewireNext drain support ──
|
|
1574
|
-
/**
|
|
1575
|
-
* Enqueue a deferred self-rewire op (issued from this node's fn via `ctx.rewireNext`).
|
|
1576
|
-
* Applied at the committed wave boundary (boundary.ts drain), never in place — the in-fn
|
|
1577
|
-
* immediate path (`subscribeDep`/`replaceDeps`/`unsubscribeDep`) still throws mid-run (D37/R-reentrancy).
|
|
1578
|
-
*/
|
|
1579
|
-
_requestRewireNext(op) {
|
|
1580
|
-
deferRewire(this._core, () => this._applyRewireNext(op), {
|
|
1581
|
-
batchToken: currentBoundaryBatchToken(),
|
|
1582
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
1583
|
-
});
|
|
1584
|
-
}
|
|
1585
|
-
/**
|
|
1586
|
-
* Enqueue a deferred up-going control wave (R-up-routing / R-pull / D59): at the committed wave
|
|
1587
|
-
* boundary, route `msgs` up from THIS node (broadcast, or up the single `towardDep` edge). The
|
|
1588
|
-
* deferred form of `ctx.up` — the SELF-demand path: a consumer issues `ctx.upNext([[RESUME,
|
|
1589
|
-
* pullId]])` to demand a dep it ALSO reads; the demand applies at the boundary (not mid-fn), so
|
|
1590
|
-
* the pull node's delivery loops back as a FRESH wave rather than re-entering the consumer (D37 /
|
|
1591
|
-
* R-reentrancy). Rides the same R-rewire-deferred (D47) drain as ctx.rewireNext.
|
|
1592
|
-
*/
|
|
1593
|
-
_requestUpNext(msgs, towardDep) {
|
|
1594
|
-
deferRewire(
|
|
1595
|
-
this._core,
|
|
1596
|
-
() => {
|
|
1597
|
-
if (!this._released) this._up(msgs, towardDep);
|
|
1598
|
-
},
|
|
1599
|
-
{
|
|
1600
|
-
batchToken: currentBoundaryBatchToken(),
|
|
1601
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
1602
|
-
}
|
|
1603
|
-
);
|
|
1604
|
-
}
|
|
1605
|
-
/** Apply one queued self-rewire at the boundary (drain thunk). */
|
|
1606
|
-
_applyRewireNext(op) {
|
|
1607
|
-
if (this._released) return;
|
|
1608
|
-
try {
|
|
1609
|
-
if (op.kind === "add") {
|
|
1610
|
-
const next = this._slot.deps.includes(op.dep) ? [...this._slot.deps] : [...this._slot.deps, op.dep];
|
|
1611
|
-
this._rewire(next, op.fn, { allowTerminalOwner: true });
|
|
1612
|
-
} else if (op.kind === "remove") {
|
|
1613
|
-
this._rewire(
|
|
1614
|
-
this._slot.deps.filter((d) => d !== op.dep),
|
|
1615
|
-
op.fn,
|
|
1616
|
-
{ allowTerminalOwner: true }
|
|
1617
|
-
);
|
|
1618
|
-
} else {
|
|
1619
|
-
this._rewire(this._dedupDeps(op.deps), op.fn, { allowTerminalOwner: true });
|
|
1620
|
-
}
|
|
1621
|
-
} catch (e) {
|
|
1622
|
-
this._down([["ERROR", errorPayload(e, "rewireNext op failed")]]);
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
2668
|
// ── rewire (R-rewire / D42): intra-graph runtime topology mutation ──
|
|
1626
2669
|
/**
|
|
1627
2670
|
* Replace this node's deps atomically (surgical, Option-C). Requires an explicit
|
|
@@ -1649,6 +2692,15 @@ var Node = class {
|
|
|
1649
2692
|
fn
|
|
1650
2693
|
);
|
|
1651
2694
|
}
|
|
2695
|
+
_requestRewireNext(op) {
|
|
2696
|
+
nodeRequestRewireNext(nodeRuntimeHost(this), op);
|
|
2697
|
+
}
|
|
2698
|
+
_requestUpNext(msgs, towardDep) {
|
|
2699
|
+
nodeRequestUpNext(nodeRuntimeHost(this), msgs, towardDep);
|
|
2700
|
+
}
|
|
2701
|
+
_applyRewireNext(op) {
|
|
2702
|
+
nodeApplyRewireNext(nodeRuntimeHost(this), op);
|
|
2703
|
+
}
|
|
1652
2704
|
_dedupDeps(deps) {
|
|
1653
2705
|
const seen = /* @__PURE__ */ new Set();
|
|
1654
2706
|
const out = [];
|
|
@@ -1659,7 +2711,6 @@ var Node = class {
|
|
|
1659
2711
|
}
|
|
1660
2712
|
return out;
|
|
1661
2713
|
}
|
|
1662
|
-
/** Is `target` reachable upstream from `from` (following deps)? Cycle-prevention DFS. */
|
|
1663
2714
|
_reachableUpstream(from, target) {
|
|
1664
2715
|
const seen = /* @__PURE__ */ new Set();
|
|
1665
2716
|
const stack = [from];
|
|
@@ -1669,1025 +2720,171 @@ var Node = class {
|
|
|
1669
2720
|
if (n === target) return true;
|
|
1670
2721
|
if (seen.has(n)) continue;
|
|
1671
2722
|
seen.add(n);
|
|
1672
|
-
for (const d of n._slot.deps) stack.push(d);
|
|
2723
|
+
for (const d of nodeRuntimeHost(n)._slot.deps) stack.push(d);
|
|
1673
2724
|
}
|
|
1674
2725
|
return false;
|
|
1675
2726
|
}
|
|
1676
2727
|
_assertRewireDepOwner(dep) {
|
|
1677
2728
|
const selfOwner = getNodeOwner(this);
|
|
1678
2729
|
const depOwner = getNodeOwner(dep);
|
|
1679
|
-
if (selfOwner !== void 0 && depOwner !== void 0 && selfOwner !== depOwner)
|
|
2730
|
+
if (selfOwner !== void 0 && depOwner !== void 0 && selfOwner !== depOwner)
|
|
1680
2731
|
throw new Error(
|
|
1681
2732
|
"rewire: dep belongs to a different graph; cross-graph deps require a wire bridge (D22 / R-graph-domain)"
|
|
1682
2733
|
);
|
|
1683
|
-
}
|
|
1684
2734
|
}
|
|
1685
2735
|
_rewire(newDeps, fn, opts = {}) {
|
|
1686
|
-
|
|
1687
|
-
throw new Error(
|
|
1688
|
-
"rewire: node is terminal (completed/errored) \u2014 cannot rewire (R-rewire / D42)"
|
|
1689
|
-
);
|
|
1690
|
-
if (this._wave.insideRunWave)
|
|
1691
|
-
throw new Error(
|
|
1692
|
-
"rewire: mid-fn topology mutation \u2014 a fn mutating its own deps mid-wave is the feedback cycle (R-rewire / D37)"
|
|
1693
|
-
);
|
|
1694
|
-
if (this._wave.inDepMutation)
|
|
1695
|
-
throw new Error(
|
|
1696
|
-
"rewire: reentrant dep mutation \u2014 another replaceDeps/subscribeDep/unsubscribeDep is in flight (R-rewire)"
|
|
1697
|
-
);
|
|
1698
|
-
if (newDeps.includes(this))
|
|
1699
|
-
throw new Error("rewire: self-dependency rejected (R-rewire / D42)");
|
|
1700
|
-
const oldDeps = this._slot.deps;
|
|
1701
|
-
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
1702
|
-
for (const d of added) {
|
|
1703
|
-
if (this._reachableUpstream(d, this))
|
|
1704
|
-
throw new Error(
|
|
1705
|
-
"rewire: would create a cycle \u2014 dep already transitively depends on this node (R-rewire / D42)"
|
|
1706
|
-
);
|
|
1707
|
-
if (d._value.terminal !== void 0 && !d._slot.resubscribable)
|
|
1708
|
-
throw new Error(
|
|
1709
|
-
"rewire: cannot add a non-resubscribable terminal dep \u2014 would wedge (R-rewire / D42)"
|
|
1710
|
-
);
|
|
1711
|
-
this._assertRewireDepOwner(d);
|
|
1712
|
-
}
|
|
1713
|
-
if (deferAfterBatchForTarget(this, () => {
|
|
1714
|
-
this._rewire(newDeps, fn, { ...opts, allowTerminalOwner: true });
|
|
1715
|
-
})) {
|
|
1716
|
-
return true;
|
|
1717
|
-
}
|
|
1718
|
-
if (!this._lifecycle.activated) this._restoredActivationPending = false;
|
|
1719
|
-
this._wave.inDepMutation = true;
|
|
1720
|
-
this._wave.rewireRunPending = false;
|
|
1721
|
-
let zeroDepUnDirty = false;
|
|
1722
|
-
try {
|
|
1723
|
-
const oldHandle = this._slot.handle;
|
|
1724
|
-
this._slot.handle = this._slot.dispatcher.register(fn, this._slot.pool);
|
|
1725
|
-
if (oldHandle !== null) this._slot.dispatcher.unregister(oldHandle);
|
|
1726
|
-
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
1727
|
-
let removedDirtyContributor = false;
|
|
1728
|
-
for (const d of removed) {
|
|
1729
|
-
const oldIdx = oldDeps.indexOf(d);
|
|
1730
|
-
if (this._dep.dirty[oldIdx]) {
|
|
1731
|
-
removedDirtyContributor = true;
|
|
1732
|
-
this._wave.pending--;
|
|
1733
|
-
}
|
|
1734
|
-
if (this._lifecycle.activated) {
|
|
1735
|
-
const box = this._dep.idxBoxes[oldIdx];
|
|
1736
|
-
if (box) box.v = -1;
|
|
1737
|
-
const unsub = this._dep.unsubs[oldIdx];
|
|
1738
|
-
if (unsub) unsub();
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
const n = newDeps.length;
|
|
1742
|
-
const newBatch = new Array(n).fill(null);
|
|
1743
|
-
const newPrev = new Array(n).fill(SENTINEL);
|
|
1744
|
-
const newHasData = new Array(n).fill(false);
|
|
1745
|
-
const newDirty = new Array(n).fill(false);
|
|
1746
|
-
const newTier = new Array(n).fill(0);
|
|
1747
|
-
const newTerminal = new Array(n).fill(void 0);
|
|
1748
|
-
const newTerminalInput = new Array(n).fill(void 0);
|
|
1749
|
-
const newUnsubs = new Array(n);
|
|
1750
|
-
const newBoxes = new Array(n);
|
|
1751
|
-
for (let j = 0; j < n; j++) {
|
|
1752
|
-
const oldIdx = oldDeps.indexOf(newDeps[j]);
|
|
1753
|
-
if (oldIdx !== -1) {
|
|
1754
|
-
newBatch[j] = this._dep.batch[oldIdx];
|
|
1755
|
-
newPrev[j] = this._dep.prev[oldIdx];
|
|
1756
|
-
newHasData[j] = this._dep.hasData[oldIdx];
|
|
1757
|
-
newDirty[j] = this._dep.dirty[oldIdx];
|
|
1758
|
-
newTier[j] = this._dep.tier[oldIdx];
|
|
1759
|
-
newTerminal[j] = this._dep.terminal[oldIdx];
|
|
1760
|
-
newUnsubs[j] = this._dep.unsubs[oldIdx];
|
|
1761
|
-
const box = this._dep.idxBoxes[oldIdx];
|
|
1762
|
-
if (box) box.v = j;
|
|
1763
|
-
newBoxes[j] = box;
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
this._slot.deps = newDeps;
|
|
1767
|
-
this._dep.batch = newBatch;
|
|
1768
|
-
this._dep.prev = newPrev;
|
|
1769
|
-
this._dep.hasData = newHasData;
|
|
1770
|
-
this._dep.dirty = newDirty;
|
|
1771
|
-
this._dep.tier = newTier;
|
|
1772
|
-
this._dep.terminal = newTerminal;
|
|
1773
|
-
this._dep.terminalInput = newTerminalInput;
|
|
1774
|
-
this._dep.unsubs = newUnsubs;
|
|
1775
|
-
this._dep.idxBoxes = newBoxes;
|
|
1776
|
-
this._dep.waveData = newDeps.map(() => []);
|
|
1777
|
-
this._dep.waveTokens = new Array(newDeps.length).fill(void 0);
|
|
1778
|
-
this._syncCtx = null;
|
|
1779
|
-
if (this._lifecycle.activated) {
|
|
1780
|
-
for (const d of added) this._subscribeDepAt(d);
|
|
1781
|
-
}
|
|
1782
|
-
notifyTopologyDepsChanged(this, oldDeps, newDeps);
|
|
1783
|
-
if (removedDirtyContributor && this._wave.pending === 0 && this._value.status === "dirty") {
|
|
1784
|
-
if (newDeps.length > 0) this._wave.rewireRunPending = true;
|
|
1785
|
-
else zeroDepUnDirty = true;
|
|
1786
|
-
}
|
|
1787
|
-
} finally {
|
|
1788
|
-
this._wave.inDepMutation = false;
|
|
1789
|
-
}
|
|
1790
|
-
if (this._wave.rewireRunPending) {
|
|
1791
|
-
this._wave.rewireRunPending = false;
|
|
1792
|
-
this._settleRewire();
|
|
1793
|
-
} else if (zeroDepUnDirty) {
|
|
1794
|
-
if (this._wave.emittedDirtyThisWave) this._down([["RESOLVED"]]);
|
|
1795
|
-
else this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
1796
|
-
}
|
|
1797
|
-
return false;
|
|
2736
|
+
return nodeRewire(nodeRuntimeHost(this), newDeps, fn, opts);
|
|
1798
2737
|
}
|
|
1799
2738
|
// ── activation / deactivation (lazy; R-rom-ram) ──
|
|
1800
2739
|
_activate() {
|
|
1801
|
-
this
|
|
1802
|
-
const seedRestoredDeps = this._restoredActivationPending;
|
|
1803
|
-
this._restoredActivationPending = false;
|
|
1804
|
-
if (this._slot.pull) this._control.pauseLockset.add(this._slot.pullLock);
|
|
1805
|
-
this._dep.unsubs = new Array(this._slot.deps.length);
|
|
1806
|
-
this._dep.idxBoxes = new Array(this._slot.deps.length);
|
|
1807
|
-
for (const dep of this._slot.deps)
|
|
1808
|
-
this._subscribeDepAt(dep, { seedRestored: seedRestoredDeps });
|
|
1809
|
-
if (this._slot.deps.length === 0 && this._slot.handle !== null && !this._wave.hasCalledFnOnce) {
|
|
1810
|
-
this._runWave();
|
|
1811
|
-
}
|
|
1812
|
-
}
|
|
1813
|
-
/**
|
|
1814
|
-
* Subscribe to a dep. The dispatch callback reads the dep's CURRENT index from a
|
|
1815
|
-
* mutable box (O(1)); a surgical rewire that reorders kept deps just updates the box
|
|
1816
|
-
* (R-rewire Option-C / D42) — no re-subscribe, no per-message indexOf scan. A removed
|
|
1817
|
-
* dep's box is set to -1 so any stale in-flight callback drops (drain).
|
|
1818
|
-
*/
|
|
1819
|
-
_subscribeDepAt(depNode, opts = {}) {
|
|
1820
|
-
const idx0 = this._slot.deps.indexOf(depNode);
|
|
1821
|
-
const box = { v: idx0 };
|
|
1822
|
-
let ignoreInitialPush = opts.seedRestored === true;
|
|
1823
|
-
if (ignoreInitialPush && idx0 !== -1) {
|
|
1824
|
-
this._seedRestoredDepAt(idx0, depNode);
|
|
1825
|
-
if (depNode._value.terminal !== void 0 && !depNode._slot.resubscribable) {
|
|
1826
|
-
this._dep.unsubs[idx0] = () => {
|
|
1827
|
-
};
|
|
1828
|
-
this._dep.idxBoxes[idx0] = box;
|
|
1829
|
-
return;
|
|
1830
|
-
}
|
|
1831
|
-
}
|
|
1832
|
-
const unsub = depNode.subscribe((msg, delivery) => {
|
|
1833
|
-
if (ignoreInitialPush && delivery === void 0) return;
|
|
1834
|
-
if (ignoreInitialPush) ignoreInitialPush = false;
|
|
1835
|
-
if (box.v === -1) return;
|
|
1836
|
-
this._receiveFromDep(box.v, msg, delivery);
|
|
1837
|
-
});
|
|
1838
|
-
if (ignoreInitialPush && idx0 !== -1 && box.v !== -1) this._seedRestoredDepAt(idx0, depNode);
|
|
1839
|
-
ignoreInitialPush = false;
|
|
1840
|
-
if (idx0 !== -1) {
|
|
1841
|
-
this._dep.unsubs[idx0] = unsub;
|
|
1842
|
-
this._dep.idxBoxes[idx0] = box;
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
_seedRestoredDepAt(idx, depNode) {
|
|
1846
|
-
const seedData = depNode._value.hasData && !depNode._slot.pull;
|
|
1847
|
-
this._dep.batch[idx] = null;
|
|
1848
|
-
this._dep.waveData[idx] = [];
|
|
1849
|
-
this._dep.waveTokens[idx] = void 0;
|
|
1850
|
-
this._dep.prev[idx] = seedData ? depNode._value.cache : SENTINEL;
|
|
1851
|
-
this._dep.hasData[idx] = seedData;
|
|
1852
|
-
this._dep.dirty[idx] = false;
|
|
1853
|
-
this._dep.tier[idx] = seedData ? 3 : 0;
|
|
1854
|
-
this._dep.terminal[idx] = depNode._value.terminal;
|
|
1855
|
-
this._dep.terminalInput[idx] = void 0;
|
|
2740
|
+
nodeActivate(nodeRuntimeHost(this));
|
|
1856
2741
|
}
|
|
1857
2742
|
_deactivate() {
|
|
1858
|
-
this
|
|
1859
|
-
for (const u of this._dep.unsubs) if (u) u();
|
|
1860
|
-
this._dep.unsubs = [];
|
|
1861
|
-
this._dep.idxBoxes = [];
|
|
1862
|
-
for (const fn of this._hooks.onDeactivation) fn();
|
|
1863
|
-
this._hooks.onDeactivation = [];
|
|
1864
|
-
this._hooks.onInvalidate = [];
|
|
1865
|
-
const isCompute = this._slot.handle !== null || this._slot.deps.length > 0;
|
|
1866
|
-
if (isCompute) {
|
|
1867
|
-
this._value.cache = SENTINEL;
|
|
1868
|
-
this._value.hasData = false;
|
|
1869
|
-
this._value.status = "sentinel";
|
|
1870
|
-
}
|
|
1871
|
-
this._resetDepState();
|
|
1872
|
-
this._wave.hasCalledFnOnce = false;
|
|
1873
|
-
this._control.pauseLockset.clear();
|
|
1874
|
-
this._control.pauseBuffer = [];
|
|
1875
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1876
|
-
this._control.demandOwed = false;
|
|
1877
|
-
this._value.replayRing = [];
|
|
1878
|
-
if (!this._privateState.persist) this._privateState.value = SENTINEL;
|
|
2743
|
+
nodeDeactivate(nodeRuntimeHost(this));
|
|
1879
2744
|
}
|
|
1880
2745
|
_assertNotReleased(op) {
|
|
1881
2746
|
if (this._released)
|
|
1882
2747
|
throw new Error(`${op}: node has been released from its graph lifecycle (D122)`);
|
|
1883
2748
|
}
|
|
1884
2749
|
_subscriberCount() {
|
|
1885
|
-
return this
|
|
2750
|
+
return nodeSubscriberCount(nodeRuntimeHost(this));
|
|
1886
2751
|
}
|
|
1887
2752
|
_isRuntimeQuiescentForRelease() {
|
|
1888
|
-
|
|
1889
|
-
return !this._released && this._value.status !== "dirty" && this._value.status !== "pending" && this._wave.pending === 0 && !this._wave.insideRunWave && !this._wave.inDepMutation && !this._wave.rewireRunPending && !this._wave.batchDirtyOwed && this._dep.dirty.every((dirty) => !dirty) && this._control.pauseBuffer.length === 0 && !this._control.pausedDepWaveOccurred && !this._control.demandOwed && !this._control.inDeliverDemand && (this._control.pauseLockset.size === 0 || allowedPullQuietLock);
|
|
2753
|
+
return nodeIsRuntimeQuiescentForRelease(nodeRuntimeHost(this));
|
|
1890
2754
|
}
|
|
1891
2755
|
_releaseRuntime() {
|
|
1892
|
-
|
|
1893
|
-
this._released = true;
|
|
1894
|
-
releasedNodes.add(this);
|
|
1895
|
-
let releaseError;
|
|
1896
|
-
const recordReleaseError = (error) => {
|
|
1897
|
-
if (releaseError === void 0) releaseError = error;
|
|
1898
|
-
};
|
|
1899
|
-
this._lifecycle.activated = false;
|
|
1900
|
-
for (const u of this._dep.unsubs) {
|
|
1901
|
-
try {
|
|
1902
|
-
u();
|
|
1903
|
-
} catch (error) {
|
|
1904
|
-
recordReleaseError(error);
|
|
1905
|
-
}
|
|
1906
|
-
}
|
|
1907
|
-
for (const fn of this._hooks.onDeactivation) {
|
|
1908
|
-
try {
|
|
1909
|
-
fn();
|
|
1910
|
-
} catch (error) {
|
|
1911
|
-
recordReleaseError(error);
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
this._dep.unsubs = [];
|
|
1915
|
-
this._dep.idxBoxes = [];
|
|
1916
|
-
this._lifecycle.subscribers.clear();
|
|
1917
|
-
if (this._slot.handle !== null) {
|
|
1918
|
-
this._slot.dispatcher.unregister(this._slot.handle);
|
|
1919
|
-
this._slot.handle = null;
|
|
1920
|
-
}
|
|
1921
|
-
this._slot.deps = [];
|
|
1922
|
-
this._dep.batch = [];
|
|
1923
|
-
this._dep.waveData = [];
|
|
1924
|
-
this._dep.waveTokens = [];
|
|
1925
|
-
this._dep.prev = [];
|
|
1926
|
-
this._dep.hasData = [];
|
|
1927
|
-
this._dep.dirty = [];
|
|
1928
|
-
this._dep.tier = [];
|
|
1929
|
-
this._dep.terminal = [];
|
|
1930
|
-
this._dep.terminalInput = [];
|
|
1931
|
-
this._value.cache = SENTINEL;
|
|
1932
|
-
this._value.hasData = false;
|
|
1933
|
-
this._value.status = "sentinel";
|
|
1934
|
-
this._value.terminal = void 0;
|
|
1935
|
-
this._value.replayRing = [];
|
|
1936
|
-
this._privateState.value = SENTINEL;
|
|
1937
|
-
this._privateState.persist = false;
|
|
1938
|
-
this._syncCtx = null;
|
|
1939
|
-
this._resetDepState();
|
|
1940
|
-
this._hooks.onDeactivation = [];
|
|
1941
|
-
this._hooks.onInvalidate = [];
|
|
1942
|
-
this._control.pauseLockset.clear();
|
|
1943
|
-
this._control.pauseBuffer = [];
|
|
1944
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1945
|
-
this._control.demandOwed = false;
|
|
1946
|
-
this._restoredActivationPending = false;
|
|
1947
|
-
checkpointReaders.delete(this);
|
|
1948
|
-
restoreWriters.delete(this);
|
|
1949
|
-
runtimeReleasers.delete(this);
|
|
1950
|
-
runtimeQuiescenceReaders.delete(this);
|
|
1951
|
-
subscriberCountReaders.delete(this);
|
|
1952
|
-
activationReaders.delete(this);
|
|
1953
|
-
ownerTokens.delete(this);
|
|
1954
|
-
topologyDepsChangedObservers.delete(this);
|
|
1955
|
-
this._core.releaseSlot(this._id);
|
|
1956
|
-
if (releaseError !== void 0) throw releaseError;
|
|
2756
|
+
nodeReleaseRuntime(nodeRuntimeHost(this));
|
|
1957
2757
|
}
|
|
1958
2758
|
_resetDepState() {
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
this._dep.tier[i] = 0;
|
|
1968
|
-
this._dep.terminal[i] = void 0;
|
|
1969
|
-
this._dep.terminalInput[i] = void 0;
|
|
1970
|
-
}
|
|
1971
|
-
this._wave.pending = 0;
|
|
1972
|
-
this._wave.emittedDirtyThisWave = false;
|
|
1973
|
-
}
|
|
1974
|
-
// ── upstream wave receive (two-phase + diamond) ──
|
|
2759
|
+
nodeResetDepState(nodeRuntimeHost(this));
|
|
2760
|
+
}
|
|
2761
|
+
_subscribeDepAt(depNode, opts = {}) {
|
|
2762
|
+
nodeSubscribeDepAt(nodeRuntimeHost(this), depNode, opts);
|
|
2763
|
+
}
|
|
2764
|
+
_seedRestoredDepAt(idx, depNode) {
|
|
2765
|
+
nodeSeedRestoredDepAt(nodeRuntimeHost(this), idx, depNode);
|
|
2766
|
+
}
|
|
1975
2767
|
_recordDepProjection(idx, delivery) {
|
|
1976
|
-
|
|
1977
|
-
if (this._dep.waveTokens[idx] !== token) {
|
|
1978
|
-
this._dep.waveData[idx].push([]);
|
|
1979
|
-
this._dep.waveTokens[idx] = token;
|
|
1980
|
-
}
|
|
1981
|
-
return this._dep.waveData[idx][this._dep.waveData[idx].length - 1];
|
|
2768
|
+
return nodeRecordDepProjection(nodeRuntimeHost(this), idx, delivery);
|
|
1982
2769
|
}
|
|
1983
2770
|
_depProjectionHasData(idx) {
|
|
1984
|
-
|
|
1985
|
-
return projection?.some((v) => v !== SENTINEL) ?? false;
|
|
2771
|
+
return nodeDepProjectionHasData(nodeRuntimeHost(this), idx);
|
|
1986
2772
|
}
|
|
1987
2773
|
_receiveFromDep(idx, msg, delivery) {
|
|
1988
|
-
|
|
1989
|
-
const t = msg[0];
|
|
1990
|
-
if (t === "START") return;
|
|
1991
|
-
const isLastInDeliveredWave = delivery?.last ?? true;
|
|
1992
|
-
if (this._value.terminal !== void 0) {
|
|
1993
|
-
if (t === "TEARDOWN") this._down([["TEARDOWN"]]);
|
|
1994
|
-
return;
|
|
1995
|
-
}
|
|
1996
|
-
if (t === "INVALIDATE") {
|
|
1997
|
-
const projection = this._recordDepProjection(idx, delivery);
|
|
1998
|
-
projection.push(SENTINEL);
|
|
1999
|
-
if (projection.some((v) => v !== SENTINEL) && isLastInDeliveredWave) this._maybeRun();
|
|
2000
|
-
this._dep.prev[idx] = SENTINEL;
|
|
2001
|
-
this._dep.hasData[idx] = false;
|
|
2002
|
-
this._dep.batch[idx] = null;
|
|
2003
|
-
if (this._dep.dirty[idx]) {
|
|
2004
|
-
this._dep.dirty[idx] = false;
|
|
2005
|
-
this._wave.pending--;
|
|
2006
|
-
}
|
|
2007
|
-
if (this._control.pausedDepWaveOccurred && this._dep.batch.every((b) => b === null)) {
|
|
2008
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2009
|
-
}
|
|
2010
|
-
const hadData = this._value.hasData;
|
|
2011
|
-
this._invalidate();
|
|
2012
|
-
if (this._wave.pending === 0 && this._wave.emittedDirtyThisWave) {
|
|
2013
|
-
if (!hadData) this._down([["RESOLVED"]]);
|
|
2014
|
-
else this._wave.emittedDirtyThisWave = false;
|
|
2015
|
-
}
|
|
2016
|
-
this._fireOwedDemandIfReady();
|
|
2017
|
-
return;
|
|
2018
|
-
}
|
|
2019
|
-
if (isTerminal(t)) {
|
|
2020
|
-
const isError = t === "ERROR";
|
|
2021
|
-
const errPayload = isError ? msg[1] : void 0;
|
|
2022
|
-
this._dep.terminal[idx] = isError ? errPayload : true;
|
|
2023
|
-
this._dep.terminalInput[idx] = isError ? errPayload : true;
|
|
2024
|
-
this._releaseDepDirty(idx);
|
|
2025
|
-
const ranValueBeforeTerminal = this._depProjectionHasData(idx) && isLastInDeliveredWave;
|
|
2026
|
-
if (ranValueBeforeTerminal) this._maybeRun();
|
|
2027
|
-
if (isError && this._slot.errorWhenDepsError) {
|
|
2028
|
-
this._down([["ERROR", errPayload]]);
|
|
2029
|
-
} else if (this._slot.terminalAsRealInput) {
|
|
2030
|
-
if (ranValueBeforeTerminal) {
|
|
2031
|
-
this._fireOwedDemandIfReady();
|
|
2032
|
-
return;
|
|
2033
|
-
}
|
|
2034
|
-
this._maybeRun();
|
|
2035
|
-
} else if (this._slot.completeWhenDepsComplete && this._allDepsTerminal()) {
|
|
2036
|
-
this._down([["COMPLETE"]]);
|
|
2037
|
-
} else {
|
|
2038
|
-
this._settleAfterAbsorbedTerminal();
|
|
2039
|
-
}
|
|
2040
|
-
this._fireOwedDemandIfReady();
|
|
2041
|
-
return;
|
|
2042
|
-
}
|
|
2043
|
-
if (t === "TEARDOWN") {
|
|
2044
|
-
this._down([["TEARDOWN"]]);
|
|
2045
|
-
return;
|
|
2046
|
-
}
|
|
2047
|
-
if (t === "DIRTY") {
|
|
2048
|
-
if (!this._dep.dirty[idx]) {
|
|
2049
|
-
this._dep.dirty[idx] = true;
|
|
2050
|
-
this._wave.pending++;
|
|
2051
|
-
this._dep.tier[idx] = 2;
|
|
2052
|
-
this._markDirty();
|
|
2053
|
-
}
|
|
2054
|
-
return;
|
|
2055
|
-
}
|
|
2056
|
-
if (t === "DATA") {
|
|
2057
|
-
const v = msg[1];
|
|
2058
|
-
this._recordDepProjection(idx, delivery).push(v);
|
|
2059
|
-
const b = this._dep.batch[idx];
|
|
2060
|
-
if (b === null) this._dep.batch[idx] = [v];
|
|
2061
|
-
else b.push(v);
|
|
2062
|
-
this._dep.prev[idx] = v;
|
|
2063
|
-
this._dep.hasData[idx] = true;
|
|
2064
|
-
this._dep.tier[idx] = 3;
|
|
2065
|
-
if (this._dep.dirty[idx]) {
|
|
2066
|
-
this._dep.dirty[idx] = false;
|
|
2067
|
-
this._wave.pending--;
|
|
2068
|
-
}
|
|
2069
|
-
if (isLastInDeliveredWave) this._maybeRun();
|
|
2070
|
-
this._fireOwedDemandIfReady();
|
|
2071
|
-
return;
|
|
2072
|
-
}
|
|
2073
|
-
if (t === "RESOLVED") {
|
|
2074
|
-
this._recordDepProjection(idx, delivery);
|
|
2075
|
-
this._dep.tier[idx] = 3;
|
|
2076
|
-
if (this._dep.dirty[idx]) {
|
|
2077
|
-
this._dep.dirty[idx] = false;
|
|
2078
|
-
this._wave.pending--;
|
|
2079
|
-
}
|
|
2080
|
-
if (isLastInDeliveredWave) this._maybeRun();
|
|
2081
|
-
this._fireOwedDemandIfReady();
|
|
2082
|
-
return;
|
|
2083
|
-
}
|
|
2774
|
+
nodeReceiveFromDep(nodeRuntimeHost(this), idx, msg, delivery);
|
|
2084
2775
|
}
|
|
2085
|
-
/**
|
|
2086
|
-
* R-terminal-settles-dirty (B35): release a dep's outstanding in-wave DIRTY contribution.
|
|
2087
|
-
* A settle-class event for that dep (DATA/RESOLVED inline above, INVALIDATE, and now
|
|
2088
|
-
* COMPLETE/ERROR) clears its dirty flag + decrements _pending. No-op if the dep already
|
|
2089
|
-
* settled this wave (DATA/RESOLVED ran first) — so the normal DATA-then-COMPLETE flow is
|
|
2090
|
-
* unaffected. This makes the exactly-one-settle invariant a single, shared step.
|
|
2091
|
-
*/
|
|
2092
2776
|
_releaseDepDirty(idx) {
|
|
2093
|
-
|
|
2094
|
-
this._dep.dirty[idx] = false;
|
|
2095
|
-
this._wave.pending--;
|
|
2096
|
-
}
|
|
2777
|
+
nodeReleaseDepDirty(nodeRuntimeHost(this), idx);
|
|
2097
2778
|
}
|
|
2098
|
-
/**
|
|
2099
|
-
* R-terminal-settles-dirty (B35): settle a node whose dirtied dep was released by an ABSORBED
|
|
2100
|
-
* terminal that is NOT a real input (a plain derived/effect — the common default-node case when
|
|
2101
|
-
* one of several deps completes while others stay live). Runs only when the release drained
|
|
2102
|
-
* _pending while the node still owes a downstream settle (it broadcast DIRTY this wave):
|
|
2103
|
-
* - if some OTHER dep delivered real DATA this wave (a value occurred) → recompute (→ DATA);
|
|
2104
|
-
* - else the terminal's signalled change did not materialise (no value) → one undirty RESOLVED
|
|
2105
|
-
* (R-resolved-undirty), keeping the cache (a terminal, unlike INVALIDATE, leaves the value).
|
|
2106
|
-
* A terminalAsRealInput node instead recomputes unconditionally (its fn reads the terminal).
|
|
2107
|
-
*/
|
|
2108
2779
|
_settleAfterAbsorbedTerminal() {
|
|
2109
|
-
|
|
2110
|
-
const sawData = this._dep.batch.some((b) => b !== null && b.length > 0);
|
|
2111
|
-
if (sawData) this._maybeRun();
|
|
2112
|
-
if (this._wave.emittedDirtyThisWave) this._down([["RESOLVED"]]);
|
|
2780
|
+
nodeSettleAfterAbsorbedTerminal(nodeRuntimeHost(this));
|
|
2113
2781
|
}
|
|
2114
2782
|
_markDirty() {
|
|
2115
|
-
this
|
|
2116
|
-
if (this._isPullQuiet()) return;
|
|
2117
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
2118
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2119
|
-
this._emitToSubs(["DIRTY"]);
|
|
2120
|
-
}
|
|
2783
|
+
nodeMarkDirty(nodeRuntimeHost(this));
|
|
2121
2784
|
}
|
|
2122
2785
|
_maybeRun() {
|
|
2123
|
-
|
|
2124
|
-
this._wave.rewireRunPending = true;
|
|
2125
|
-
return;
|
|
2126
|
-
}
|
|
2127
|
-
if (this._slot.pausable === true && this._isPaused()) {
|
|
2128
|
-
this._control.pausedDepWaveOccurred = true;
|
|
2129
|
-
return;
|
|
2130
|
-
}
|
|
2131
|
-
this._tryRun();
|
|
2786
|
+
nodeMaybeRun(nodeRuntimeHost(this));
|
|
2132
2787
|
}
|
|
2133
|
-
/**
|
|
2134
|
-
* R-rewire atomic settle (after a rewire that warrants a recompute): emit a proper
|
|
2135
|
-
* two-phase DIRTY→DATA wave (R-dirty-before-data — a rewire-triggered settle is a wave),
|
|
2136
|
-
* once, with every added dep already wired. Mirrors _maybeRun/_tryRun's pause + gate +
|
|
2137
|
-
* pending guards, then injects the phase-1 DIRTY the added dep's [START,DATA] handshake
|
|
2138
|
-
* did not carry.
|
|
2139
|
-
*/
|
|
2140
2788
|
_settleRewire() {
|
|
2141
|
-
|
|
2142
|
-
this._control.pausedDepWaveOccurred = true;
|
|
2143
|
-
return;
|
|
2144
|
-
}
|
|
2145
|
-
if (this._wave.pending > 0) return;
|
|
2146
|
-
if (this._slot.handle === null) {
|
|
2147
|
-
this._passthroughEmit();
|
|
2148
|
-
return;
|
|
2149
|
-
}
|
|
2150
|
-
if (!this._wave.hasCalledFnOnce && !(this._slot.partial || this._allDepsSettled())) return;
|
|
2151
|
-
this._markDirty();
|
|
2152
|
-
this._runWave();
|
|
2789
|
+
nodeSettleRewire(nodeRuntimeHost(this));
|
|
2153
2790
|
}
|
|
2154
2791
|
_tryRun() {
|
|
2155
|
-
|
|
2156
|
-
if (this._slot.handle === null) {
|
|
2157
|
-
this._passthroughEmit();
|
|
2158
|
-
return;
|
|
2159
|
-
}
|
|
2160
|
-
if (!this._wave.hasCalledFnOnce) {
|
|
2161
|
-
if (this._slot.partial || this._allDepsSettled()) this._runWave();
|
|
2162
|
-
return;
|
|
2163
|
-
}
|
|
2164
|
-
this._runWave();
|
|
2792
|
+
nodeTryRun(nodeRuntimeHost(this));
|
|
2165
2793
|
}
|
|
2166
2794
|
_allDepsSettled() {
|
|
2167
|
-
|
|
2168
|
-
if (this._dep.hasData[i]) continue;
|
|
2169
|
-
if (this._slot.terminalAsRealInput && this._dep.terminal[i] !== void 0) continue;
|
|
2170
|
-
return false;
|
|
2171
|
-
}
|
|
2172
|
-
return true;
|
|
2795
|
+
return nodeAllDepsSettled(nodeRuntimeHost(this));
|
|
2173
2796
|
}
|
|
2174
2797
|
_passthroughEmit() {
|
|
2175
|
-
|
|
2176
|
-
if (b !== null && b.length > 0) {
|
|
2177
|
-
this._down([["DATA", b[b.length - 1]]]);
|
|
2178
|
-
} else if (this._wave.emittedDirtyThisWave) {
|
|
2179
|
-
this._down([["RESOLVED"]]);
|
|
2180
|
-
}
|
|
2181
|
-
this._dep.batch[0] = null;
|
|
2182
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2798
|
+
nodePassthroughEmit(nodeRuntimeHost(this));
|
|
2183
2799
|
}
|
|
2184
2800
|
_runWave() {
|
|
2185
|
-
|
|
2186
|
-
throw new Error(
|
|
2187
|
-
"synchronous feedback cycle: node fn re-entered its own wave (R-reentrancy / D37)"
|
|
2188
|
-
);
|
|
2189
|
-
this._wave.hasCalledFnOnce = true;
|
|
2190
|
-
this._hooks.onInvalidate = [];
|
|
2191
|
-
this._hooks.onDeactivation = [];
|
|
2192
|
-
const ctx = this._buildCtx();
|
|
2193
|
-
const wasDirty = this._wave.emittedDirtyThisWave;
|
|
2194
|
-
this._wave.emittedSettleThisWave = false;
|
|
2195
|
-
this._wave.insideRunWave = true;
|
|
2196
|
-
try {
|
|
2197
|
-
this._slot.dispatcher.invoke(this._slot.handle, ctx);
|
|
2198
|
-
} finally {
|
|
2199
|
-
this._wave.insideRunWave = false;
|
|
2200
|
-
}
|
|
2201
|
-
if (wasDirty && !this._wave.emittedSettleThisWave && this._value.terminal === void 0 && !this._isAsyncPool()) {
|
|
2202
|
-
this._down([["RESOLVED"]]);
|
|
2203
|
-
}
|
|
2204
|
-
for (let i = 0; i < this._dep.batch.length; i++) {
|
|
2205
|
-
this._dep.batch[i] = null;
|
|
2206
|
-
this._dep.waveData[i] = [];
|
|
2207
|
-
this._dep.waveTokens[i] = void 0;
|
|
2208
|
-
this._dep.terminalInput[i] = void 0;
|
|
2209
|
-
}
|
|
2210
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2801
|
+
nodeRunWave(nodeRuntimeHost(this));
|
|
2211
2802
|
}
|
|
2212
|
-
// ── ctx construction (L3-Q5: sync = node-stable reused ctx; async = per-invocation) ──
|
|
2213
2803
|
_buildCtx() {
|
|
2214
|
-
|
|
2215
|
-
if (kind === "sync") {
|
|
2216
|
-
if (this._syncCtx === null) this._syncCtx = this._makeCtx();
|
|
2217
|
-
this._refreshCtx(this._syncCtx);
|
|
2218
|
-
return this._syncCtx;
|
|
2219
|
-
}
|
|
2220
|
-
return this._makeCtx({
|
|
2221
|
-
waveData: this._dep.waveData.map((waves) => waves.map((w) => [...w])),
|
|
2222
|
-
terminal: this._dep.terminalInput.map(terminalView),
|
|
2223
|
-
latest: [...this._dep.prev]
|
|
2224
|
-
});
|
|
2804
|
+
return nodeBuildCtx(nodeRuntimeHost(this));
|
|
2225
2805
|
}
|
|
2226
2806
|
_makeCtx(snapshot) {
|
|
2227
|
-
|
|
2228
|
-
// Wave-owner boundary (D47): a SYNC fn's emit nests under the public entry that drove
|
|
2229
|
-
// it (cheap inc/dec, no early drain); an ASYNC-pool fn re-enters here from its stashed
|
|
2230
|
-
// ctx at depth 0, so this is the boundary that drains any rewireNext it issued.
|
|
2231
|
-
up: (msgs, towardDep) => {
|
|
2232
|
-
if (this._released) return;
|
|
2233
|
-
enterWave();
|
|
2234
|
-
try {
|
|
2235
|
-
this._up(msgs, towardDep);
|
|
2236
|
-
} finally {
|
|
2237
|
-
exitWave();
|
|
2238
|
-
}
|
|
2239
|
-
},
|
|
2240
|
-
down: (msgs) => {
|
|
2241
|
-
if (this._released) return;
|
|
2242
|
-
enterWave();
|
|
2243
|
-
try {
|
|
2244
|
-
this._down(msgs);
|
|
2245
|
-
} finally {
|
|
2246
|
-
exitWave();
|
|
2247
|
-
}
|
|
2248
|
-
},
|
|
2249
|
-
waveData: snapshot?.waveData ?? this._dep.waveData,
|
|
2250
|
-
terminal: snapshot?.terminal ?? this._dep.terminalInput.map(terminalView),
|
|
2251
|
-
state: this._makeState(),
|
|
2252
|
-
onDeactivation: (fn) => {
|
|
2253
|
-
if (this._released) return;
|
|
2254
|
-
this._hooks.onDeactivation.push(fn);
|
|
2255
|
-
},
|
|
2256
|
-
onInvalidate: (fn) => {
|
|
2257
|
-
if (this._released) return;
|
|
2258
|
-
this._hooks.onInvalidate.push(fn);
|
|
2259
|
-
},
|
|
2260
|
-
environment: () => this._slot.environment,
|
|
2261
|
-
// R-rewire-deferred (D47): defer a self-dep-set mutation to the committed boundary.
|
|
2262
|
-
rewireNext: {
|
|
2263
|
-
subscribeDep: (dep, fn) => this._requestRewireNext({ kind: "add", dep, fn }),
|
|
2264
|
-
unsubscribeDep: (dep, fn) => this._requestRewireNext({ kind: "remove", dep, fn }),
|
|
2265
|
-
replaceDeps: (deps, fn) => this._requestRewireNext({ kind: "set", deps, fn })
|
|
2266
|
-
},
|
|
2267
|
-
// R-up-routing / R-pull (D59): deferred up — route a control wave (e.g. a RESUME pull
|
|
2268
|
-
// DEMAND) up the declared cone at the committed boundary. The SELF-demand path: an
|
|
2269
|
-
// immediate ctx.up whose delivery loops back re-enters this fn (D37 / R-reentrancy).
|
|
2270
|
-
upNext: (msgs, towardDep) => this._requestUpNext(msgs, towardDep),
|
|
2271
|
-
[CTX_DEP_CACHE]: { latest: snapshot?.latest ?? this._dep.prev },
|
|
2272
|
-
[CTX_NODE_BINDING]: {
|
|
2273
|
-
dispatcher: this._slot.dispatcher,
|
|
2274
|
-
create: (factory) => withEnvironmentDrivers(this._slot.environment, () => withNodeCore(this._core, factory))
|
|
2275
|
-
}
|
|
2276
|
-
};
|
|
2277
|
-
if (this._slot.dynamic) {
|
|
2278
|
-
ctx.track = (i) => ctx[CTX_DEP_CACHE]?.latest[i];
|
|
2279
|
-
}
|
|
2280
|
-
return ctx;
|
|
2807
|
+
return nodeMakeCtx(nodeRuntimeHost(this), snapshot);
|
|
2281
2808
|
}
|
|
2282
2809
|
_refreshCtx(ctx) {
|
|
2283
|
-
ctx
|
|
2284
|
-
ctx.terminal = this._dep.terminalInput.map(terminalView);
|
|
2285
|
-
ctx[CTX_DEP_CACHE] = { latest: this._dep.prev };
|
|
2810
|
+
nodeRefreshCtx(nodeRuntimeHost(this), ctx);
|
|
2286
2811
|
}
|
|
2287
2812
|
_makeState() {
|
|
2288
|
-
return
|
|
2289
|
-
get: () => this._privateState.value,
|
|
2290
|
-
set: (v) => {
|
|
2291
|
-
this._privateState.value = v;
|
|
2292
|
-
},
|
|
2293
|
-
persist: (on = true) => {
|
|
2294
|
-
this._privateState.persist = on;
|
|
2295
|
-
}
|
|
2296
|
-
};
|
|
2813
|
+
return nodeMakeState(nodeRuntimeHost(this));
|
|
2297
2814
|
}
|
|
2298
2815
|
// ── downstream emission pipeline (the unified waist) ──
|
|
2299
2816
|
_down(msgs) {
|
|
2300
|
-
|
|
2301
|
-
validateDownPayloads(msgs);
|
|
2302
|
-
const deliveryWave = {};
|
|
2303
|
-
const assertVersionDataCompatible = (wave) => {
|
|
2304
|
-
for (const m of wave) {
|
|
2305
|
-
if (m[0] === "DATA") assertNodeVersionDataCompatible(this._version.policy, m[1]);
|
|
2306
|
-
}
|
|
2307
|
-
};
|
|
2308
|
-
const snapshotVersionData = (wave) => wave.map(
|
|
2309
|
-
(m) => m[0] === "DATA" ? ["DATA", snapshotNodeVersionData(this._version.policy, m[1])] : m
|
|
2310
|
-
);
|
|
2311
|
-
assertVersionDataCompatible(msgs);
|
|
2312
|
-
if (this._value.terminal !== void 0) {
|
|
2313
|
-
if (!msgs.some((m) => m[0] === "TEARDOWN")) return;
|
|
2314
|
-
this._value.hasTorndown = true;
|
|
2315
|
-
if (this._slot.resetOnTeardown) {
|
|
2316
|
-
this._value.cache = SENTINEL;
|
|
2317
|
-
this._value.hasData = false;
|
|
2318
|
-
}
|
|
2319
|
-
this._emitToSubs(["TEARDOWN"], { wave: deliveryWave, last: true });
|
|
2320
|
-
return;
|
|
2321
|
-
}
|
|
2322
|
-
let sorted = [...msgs].sort((a, b) => messageTier(a[0]) - messageTier(b[0]));
|
|
2323
|
-
const firstInvalidate = sorted.findIndex((m) => m[0] === "INVALIDATE");
|
|
2324
|
-
if (firstInvalidate !== -1) {
|
|
2325
|
-
sorted = sorted.filter((m, i) => m[0] !== "INVALIDATE" || i === firstInvalidate);
|
|
2326
|
-
}
|
|
2327
|
-
const hasTeardown = sorted.some((m) => m[0] === "TEARDOWN");
|
|
2328
|
-
const hasTerminal = sorted.some((m) => m[0] === "COMPLETE" || m[0] === "ERROR");
|
|
2329
|
-
if (hasTeardown && !hasTerminal && this._value.terminal === void 0 && !this._value.hasTorndown) {
|
|
2330
|
-
sorted = [["COMPLETE"], ...sorted];
|
|
2331
|
-
}
|
|
2332
|
-
if (!this._wave.insideRunWave && currentBatch()) {
|
|
2333
|
-
const deferred = snapshotVersionData(sorted.filter((m) => isDeferredTier(m[0])));
|
|
2334
|
-
if (deferred.length > 0) {
|
|
2335
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
2336
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2337
|
-
this._value.status = "dirty";
|
|
2338
|
-
this._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
2339
|
-
}
|
|
2340
|
-
this._wave.batchDirtyOwed = true;
|
|
2341
|
-
deferToBatch(this, deferred);
|
|
2342
|
-
return;
|
|
2343
|
-
}
|
|
2344
|
-
}
|
|
2345
|
-
if (this._shouldBufferOnPause()) {
|
|
2346
|
-
const buffered = snapshotVersionData(sorted.filter((m) => isPauseBufferedTier(m[0])));
|
|
2347
|
-
if (buffered.length > 0) {
|
|
2348
|
-
this._wave.emittedSettleThisWave = true;
|
|
2349
|
-
this._control.pauseBuffer.push(buffered);
|
|
2350
|
-
}
|
|
2351
|
-
sorted = sorted.filter((m) => !isPauseBufferedTier(m[0]));
|
|
2352
|
-
if (sorted.length === 0) return;
|
|
2353
|
-
}
|
|
2354
|
-
let dataCount = 0;
|
|
2355
|
-
let hasTier3 = false;
|
|
2356
|
-
let hasResolved = false;
|
|
2357
|
-
for (const m of sorted) {
|
|
2358
|
-
if (m[0] === "DATA") dataCount++;
|
|
2359
|
-
if (m[0] === "RESOLVED") hasResolved = true;
|
|
2360
|
-
if (isValueTier(m[0])) hasTier3 = true;
|
|
2361
|
-
}
|
|
2362
|
-
if (dataCount >= 1 && hasResolved) {
|
|
2363
|
-
throw new Error(
|
|
2364
|
-
"down: a wave cannot mix DATA and RESOLVED (tier-3 exclusivity, R-resolved-undirty)"
|
|
2365
|
-
);
|
|
2366
|
-
}
|
|
2367
|
-
const plannedVersions = new Array(sorted.length);
|
|
2368
|
-
if (dataCount > 0) {
|
|
2369
|
-
let plannedVersion = this._version.value;
|
|
2370
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
2371
|
-
const m = sorted[i];
|
|
2372
|
-
if (m[0] !== "DATA") continue;
|
|
2373
|
-
plannedVersion = advanceNodeVersion(plannedVersion, this._version.policy, m[1]);
|
|
2374
|
-
plannedVersions[i] = plannedVersion;
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
|
-
if (hasTier3 && !this._wave.insideRunWave && !this._wave.emittedDirtyThisWave) {
|
|
2378
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2379
|
-
this._value.status = "dirty";
|
|
2380
|
-
this._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
2381
|
-
}
|
|
2382
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
2383
|
-
const m = sorted[i];
|
|
2384
|
-
const delivery = { wave: deliveryWave, last: i === sorted.length - 1 };
|
|
2385
|
-
if (isDeferredTier(m[0])) this._wave.emittedSettleThisWave = true;
|
|
2386
|
-
if (m[0] === "DIRTY") {
|
|
2387
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
2388
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2389
|
-
this._value.status = "dirty";
|
|
2390
|
-
this._emitToSubs(["DIRTY"], delivery);
|
|
2391
|
-
}
|
|
2392
|
-
continue;
|
|
2393
|
-
}
|
|
2394
|
-
if (m[0] === "DATA") {
|
|
2395
|
-
const v = m[1];
|
|
2396
|
-
this._value.cache = v;
|
|
2397
|
-
this._value.hasData = true;
|
|
2398
|
-
this._value.status = "settled";
|
|
2399
|
-
this._version.value = plannedVersions[i];
|
|
2400
|
-
if (this._slot.replayN > 0) {
|
|
2401
|
-
this._value.replayRing.push(v);
|
|
2402
|
-
if (this._value.replayRing.length > this._slot.replayN) this._value.replayRing.shift();
|
|
2403
|
-
}
|
|
2404
|
-
this._emitToSubs(["DATA", v], delivery);
|
|
2405
|
-
continue;
|
|
2406
|
-
}
|
|
2407
|
-
if (m[0] === "RESOLVED") {
|
|
2408
|
-
this._value.status = this._value.hasData ? "resolved" : "sentinel";
|
|
2409
|
-
this._emitToSubs(["RESOLVED"], delivery);
|
|
2410
|
-
continue;
|
|
2411
|
-
}
|
|
2412
|
-
if (m[0] === "INVALIDATE") {
|
|
2413
|
-
this._invalidate(delivery);
|
|
2414
|
-
continue;
|
|
2415
|
-
}
|
|
2416
|
-
if (m[0] === "COMPLETE") {
|
|
2417
|
-
if (this._value.terminal !== void 0) continue;
|
|
2418
|
-
this._value.terminal = true;
|
|
2419
|
-
this._control.pauseBuffer = [];
|
|
2420
|
-
this._value.status = "completed";
|
|
2421
|
-
this._emitToSubs(["COMPLETE"], delivery);
|
|
2422
|
-
continue;
|
|
2423
|
-
}
|
|
2424
|
-
if (m[0] === "ERROR") {
|
|
2425
|
-
if (this._value.terminal !== void 0) continue;
|
|
2426
|
-
this._value.terminal = m[1];
|
|
2427
|
-
this._control.pauseBuffer = [];
|
|
2428
|
-
this._value.status = "errored";
|
|
2429
|
-
this._emitToSubs(["ERROR", m[1]], delivery);
|
|
2430
|
-
continue;
|
|
2431
|
-
}
|
|
2432
|
-
if (m[0] === "TEARDOWN") {
|
|
2433
|
-
this._value.hasTorndown = true;
|
|
2434
|
-
if (this._slot.resetOnTeardown) {
|
|
2435
|
-
this._value.cache = SENTINEL;
|
|
2436
|
-
this._value.hasData = false;
|
|
2437
|
-
}
|
|
2438
|
-
this._emitToSubs(["TEARDOWN"], delivery);
|
|
2439
|
-
}
|
|
2440
|
-
}
|
|
2441
|
-
if (!this._wave.insideRunWave) this._wave.emittedDirtyThisWave = false;
|
|
2817
|
+
nodeDown(nodeRuntimeHost(this), msgs);
|
|
2442
2818
|
}
|
|
2443
2819
|
_up(msgs, towardDep, route) {
|
|
2444
|
-
|
|
2445
|
-
const routeState = route ?? { demandFired: /* @__PURE__ */ new Map() };
|
|
2446
|
-
for (const m of msgs) {
|
|
2447
|
-
if (!isUpAllowed(m[0])) {
|
|
2448
|
-
throw new Error(
|
|
2449
|
-
`ctx.up: ${m[0]} is down-only (tier ${messageTier(m[0])}); up carries control tiers only (R-ctx-up)`
|
|
2450
|
-
);
|
|
2451
|
-
}
|
|
2452
|
-
}
|
|
2453
|
-
for (const m of msgs) {
|
|
2454
|
-
if (m[0] === "PAUSE") {
|
|
2455
|
-
this._pauseAcquire(m[1]);
|
|
2456
|
-
} else if (m[0] === "RESUME") {
|
|
2457
|
-
if (this._slot.pull && m[1] === this._slot.pullLock) {
|
|
2458
|
-
if (!this._markDemandRouted(m[1], routeState)) this._onDemand();
|
|
2459
|
-
} else if (this._control.pauseLockset.has(m[1])) {
|
|
2460
|
-
this._pauseRelease(m[1]);
|
|
2461
|
-
} else {
|
|
2462
|
-
this._forwardUp(m, towardDep, routeState);
|
|
2463
|
-
}
|
|
2464
|
-
} else if (this._slot.deps.length === 0) {
|
|
2465
|
-
if (m[0] === "INVALIDATE") this._down([["INVALIDATE"]]);
|
|
2466
|
-
} else {
|
|
2467
|
-
this._forwardUp(m, towardDep, routeState);
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2820
|
+
nodeUp(nodeRuntimeHost(this), msgs, towardDep, route);
|
|
2470
2821
|
}
|
|
2471
2822
|
_markDemandRouted(lockId, route) {
|
|
2472
|
-
|
|
2473
|
-
if (holders === void 0) {
|
|
2474
|
-
holders = /* @__PURE__ */ new Set();
|
|
2475
|
-
route.demandFired.set(lockId, holders);
|
|
2476
|
-
}
|
|
2477
|
-
if (holders.has(this)) return true;
|
|
2478
|
-
holders.add(this);
|
|
2479
|
-
return false;
|
|
2823
|
+
return nodeMarkDemandRouted(nodeRuntimeHost(this), lockId, route);
|
|
2480
2824
|
}
|
|
2481
|
-
/**
|
|
2482
|
-
* Forward one up-going control message toward deps (R-up-routing): up the single declared edge
|
|
2483
|
-
* `towardDep` (directed — prunes other branches; only meaningful on the issuer's FIRST hop) or
|
|
2484
|
-
* broadcast up ALL deps. A depless source has no deps → the message DROPS here (the terminus —
|
|
2485
|
-
* e.g. a cone-routed RESUME whose pullId no node up this cone holds, R-up-at-source). Recursive
|
|
2486
|
-
* forwarding carries the same per-wave route state and no `towardDep` → broadcast beyond the
|
|
2487
|
-
* first hop.
|
|
2488
|
-
*/
|
|
2489
2825
|
_forwardUp(m, towardDep, route) {
|
|
2490
|
-
|
|
2491
|
-
if (towardDep !== void 0) {
|
|
2492
|
-
const d = this._slot.deps[towardDep];
|
|
2493
|
-
if (d !== void 0) d._up([m], void 0, route);
|
|
2494
|
-
} else {
|
|
2495
|
-
for (const dep of this._slot.deps) dep._up([m], void 0, route);
|
|
2496
|
-
}
|
|
2826
|
+
nodeForwardUp(nodeRuntimeHost(this), m, towardDep, route);
|
|
2497
2827
|
}
|
|
2498
|
-
// ── PAUSE/RESUME lockset (R-pause-lockset) + modes (R-pause-modes) ──
|
|
2499
2828
|
_isPaused() {
|
|
2500
|
-
return this
|
|
2829
|
+
return nodeIsPaused(nodeRuntimeHost(this));
|
|
2501
2830
|
}
|
|
2502
2831
|
_hasBoundaryPauseLock() {
|
|
2503
|
-
|
|
2504
|
-
let locks = this._control.pauseLockset.size;
|
|
2505
|
-
if (this._slot.pull && this._control.pauseLockset.has(this._slot.pullLock)) locks--;
|
|
2506
|
-
return locks > 0;
|
|
2832
|
+
return nodeHasBoundaryPauseLock(nodeRuntimeHost(this));
|
|
2507
2833
|
}
|
|
2508
2834
|
_isAsyncPool() {
|
|
2509
|
-
return
|
|
2835
|
+
return nodeIsAsyncPool(nodeRuntimeHost(this));
|
|
2510
2836
|
}
|
|
2511
2837
|
_pauseAcquire(lockId) {
|
|
2512
|
-
this
|
|
2838
|
+
nodePauseAcquire(nodeRuntimeHost(this), lockId);
|
|
2513
2839
|
}
|
|
2514
2840
|
_pauseRelease(lockId) {
|
|
2515
|
-
|
|
2516
|
-
this._control.pauseLockset.delete(lockId);
|
|
2517
|
-
if (this._slot.pull && this._control.demandOwed) this._fireOwedDemandIfReady();
|
|
2518
|
-
if (this._hasBoundaryPauseLock()) return;
|
|
2519
|
-
scheduleBoundaryDrain(this._core);
|
|
2520
|
-
if (this._control.pauseLockset.size > 0) return;
|
|
2521
|
-
this._onResume();
|
|
2841
|
+
nodePauseRelease(nodeRuntimeHost(this), lockId);
|
|
2522
2842
|
}
|
|
2523
2843
|
_onResume() {
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2527
|
-
this._control.demandOwed = false;
|
|
2528
|
-
return;
|
|
2529
|
-
}
|
|
2530
|
-
if (this._control.pauseBuffer.length > 0) {
|
|
2531
|
-
const buf = this._control.pauseBuffer;
|
|
2532
|
-
this._control.pauseBuffer = [];
|
|
2533
|
-
for (const wave of buf) this._down(wave);
|
|
2534
|
-
}
|
|
2535
|
-
if (this._control.pausedDepWaveOccurred) {
|
|
2536
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2537
|
-
this._tryRun();
|
|
2538
|
-
}
|
|
2539
|
-
}
|
|
2540
|
-
/**
|
|
2541
|
-
* R-pull (D59): can this pull node fire a demand NOW? — not terminal, settle-ready (_pending===0),
|
|
2542
|
-
* and no OTHER (non-pullId) lock holds it paused. The gate that decides fire-now vs OWE.
|
|
2543
|
-
*/
|
|
2844
|
+
nodeOnResume(nodeRuntimeHost(this));
|
|
2845
|
+
}
|
|
2544
2846
|
_canFireDemand() {
|
|
2545
|
-
|
|
2546
|
-
const own = this._control.pauseLockset.has(this._slot.pullLock) ? 1 : 0;
|
|
2547
|
-
return this._control.pauseLockset.size <= own;
|
|
2847
|
+
return nodeCanFireDemand(nodeRuntimeHost(this));
|
|
2548
2848
|
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
* absorbed), fire it, then RE-QUIET (1:1). The pullId re-add + the re-entrancy flag are in a
|
|
2552
|
-
* `finally` so a throwing pull fn (graph-less node, no D30 catch) cannot leave the node
|
|
2553
|
-
* permanently non-quiet (the wedge-fix silently disabled) — QA-found robustness fix.
|
|
2554
|
-
*/
|
|
2555
|
-
_deliverPullDemand() {
|
|
2556
|
-
this._control.demandOwed = false;
|
|
2557
|
-
this._control.inDeliverDemand = true;
|
|
2558
|
-
this._control.pauseLockset.delete(this._slot.pullLock);
|
|
2559
|
-
try {
|
|
2560
|
-
this._firePullDemand();
|
|
2561
|
-
} finally {
|
|
2562
|
-
this._control.pauseLockset.add(this._slot.pullLock);
|
|
2563
|
-
this._control.inDeliverDemand = false;
|
|
2564
|
-
}
|
|
2849
|
+
_deliverPullDemand(demand) {
|
|
2850
|
+
nodeDeliverPullDemand(nodeRuntimeHost(this), demand);
|
|
2565
2851
|
}
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
* Fire immediately if able; else OWE it — pin-5 (a dep DIRTY in flight, _pending>0) or F4/F5 (an
|
|
2569
|
-
* external PAUSE lock co-holds the node) — and fire when the node next becomes able. A demand
|
|
2570
|
-
* arriving WHILE a delivery is in flight (synchronous re-entry) is DROPPED (1:1, QA guard).
|
|
2571
|
-
*/
|
|
2572
|
-
_onDemand() {
|
|
2573
|
-
if (this._control.inDeliverDemand) return;
|
|
2574
|
-
if (this._canFireDemand()) this._deliverPullDemand();
|
|
2575
|
-
else this._control.demandOwed = true;
|
|
2852
|
+
_onDemand(demand) {
|
|
2853
|
+
nodeOnDemand(nodeRuntimeHost(this), demand);
|
|
2576
2854
|
}
|
|
2577
|
-
/**
|
|
2578
|
-
* R-pull (D55): service ONE demand. Delivery content = the orthogonal pausable mode:
|
|
2579
|
-
* - 'resumeAll' → drain the buffered BACKLOG (each `_down` re-synthesizes a leading DIRTY, so
|
|
2580
|
-
* the per-entry replay is DIRTY-before-DATA — R-pause-modes per-entry arrival order);
|
|
2581
|
-
* - true → deliver the coalesced LATEST as ONE DIRTY-before-DATA wave (pin 2: the quiet absorb
|
|
2582
|
-
* suppressed the dep's original DIRTY, so the demand wave restores it before the value).
|
|
2583
|
-
* Neither branch fires when nothing changed since the last demand → the demand is SILENT.
|
|
2584
|
-
* Called by `_deliverPullDemand` only when settle-ready; the caller has released the pullId, so
|
|
2585
|
-
* `_markDirty` relays the leading DIRTY (not absorbed).
|
|
2586
|
-
*/
|
|
2587
2855
|
_firePullDemand() {
|
|
2588
|
-
|
|
2589
|
-
const buf = this._control.pauseBuffer;
|
|
2590
|
-
this._control.pauseBuffer = [];
|
|
2591
|
-
for (const wave of buf) this._down(wave);
|
|
2592
|
-
}
|
|
2593
|
-
if (this._control.pausedDepWaveOccurred) {
|
|
2594
|
-
const gated = this._slot.handle !== null && !this._wave.hasCalledFnOnce && !(this._slot.partial || this._allDepsSettled());
|
|
2595
|
-
if (this._wave.pending > 0 || gated) return;
|
|
2596
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2597
|
-
this._markDirty();
|
|
2598
|
-
this._tryRun();
|
|
2599
|
-
}
|
|
2856
|
+
nodeFirePullDemand(nodeRuntimeHost(this));
|
|
2600
2857
|
}
|
|
2601
|
-
/**
|
|
2602
|
-
* R-pull (D55/D59): fire a demand that was OWED (deferred at demand time) once the node becomes
|
|
2603
|
-
* able — called from the dep-settle arms (DATA/RESOLVED/INVALIDATE/terminal drain _pending, pin-5
|
|
2604
|
-
* + B1/F6) and from `_pauseRelease` (an external PAUSE lock releases, F4/F5).
|
|
2605
|
-
*/
|
|
2606
2858
|
_fireOwedDemandIfReady() {
|
|
2607
|
-
|
|
2608
|
-
if (this._slot.pull && this._control.demandOwed && this._canFireDemand())
|
|
2609
|
-
this._deliverPullDemand();
|
|
2859
|
+
nodeFireOwedDemandIfReady(nodeRuntimeHost(this));
|
|
2610
2860
|
}
|
|
2611
|
-
/** Should an outgoing settle slice be deferred into the pause buffer? */
|
|
2612
2861
|
_shouldBufferOnPause() {
|
|
2613
|
-
|
|
2614
|
-
if (!this._isPaused()) return false;
|
|
2615
|
-
if (this._slot.pausable === "resumeAll") return true;
|
|
2616
|
-
if (!this._wave.insideRunWave && this._isAsyncPool() && this._slot.deps.length > 0) return true;
|
|
2617
|
-
return false;
|
|
2862
|
+
return nodeShouldBufferOnPause(nodeRuntimeHost(this));
|
|
2618
2863
|
}
|
|
2619
|
-
/** R-invalidate-idempotent: clear cache + flush + cascade; no-op if nothing cached. */
|
|
2620
2864
|
_invalidate(delivery) {
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
this._value.hasData = false;
|
|
2624
|
-
this._value.status = "sentinel";
|
|
2625
|
-
this._value.replayRing = [];
|
|
2626
|
-
for (const fn of this._hooks.onInvalidate) fn();
|
|
2627
|
-
this._emitToSubs(["INVALIDATE"], delivery);
|
|
2628
|
-
}
|
|
2629
|
-
// B42 (R-deps-terminal): ALL deps TERMINAL = every dep has reached COMPLETE *or* an ABSORBED
|
|
2630
|
-
// ERROR. Block only on a LIVE dep (_depTerminal[i] === undefined); an errored dep (terminal = the
|
|
2631
|
-
// error payload, which R-data-payload guarantees is !== undefined and non-boolean) COUNTS as
|
|
2632
|
-
// terminal-done. Was
|
|
2633
|
-
// `tm !== true`, which wedged a node whose errorWhenDepsError:false dep ERRORed (it never
|
|
2634
|
-
// auto-completed even after every other dep completed). Drives the completeWhenDepsComplete cascade.
|
|
2865
|
+
nodeInvalidate(nodeRuntimeHost(this), delivery);
|
|
2866
|
+
}
|
|
2635
2867
|
_allDepsTerminal() {
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2868
|
+
return nodeAllDepsTerminal(nodeRuntimeHost(this));
|
|
2869
|
+
}
|
|
2870
|
+
_emitToSubs(msg, delivery) {
|
|
2871
|
+
nodeEmitToSubs(nodeRuntimeHost(this), msg, delivery);
|
|
2639
2872
|
}
|
|
2640
2873
|
/** R-terminal: resubscribable reset clears terminal + dep state + re-arms the gate. */
|
|
2641
2874
|
_resetLifecycle() {
|
|
2642
|
-
|
|
2643
|
-
this._dep.unsubs = [];
|
|
2644
|
-
this._dep.idxBoxes = [];
|
|
2645
|
-
this._lifecycle.subscribers.clear();
|
|
2646
|
-
this._lifecycle.activated = false;
|
|
2647
|
-
this._value.terminal = void 0;
|
|
2648
|
-
this._value.hasTorndown = false;
|
|
2649
|
-
this._wave.hasCalledFnOnce = false;
|
|
2650
|
-
this._resetDepState();
|
|
2651
|
-
this._control.pauseLockset.clear();
|
|
2652
|
-
this._control.pauseBuffer = [];
|
|
2653
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2654
|
-
this._control.demandOwed = false;
|
|
2655
|
-
this._value.replayRing = [];
|
|
2656
|
-
const isCompute = this._slot.handle !== null || this._slot.deps.length > 0;
|
|
2657
|
-
if (isCompute) {
|
|
2658
|
-
this._value.cache = SENTINEL;
|
|
2659
|
-
this._value.hasData = false;
|
|
2660
|
-
this._value.status = "sentinel";
|
|
2661
|
-
} else {
|
|
2662
|
-
this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
2663
|
-
}
|
|
2664
|
-
if (!this._privateState.persist) this._privateState.value = SENTINEL;
|
|
2665
|
-
}
|
|
2666
|
-
_emitToSubs(msg, delivery) {
|
|
2667
|
-
if (this._released) return;
|
|
2668
|
-
const subs = [...this._lifecycle.subscribers];
|
|
2669
|
-
for (const sink of subs) sink(msg, delivery);
|
|
2875
|
+
nodeResetLifecycle(nodeRuntimeHost(this));
|
|
2670
2876
|
}
|
|
2671
2877
|
/** Batch commit (R-batch-coalesce): deliver the deferred tier-3 wave now. */
|
|
2672
2878
|
__commitBatchedWave(wave) {
|
|
2673
|
-
this
|
|
2674
|
-
this._down(wave);
|
|
2879
|
+
nodeCommitBatchedWave(nodeRuntimeHost(this), wave);
|
|
2675
2880
|
}
|
|
2676
2881
|
/** Batch rollback: balance the immediate DIRTY with a RESOLVED so downstream un-dirties. */
|
|
2677
2882
|
__rollbackBatched() {
|
|
2678
|
-
|
|
2679
|
-
this._wave.batchDirtyOwed = false;
|
|
2680
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2681
|
-
this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
2682
|
-
this._emitToSubs(["RESOLVED"]);
|
|
2683
|
-
}
|
|
2883
|
+
nodeRollbackBatched(nodeRuntimeHost(this));
|
|
2684
2884
|
}
|
|
2685
2885
|
/** B49: enqueue a committed-boundary task on this node's graph-local core. */
|
|
2686
2886
|
__deferBoundary(fn, batchToken) {
|
|
2687
|
-
|
|
2688
|
-
batchToken,
|
|
2689
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
2690
|
-
});
|
|
2887
|
+
nodeDeferBoundary(nodeRuntimeHost(this), fn, batchToken);
|
|
2691
2888
|
}
|
|
2692
2889
|
};
|
|
2693
2890
|
function node(deps = [], handleOrFn = null, opts = {}) {
|
|
@@ -3053,7 +3250,10 @@ function collectionCore(backend, factory, opts = {}, restore) {
|
|
|
3053
3250
|
name: name ? `${name}.delta` : void 0
|
|
3054
3251
|
});
|
|
3055
3252
|
const pullId = /* @__PURE__ */ Symbol(name ? `${name}.snapshot` : `${factory}.snapshot`);
|
|
3253
|
+
let deliveredVersion = backend.version;
|
|
3056
3254
|
const snapFn = (ctx) => {
|
|
3255
|
+
if (ctx.pull !== void 0 && backend.version === deliveredVersion) return;
|
|
3256
|
+
deliveredVersion = backend.version;
|
|
3057
3257
|
ctx.down([["DATA", backend.snapshot()]]);
|
|
3058
3258
|
};
|
|
3059
3259
|
const snapshot = graph2 ? graph2.node([delta], snapFn, {
|
|
@@ -6034,28 +6234,110 @@ function cloneTopologyValue(value, seen) {
|
|
|
6034
6234
|
return out;
|
|
6035
6235
|
}
|
|
6036
6236
|
|
|
6037
|
-
// src/graph/graph.ts
|
|
6237
|
+
// src/graph/graph-lifecycle.ts
|
|
6038
6238
|
var restoreRegistrars = /* @__PURE__ */ new WeakMap();
|
|
6039
6239
|
var lifecycleRegistrars = /* @__PURE__ */ new WeakMap();
|
|
6040
|
-
|
|
6041
|
-
|
|
6240
|
+
|
|
6241
|
+
// src/graph/graph-support.ts
|
|
6242
|
+
function isNonAuthoritativeCollectionHelperMeta(meta) {
|
|
6243
|
+
return meta?.kind === "collection_delta" || meta?.kind === "collection_intent" || meta?.kind === "collection_policy_apply" || meta?.kind === "collection_snapshot" || meta?.kind === "collection_snapshot_prep";
|
|
6042
6244
|
}
|
|
6043
|
-
function
|
|
6044
|
-
if (
|
|
6045
|
-
throw new Error(`${label} has been released from its graph lifecycle (D122)`);
|
|
6046
|
-
}
|
|
6047
|
-
const existing = nodeOwner(n);
|
|
6048
|
-
if (existing !== void 0 && existing !== owner) {
|
|
6245
|
+
function assertCheckpointQuiescentStatus(status, id, op) {
|
|
6246
|
+
if (status === "pending" || status === "dirty") {
|
|
6049
6247
|
throw new Error(
|
|
6050
|
-
`${
|
|
6248
|
+
`${op}: node '${id}' has non-quiescent status '${status}' that cannot be checkpoint-restored yet`
|
|
6051
6249
|
);
|
|
6052
6250
|
}
|
|
6053
6251
|
}
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6252
|
+
function topologyPathMatches(eventPath, path) {
|
|
6253
|
+
return eventPath === path || eventPath.startsWith(`${path}::`);
|
|
6254
|
+
}
|
|
6255
|
+
function prefixTopologyPath(prefix, path) {
|
|
6256
|
+
return `${prefix}::${path}`;
|
|
6257
|
+
}
|
|
6258
|
+
function cloneTopologyEvent(event) {
|
|
6259
|
+
const deps = Object.freeze([...event.deps]);
|
|
6260
|
+
const prevDeps = event.prevDeps === void 0 ? void 0 : Object.freeze([...event.prevDeps]);
|
|
6261
|
+
return Object.freeze({
|
|
6262
|
+
kind: event.kind,
|
|
6263
|
+
path: event.path,
|
|
6264
|
+
deps,
|
|
6265
|
+
...prevDeps !== void 0 ? { prevDeps } : {},
|
|
6266
|
+
...event.factory !== void 0 ? { factory: event.factory } : {},
|
|
6267
|
+
seq: event.seq
|
|
6268
|
+
});
|
|
6269
|
+
}
|
|
6270
|
+
function checkpointFactory(name, node2, unregistered, restore, meta) {
|
|
6271
|
+
const state = checkpointStateOfNode(node2);
|
|
6272
|
+
if (unregistered) {
|
|
6273
|
+
return {
|
|
6274
|
+
kind: "local-only",
|
|
6275
|
+
name,
|
|
6276
|
+
reason: "node is an unregistered live dependency auto-discovered from topology"
|
|
6277
|
+
};
|
|
6057
6278
|
}
|
|
6058
|
-
|
|
6279
|
+
if (restore === void 0 && typeof meta?.kind === "string" && meta.kind.startsWith("collection_")) {
|
|
6280
|
+
return {
|
|
6281
|
+
kind: "local-only",
|
|
6282
|
+
name,
|
|
6283
|
+
reason: "collection helper node has no backend checkpoint restore metadata"
|
|
6284
|
+
};
|
|
6285
|
+
}
|
|
6286
|
+
if (restore !== void 0) {
|
|
6287
|
+
const out = {
|
|
6288
|
+
kind: "registry-ref",
|
|
6289
|
+
ref: toCheckpointJson(restore.ref, `${name}.factory.ref`)
|
|
6290
|
+
};
|
|
6291
|
+
if (restore.config !== void 0)
|
|
6292
|
+
out.config = toCheckpointJson(restore.config, `${name}.factory.config`);
|
|
6293
|
+
if (restore.configVersion !== void 0)
|
|
6294
|
+
out.configVersion = toCheckpointJson(restore.configVersion, `${name}.factory.configVersion`);
|
|
6295
|
+
return out;
|
|
6296
|
+
}
|
|
6297
|
+
if (state.handle !== null) {
|
|
6298
|
+
return {
|
|
6299
|
+
kind: "local-only",
|
|
6300
|
+
name,
|
|
6301
|
+
reason: "node uses a function body; first-cut checkpoints do not serialize local functions"
|
|
6302
|
+
};
|
|
6303
|
+
}
|
|
6304
|
+
return { kind: "registry-ref", ref: name };
|
|
6305
|
+
}
|
|
6306
|
+
function explainSubset(snap, chain) {
|
|
6307
|
+
const fwd = /* @__PURE__ */ new Map();
|
|
6308
|
+
const rev = /* @__PURE__ */ new Map();
|
|
6309
|
+
const push = (map2, k, v) => {
|
|
6310
|
+
const a = map2.get(k);
|
|
6311
|
+
if (a) a.push(v);
|
|
6312
|
+
else map2.set(k, [v]);
|
|
6313
|
+
};
|
|
6314
|
+
for (const e of snap.edges) {
|
|
6315
|
+
push(fwd, e.from, e.to);
|
|
6316
|
+
push(rev, e.to, e.from);
|
|
6317
|
+
}
|
|
6318
|
+
const reach = (start, adj) => {
|
|
6319
|
+
const seen = /* @__PURE__ */ new Set([start]);
|
|
6320
|
+
const stack = [start];
|
|
6321
|
+
while (stack.length > 0) {
|
|
6322
|
+
const cur = stack.pop();
|
|
6323
|
+
for (const nxt of adj.get(cur) ?? []) {
|
|
6324
|
+
if (!seen.has(nxt)) {
|
|
6325
|
+
seen.add(nxt);
|
|
6326
|
+
stack.push(nxt);
|
|
6327
|
+
}
|
|
6328
|
+
}
|
|
6329
|
+
}
|
|
6330
|
+
return seen;
|
|
6331
|
+
};
|
|
6332
|
+
const onPath = new Set([...reach(chain.from, fwd)].filter((id) => reach(chain.to, rev).has(id)));
|
|
6333
|
+
return {
|
|
6334
|
+
...snap.name !== void 0 ? { name: snap.name } : {},
|
|
6335
|
+
nodes: snap.nodes.filter((n) => onPath.has(n.id)),
|
|
6336
|
+
edges: snap.edges.filter((e) => onPath.has(e.from) && onPath.has(e.to))
|
|
6337
|
+
};
|
|
6338
|
+
}
|
|
6339
|
+
|
|
6340
|
+
// src/graph/graph-topology-group.ts
|
|
6059
6341
|
var GraphTopologyGroup = class {
|
|
6060
6342
|
name;
|
|
6061
6343
|
_graph;
|
|
@@ -6116,6 +6398,27 @@ var GraphTopologyGroup = class {
|
|
|
6116
6398
|
}
|
|
6117
6399
|
}
|
|
6118
6400
|
};
|
|
6401
|
+
|
|
6402
|
+
// src/graph/graph.ts
|
|
6403
|
+
function nodeOwner(n) {
|
|
6404
|
+
return getNodeOwner(n);
|
|
6405
|
+
}
|
|
6406
|
+
function assertGraphLocalNode(owner, n, label) {
|
|
6407
|
+
if (isNodeRuntimeReleased(n)) {
|
|
6408
|
+
throw new Error(`${label} has been released from its graph lifecycle (D122)`);
|
|
6409
|
+
}
|
|
6410
|
+
const existing = nodeOwner(n);
|
|
6411
|
+
if (existing !== void 0 && existing !== owner) {
|
|
6412
|
+
throw new Error(
|
|
6413
|
+
`${label} belongs to a different graph; cross-graph deps require a wire bridge`
|
|
6414
|
+
);
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
var StateNode = class extends Node {
|
|
6418
|
+
set(v) {
|
|
6419
|
+
this.down([["DATA", v]]);
|
|
6420
|
+
}
|
|
6421
|
+
};
|
|
6119
6422
|
var Graph = class {
|
|
6120
6423
|
name;
|
|
6121
6424
|
_dispatcher;
|
|
@@ -6221,7 +6524,13 @@ var Graph = class {
|
|
|
6221
6524
|
}
|
|
6222
6525
|
/** Look up a registered node by its id. */
|
|
6223
6526
|
find(id) {
|
|
6224
|
-
|
|
6527
|
+
const local = this._byId.get(id);
|
|
6528
|
+
if (local !== void 0) return local;
|
|
6529
|
+
const separator = id.indexOf("::");
|
|
6530
|
+
if (separator < 0) return void 0;
|
|
6531
|
+
const mountPath = id.slice(0, separator);
|
|
6532
|
+
const childPath = id.slice(separator + 2);
|
|
6533
|
+
return this._mounts.find((mount) => mount.at === mountPath)?.graph.find(childPath);
|
|
6225
6534
|
}
|
|
6226
6535
|
_releaseNodes(nodes, _opts = {}) {
|
|
6227
6536
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -6775,103 +7084,6 @@ var Graph = class {
|
|
|
6775
7084
|
return out;
|
|
6776
7085
|
}
|
|
6777
7086
|
};
|
|
6778
|
-
function isNonAuthoritativeCollectionHelperMeta(meta) {
|
|
6779
|
-
return meta?.kind === "collection_delta" || meta?.kind === "collection_intent" || meta?.kind === "collection_policy_apply" || meta?.kind === "collection_snapshot" || meta?.kind === "collection_snapshot_prep";
|
|
6780
|
-
}
|
|
6781
|
-
function assertCheckpointQuiescentStatus(status, id, op) {
|
|
6782
|
-
if (status === "pending" || status === "dirty") {
|
|
6783
|
-
throw new Error(
|
|
6784
|
-
`${op}: node '${id}' has non-quiescent status '${status}' that cannot be checkpoint-restored yet`
|
|
6785
|
-
);
|
|
6786
|
-
}
|
|
6787
|
-
}
|
|
6788
|
-
function topologyPathMatches(eventPath, path) {
|
|
6789
|
-
return eventPath === path || eventPath.startsWith(`${path}::`);
|
|
6790
|
-
}
|
|
6791
|
-
function prefixTopologyPath(prefix, path) {
|
|
6792
|
-
return `${prefix}::${path}`;
|
|
6793
|
-
}
|
|
6794
|
-
function cloneTopologyEvent(event) {
|
|
6795
|
-
const deps = Object.freeze([...event.deps]);
|
|
6796
|
-
const prevDeps = event.prevDeps === void 0 ? void 0 : Object.freeze([...event.prevDeps]);
|
|
6797
|
-
return Object.freeze({
|
|
6798
|
-
kind: event.kind,
|
|
6799
|
-
path: event.path,
|
|
6800
|
-
deps,
|
|
6801
|
-
...prevDeps !== void 0 ? { prevDeps } : {},
|
|
6802
|
-
...event.factory !== void 0 ? { factory: event.factory } : {},
|
|
6803
|
-
seq: event.seq
|
|
6804
|
-
});
|
|
6805
|
-
}
|
|
6806
|
-
function checkpointFactory(name, node2, unregistered, restore, meta) {
|
|
6807
|
-
const state = checkpointStateOfNode(node2);
|
|
6808
|
-
if (unregistered) {
|
|
6809
|
-
return {
|
|
6810
|
-
kind: "local-only",
|
|
6811
|
-
name,
|
|
6812
|
-
reason: "node is an unregistered live dependency auto-discovered from topology"
|
|
6813
|
-
};
|
|
6814
|
-
}
|
|
6815
|
-
if (restore === void 0 && typeof meta?.kind === "string" && meta.kind.startsWith("collection_")) {
|
|
6816
|
-
return {
|
|
6817
|
-
kind: "local-only",
|
|
6818
|
-
name,
|
|
6819
|
-
reason: "collection helper node has no backend checkpoint restore metadata"
|
|
6820
|
-
};
|
|
6821
|
-
}
|
|
6822
|
-
if (restore !== void 0) {
|
|
6823
|
-
const out = {
|
|
6824
|
-
kind: "registry-ref",
|
|
6825
|
-
ref: toCheckpointJson(restore.ref, `${name}.factory.ref`)
|
|
6826
|
-
};
|
|
6827
|
-
if (restore.config !== void 0)
|
|
6828
|
-
out.config = toCheckpointJson(restore.config, `${name}.factory.config`);
|
|
6829
|
-
if (restore.configVersion !== void 0)
|
|
6830
|
-
out.configVersion = toCheckpointJson(restore.configVersion, `${name}.factory.configVersion`);
|
|
6831
|
-
return out;
|
|
6832
|
-
}
|
|
6833
|
-
if (state.handle !== null) {
|
|
6834
|
-
return {
|
|
6835
|
-
kind: "local-only",
|
|
6836
|
-
name,
|
|
6837
|
-
reason: "node uses a function body; first-cut checkpoints do not serialize local functions"
|
|
6838
|
-
};
|
|
6839
|
-
}
|
|
6840
|
-
return { kind: "registry-ref", ref: name };
|
|
6841
|
-
}
|
|
6842
|
-
function explainSubset(snap, chain) {
|
|
6843
|
-
const fwd = /* @__PURE__ */ new Map();
|
|
6844
|
-
const rev = /* @__PURE__ */ new Map();
|
|
6845
|
-
const push = (map2, k, v) => {
|
|
6846
|
-
const a = map2.get(k);
|
|
6847
|
-
if (a) a.push(v);
|
|
6848
|
-
else map2.set(k, [v]);
|
|
6849
|
-
};
|
|
6850
|
-
for (const e of snap.edges) {
|
|
6851
|
-
push(fwd, e.from, e.to);
|
|
6852
|
-
push(rev, e.to, e.from);
|
|
6853
|
-
}
|
|
6854
|
-
const reach = (start, adj) => {
|
|
6855
|
-
const seen = /* @__PURE__ */ new Set([start]);
|
|
6856
|
-
const stack = [start];
|
|
6857
|
-
while (stack.length > 0) {
|
|
6858
|
-
const cur = stack.pop();
|
|
6859
|
-
for (const nxt of adj.get(cur) ?? []) {
|
|
6860
|
-
if (!seen.has(nxt)) {
|
|
6861
|
-
seen.add(nxt);
|
|
6862
|
-
stack.push(nxt);
|
|
6863
|
-
}
|
|
6864
|
-
}
|
|
6865
|
-
}
|
|
6866
|
-
return seen;
|
|
6867
|
-
};
|
|
6868
|
-
const onPath = new Set([...reach(chain.from, fwd)].filter((id) => reach(chain.to, rev).has(id)));
|
|
6869
|
-
return {
|
|
6870
|
-
...snap.name !== void 0 ? { name: snap.name } : {},
|
|
6871
|
-
nodes: snap.nodes.filter((n) => onPath.has(n.id)),
|
|
6872
|
-
edges: snap.edges.filter((e) => onPath.has(e.from) && onPath.has(e.to))
|
|
6873
|
-
};
|
|
6874
|
-
}
|
|
6875
7087
|
function graph(opts = {}) {
|
|
6876
7088
|
return new Graph(opts);
|
|
6877
7089
|
}
|