@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
|
@@ -52,6 +52,7 @@ var TIER = {
|
|
|
52
52
|
START: TIER_START,
|
|
53
53
|
PAUSE: TIER_CONTROL,
|
|
54
54
|
RESUME: TIER_CONTROL,
|
|
55
|
+
PULL: TIER_CONTROL,
|
|
55
56
|
DIRTY: TIER_NOTIFICATION,
|
|
56
57
|
DATA: TIER_VALUE,
|
|
57
58
|
RESOLVED: TIER_VALUE,
|
|
@@ -154,30 +155,6 @@ function drain() {
|
|
|
154
155
|
if (escaped !== null) throw escaped.e;
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
// src/batch/batch.ts
|
|
158
|
-
var active = null;
|
|
159
|
-
var boundaryOwner = null;
|
|
160
|
-
function currentBatch() {
|
|
161
|
-
return active !== null;
|
|
162
|
-
}
|
|
163
|
-
function currentBoundaryBatchToken() {
|
|
164
|
-
return active ?? boundaryOwner ?? void 0;
|
|
165
|
-
}
|
|
166
|
-
function deferToBatch(target, tier3Wave) {
|
|
167
|
-
if (active === null) return false;
|
|
168
|
-
if (!active.deferred.has(target)) active.order.push(target);
|
|
169
|
-
active.deferred.set(target, tier3Wave);
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
172
|
-
function deferAfterBatchForTarget(target, fn) {
|
|
173
|
-
if (active === null || !active.deferred.has(target)) return false;
|
|
174
|
-
const owner = active;
|
|
175
|
-
target.__deferBoundary(() => {
|
|
176
|
-
if (owner.committed) fn();
|
|
177
|
-
}, owner);
|
|
178
|
-
return true;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
158
|
// src/dispatcher/index.ts
|
|
182
159
|
var PoolTable = class {
|
|
183
160
|
constructor(kind) {
|
|
@@ -484,6 +461,589 @@ function makeDepBookkeeping(depCount2) {
|
|
|
484
461
|
};
|
|
485
462
|
}
|
|
486
463
|
|
|
464
|
+
// src/node/protocol-guards.ts
|
|
465
|
+
function terminalView(t) {
|
|
466
|
+
return t === void 0 ? false : t;
|
|
467
|
+
}
|
|
468
|
+
function normalizePullDemand(demand) {
|
|
469
|
+
if (typeof demand !== "object" || demand === null || Array.isArray(demand)) {
|
|
470
|
+
throw new Error("ctx.up: PULL requires { pullId, params? } demand payload (D269)");
|
|
471
|
+
}
|
|
472
|
+
const pullId = demand.pullId;
|
|
473
|
+
if (typeof pullId !== "string" && typeof pullId !== "symbol") {
|
|
474
|
+
throw new Error("ctx.up: PULL demand requires a string or symbol pullId (D269)");
|
|
475
|
+
}
|
|
476
|
+
const params = demand.params;
|
|
477
|
+
return params === void 0 ? { pullId } : { pullId, params };
|
|
478
|
+
}
|
|
479
|
+
function validateDownPayloads(msgs) {
|
|
480
|
+
for (const m of msgs) {
|
|
481
|
+
if (m[0] === "DATA" && m[1] === void 0) {
|
|
482
|
+
throw new Error("down: DATA requires a non-SENTINEL payload (R-data-payload)");
|
|
483
|
+
}
|
|
484
|
+
if (m[0] === "ERROR" && isInvalidErrorPayload(m[1])) {
|
|
485
|
+
throw new Error("down: ERROR requires a non-SENTINEL, non-boolean payload (R-data-payload)");
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// src/node/runtime-accessors.ts
|
|
491
|
+
var constructingCore;
|
|
492
|
+
var constructingEnvironment;
|
|
493
|
+
var ownerTokens = /* @__PURE__ */ new WeakMap();
|
|
494
|
+
var topologyDepsChangedObservers = /* @__PURE__ */ new WeakMap();
|
|
495
|
+
var checkpointReaders = /* @__PURE__ */ new WeakMap();
|
|
496
|
+
var restoreWriters = /* @__PURE__ */ new WeakMap();
|
|
497
|
+
var runtimeReleasers = /* @__PURE__ */ new WeakMap();
|
|
498
|
+
var runtimeQuiescenceReaders = /* @__PURE__ */ new WeakMap();
|
|
499
|
+
var subscriberCountReaders = /* @__PURE__ */ new WeakMap();
|
|
500
|
+
var activationReaders = /* @__PURE__ */ new WeakMap();
|
|
501
|
+
var releasedNodes = /* @__PURE__ */ new WeakSet();
|
|
502
|
+
function withNodeCore(core, create) {
|
|
503
|
+
const prev = constructingCore;
|
|
504
|
+
constructingCore = core;
|
|
505
|
+
try {
|
|
506
|
+
return create();
|
|
507
|
+
} finally {
|
|
508
|
+
constructingCore = prev;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
function takeConstructingNodeCore() {
|
|
512
|
+
const core = constructingCore;
|
|
513
|
+
constructingCore = void 0;
|
|
514
|
+
return core;
|
|
515
|
+
}
|
|
516
|
+
function withEnvironmentDrivers(environment, create) {
|
|
517
|
+
const prev = constructingEnvironment;
|
|
518
|
+
constructingEnvironment = environment;
|
|
519
|
+
try {
|
|
520
|
+
return create();
|
|
521
|
+
} finally {
|
|
522
|
+
constructingEnvironment = prev;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function takeConstructingEnvironmentDrivers() {
|
|
526
|
+
const environment = constructingEnvironment;
|
|
527
|
+
constructingEnvironment = void 0;
|
|
528
|
+
return environment;
|
|
529
|
+
}
|
|
530
|
+
function getNodeOwner(n) {
|
|
531
|
+
return ownerTokens.get(n);
|
|
532
|
+
}
|
|
533
|
+
function notifyTopologyDepsChanged(node2, prevDeps, deps) {
|
|
534
|
+
topologyDepsChangedObservers.get(node2)?.(node2, prevDeps, deps);
|
|
535
|
+
}
|
|
536
|
+
function releaseRuntimeOfNode(n) {
|
|
537
|
+
runtimeReleasers.get(n)?.();
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/node/node-context-runtime.ts
|
|
541
|
+
function nodeBuildCtx(self) {
|
|
542
|
+
const kind = self._slot.handle ? self._slot.dispatcher.poolKind(self._slot.handle.poolId) : "sync";
|
|
543
|
+
if (kind === "sync") {
|
|
544
|
+
if (self._syncCtx === null) self._syncCtx = self._makeCtx();
|
|
545
|
+
self._refreshCtx(self._syncCtx);
|
|
546
|
+
return self._syncCtx;
|
|
547
|
+
}
|
|
548
|
+
return self._makeCtx({
|
|
549
|
+
waveData: self._dep.waveData.map((waves) => waves.map((w) => [...w])),
|
|
550
|
+
terminal: self._dep.terminalInput.map(terminalView),
|
|
551
|
+
latest: [...self._dep.prev]
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
function nodeMakeCtx(self, snapshot) {
|
|
555
|
+
const ctx = {
|
|
556
|
+
// Wave-owner boundary (D47): a SYNC fn's emit nests under the public entry that drove
|
|
557
|
+
// it (cheap inc/dec, no early drain); an ASYNC-pool fn re-enters here from its stashed
|
|
558
|
+
// ctx at depth 0, so this is the boundary that drains any rewireNext it issued.
|
|
559
|
+
up: (msgs, towardDep) => {
|
|
560
|
+
if (self._released) return;
|
|
561
|
+
enterWave();
|
|
562
|
+
try {
|
|
563
|
+
self._up(msgs, towardDep);
|
|
564
|
+
} finally {
|
|
565
|
+
exitWave();
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
down: (msgs) => {
|
|
569
|
+
if (self._released) return;
|
|
570
|
+
enterWave();
|
|
571
|
+
try {
|
|
572
|
+
self._down(msgs);
|
|
573
|
+
} finally {
|
|
574
|
+
exitWave();
|
|
575
|
+
}
|
|
576
|
+
},
|
|
577
|
+
waveData: snapshot?.waveData ?? self._dep.waveData,
|
|
578
|
+
terminal: snapshot?.terminal ?? self._dep.terminalInput.map(terminalView),
|
|
579
|
+
state: self._makeState(),
|
|
580
|
+
onDeactivation: (fn) => {
|
|
581
|
+
if (self._released) return;
|
|
582
|
+
self._hooks.onDeactivation.push(fn);
|
|
583
|
+
},
|
|
584
|
+
onInvalidate: (fn) => {
|
|
585
|
+
if (self._released) return;
|
|
586
|
+
self._hooks.onInvalidate.push(fn);
|
|
587
|
+
},
|
|
588
|
+
environment: () => self._slot.environment,
|
|
589
|
+
// R-rewire-deferred (D47): defer a self-dep-set mutation to the committed boundary.
|
|
590
|
+
rewireNext: {
|
|
591
|
+
subscribeDep: (dep, fn) => self._requestRewireNext({ kind: "add", dep, fn }),
|
|
592
|
+
unsubscribeDep: (dep, fn) => self._requestRewireNext({ kind: "remove", dep, fn }),
|
|
593
|
+
replaceDeps: (deps, fn) => self._requestRewireNext({ kind: "set", deps, fn })
|
|
594
|
+
},
|
|
595
|
+
// R-up-routing / R-pull (D269): deferred up — route a control/demand wave (e.g. PULL)
|
|
596
|
+
// up the declared cone at the committed boundary. The SELF-demand path: an
|
|
597
|
+
// immediate ctx.up whose delivery loops back re-enters this fn (D37 / R-reentrancy).
|
|
598
|
+
upNext: (msgs, towardDep) => self._requestUpNext(msgs, towardDep),
|
|
599
|
+
...self._control.activePull === void 0 ? {} : { pull: self._control.activePull },
|
|
600
|
+
[CTX_DEP_CACHE]: { latest: snapshot?.latest ?? self._dep.prev },
|
|
601
|
+
[CTX_NODE_BINDING]: {
|
|
602
|
+
dispatcher: self._slot.dispatcher,
|
|
603
|
+
create: (factory) => withEnvironmentDrivers(self._slot.environment, () => withNodeCore(self._core, factory))
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
if (self._slot.dynamic) {
|
|
607
|
+
ctx.track = (i) => ctx[CTX_DEP_CACHE]?.latest[i];
|
|
608
|
+
}
|
|
609
|
+
return ctx;
|
|
610
|
+
}
|
|
611
|
+
function nodeRefreshCtx(self, ctx) {
|
|
612
|
+
ctx.waveData = self._dep.waveData;
|
|
613
|
+
ctx.terminal = self._dep.terminalInput.map(terminalView);
|
|
614
|
+
if (self._control.activePull === void 0) {
|
|
615
|
+
delete ctx.pull;
|
|
616
|
+
} else {
|
|
617
|
+
ctx.pull = self._control.activePull;
|
|
618
|
+
}
|
|
619
|
+
ctx[CTX_DEP_CACHE] = { latest: self._dep.prev };
|
|
620
|
+
}
|
|
621
|
+
function nodeMakeState(self) {
|
|
622
|
+
return {
|
|
623
|
+
get: () => self._privateState.value,
|
|
624
|
+
set: (v) => {
|
|
625
|
+
self._privateState.value = v;
|
|
626
|
+
},
|
|
627
|
+
persist: (on = true) => {
|
|
628
|
+
self._privateState.persist = on;
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// src/node/node-input-runtime.ts
|
|
634
|
+
function nodeRecordDepProjection(self, idx, delivery) {
|
|
635
|
+
const token = delivery?.wave ?? {};
|
|
636
|
+
if (self._dep.waveTokens[idx] !== token) {
|
|
637
|
+
self._dep.waveData[idx].push([]);
|
|
638
|
+
self._dep.waveTokens[idx] = token;
|
|
639
|
+
}
|
|
640
|
+
return self._dep.waveData[idx][self._dep.waveData[idx].length - 1];
|
|
641
|
+
}
|
|
642
|
+
function nodeDepProjectionHasData(self, idx) {
|
|
643
|
+
const projection = self._dep.waveData[idx][self._dep.waveData[idx].length - 1];
|
|
644
|
+
return projection?.some((v) => v !== SENTINEL) ?? false;
|
|
645
|
+
}
|
|
646
|
+
function nodeReceiveFromDep(self, idx, msg, delivery) {
|
|
647
|
+
if (self._released) return;
|
|
648
|
+
const t = msg[0];
|
|
649
|
+
if (t === "START") return;
|
|
650
|
+
const isLastInDeliveredWave = delivery?.last ?? true;
|
|
651
|
+
if (self._value.terminal !== void 0) {
|
|
652
|
+
if (t === "TEARDOWN") self._down([["TEARDOWN"]]);
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
if (t === "INVALIDATE") {
|
|
656
|
+
const projection = self._recordDepProjection(idx, delivery);
|
|
657
|
+
projection.push(SENTINEL);
|
|
658
|
+
if (projection.some((v) => v !== SENTINEL) && isLastInDeliveredWave) self._maybeRun();
|
|
659
|
+
self._dep.prev[idx] = SENTINEL;
|
|
660
|
+
self._dep.hasData[idx] = false;
|
|
661
|
+
self._dep.batch[idx] = null;
|
|
662
|
+
if (self._dep.dirty[idx]) {
|
|
663
|
+
self._dep.dirty[idx] = false;
|
|
664
|
+
self._wave.pending--;
|
|
665
|
+
}
|
|
666
|
+
if (self._control.pausedDepWaveOccurred && self._dep.batch.every((b) => b === null)) {
|
|
667
|
+
self._control.pausedDepWaveOccurred = false;
|
|
668
|
+
}
|
|
669
|
+
const hadData = self._value.hasData;
|
|
670
|
+
self._invalidate();
|
|
671
|
+
if (self._wave.pending === 0 && self._wave.emittedDirtyThisWave) {
|
|
672
|
+
if (!hadData) self._down([["RESOLVED"]]);
|
|
673
|
+
else self._wave.emittedDirtyThisWave = false;
|
|
674
|
+
}
|
|
675
|
+
self._fireOwedDemandIfReady();
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
if (isTerminal(t)) {
|
|
679
|
+
const isError = t === "ERROR";
|
|
680
|
+
const errPayload = isError ? msg[1] : void 0;
|
|
681
|
+
self._dep.terminal[idx] = isError ? errPayload : true;
|
|
682
|
+
self._dep.terminalInput[idx] = isError ? errPayload : true;
|
|
683
|
+
self._releaseDepDirty(idx);
|
|
684
|
+
const ranValueBeforeTerminal = self._depProjectionHasData(idx) && isLastInDeliveredWave;
|
|
685
|
+
if (ranValueBeforeTerminal) self._maybeRun();
|
|
686
|
+
if (isError && self._slot.errorWhenDepsError) {
|
|
687
|
+
self._down([["ERROR", errPayload]]);
|
|
688
|
+
} else if (self._slot.terminalAsRealInput) {
|
|
689
|
+
if (ranValueBeforeTerminal) {
|
|
690
|
+
self._fireOwedDemandIfReady();
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
self._maybeRun();
|
|
694
|
+
} else if (self._slot.completeWhenDepsComplete && self._allDepsTerminal()) {
|
|
695
|
+
self._down([["COMPLETE"]]);
|
|
696
|
+
} else {
|
|
697
|
+
self._settleAfterAbsorbedTerminal();
|
|
698
|
+
}
|
|
699
|
+
self._fireOwedDemandIfReady();
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
if (t === "TEARDOWN") {
|
|
703
|
+
self._down([["TEARDOWN"]]);
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
if (t === "DIRTY") {
|
|
707
|
+
if (!self._dep.dirty[idx]) {
|
|
708
|
+
self._dep.dirty[idx] = true;
|
|
709
|
+
self._wave.pending++;
|
|
710
|
+
self._dep.tier[idx] = 2;
|
|
711
|
+
self._markDirty();
|
|
712
|
+
}
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (t === "DATA") {
|
|
716
|
+
const v = msg[1];
|
|
717
|
+
self._recordDepProjection(idx, delivery).push(v);
|
|
718
|
+
const b = self._dep.batch[idx];
|
|
719
|
+
if (b === null) self._dep.batch[idx] = [v];
|
|
720
|
+
else b.push(v);
|
|
721
|
+
self._dep.prev[idx] = v;
|
|
722
|
+
self._dep.hasData[idx] = true;
|
|
723
|
+
self._dep.tier[idx] = 3;
|
|
724
|
+
if (self._dep.dirty[idx]) {
|
|
725
|
+
self._dep.dirty[idx] = false;
|
|
726
|
+
self._wave.pending--;
|
|
727
|
+
}
|
|
728
|
+
if (isLastInDeliveredWave) self._maybeRun();
|
|
729
|
+
self._fireOwedDemandIfReady();
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
if (t === "RESOLVED") {
|
|
733
|
+
self._recordDepProjection(idx, delivery);
|
|
734
|
+
self._dep.tier[idx] = 3;
|
|
735
|
+
if (self._dep.dirty[idx]) {
|
|
736
|
+
self._dep.dirty[idx] = false;
|
|
737
|
+
self._wave.pending--;
|
|
738
|
+
}
|
|
739
|
+
if (isLastInDeliveredWave) self._maybeRun();
|
|
740
|
+
self._fireOwedDemandIfReady();
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
function nodeReleaseDepDirty(self, idx) {
|
|
745
|
+
if (self._dep.dirty[idx]) {
|
|
746
|
+
self._dep.dirty[idx] = false;
|
|
747
|
+
self._wave.pending--;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
function nodeSettleAfterAbsorbedTerminal(self) {
|
|
751
|
+
if (self._wave.pending !== 0 || !self._wave.emittedDirtyThisWave) return;
|
|
752
|
+
const sawData = self._dep.batch.some((b) => b !== null && b.length > 0);
|
|
753
|
+
if (sawData) self._maybeRun();
|
|
754
|
+
if (self._wave.emittedDirtyThisWave) self._down([["RESOLVED"]]);
|
|
755
|
+
}
|
|
756
|
+
function nodeMarkDirty(self) {
|
|
757
|
+
self._value.status = "dirty";
|
|
758
|
+
if (self._isPullQuiet()) return;
|
|
759
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
760
|
+
self._wave.emittedDirtyThisWave = true;
|
|
761
|
+
self._emitToSubs(["DIRTY"]);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
function nodeMaybeRun(self) {
|
|
765
|
+
if (self._wave.inDepMutation) {
|
|
766
|
+
self._wave.rewireRunPending = true;
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
if (self._slot.pausable === true && (self._isPaused() || self._isPullQuiet())) {
|
|
770
|
+
self._control.pausedDepWaveOccurred = true;
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
self._tryRun();
|
|
774
|
+
}
|
|
775
|
+
function nodeSettleRewire(self) {
|
|
776
|
+
if (self._slot.pausable === true && self._isPaused()) {
|
|
777
|
+
self._control.pausedDepWaveOccurred = true;
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
if (self._wave.pending > 0) return;
|
|
781
|
+
if (self._slot.handle === null) {
|
|
782
|
+
self._passthroughEmit();
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
if (!self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled())) return;
|
|
786
|
+
self._markDirty();
|
|
787
|
+
self._runWave();
|
|
788
|
+
}
|
|
789
|
+
function nodeTryRun(self) {
|
|
790
|
+
if (self._wave.pending > 0) return;
|
|
791
|
+
if (self._slot.handle === null) {
|
|
792
|
+
self._passthroughEmit();
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
if (!self._wave.hasCalledFnOnce) {
|
|
796
|
+
if (self._slot.partial || self._allDepsSettled()) self._runWave();
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
self._runWave();
|
|
800
|
+
}
|
|
801
|
+
function nodeAllDepsSettled(self) {
|
|
802
|
+
for (let i = 0; i < self._slot.deps.length; i++) {
|
|
803
|
+
if (self._dep.hasData[i]) continue;
|
|
804
|
+
if (self._slot.terminalAsRealInput && self._dep.terminal[i] !== void 0) continue;
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
return true;
|
|
808
|
+
}
|
|
809
|
+
function nodePassthroughEmit(self) {
|
|
810
|
+
const b = self._dep.batch[0];
|
|
811
|
+
if (b !== null && b.length > 0) {
|
|
812
|
+
self._down([["DATA", b[b.length - 1]]]);
|
|
813
|
+
} else if (self._wave.emittedDirtyThisWave) {
|
|
814
|
+
self._down([["RESOLVED"]]);
|
|
815
|
+
}
|
|
816
|
+
self._dep.batch[0] = null;
|
|
817
|
+
self._wave.emittedDirtyThisWave = false;
|
|
818
|
+
}
|
|
819
|
+
function nodeRunWave(self) {
|
|
820
|
+
if (self._wave.insideRunWave)
|
|
821
|
+
throw new Error(
|
|
822
|
+
"synchronous feedback cycle: node fn re-entered its own wave (R-reentrancy / D37)"
|
|
823
|
+
);
|
|
824
|
+
self._wave.hasCalledFnOnce = true;
|
|
825
|
+
self._hooks.onInvalidate = [];
|
|
826
|
+
self._hooks.onDeactivation = [];
|
|
827
|
+
const ctx = self._buildCtx();
|
|
828
|
+
const wasDirty = self._wave.emittedDirtyThisWave;
|
|
829
|
+
self._wave.emittedSettleThisWave = false;
|
|
830
|
+
self._wave.insideRunWave = true;
|
|
831
|
+
try {
|
|
832
|
+
self._slot.dispatcher.invoke(self._slot.handle, ctx);
|
|
833
|
+
} finally {
|
|
834
|
+
self._wave.insideRunWave = false;
|
|
835
|
+
}
|
|
836
|
+
if (wasDirty && !self._wave.emittedSettleThisWave && self._value.terminal === void 0 && !self._isAsyncPool()) {
|
|
837
|
+
self._down([["RESOLVED"]]);
|
|
838
|
+
}
|
|
839
|
+
for (let i = 0; i < self._dep.batch.length; i++) {
|
|
840
|
+
self._dep.batch[i] = null;
|
|
841
|
+
self._dep.waveData[i] = [];
|
|
842
|
+
self._dep.waveTokens[i] = void 0;
|
|
843
|
+
self._dep.terminalInput[i] = void 0;
|
|
844
|
+
}
|
|
845
|
+
self._wave.emittedDirtyThisWave = false;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// src/node/node-runtime-host.ts
|
|
849
|
+
function nodeRuntimeHost(node2) {
|
|
850
|
+
return node2;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// src/node/node-lifecycle-runtime.ts
|
|
854
|
+
function nodeActivate(self) {
|
|
855
|
+
self._lifecycle.activated = true;
|
|
856
|
+
const seedRestoredDeps = self._restoredActivationPending;
|
|
857
|
+
self._restoredActivationPending = false;
|
|
858
|
+
self._dep.unsubs = new Array(self._slot.deps.length);
|
|
859
|
+
self._dep.idxBoxes = new Array(self._slot.deps.length);
|
|
860
|
+
for (const dep of self._slot.deps) self._subscribeDepAt(dep, { seedRestored: seedRestoredDeps });
|
|
861
|
+
if (self._slot.deps.length === 0 && self._slot.handle !== null && !self._wave.hasCalledFnOnce) {
|
|
862
|
+
self._runWave();
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
function nodeSubscribeDepAt(self, depNode, opts = {}) {
|
|
866
|
+
const idx0 = self._slot.deps.indexOf(depNode);
|
|
867
|
+
const box = { v: idx0 };
|
|
868
|
+
let ignoreInitialPush = opts.seedRestored === true;
|
|
869
|
+
if (ignoreInitialPush && idx0 !== -1) {
|
|
870
|
+
self._seedRestoredDepAt(idx0, depNode);
|
|
871
|
+
const dep = nodeRuntimeHost(depNode);
|
|
872
|
+
if (dep._value.terminal !== void 0 && !dep._slot.resubscribable) {
|
|
873
|
+
self._dep.unsubs[idx0] = () => {
|
|
874
|
+
};
|
|
875
|
+
self._dep.idxBoxes[idx0] = box;
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
const unsub = depNode.subscribe((msg, delivery) => {
|
|
880
|
+
if (ignoreInitialPush && delivery === void 0) return;
|
|
881
|
+
if (ignoreInitialPush) ignoreInitialPush = false;
|
|
882
|
+
if (box.v === -1) return;
|
|
883
|
+
self._receiveFromDep(box.v, msg, delivery);
|
|
884
|
+
});
|
|
885
|
+
if (ignoreInitialPush && idx0 !== -1 && box.v !== -1) self._seedRestoredDepAt(idx0, depNode);
|
|
886
|
+
ignoreInitialPush = false;
|
|
887
|
+
if (idx0 !== -1) {
|
|
888
|
+
self._dep.unsubs[idx0] = unsub;
|
|
889
|
+
self._dep.idxBoxes[idx0] = box;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
function nodeSeedRestoredDepAt(self, idx, depNode) {
|
|
893
|
+
const dep = nodeRuntimeHost(depNode);
|
|
894
|
+
const seedData = dep._value.hasData && !dep._slot.pull;
|
|
895
|
+
self._dep.batch[idx] = null;
|
|
896
|
+
self._dep.waveData[idx] = [];
|
|
897
|
+
self._dep.waveTokens[idx] = void 0;
|
|
898
|
+
self._dep.prev[idx] = seedData ? dep._value.cache : SENTINEL;
|
|
899
|
+
self._dep.hasData[idx] = seedData;
|
|
900
|
+
self._dep.dirty[idx] = false;
|
|
901
|
+
self._dep.tier[idx] = seedData ? 3 : 0;
|
|
902
|
+
self._dep.terminal[idx] = dep._value.terminal;
|
|
903
|
+
self._dep.terminalInput[idx] = void 0;
|
|
904
|
+
}
|
|
905
|
+
function nodeDeactivate(self) {
|
|
906
|
+
self._lifecycle.activated = false;
|
|
907
|
+
for (const u of self._dep.unsubs) if (u) u();
|
|
908
|
+
self._dep.unsubs = [];
|
|
909
|
+
self._dep.idxBoxes = [];
|
|
910
|
+
for (const fn of self._hooks.onDeactivation) fn();
|
|
911
|
+
self._hooks.onDeactivation = [];
|
|
912
|
+
self._hooks.onInvalidate = [];
|
|
913
|
+
const isCompute = self._slot.handle !== null || self._slot.deps.length > 0;
|
|
914
|
+
if (isCompute) {
|
|
915
|
+
self._value.cache = SENTINEL;
|
|
916
|
+
self._value.hasData = false;
|
|
917
|
+
self._value.status = "sentinel";
|
|
918
|
+
}
|
|
919
|
+
self._resetDepState();
|
|
920
|
+
self._wave.hasCalledFnOnce = false;
|
|
921
|
+
self._control.pauseLockset.clear();
|
|
922
|
+
self._control.pauseBuffer = [];
|
|
923
|
+
self._control.pausedDepWaveOccurred = false;
|
|
924
|
+
self._control.demandOwed = void 0;
|
|
925
|
+
self._control.activePull = void 0;
|
|
926
|
+
self._control.pullDirtyOwed = false;
|
|
927
|
+
self._value.replayRing = [];
|
|
928
|
+
if (!self._privateState.persist) self._privateState.value = SENTINEL;
|
|
929
|
+
}
|
|
930
|
+
function nodeSubscriberCount(self) {
|
|
931
|
+
return self._lifecycle.subscribers.size;
|
|
932
|
+
}
|
|
933
|
+
function nodeIsRuntimeQuiescentForRelease(self) {
|
|
934
|
+
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;
|
|
935
|
+
}
|
|
936
|
+
function nodeReleaseRuntime(self) {
|
|
937
|
+
if (self._released) return;
|
|
938
|
+
self._released = true;
|
|
939
|
+
const node2 = self;
|
|
940
|
+
releasedNodes.add(node2);
|
|
941
|
+
let releaseError;
|
|
942
|
+
const recordReleaseError = (error) => {
|
|
943
|
+
if (releaseError === void 0) releaseError = error;
|
|
944
|
+
};
|
|
945
|
+
self._lifecycle.activated = false;
|
|
946
|
+
for (const u of self._dep.unsubs) {
|
|
947
|
+
try {
|
|
948
|
+
u();
|
|
949
|
+
} catch (error) {
|
|
950
|
+
recordReleaseError(error);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
for (const fn of self._hooks.onDeactivation) {
|
|
954
|
+
try {
|
|
955
|
+
fn();
|
|
956
|
+
} catch (error) {
|
|
957
|
+
recordReleaseError(error);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
self._dep.unsubs = [];
|
|
961
|
+
self._dep.idxBoxes = [];
|
|
962
|
+
self._lifecycle.subscribers.clear();
|
|
963
|
+
if (self._slot.handle !== null) {
|
|
964
|
+
self._slot.dispatcher.unregister(self._slot.handle);
|
|
965
|
+
self._slot.handle = null;
|
|
966
|
+
}
|
|
967
|
+
self._slot.deps = [];
|
|
968
|
+
self._dep.batch = [];
|
|
969
|
+
self._dep.waveData = [];
|
|
970
|
+
self._dep.waveTokens = [];
|
|
971
|
+
self._dep.prev = [];
|
|
972
|
+
self._dep.hasData = [];
|
|
973
|
+
self._dep.dirty = [];
|
|
974
|
+
self._dep.tier = [];
|
|
975
|
+
self._dep.terminal = [];
|
|
976
|
+
self._dep.terminalInput = [];
|
|
977
|
+
self._value.cache = SENTINEL;
|
|
978
|
+
self._value.hasData = false;
|
|
979
|
+
self._value.status = "sentinel";
|
|
980
|
+
self._value.terminal = void 0;
|
|
981
|
+
self._value.replayRing = [];
|
|
982
|
+
self._privateState.value = SENTINEL;
|
|
983
|
+
self._privateState.persist = false;
|
|
984
|
+
self._syncCtx = null;
|
|
985
|
+
self._resetDepState();
|
|
986
|
+
self._hooks.onDeactivation = [];
|
|
987
|
+
self._hooks.onInvalidate = [];
|
|
988
|
+
self._control.pauseLockset.clear();
|
|
989
|
+
self._control.pauseBuffer = [];
|
|
990
|
+
self._control.pausedDepWaveOccurred = false;
|
|
991
|
+
self._control.demandOwed = void 0;
|
|
992
|
+
self._control.activePull = void 0;
|
|
993
|
+
self._control.pullDirtyOwed = false;
|
|
994
|
+
self._restoredActivationPending = false;
|
|
995
|
+
checkpointReaders.delete(node2);
|
|
996
|
+
restoreWriters.delete(node2);
|
|
997
|
+
runtimeReleasers.delete(node2);
|
|
998
|
+
runtimeQuiescenceReaders.delete(node2);
|
|
999
|
+
subscriberCountReaders.delete(node2);
|
|
1000
|
+
activationReaders.delete(node2);
|
|
1001
|
+
ownerTokens.delete(node2);
|
|
1002
|
+
topologyDepsChangedObservers.delete(node2);
|
|
1003
|
+
self._core.releaseSlot(self._id);
|
|
1004
|
+
if (releaseError !== void 0) throw releaseError;
|
|
1005
|
+
}
|
|
1006
|
+
function nodeResetDepState(self) {
|
|
1007
|
+
const n = self._slot.deps.length;
|
|
1008
|
+
for (let i = 0; i < n; i++) {
|
|
1009
|
+
self._dep.batch[i] = null;
|
|
1010
|
+
self._dep.waveData[i] = [];
|
|
1011
|
+
self._dep.waveTokens[i] = void 0;
|
|
1012
|
+
self._dep.prev[i] = SENTINEL;
|
|
1013
|
+
self._dep.hasData[i] = false;
|
|
1014
|
+
self._dep.dirty[i] = false;
|
|
1015
|
+
self._dep.tier[i] = 0;
|
|
1016
|
+
self._dep.terminal[i] = void 0;
|
|
1017
|
+
self._dep.terminalInput[i] = void 0;
|
|
1018
|
+
}
|
|
1019
|
+
self._wave.pending = 0;
|
|
1020
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// src/batch/batch.ts
|
|
1024
|
+
var active = null;
|
|
1025
|
+
var boundaryOwner = null;
|
|
1026
|
+
function currentBatch() {
|
|
1027
|
+
return active !== null;
|
|
1028
|
+
}
|
|
1029
|
+
function currentBoundaryBatchToken() {
|
|
1030
|
+
return active ?? boundaryOwner ?? void 0;
|
|
1031
|
+
}
|
|
1032
|
+
function deferToBatch(target, tier3Wave) {
|
|
1033
|
+
if (active === null) return false;
|
|
1034
|
+
if (!active.deferred.has(target)) active.order.push(target);
|
|
1035
|
+
active.deferred.set(target, tier3Wave);
|
|
1036
|
+
return true;
|
|
1037
|
+
}
|
|
1038
|
+
function deferAfterBatchForTarget(target, fn) {
|
|
1039
|
+
if (active === null || !active.deferred.has(target)) return false;
|
|
1040
|
+
const owner = active;
|
|
1041
|
+
target.__deferBoundary(() => {
|
|
1042
|
+
if (owner.committed) fn();
|
|
1043
|
+
}, owner);
|
|
1044
|
+
return true;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
487
1047
|
// src/json/codec.ts
|
|
488
1048
|
var JS_MIN_NORMAL_NUMBER = 2 ** -1022;
|
|
489
1049
|
function assertStableJsonNumber(value, path) {
|
|
@@ -528,9 +1088,16 @@ function sortedJsonValue(value, seen = /* @__PURE__ */ new Set(), path = "$", st
|
|
|
528
1088
|
}
|
|
529
1089
|
for (const key of Object.getOwnPropertyNames(value)) {
|
|
530
1090
|
const isIndex = /^(0|[1-9]\d*)$/.test(key) && Number.isSafeInteger(Number(key)) && Number(key) < value.length;
|
|
1091
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1092
|
+
if (descriptor !== void 0 && ("get" in descriptor || "set" in descriptor)) {
|
|
1093
|
+
throw new TypeError(`stableJsonString: accessor property at ${path}.${key}`);
|
|
1094
|
+
}
|
|
531
1095
|
if (key !== "length" && !isIndex) {
|
|
532
1096
|
throw new TypeError(`stableJsonString: non-index array property at ${path}.${key}`);
|
|
533
1097
|
}
|
|
1098
|
+
if (key !== "length" && descriptor !== void 0 && !descriptor.enumerable) {
|
|
1099
|
+
throw new TypeError(`stableJsonString: non-enumerable array property at ${path}.${key}`);
|
|
1100
|
+
}
|
|
534
1101
|
}
|
|
535
1102
|
const out2 = [];
|
|
536
1103
|
for (let i = 0; i < value.length; i += 1) {
|
|
@@ -544,6 +1111,15 @@ function sortedJsonValue(value, seen = /* @__PURE__ */ new Set(), path = "$", st
|
|
|
544
1111
|
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
545
1112
|
throw new TypeError(`stableJsonString: symbol-keyed properties at ${path}`);
|
|
546
1113
|
}
|
|
1114
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
1115
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1116
|
+
if (descriptor !== void 0 && ("get" in descriptor || "set" in descriptor)) {
|
|
1117
|
+
throw new TypeError(`stableJsonString: accessor property at ${path}.${key}`);
|
|
1118
|
+
}
|
|
1119
|
+
if (descriptor !== void 0 && !descriptor.enumerable) {
|
|
1120
|
+
throw new TypeError(`stableJsonString: non-enumerable property at ${path}.${key}`);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
547
1123
|
const out = /* @__PURE__ */ Object.create(null);
|
|
548
1124
|
for (const key of Object.keys(value).sort()) {
|
|
549
1125
|
out[key] = sortedJsonValue(
|
|
@@ -866,59 +1442,532 @@ function restoredV1Cid(policy, hasData, cache) {
|
|
|
866
1442
|
return computeV1Cid(policy, hasData ? cache : ABSENT_V1_SEED);
|
|
867
1443
|
}
|
|
868
1444
|
|
|
869
|
-
// src/node/node.ts
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
1445
|
+
// src/node/node-output-runtime.ts
|
|
1446
|
+
function nodeDown(self, msgs) {
|
|
1447
|
+
if (self._released) return;
|
|
1448
|
+
validateDownPayloads(msgs);
|
|
1449
|
+
const deliveryWave = {};
|
|
1450
|
+
const assertVersionDataCompatible = (wave) => {
|
|
1451
|
+
for (const m of wave) {
|
|
1452
|
+
if (m[0] === "DATA") assertNodeVersionDataCompatible(self._version.policy, m[1]);
|
|
1453
|
+
}
|
|
1454
|
+
};
|
|
1455
|
+
const snapshotVersionData = (wave) => wave.map(
|
|
1456
|
+
(m) => m[0] === "DATA" ? ["DATA", snapshotNodeVersionData(self._version.policy, m[1])] : m
|
|
1457
|
+
);
|
|
1458
|
+
assertVersionDataCompatible(msgs);
|
|
1459
|
+
if (self._value.terminal !== void 0) {
|
|
1460
|
+
if (!msgs.some((m) => m[0] === "TEARDOWN")) return;
|
|
1461
|
+
self._value.hasTorndown = true;
|
|
1462
|
+
if (self._slot.resetOnTeardown) {
|
|
1463
|
+
self._value.cache = SENTINEL;
|
|
1464
|
+
self._value.hasData = false;
|
|
1465
|
+
}
|
|
1466
|
+
self._emitToSubs(["TEARDOWN"], { wave: deliveryWave, last: true });
|
|
1467
|
+
return;
|
|
888
1468
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1469
|
+
let sorted = [...msgs].sort((a, b) => messageTier(a[0]) - messageTier(b[0]));
|
|
1470
|
+
const firstInvalidate = sorted.findIndex((m) => m[0] === "INVALIDATE");
|
|
1471
|
+
if (firstInvalidate !== -1) {
|
|
1472
|
+
sorted = sorted.filter((m, i) => m[0] !== "INVALIDATE" || i === firstInvalidate);
|
|
1473
|
+
}
|
|
1474
|
+
const hasTeardown = sorted.some((m) => m[0] === "TEARDOWN");
|
|
1475
|
+
const hasTerminal = sorted.some((m) => m[0] === "COMPLETE" || m[0] === "ERROR");
|
|
1476
|
+
if (hasTeardown && !hasTerminal && self._value.terminal === void 0 && !self._value.hasTorndown) {
|
|
1477
|
+
sorted = [["COMPLETE"], ...sorted];
|
|
1478
|
+
}
|
|
1479
|
+
if (!self._wave.insideRunWave && currentBatch()) {
|
|
1480
|
+
const deferred = snapshotVersionData(sorted.filter((m) => isDeferredTier(m[0])));
|
|
1481
|
+
if (deferred.length > 0) {
|
|
1482
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1483
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1484
|
+
self._value.status = "dirty";
|
|
1485
|
+
self._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1486
|
+
}
|
|
1487
|
+
self._wave.batchDirtyOwed = true;
|
|
1488
|
+
deferToBatch(self, deferred);
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
897
1491
|
}
|
|
1492
|
+
if (self._shouldBufferOnPause()) {
|
|
1493
|
+
const buffered = snapshotVersionData(sorted.filter((m) => isPauseBufferedTier(m[0])));
|
|
1494
|
+
if (buffered.length > 0) {
|
|
1495
|
+
self._wave.emittedSettleThisWave = true;
|
|
1496
|
+
self._control.pauseBuffer.push(buffered);
|
|
1497
|
+
}
|
|
1498
|
+
sorted = sorted.filter((m) => !isPauseBufferedTier(m[0]));
|
|
1499
|
+
if (sorted.length === 0) return;
|
|
1500
|
+
}
|
|
1501
|
+
let dataCount = 0;
|
|
1502
|
+
let hasTier3 = false;
|
|
1503
|
+
let hasResolved = false;
|
|
1504
|
+
for (const m of sorted) {
|
|
1505
|
+
if (m[0] === "DATA") dataCount++;
|
|
1506
|
+
if (m[0] === "RESOLVED") hasResolved = true;
|
|
1507
|
+
if (isValueTier(m[0])) hasTier3 = true;
|
|
1508
|
+
}
|
|
1509
|
+
if (dataCount >= 1 && hasResolved) {
|
|
1510
|
+
throw new Error(
|
|
1511
|
+
"down: a wave cannot mix DATA and RESOLVED (tier-3 exclusivity, R-resolved-undirty)"
|
|
1512
|
+
);
|
|
1513
|
+
}
|
|
1514
|
+
const plannedVersions = new Array(sorted.length);
|
|
1515
|
+
if (dataCount > 0) {
|
|
1516
|
+
let plannedVersion = self._version.value;
|
|
1517
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1518
|
+
const m = sorted[i];
|
|
1519
|
+
if (m[0] !== "DATA") continue;
|
|
1520
|
+
plannedVersion = advanceNodeVersion(plannedVersion, self._version.policy, m[1]);
|
|
1521
|
+
plannedVersions[i] = plannedVersion;
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
if (hasTier3 && (!self._wave.insideRunWave || self._control.pullDirtyOwed) && !self._wave.emittedDirtyThisWave) {
|
|
1525
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1526
|
+
self._value.status = "dirty";
|
|
1527
|
+
self._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1528
|
+
}
|
|
1529
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1530
|
+
const m = sorted[i];
|
|
1531
|
+
const delivery = { wave: deliveryWave, last: i === sorted.length - 1 };
|
|
1532
|
+
if (isDeferredTier(m[0])) self._wave.emittedSettleThisWave = true;
|
|
1533
|
+
if (m[0] === "DIRTY") {
|
|
1534
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1535
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1536
|
+
self._value.status = "dirty";
|
|
1537
|
+
self._emitToSubs(["DIRTY"], delivery);
|
|
1538
|
+
}
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1541
|
+
if (m[0] === "DATA") {
|
|
1542
|
+
const v = m[1];
|
|
1543
|
+
self._value.cache = v;
|
|
1544
|
+
self._value.hasData = true;
|
|
1545
|
+
self._value.status = "settled";
|
|
1546
|
+
self._version.value = plannedVersions[i];
|
|
1547
|
+
if (self._slot.replayN > 0) {
|
|
1548
|
+
self._value.replayRing.push(v);
|
|
1549
|
+
if (self._value.replayRing.length > self._slot.replayN) self._value.replayRing.shift();
|
|
1550
|
+
}
|
|
1551
|
+
self._emitToSubs(["DATA", v], delivery);
|
|
1552
|
+
continue;
|
|
1553
|
+
}
|
|
1554
|
+
if (m[0] === "RESOLVED") {
|
|
1555
|
+
self._value.status = self._value.hasData ? "resolved" : "sentinel";
|
|
1556
|
+
self._emitToSubs(["RESOLVED"], delivery);
|
|
1557
|
+
continue;
|
|
1558
|
+
}
|
|
1559
|
+
if (m[0] === "INVALIDATE") {
|
|
1560
|
+
self._invalidate(delivery);
|
|
1561
|
+
continue;
|
|
1562
|
+
}
|
|
1563
|
+
if (m[0] === "COMPLETE") {
|
|
1564
|
+
if (self._value.terminal !== void 0) continue;
|
|
1565
|
+
self._value.terminal = true;
|
|
1566
|
+
self._control.pauseBuffer = [];
|
|
1567
|
+
self._value.status = "completed";
|
|
1568
|
+
self._emitToSubs(["COMPLETE"], delivery);
|
|
1569
|
+
continue;
|
|
1570
|
+
}
|
|
1571
|
+
if (m[0] === "ERROR") {
|
|
1572
|
+
if (self._value.terminal !== void 0) continue;
|
|
1573
|
+
self._value.terminal = m[1];
|
|
1574
|
+
self._control.pauseBuffer = [];
|
|
1575
|
+
self._value.status = "errored";
|
|
1576
|
+
self._emitToSubs(["ERROR", m[1]], delivery);
|
|
1577
|
+
continue;
|
|
1578
|
+
}
|
|
1579
|
+
if (m[0] === "TEARDOWN") {
|
|
1580
|
+
self._value.hasTorndown = true;
|
|
1581
|
+
if (self._slot.resetOnTeardown) {
|
|
1582
|
+
self._value.cache = SENTINEL;
|
|
1583
|
+
self._value.hasData = false;
|
|
1584
|
+
}
|
|
1585
|
+
self._emitToSubs(["TEARDOWN"], delivery);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
if (!self._wave.insideRunWave) self._wave.emittedDirtyThisWave = false;
|
|
898
1589
|
}
|
|
899
|
-
function
|
|
900
|
-
|
|
901
|
-
}
|
|
902
|
-
function notifyTopologyDepsChanged(node2, prevDeps, deps) {
|
|
903
|
-
topologyDepsChangedObservers.get(node2)?.(node2, prevDeps, deps);
|
|
904
|
-
}
|
|
905
|
-
function releaseRuntimeOfNode(n) {
|
|
906
|
-
runtimeReleasers.get(n)?.();
|
|
907
|
-
}
|
|
908
|
-
function terminalView(t) {
|
|
909
|
-
return t === void 0 ? false : t;
|
|
910
|
-
}
|
|
911
|
-
function validateDownPayloads(msgs) {
|
|
1590
|
+
function nodeUp(self, msgs, towardDep, route) {
|
|
1591
|
+
if (self._released) return;
|
|
1592
|
+
const routeState = route ?? { demandFired: /* @__PURE__ */ new Map() };
|
|
912
1593
|
for (const m of msgs) {
|
|
913
|
-
if (m[0]
|
|
914
|
-
throw new Error(
|
|
1594
|
+
if (!isUpAllowed(m[0])) {
|
|
1595
|
+
throw new Error(
|
|
1596
|
+
`ctx.up: ${m[0]} is down-only (tier ${messageTier(m[0])}); up carries control tiers only (R-ctx-up)`
|
|
1597
|
+
);
|
|
915
1598
|
}
|
|
916
|
-
|
|
917
|
-
|
|
1599
|
+
}
|
|
1600
|
+
for (const m of msgs) {
|
|
1601
|
+
if (m[0] === "PAUSE") {
|
|
1602
|
+
self._pauseAcquire(m[1]);
|
|
1603
|
+
} else if (m[0] === "RESUME") {
|
|
1604
|
+
if (self._control.pauseLockset.has(m[1])) {
|
|
1605
|
+
self._pauseRelease(m[1]);
|
|
1606
|
+
} else {
|
|
1607
|
+
self._forwardUp(m, towardDep, routeState);
|
|
1608
|
+
}
|
|
1609
|
+
} else if (m[0] === "PULL") {
|
|
1610
|
+
const demand = normalizePullDemand(m[1]);
|
|
1611
|
+
if (self._slot.pull && demand.pullId === self._slot.pullLock) {
|
|
1612
|
+
if (!self._markDemandRouted(demand.pullId, routeState)) self._onDemand(demand);
|
|
1613
|
+
} else {
|
|
1614
|
+
self._forwardUp(["PULL", demand], towardDep, routeState);
|
|
1615
|
+
}
|
|
1616
|
+
} else if (self._slot.deps.length === 0) {
|
|
1617
|
+
if (m[0] === "INVALIDATE") self._down([["INVALIDATE"]]);
|
|
1618
|
+
} else {
|
|
1619
|
+
self._forwardUp(m, towardDep, routeState);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
function nodeMarkDemandRouted(self, lockId, route) {
|
|
1624
|
+
let holders = route.demandFired.get(lockId);
|
|
1625
|
+
if (holders === void 0) {
|
|
1626
|
+
holders = /* @__PURE__ */ new Set();
|
|
1627
|
+
route.demandFired.set(lockId, holders);
|
|
1628
|
+
}
|
|
1629
|
+
const node2 = self;
|
|
1630
|
+
if (holders.has(node2)) return true;
|
|
1631
|
+
holders.add(node2);
|
|
1632
|
+
return false;
|
|
1633
|
+
}
|
|
1634
|
+
function nodeForwardUp(self, m, towardDep, route) {
|
|
1635
|
+
if (self._slot.deps.length === 0) return;
|
|
1636
|
+
if (towardDep !== void 0) {
|
|
1637
|
+
const d = self._slot.deps[towardDep];
|
|
1638
|
+
if (d !== void 0) nodeRuntimeHost(d)._up([m], void 0, route);
|
|
1639
|
+
} else {
|
|
1640
|
+
for (const dep of self._slot.deps) nodeRuntimeHost(dep)._up([m], void 0, route);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
function nodeIsPaused(self) {
|
|
1644
|
+
return self._control.pauseLockset.size > 0;
|
|
1645
|
+
}
|
|
1646
|
+
function nodeHasBoundaryPauseLock(self) {
|
|
1647
|
+
if (self._slot.pausable === false) return false;
|
|
1648
|
+
return self._control.pauseLockset.size > 0;
|
|
1649
|
+
}
|
|
1650
|
+
function nodeIsAsyncPool(self) {
|
|
1651
|
+
return self._slot.handle !== null && self._slot.dispatcher.poolKind(self._slot.handle.poolId) === "async";
|
|
1652
|
+
}
|
|
1653
|
+
function nodePauseAcquire(self, lockId) {
|
|
1654
|
+
self._control.pauseLockset.add(lockId);
|
|
1655
|
+
}
|
|
1656
|
+
function nodePauseRelease(self, lockId) {
|
|
1657
|
+
if (!self._control.pauseLockset.has(lockId)) return;
|
|
1658
|
+
self._control.pauseLockset.delete(lockId);
|
|
1659
|
+
if (self._slot.pull && self._control.demandOwed !== void 0) self._fireOwedDemandIfReady();
|
|
1660
|
+
if (self._hasBoundaryPauseLock()) return;
|
|
1661
|
+
scheduleBoundaryDrain(self._core);
|
|
1662
|
+
if (self._slot.pull) return;
|
|
1663
|
+
self._onResume();
|
|
1664
|
+
}
|
|
1665
|
+
function nodeOnResume(self) {
|
|
1666
|
+
if (self._value.terminal !== void 0) {
|
|
1667
|
+
self._control.pauseBuffer = [];
|
|
1668
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1669
|
+
self._control.demandOwed = void 0;
|
|
1670
|
+
self._control.activePull = void 0;
|
|
1671
|
+
self._control.pullDirtyOwed = false;
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1674
|
+
if (self._control.pauseBuffer.length > 0) {
|
|
1675
|
+
const buf = self._control.pauseBuffer;
|
|
1676
|
+
self._control.pauseBuffer = [];
|
|
1677
|
+
for (const wave of buf) self._down(wave);
|
|
1678
|
+
}
|
|
1679
|
+
if (self._control.pausedDepWaveOccurred) {
|
|
1680
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1681
|
+
self._tryRun();
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
function nodeCanFireDemand(self) {
|
|
1685
|
+
if (self._value.terminal !== void 0 || self._wave.pending > 0) return false;
|
|
1686
|
+
return self._control.pauseLockset.size === 0;
|
|
1687
|
+
}
|
|
1688
|
+
function nodeDeliverPullDemand(self, demand) {
|
|
1689
|
+
self._control.demandOwed = void 0;
|
|
1690
|
+
self._control.activePull = demand;
|
|
1691
|
+
self._control.inDeliverDemand = true;
|
|
1692
|
+
try {
|
|
1693
|
+
self._firePullDemand();
|
|
1694
|
+
} finally {
|
|
1695
|
+
self._control.activePull = void 0;
|
|
1696
|
+
self._control.inDeliverDemand = false;
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
function nodeOnDemand(self, demand) {
|
|
1700
|
+
if (self._control.inDeliverDemand) return;
|
|
1701
|
+
if (self._canFireDemand()) self._deliverPullDemand(demand);
|
|
1702
|
+
else self._control.demandOwed = demand;
|
|
1703
|
+
}
|
|
1704
|
+
function nodeFirePullDemand(self) {
|
|
1705
|
+
let drainedBuffer = false;
|
|
1706
|
+
if (self._control.pauseBuffer.length > 0) {
|
|
1707
|
+
const buf = self._control.pauseBuffer;
|
|
1708
|
+
self._control.pauseBuffer = [];
|
|
1709
|
+
for (const wave of buf) self._down(wave);
|
|
1710
|
+
drainedBuffer = true;
|
|
1711
|
+
}
|
|
1712
|
+
if (drainedBuffer) return;
|
|
1713
|
+
if (self._control.pausedDepWaveOccurred) {
|
|
1714
|
+
const gated = self._slot.handle !== null && !self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled());
|
|
1715
|
+
if (self._wave.pending > 0 || gated) return;
|
|
1716
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1717
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1718
|
+
self._control.pullDirtyOwed = true;
|
|
1719
|
+
try {
|
|
1720
|
+
self._tryRun();
|
|
1721
|
+
} finally {
|
|
1722
|
+
self._control.pullDirtyOwed = false;
|
|
1723
|
+
}
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1726
|
+
if (self._slot.handle !== null) {
|
|
1727
|
+
if (!self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled())) return;
|
|
1728
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1729
|
+
self._control.pullDirtyOwed = true;
|
|
1730
|
+
try {
|
|
1731
|
+
self._runWave();
|
|
1732
|
+
} finally {
|
|
1733
|
+
self._control.pullDirtyOwed = false;
|
|
918
1734
|
}
|
|
919
1735
|
}
|
|
920
1736
|
}
|
|
921
|
-
|
|
1737
|
+
function nodeFireOwedDemandIfReady(self) {
|
|
1738
|
+
if (self._control.inDeliverDemand) return;
|
|
1739
|
+
if (self._slot.pull && self._control.demandOwed !== void 0 && self._canFireDemand()) {
|
|
1740
|
+
self._deliverPullDemand(self._control.demandOwed);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
function nodeShouldBufferOnPause(self) {
|
|
1744
|
+
if (self._slot.pausable === false) return false;
|
|
1745
|
+
if (!self._isPaused() && !self._isPullQuiet()) return false;
|
|
1746
|
+
if (self._slot.pausable === "resumeAll") return true;
|
|
1747
|
+
if (!self._wave.insideRunWave && self._isAsyncPool() && self._slot.deps.length > 0) return true;
|
|
1748
|
+
return false;
|
|
1749
|
+
}
|
|
1750
|
+
function nodeInvalidate(self, delivery) {
|
|
1751
|
+
if (!self._value.hasData) return;
|
|
1752
|
+
self._value.cache = SENTINEL;
|
|
1753
|
+
self._value.hasData = false;
|
|
1754
|
+
self._value.status = "sentinel";
|
|
1755
|
+
self._value.replayRing = [];
|
|
1756
|
+
for (const fn of self._hooks.onInvalidate) fn();
|
|
1757
|
+
self._emitToSubs(["INVALIDATE"], delivery);
|
|
1758
|
+
}
|
|
1759
|
+
function nodeAllDepsTerminal(self) {
|
|
1760
|
+
if (self._slot.deps.length === 0) return false;
|
|
1761
|
+
for (const tm of self._dep.terminal) if (tm === void 0) return false;
|
|
1762
|
+
return true;
|
|
1763
|
+
}
|
|
1764
|
+
function nodeResetLifecycle(self) {
|
|
1765
|
+
for (const u of self._dep.unsubs) if (u) u();
|
|
1766
|
+
self._dep.unsubs = [];
|
|
1767
|
+
self._dep.idxBoxes = [];
|
|
1768
|
+
self._lifecycle.subscribers.clear();
|
|
1769
|
+
self._lifecycle.activated = false;
|
|
1770
|
+
self._value.terminal = void 0;
|
|
1771
|
+
self._value.hasTorndown = false;
|
|
1772
|
+
self._wave.hasCalledFnOnce = false;
|
|
1773
|
+
self._resetDepState();
|
|
1774
|
+
self._control.pauseLockset.clear();
|
|
1775
|
+
self._control.pauseBuffer = [];
|
|
1776
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1777
|
+
self._control.demandOwed = void 0;
|
|
1778
|
+
self._control.activePull = void 0;
|
|
1779
|
+
self._control.pullDirtyOwed = false;
|
|
1780
|
+
self._value.replayRing = [];
|
|
1781
|
+
const isCompute = self._slot.handle !== null || self._slot.deps.length > 0;
|
|
1782
|
+
if (isCompute) {
|
|
1783
|
+
self._value.cache = SENTINEL;
|
|
1784
|
+
self._value.hasData = false;
|
|
1785
|
+
self._value.status = "sentinel";
|
|
1786
|
+
} else {
|
|
1787
|
+
self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1788
|
+
}
|
|
1789
|
+
if (!self._privateState.persist) self._privateState.value = SENTINEL;
|
|
1790
|
+
}
|
|
1791
|
+
function nodeEmitToSubs(self, msg, delivery) {
|
|
1792
|
+
if (self._released) return;
|
|
1793
|
+
const subs = [...self._lifecycle.subscribers];
|
|
1794
|
+
for (const sink of subs) sink(msg, delivery);
|
|
1795
|
+
}
|
|
1796
|
+
function nodeCommitBatchedWave(self, wave) {
|
|
1797
|
+
self._wave.batchDirtyOwed = false;
|
|
1798
|
+
self._down(wave);
|
|
1799
|
+
}
|
|
1800
|
+
function nodeRollbackBatched(self) {
|
|
1801
|
+
if (self._wave.batchDirtyOwed) {
|
|
1802
|
+
self._wave.batchDirtyOwed = false;
|
|
1803
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1804
|
+
self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1805
|
+
self._emitToSubs(["RESOLVED"]);
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
function nodeDeferBoundary(self, fn, batchToken) {
|
|
1809
|
+
deferRewire(self._core, fn, {
|
|
1810
|
+
batchToken,
|
|
1811
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
// src/node/node-rewire-runtime.ts
|
|
1816
|
+
function nodeRequestRewireNext(self, op) {
|
|
1817
|
+
deferRewire(self._core, () => self._applyRewireNext(op), {
|
|
1818
|
+
batchToken: currentBoundaryBatchToken(),
|
|
1819
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
function nodeRequestUpNext(self, msgs, towardDep) {
|
|
1823
|
+
deferRewire(
|
|
1824
|
+
self._core,
|
|
1825
|
+
() => {
|
|
1826
|
+
if (!self._released) self._up(msgs, towardDep);
|
|
1827
|
+
},
|
|
1828
|
+
{
|
|
1829
|
+
batchToken: currentBoundaryBatchToken(),
|
|
1830
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1831
|
+
}
|
|
1832
|
+
);
|
|
1833
|
+
}
|
|
1834
|
+
function nodeApplyRewireNext(self, op) {
|
|
1835
|
+
if (self._released) return;
|
|
1836
|
+
try {
|
|
1837
|
+
if (op.kind === "add") {
|
|
1838
|
+
const next = self._slot.deps.includes(op.dep) ? [...self._slot.deps] : [...self._slot.deps, op.dep];
|
|
1839
|
+
self._rewire(next, op.fn, { allowTerminalOwner: true });
|
|
1840
|
+
} else if (op.kind === "remove") {
|
|
1841
|
+
self._rewire(
|
|
1842
|
+
self._slot.deps.filter((d) => d !== op.dep),
|
|
1843
|
+
op.fn,
|
|
1844
|
+
{ allowTerminalOwner: true }
|
|
1845
|
+
);
|
|
1846
|
+
} else {
|
|
1847
|
+
self._rewire(self._dedupDeps(op.deps), op.fn, { allowTerminalOwner: true });
|
|
1848
|
+
}
|
|
1849
|
+
} catch (e) {
|
|
1850
|
+
self._down([["ERROR", errorPayload(e, "rewireNext op failed")]]);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
function nodeRewire(self, newDeps, fn, opts = {}) {
|
|
1854
|
+
const node2 = self;
|
|
1855
|
+
if (self._value.terminal !== void 0 && !opts.allowTerminalOwner)
|
|
1856
|
+
throw new Error(
|
|
1857
|
+
"rewire: node is terminal (completed/errored) \u2014 cannot rewire (R-rewire / D42)"
|
|
1858
|
+
);
|
|
1859
|
+
if (self._wave.insideRunWave)
|
|
1860
|
+
throw new Error(
|
|
1861
|
+
"rewire: mid-fn topology mutation \u2014 a fn mutating its own deps mid-wave is the feedback cycle (R-rewire / D37)"
|
|
1862
|
+
);
|
|
1863
|
+
if (self._wave.inDepMutation)
|
|
1864
|
+
throw new Error(
|
|
1865
|
+
"rewire: reentrant dep mutation \u2014 another replaceDeps/subscribeDep/unsubscribeDep is in flight (R-rewire)"
|
|
1866
|
+
);
|
|
1867
|
+
if (newDeps.includes(node2)) throw new Error("rewire: self-dependency rejected (R-rewire / D42)");
|
|
1868
|
+
const oldDeps = self._slot.deps;
|
|
1869
|
+
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
1870
|
+
for (const d of added) {
|
|
1871
|
+
if (self._reachableUpstream(d, node2))
|
|
1872
|
+
throw new Error(
|
|
1873
|
+
"rewire: would create a cycle \u2014 dep already transitively depends on this node (R-rewire / D42)"
|
|
1874
|
+
);
|
|
1875
|
+
const dep = nodeRuntimeHost(d);
|
|
1876
|
+
if (dep._value.terminal !== void 0 && !dep._slot.resubscribable)
|
|
1877
|
+
throw new Error(
|
|
1878
|
+
"rewire: cannot add a non-resubscribable terminal dep \u2014 would wedge (R-rewire / D42)"
|
|
1879
|
+
);
|
|
1880
|
+
self._assertRewireDepOwner(d);
|
|
1881
|
+
}
|
|
1882
|
+
if (deferAfterBatchForTarget(node2, () => {
|
|
1883
|
+
self._rewire(newDeps, fn, { ...opts, allowTerminalOwner: true });
|
|
1884
|
+
})) {
|
|
1885
|
+
return true;
|
|
1886
|
+
}
|
|
1887
|
+
if (!self._lifecycle.activated) self._restoredActivationPending = false;
|
|
1888
|
+
self._wave.inDepMutation = true;
|
|
1889
|
+
self._wave.rewireRunPending = false;
|
|
1890
|
+
let zeroDepUnDirty = false;
|
|
1891
|
+
try {
|
|
1892
|
+
const oldHandle = self._slot.handle;
|
|
1893
|
+
self._slot.handle = self._slot.dispatcher.register(fn, self._slot.pool);
|
|
1894
|
+
if (oldHandle !== null) self._slot.dispatcher.unregister(oldHandle);
|
|
1895
|
+
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
1896
|
+
let removedDirtyContributor = false;
|
|
1897
|
+
for (const d of removed) {
|
|
1898
|
+
const oldIdx = oldDeps.indexOf(d);
|
|
1899
|
+
if (self._dep.dirty[oldIdx]) {
|
|
1900
|
+
removedDirtyContributor = true;
|
|
1901
|
+
self._wave.pending--;
|
|
1902
|
+
}
|
|
1903
|
+
if (self._lifecycle.activated) {
|
|
1904
|
+
const box = self._dep.idxBoxes[oldIdx];
|
|
1905
|
+
if (box) box.v = -1;
|
|
1906
|
+
const unsub = self._dep.unsubs[oldIdx];
|
|
1907
|
+
if (unsub) unsub();
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
const n = newDeps.length;
|
|
1911
|
+
const newBatch = new Array(n).fill(null);
|
|
1912
|
+
const newPrev = new Array(n).fill(SENTINEL);
|
|
1913
|
+
const newHasData = new Array(n).fill(false);
|
|
1914
|
+
const newDirty = new Array(n).fill(false);
|
|
1915
|
+
const newTier = new Array(n).fill(0);
|
|
1916
|
+
const newTerminal = new Array(n).fill(void 0);
|
|
1917
|
+
const newTerminalInput = new Array(n).fill(void 0);
|
|
1918
|
+
const newUnsubs = new Array(n);
|
|
1919
|
+
const newBoxes = new Array(n);
|
|
1920
|
+
for (let j = 0; j < n; j++) {
|
|
1921
|
+
const oldIdx = oldDeps.indexOf(newDeps[j]);
|
|
1922
|
+
if (oldIdx !== -1) {
|
|
1923
|
+
newBatch[j] = self._dep.batch[oldIdx];
|
|
1924
|
+
newPrev[j] = self._dep.prev[oldIdx];
|
|
1925
|
+
newHasData[j] = self._dep.hasData[oldIdx];
|
|
1926
|
+
newDirty[j] = self._dep.dirty[oldIdx];
|
|
1927
|
+
newTier[j] = self._dep.tier[oldIdx];
|
|
1928
|
+
newTerminal[j] = self._dep.terminal[oldIdx];
|
|
1929
|
+
newUnsubs[j] = self._dep.unsubs[oldIdx];
|
|
1930
|
+
const box = self._dep.idxBoxes[oldIdx];
|
|
1931
|
+
if (box) box.v = j;
|
|
1932
|
+
newBoxes[j] = box;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
self._slot.deps = newDeps;
|
|
1936
|
+
self._dep.batch = newBatch;
|
|
1937
|
+
self._dep.prev = newPrev;
|
|
1938
|
+
self._dep.hasData = newHasData;
|
|
1939
|
+
self._dep.dirty = newDirty;
|
|
1940
|
+
self._dep.tier = newTier;
|
|
1941
|
+
self._dep.terminal = newTerminal;
|
|
1942
|
+
self._dep.terminalInput = newTerminalInput;
|
|
1943
|
+
self._dep.unsubs = newUnsubs;
|
|
1944
|
+
self._dep.idxBoxes = newBoxes;
|
|
1945
|
+
self._dep.waveData = newDeps.map(() => []);
|
|
1946
|
+
self._dep.waveTokens = new Array(newDeps.length).fill(void 0);
|
|
1947
|
+
self._syncCtx = null;
|
|
1948
|
+
if (self._lifecycle.activated) {
|
|
1949
|
+
for (const d of added) self._subscribeDepAt(d);
|
|
1950
|
+
}
|
|
1951
|
+
notifyTopologyDepsChanged(node2, oldDeps, newDeps);
|
|
1952
|
+
if (removedDirtyContributor && self._wave.pending === 0 && self._value.status === "dirty") {
|
|
1953
|
+
if (newDeps.length > 0) self._wave.rewireRunPending = true;
|
|
1954
|
+
else zeroDepUnDirty = true;
|
|
1955
|
+
}
|
|
1956
|
+
} finally {
|
|
1957
|
+
self._wave.inDepMutation = false;
|
|
1958
|
+
}
|
|
1959
|
+
if (self._wave.rewireRunPending) {
|
|
1960
|
+
self._wave.rewireRunPending = false;
|
|
1961
|
+
self._settleRewire();
|
|
1962
|
+
} else if (zeroDepUnDirty) {
|
|
1963
|
+
if (self._wave.emittedDirtyThisWave) self._down([["RESOLVED"]]);
|
|
1964
|
+
else self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1965
|
+
}
|
|
1966
|
+
return false;
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
// src/node/node.ts
|
|
1970
|
+
var Node = class _Node {
|
|
922
1971
|
_core;
|
|
923
1972
|
_id;
|
|
924
1973
|
_slot;
|
|
@@ -939,19 +1988,63 @@ var Node = class {
|
|
|
939
1988
|
set _syncCtx(ctx) {
|
|
940
1989
|
this._syncCtxState.value = ctx;
|
|
941
1990
|
}
|
|
1991
|
+
static _retainIndirectRuntimeMethods(node2) {
|
|
1992
|
+
void node2._dep;
|
|
1993
|
+
void node2._hooks;
|
|
1994
|
+
void node2._restoredActivationPending;
|
|
1995
|
+
void node2._requestRewireNext;
|
|
1996
|
+
void node2._requestUpNext;
|
|
1997
|
+
void node2._applyRewireNext;
|
|
1998
|
+
void node2._reachableUpstream;
|
|
1999
|
+
void node2._assertRewireDepOwner;
|
|
2000
|
+
void node2._subscribeDepAt;
|
|
2001
|
+
void node2._seedRestoredDepAt;
|
|
2002
|
+
void node2._recordDepProjection;
|
|
2003
|
+
void node2._depProjectionHasData;
|
|
2004
|
+
void node2._receiveFromDep;
|
|
2005
|
+
void node2._releaseDepDirty;
|
|
2006
|
+
void node2._settleAfterAbsorbedTerminal;
|
|
2007
|
+
void node2._markDirty;
|
|
2008
|
+
void node2._maybeRun;
|
|
2009
|
+
void node2._settleRewire;
|
|
2010
|
+
void node2._tryRun;
|
|
2011
|
+
void node2._allDepsSettled;
|
|
2012
|
+
void node2._passthroughEmit;
|
|
2013
|
+
void node2._runWave;
|
|
2014
|
+
void node2._buildCtx;
|
|
2015
|
+
void node2._makeCtx;
|
|
2016
|
+
void node2._refreshCtx;
|
|
2017
|
+
void node2._makeState;
|
|
2018
|
+
void node2._markDemandRouted;
|
|
2019
|
+
void node2._forwardUp;
|
|
2020
|
+
void node2._isPullQuiet;
|
|
2021
|
+
void node2._isPaused;
|
|
2022
|
+
void node2._hasBoundaryPauseLock;
|
|
2023
|
+
void node2._isAsyncPool;
|
|
2024
|
+
void node2._pauseAcquire;
|
|
2025
|
+
void node2._pauseRelease;
|
|
2026
|
+
void node2._onResume;
|
|
2027
|
+
void node2._canFireDemand;
|
|
2028
|
+
void node2._deliverPullDemand;
|
|
2029
|
+
void node2._onDemand;
|
|
2030
|
+
void node2._firePullDemand;
|
|
2031
|
+
void node2._fireOwedDemandIfReady;
|
|
2032
|
+
void node2._shouldBufferOnPause;
|
|
2033
|
+
void node2._invalidate;
|
|
2034
|
+
void node2._allDepsTerminal;
|
|
2035
|
+
void node2._emitToSubs;
|
|
2036
|
+
}
|
|
942
2037
|
constructor(deps, handleOrFn, opts = {}) {
|
|
943
|
-
const core =
|
|
944
|
-
constructingCore = void 0;
|
|
2038
|
+
const core = takeConstructingNodeCore();
|
|
945
2039
|
const dispatcher = opts.dispatcher ?? defaultDispatcher;
|
|
946
|
-
const environment =
|
|
947
|
-
constructingEnvironment = void 0;
|
|
2040
|
+
const environment = takeConstructingEnvironmentDrivers() ?? EnvironmentDrivers.empty();
|
|
948
2041
|
const pool = opts.pool ?? "sync";
|
|
949
2042
|
const pausable = opts.pausable ?? true;
|
|
950
2043
|
const pullLock = opts.pullId;
|
|
951
2044
|
const pull = opts.pullId !== void 0;
|
|
952
2045
|
if (pull && pausable === false)
|
|
953
2046
|
throw new Error(
|
|
954
|
-
"node: pullId is incompatible with pausable:false \u2014 a pull node
|
|
2047
|
+
"node: pullId is incompatible with pausable:false \u2014 a pull node uses the pausable delivery-content axis (R-pull / R-pause-modes / D55,D269)"
|
|
955
2048
|
);
|
|
956
2049
|
let handle;
|
|
957
2050
|
if (handleOrFn === null) handle = null;
|
|
@@ -974,7 +2067,6 @@ var Node = class {
|
|
|
974
2067
|
value.status = "settled";
|
|
975
2068
|
}
|
|
976
2069
|
const pauseLockset = /* @__PURE__ */ new Set();
|
|
977
|
-
if (pull) pauseLockset.add(pullLock);
|
|
978
2070
|
this._core = core ?? new NodeCore();
|
|
979
2071
|
const created = this._core.createSlot(
|
|
980
2072
|
{
|
|
@@ -1015,7 +2107,9 @@ var Node = class {
|
|
|
1015
2107
|
pauseLockset,
|
|
1016
2108
|
pausedDepWaveOccurred: false,
|
|
1017
2109
|
pauseBuffer: [],
|
|
1018
|
-
demandOwed:
|
|
2110
|
+
demandOwed: void 0,
|
|
2111
|
+
activePull: void 0,
|
|
2112
|
+
pullDirtyOwed: false,
|
|
1019
2113
|
inDeliverDemand: false
|
|
1020
2114
|
},
|
|
1021
2115
|
privateState: { value: SENTINEL, persist: false },
|
|
@@ -1072,10 +2166,11 @@ var Node = class {
|
|
|
1072
2166
|
this._wave.batchDirtyOwed = false;
|
|
1073
2167
|
this._control.pauseBuffer = [];
|
|
1074
2168
|
this._control.pausedDepWaveOccurred = false;
|
|
1075
|
-
this._control.demandOwed =
|
|
2169
|
+
this._control.demandOwed = void 0;
|
|
2170
|
+
this._control.activePull = void 0;
|
|
2171
|
+
this._control.pullDirtyOwed = false;
|
|
1076
2172
|
this._control.inDeliverDemand = false;
|
|
1077
2173
|
this._control.pauseLockset.clear();
|
|
1078
|
-
if (this._slot.pull) this._control.pauseLockset.add(this._slot.pullLock);
|
|
1079
2174
|
this._privateState.value = state.ctxState.value;
|
|
1080
2175
|
this._privateState.persist = state.ctxState.persist;
|
|
1081
2176
|
if (state.version === false) {
|
|
@@ -1113,18 +2208,18 @@ var Node = class {
|
|
|
1113
2208
|
runtimeQuiescenceReaders.set(this, () => this._isRuntimeQuiescentForRelease());
|
|
1114
2209
|
subscriberCountReaders.set(this, () => this._subscriberCount());
|
|
1115
2210
|
activationReaders.set(this, () => this._lifecycle.activated);
|
|
2211
|
+
_Node._retainIndirectRuntimeMethods(this);
|
|
1116
2212
|
}
|
|
1117
|
-
/** R-pull (D55): true while a pull node is
|
|
2213
|
+
/** R-pull (D55/D272): true while a pull node is not serving a PULL demand pulse. */
|
|
1118
2214
|
_isPullQuiet() {
|
|
1119
|
-
return this._slot.pull && this._control.
|
|
2215
|
+
return this._slot.pull && this._control.activePull === void 0;
|
|
1120
2216
|
}
|
|
1121
2217
|
/**
|
|
1122
|
-
* R-pull (
|
|
1123
|
-
* triggers computation). A consumer demands one delivery by cone-routing
|
|
1124
|
-
* reference): `ctx.up([["
|
|
1125
|
-
* `ctx.upNext([["
|
|
1126
|
-
*
|
|
1127
|
-
* for inspection/describe; routing matches by the pullId value carried in the RESUME, by identity.
|
|
2218
|
+
* R-pull (D269/D272): this pull node's pullId (pure data, like {@link cache}/{@link handle} —
|
|
2219
|
+
* never triggers computation). A consumer demands one delivery by cone-routing PULL of it (no
|
|
2220
|
+
* node reference): `ctx.up([["PULL", { pullId }]])` (immediate; loops back → D37 for a self-read
|
|
2221
|
+
* dep) or `ctx.upNext([["PULL", { pullId }]])` (boundary-deferred self-demand). Undefined for a
|
|
2222
|
+
* non-pull node. The author writes the pullId verbatim; routing matches by identity.
|
|
1128
2223
|
*/
|
|
1129
2224
|
get pullId() {
|
|
1130
2225
|
return this._slot.pullLock;
|
|
@@ -1218,58 +2313,6 @@ var Node = class {
|
|
|
1218
2313
|
exitWave();
|
|
1219
2314
|
}
|
|
1220
2315
|
}
|
|
1221
|
-
// ── deferred self-rewire (R-rewire-deferred / D47): ctx.rewireNext drain support ──
|
|
1222
|
-
/**
|
|
1223
|
-
* Enqueue a deferred self-rewire op (issued from this node's fn via `ctx.rewireNext`).
|
|
1224
|
-
* Applied at the committed wave boundary (boundary.ts drain), never in place — the in-fn
|
|
1225
|
-
* immediate path (`subscribeDep`/`replaceDeps`/`unsubscribeDep`) still throws mid-run (D37/R-reentrancy).
|
|
1226
|
-
*/
|
|
1227
|
-
_requestRewireNext(op) {
|
|
1228
|
-
deferRewire(this._core, () => this._applyRewireNext(op), {
|
|
1229
|
-
batchToken: currentBoundaryBatchToken(),
|
|
1230
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
/**
|
|
1234
|
-
* Enqueue a deferred up-going control wave (R-up-routing / R-pull / D59): at the committed wave
|
|
1235
|
-
* boundary, route `msgs` up from THIS node (broadcast, or up the single `towardDep` edge). The
|
|
1236
|
-
* deferred form of `ctx.up` — the SELF-demand path: a consumer issues `ctx.upNext([[RESUME,
|
|
1237
|
-
* pullId]])` to demand a dep it ALSO reads; the demand applies at the boundary (not mid-fn), so
|
|
1238
|
-
* the pull node's delivery loops back as a FRESH wave rather than re-entering the consumer (D37 /
|
|
1239
|
-
* R-reentrancy). Rides the same R-rewire-deferred (D47) drain as ctx.rewireNext.
|
|
1240
|
-
*/
|
|
1241
|
-
_requestUpNext(msgs, towardDep) {
|
|
1242
|
-
deferRewire(
|
|
1243
|
-
this._core,
|
|
1244
|
-
() => {
|
|
1245
|
-
if (!this._released) this._up(msgs, towardDep);
|
|
1246
|
-
},
|
|
1247
|
-
{
|
|
1248
|
-
batchToken: currentBoundaryBatchToken(),
|
|
1249
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
1250
|
-
}
|
|
1251
|
-
);
|
|
1252
|
-
}
|
|
1253
|
-
/** Apply one queued self-rewire at the boundary (drain thunk). */
|
|
1254
|
-
_applyRewireNext(op) {
|
|
1255
|
-
if (this._released) return;
|
|
1256
|
-
try {
|
|
1257
|
-
if (op.kind === "add") {
|
|
1258
|
-
const next = this._slot.deps.includes(op.dep) ? [...this._slot.deps] : [...this._slot.deps, op.dep];
|
|
1259
|
-
this._rewire(next, op.fn, { allowTerminalOwner: true });
|
|
1260
|
-
} else if (op.kind === "remove") {
|
|
1261
|
-
this._rewire(
|
|
1262
|
-
this._slot.deps.filter((d) => d !== op.dep),
|
|
1263
|
-
op.fn,
|
|
1264
|
-
{ allowTerminalOwner: true }
|
|
1265
|
-
);
|
|
1266
|
-
} else {
|
|
1267
|
-
this._rewire(this._dedupDeps(op.deps), op.fn, { allowTerminalOwner: true });
|
|
1268
|
-
}
|
|
1269
|
-
} catch (e) {
|
|
1270
|
-
this._down([["ERROR", errorPayload(e, "rewireNext op failed")]]);
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
2316
|
// ── rewire (R-rewire / D42): intra-graph runtime topology mutation ──
|
|
1274
2317
|
/**
|
|
1275
2318
|
* Replace this node's deps atomically (surgical, Option-C). Requires an explicit
|
|
@@ -1297,6 +2340,15 @@ var Node = class {
|
|
|
1297
2340
|
fn
|
|
1298
2341
|
);
|
|
1299
2342
|
}
|
|
2343
|
+
_requestRewireNext(op) {
|
|
2344
|
+
nodeRequestRewireNext(nodeRuntimeHost(this), op);
|
|
2345
|
+
}
|
|
2346
|
+
_requestUpNext(msgs, towardDep) {
|
|
2347
|
+
nodeRequestUpNext(nodeRuntimeHost(this), msgs, towardDep);
|
|
2348
|
+
}
|
|
2349
|
+
_applyRewireNext(op) {
|
|
2350
|
+
nodeApplyRewireNext(nodeRuntimeHost(this), op);
|
|
2351
|
+
}
|
|
1300
2352
|
_dedupDeps(deps) {
|
|
1301
2353
|
const seen = /* @__PURE__ */ new Set();
|
|
1302
2354
|
const out = [];
|
|
@@ -1307,7 +2359,6 @@ var Node = class {
|
|
|
1307
2359
|
}
|
|
1308
2360
|
return out;
|
|
1309
2361
|
}
|
|
1310
|
-
/** Is `target` reachable upstream from `from` (following deps)? Cycle-prevention DFS. */
|
|
1311
2362
|
_reachableUpstream(from, target) {
|
|
1312
2363
|
const seen = /* @__PURE__ */ new Set();
|
|
1313
2364
|
const stack = [from];
|
|
@@ -1317,1025 +2368,171 @@ var Node = class {
|
|
|
1317
2368
|
if (n === target) return true;
|
|
1318
2369
|
if (seen.has(n)) continue;
|
|
1319
2370
|
seen.add(n);
|
|
1320
|
-
for (const d of n._slot.deps) stack.push(d);
|
|
2371
|
+
for (const d of nodeRuntimeHost(n)._slot.deps) stack.push(d);
|
|
1321
2372
|
}
|
|
1322
2373
|
return false;
|
|
1323
2374
|
}
|
|
1324
2375
|
_assertRewireDepOwner(dep) {
|
|
1325
2376
|
const selfOwner = getNodeOwner(this);
|
|
1326
2377
|
const depOwner = getNodeOwner(dep);
|
|
1327
|
-
if (selfOwner !== void 0 && depOwner !== void 0 && selfOwner !== depOwner)
|
|
2378
|
+
if (selfOwner !== void 0 && depOwner !== void 0 && selfOwner !== depOwner)
|
|
1328
2379
|
throw new Error(
|
|
1329
2380
|
"rewire: dep belongs to a different graph; cross-graph deps require a wire bridge (D22 / R-graph-domain)"
|
|
1330
2381
|
);
|
|
1331
|
-
}
|
|
1332
2382
|
}
|
|
1333
2383
|
_rewire(newDeps, fn, opts = {}) {
|
|
1334
|
-
|
|
1335
|
-
throw new Error(
|
|
1336
|
-
"rewire: node is terminal (completed/errored) \u2014 cannot rewire (R-rewire / D42)"
|
|
1337
|
-
);
|
|
1338
|
-
if (this._wave.insideRunWave)
|
|
1339
|
-
throw new Error(
|
|
1340
|
-
"rewire: mid-fn topology mutation \u2014 a fn mutating its own deps mid-wave is the feedback cycle (R-rewire / D37)"
|
|
1341
|
-
);
|
|
1342
|
-
if (this._wave.inDepMutation)
|
|
1343
|
-
throw new Error(
|
|
1344
|
-
"rewire: reentrant dep mutation \u2014 another replaceDeps/subscribeDep/unsubscribeDep is in flight (R-rewire)"
|
|
1345
|
-
);
|
|
1346
|
-
if (newDeps.includes(this))
|
|
1347
|
-
throw new Error("rewire: self-dependency rejected (R-rewire / D42)");
|
|
1348
|
-
const oldDeps = this._slot.deps;
|
|
1349
|
-
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
1350
|
-
for (const d of added) {
|
|
1351
|
-
if (this._reachableUpstream(d, this))
|
|
1352
|
-
throw new Error(
|
|
1353
|
-
"rewire: would create a cycle \u2014 dep already transitively depends on this node (R-rewire / D42)"
|
|
1354
|
-
);
|
|
1355
|
-
if (d._value.terminal !== void 0 && !d._slot.resubscribable)
|
|
1356
|
-
throw new Error(
|
|
1357
|
-
"rewire: cannot add a non-resubscribable terminal dep \u2014 would wedge (R-rewire / D42)"
|
|
1358
|
-
);
|
|
1359
|
-
this._assertRewireDepOwner(d);
|
|
1360
|
-
}
|
|
1361
|
-
if (deferAfterBatchForTarget(this, () => {
|
|
1362
|
-
this._rewire(newDeps, fn, { ...opts, allowTerminalOwner: true });
|
|
1363
|
-
})) {
|
|
1364
|
-
return true;
|
|
1365
|
-
}
|
|
1366
|
-
if (!this._lifecycle.activated) this._restoredActivationPending = false;
|
|
1367
|
-
this._wave.inDepMutation = true;
|
|
1368
|
-
this._wave.rewireRunPending = false;
|
|
1369
|
-
let zeroDepUnDirty = false;
|
|
1370
|
-
try {
|
|
1371
|
-
const oldHandle = this._slot.handle;
|
|
1372
|
-
this._slot.handle = this._slot.dispatcher.register(fn, this._slot.pool);
|
|
1373
|
-
if (oldHandle !== null) this._slot.dispatcher.unregister(oldHandle);
|
|
1374
|
-
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
1375
|
-
let removedDirtyContributor = false;
|
|
1376
|
-
for (const d of removed) {
|
|
1377
|
-
const oldIdx = oldDeps.indexOf(d);
|
|
1378
|
-
if (this._dep.dirty[oldIdx]) {
|
|
1379
|
-
removedDirtyContributor = true;
|
|
1380
|
-
this._wave.pending--;
|
|
1381
|
-
}
|
|
1382
|
-
if (this._lifecycle.activated) {
|
|
1383
|
-
const box = this._dep.idxBoxes[oldIdx];
|
|
1384
|
-
if (box) box.v = -1;
|
|
1385
|
-
const unsub = this._dep.unsubs[oldIdx];
|
|
1386
|
-
if (unsub) unsub();
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1389
|
-
const n = newDeps.length;
|
|
1390
|
-
const newBatch = new Array(n).fill(null);
|
|
1391
|
-
const newPrev = new Array(n).fill(SENTINEL);
|
|
1392
|
-
const newHasData = new Array(n).fill(false);
|
|
1393
|
-
const newDirty = new Array(n).fill(false);
|
|
1394
|
-
const newTier = new Array(n).fill(0);
|
|
1395
|
-
const newTerminal = new Array(n).fill(void 0);
|
|
1396
|
-
const newTerminalInput = new Array(n).fill(void 0);
|
|
1397
|
-
const newUnsubs = new Array(n);
|
|
1398
|
-
const newBoxes = new Array(n);
|
|
1399
|
-
for (let j = 0; j < n; j++) {
|
|
1400
|
-
const oldIdx = oldDeps.indexOf(newDeps[j]);
|
|
1401
|
-
if (oldIdx !== -1) {
|
|
1402
|
-
newBatch[j] = this._dep.batch[oldIdx];
|
|
1403
|
-
newPrev[j] = this._dep.prev[oldIdx];
|
|
1404
|
-
newHasData[j] = this._dep.hasData[oldIdx];
|
|
1405
|
-
newDirty[j] = this._dep.dirty[oldIdx];
|
|
1406
|
-
newTier[j] = this._dep.tier[oldIdx];
|
|
1407
|
-
newTerminal[j] = this._dep.terminal[oldIdx];
|
|
1408
|
-
newUnsubs[j] = this._dep.unsubs[oldIdx];
|
|
1409
|
-
const box = this._dep.idxBoxes[oldIdx];
|
|
1410
|
-
if (box) box.v = j;
|
|
1411
|
-
newBoxes[j] = box;
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
this._slot.deps = newDeps;
|
|
1415
|
-
this._dep.batch = newBatch;
|
|
1416
|
-
this._dep.prev = newPrev;
|
|
1417
|
-
this._dep.hasData = newHasData;
|
|
1418
|
-
this._dep.dirty = newDirty;
|
|
1419
|
-
this._dep.tier = newTier;
|
|
1420
|
-
this._dep.terminal = newTerminal;
|
|
1421
|
-
this._dep.terminalInput = newTerminalInput;
|
|
1422
|
-
this._dep.unsubs = newUnsubs;
|
|
1423
|
-
this._dep.idxBoxes = newBoxes;
|
|
1424
|
-
this._dep.waveData = newDeps.map(() => []);
|
|
1425
|
-
this._dep.waveTokens = new Array(newDeps.length).fill(void 0);
|
|
1426
|
-
this._syncCtx = null;
|
|
1427
|
-
if (this._lifecycle.activated) {
|
|
1428
|
-
for (const d of added) this._subscribeDepAt(d);
|
|
1429
|
-
}
|
|
1430
|
-
notifyTopologyDepsChanged(this, oldDeps, newDeps);
|
|
1431
|
-
if (removedDirtyContributor && this._wave.pending === 0 && this._value.status === "dirty") {
|
|
1432
|
-
if (newDeps.length > 0) this._wave.rewireRunPending = true;
|
|
1433
|
-
else zeroDepUnDirty = true;
|
|
1434
|
-
}
|
|
1435
|
-
} finally {
|
|
1436
|
-
this._wave.inDepMutation = false;
|
|
1437
|
-
}
|
|
1438
|
-
if (this._wave.rewireRunPending) {
|
|
1439
|
-
this._wave.rewireRunPending = false;
|
|
1440
|
-
this._settleRewire();
|
|
1441
|
-
} else if (zeroDepUnDirty) {
|
|
1442
|
-
if (this._wave.emittedDirtyThisWave) this._down([["RESOLVED"]]);
|
|
1443
|
-
else this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
1444
|
-
}
|
|
1445
|
-
return false;
|
|
2384
|
+
return nodeRewire(nodeRuntimeHost(this), newDeps, fn, opts);
|
|
1446
2385
|
}
|
|
1447
2386
|
// ── activation / deactivation (lazy; R-rom-ram) ──
|
|
1448
2387
|
_activate() {
|
|
1449
|
-
this
|
|
1450
|
-
const seedRestoredDeps = this._restoredActivationPending;
|
|
1451
|
-
this._restoredActivationPending = false;
|
|
1452
|
-
if (this._slot.pull) this._control.pauseLockset.add(this._slot.pullLock);
|
|
1453
|
-
this._dep.unsubs = new Array(this._slot.deps.length);
|
|
1454
|
-
this._dep.idxBoxes = new Array(this._slot.deps.length);
|
|
1455
|
-
for (const dep of this._slot.deps)
|
|
1456
|
-
this._subscribeDepAt(dep, { seedRestored: seedRestoredDeps });
|
|
1457
|
-
if (this._slot.deps.length === 0 && this._slot.handle !== null && !this._wave.hasCalledFnOnce) {
|
|
1458
|
-
this._runWave();
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
|
-
/**
|
|
1462
|
-
* Subscribe to a dep. The dispatch callback reads the dep's CURRENT index from a
|
|
1463
|
-
* mutable box (O(1)); a surgical rewire that reorders kept deps just updates the box
|
|
1464
|
-
* (R-rewire Option-C / D42) — no re-subscribe, no per-message indexOf scan. A removed
|
|
1465
|
-
* dep's box is set to -1 so any stale in-flight callback drops (drain).
|
|
1466
|
-
*/
|
|
1467
|
-
_subscribeDepAt(depNode, opts = {}) {
|
|
1468
|
-
const idx0 = this._slot.deps.indexOf(depNode);
|
|
1469
|
-
const box = { v: idx0 };
|
|
1470
|
-
let ignoreInitialPush = opts.seedRestored === true;
|
|
1471
|
-
if (ignoreInitialPush && idx0 !== -1) {
|
|
1472
|
-
this._seedRestoredDepAt(idx0, depNode);
|
|
1473
|
-
if (depNode._value.terminal !== void 0 && !depNode._slot.resubscribable) {
|
|
1474
|
-
this._dep.unsubs[idx0] = () => {
|
|
1475
|
-
};
|
|
1476
|
-
this._dep.idxBoxes[idx0] = box;
|
|
1477
|
-
return;
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
const unsub = depNode.subscribe((msg, delivery) => {
|
|
1481
|
-
if (ignoreInitialPush && delivery === void 0) return;
|
|
1482
|
-
if (ignoreInitialPush) ignoreInitialPush = false;
|
|
1483
|
-
if (box.v === -1) return;
|
|
1484
|
-
this._receiveFromDep(box.v, msg, delivery);
|
|
1485
|
-
});
|
|
1486
|
-
if (ignoreInitialPush && idx0 !== -1 && box.v !== -1) this._seedRestoredDepAt(idx0, depNode);
|
|
1487
|
-
ignoreInitialPush = false;
|
|
1488
|
-
if (idx0 !== -1) {
|
|
1489
|
-
this._dep.unsubs[idx0] = unsub;
|
|
1490
|
-
this._dep.idxBoxes[idx0] = box;
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
_seedRestoredDepAt(idx, depNode) {
|
|
1494
|
-
const seedData = depNode._value.hasData && !depNode._slot.pull;
|
|
1495
|
-
this._dep.batch[idx] = null;
|
|
1496
|
-
this._dep.waveData[idx] = [];
|
|
1497
|
-
this._dep.waveTokens[idx] = void 0;
|
|
1498
|
-
this._dep.prev[idx] = seedData ? depNode._value.cache : SENTINEL;
|
|
1499
|
-
this._dep.hasData[idx] = seedData;
|
|
1500
|
-
this._dep.dirty[idx] = false;
|
|
1501
|
-
this._dep.tier[idx] = seedData ? 3 : 0;
|
|
1502
|
-
this._dep.terminal[idx] = depNode._value.terminal;
|
|
1503
|
-
this._dep.terminalInput[idx] = void 0;
|
|
2388
|
+
nodeActivate(nodeRuntimeHost(this));
|
|
1504
2389
|
}
|
|
1505
2390
|
_deactivate() {
|
|
1506
|
-
this
|
|
1507
|
-
for (const u of this._dep.unsubs) if (u) u();
|
|
1508
|
-
this._dep.unsubs = [];
|
|
1509
|
-
this._dep.idxBoxes = [];
|
|
1510
|
-
for (const fn of this._hooks.onDeactivation) fn();
|
|
1511
|
-
this._hooks.onDeactivation = [];
|
|
1512
|
-
this._hooks.onInvalidate = [];
|
|
1513
|
-
const isCompute = this._slot.handle !== null || this._slot.deps.length > 0;
|
|
1514
|
-
if (isCompute) {
|
|
1515
|
-
this._value.cache = SENTINEL;
|
|
1516
|
-
this._value.hasData = false;
|
|
1517
|
-
this._value.status = "sentinel";
|
|
1518
|
-
}
|
|
1519
|
-
this._resetDepState();
|
|
1520
|
-
this._wave.hasCalledFnOnce = false;
|
|
1521
|
-
this._control.pauseLockset.clear();
|
|
1522
|
-
this._control.pauseBuffer = [];
|
|
1523
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1524
|
-
this._control.demandOwed = false;
|
|
1525
|
-
this._value.replayRing = [];
|
|
1526
|
-
if (!this._privateState.persist) this._privateState.value = SENTINEL;
|
|
2391
|
+
nodeDeactivate(nodeRuntimeHost(this));
|
|
1527
2392
|
}
|
|
1528
2393
|
_assertNotReleased(op) {
|
|
1529
2394
|
if (this._released)
|
|
1530
2395
|
throw new Error(`${op}: node has been released from its graph lifecycle (D122)`);
|
|
1531
2396
|
}
|
|
1532
2397
|
_subscriberCount() {
|
|
1533
|
-
return this
|
|
2398
|
+
return nodeSubscriberCount(nodeRuntimeHost(this));
|
|
1534
2399
|
}
|
|
1535
2400
|
_isRuntimeQuiescentForRelease() {
|
|
1536
|
-
|
|
1537
|
-
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);
|
|
2401
|
+
return nodeIsRuntimeQuiescentForRelease(nodeRuntimeHost(this));
|
|
1538
2402
|
}
|
|
1539
2403
|
_releaseRuntime() {
|
|
1540
|
-
|
|
1541
|
-
this._released = true;
|
|
1542
|
-
releasedNodes.add(this);
|
|
1543
|
-
let releaseError;
|
|
1544
|
-
const recordReleaseError = (error) => {
|
|
1545
|
-
if (releaseError === void 0) releaseError = error;
|
|
1546
|
-
};
|
|
1547
|
-
this._lifecycle.activated = false;
|
|
1548
|
-
for (const u of this._dep.unsubs) {
|
|
1549
|
-
try {
|
|
1550
|
-
u();
|
|
1551
|
-
} catch (error) {
|
|
1552
|
-
recordReleaseError(error);
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
for (const fn of this._hooks.onDeactivation) {
|
|
1556
|
-
try {
|
|
1557
|
-
fn();
|
|
1558
|
-
} catch (error) {
|
|
1559
|
-
recordReleaseError(error);
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
this._dep.unsubs = [];
|
|
1563
|
-
this._dep.idxBoxes = [];
|
|
1564
|
-
this._lifecycle.subscribers.clear();
|
|
1565
|
-
if (this._slot.handle !== null) {
|
|
1566
|
-
this._slot.dispatcher.unregister(this._slot.handle);
|
|
1567
|
-
this._slot.handle = null;
|
|
1568
|
-
}
|
|
1569
|
-
this._slot.deps = [];
|
|
1570
|
-
this._dep.batch = [];
|
|
1571
|
-
this._dep.waveData = [];
|
|
1572
|
-
this._dep.waveTokens = [];
|
|
1573
|
-
this._dep.prev = [];
|
|
1574
|
-
this._dep.hasData = [];
|
|
1575
|
-
this._dep.dirty = [];
|
|
1576
|
-
this._dep.tier = [];
|
|
1577
|
-
this._dep.terminal = [];
|
|
1578
|
-
this._dep.terminalInput = [];
|
|
1579
|
-
this._value.cache = SENTINEL;
|
|
1580
|
-
this._value.hasData = false;
|
|
1581
|
-
this._value.status = "sentinel";
|
|
1582
|
-
this._value.terminal = void 0;
|
|
1583
|
-
this._value.replayRing = [];
|
|
1584
|
-
this._privateState.value = SENTINEL;
|
|
1585
|
-
this._privateState.persist = false;
|
|
1586
|
-
this._syncCtx = null;
|
|
1587
|
-
this._resetDepState();
|
|
1588
|
-
this._hooks.onDeactivation = [];
|
|
1589
|
-
this._hooks.onInvalidate = [];
|
|
1590
|
-
this._control.pauseLockset.clear();
|
|
1591
|
-
this._control.pauseBuffer = [];
|
|
1592
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1593
|
-
this._control.demandOwed = false;
|
|
1594
|
-
this._restoredActivationPending = false;
|
|
1595
|
-
checkpointReaders.delete(this);
|
|
1596
|
-
restoreWriters.delete(this);
|
|
1597
|
-
runtimeReleasers.delete(this);
|
|
1598
|
-
runtimeQuiescenceReaders.delete(this);
|
|
1599
|
-
subscriberCountReaders.delete(this);
|
|
1600
|
-
activationReaders.delete(this);
|
|
1601
|
-
ownerTokens.delete(this);
|
|
1602
|
-
topologyDepsChangedObservers.delete(this);
|
|
1603
|
-
this._core.releaseSlot(this._id);
|
|
1604
|
-
if (releaseError !== void 0) throw releaseError;
|
|
2404
|
+
nodeReleaseRuntime(nodeRuntimeHost(this));
|
|
1605
2405
|
}
|
|
1606
2406
|
_resetDepState() {
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
this._dep.dirty[i] = false;
|
|
1615
|
-
this._dep.tier[i] = 0;
|
|
1616
|
-
this._dep.terminal[i] = void 0;
|
|
1617
|
-
this._dep.terminalInput[i] = void 0;
|
|
1618
|
-
}
|
|
1619
|
-
this._wave.pending = 0;
|
|
1620
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2407
|
+
nodeResetDepState(nodeRuntimeHost(this));
|
|
2408
|
+
}
|
|
2409
|
+
_subscribeDepAt(depNode, opts = {}) {
|
|
2410
|
+
nodeSubscribeDepAt(nodeRuntimeHost(this), depNode, opts);
|
|
2411
|
+
}
|
|
2412
|
+
_seedRestoredDepAt(idx, depNode) {
|
|
2413
|
+
nodeSeedRestoredDepAt(nodeRuntimeHost(this), idx, depNode);
|
|
1621
2414
|
}
|
|
1622
|
-
// ── upstream wave receive (two-phase + diamond) ──
|
|
1623
2415
|
_recordDepProjection(idx, delivery) {
|
|
1624
|
-
|
|
1625
|
-
if (this._dep.waveTokens[idx] !== token) {
|
|
1626
|
-
this._dep.waveData[idx].push([]);
|
|
1627
|
-
this._dep.waveTokens[idx] = token;
|
|
1628
|
-
}
|
|
1629
|
-
return this._dep.waveData[idx][this._dep.waveData[idx].length - 1];
|
|
2416
|
+
return nodeRecordDepProjection(nodeRuntimeHost(this), idx, delivery);
|
|
1630
2417
|
}
|
|
1631
2418
|
_depProjectionHasData(idx) {
|
|
1632
|
-
|
|
1633
|
-
return projection?.some((v) => v !== SENTINEL) ?? false;
|
|
2419
|
+
return nodeDepProjectionHasData(nodeRuntimeHost(this), idx);
|
|
1634
2420
|
}
|
|
1635
2421
|
_receiveFromDep(idx, msg, delivery) {
|
|
1636
|
-
|
|
1637
|
-
const t = msg[0];
|
|
1638
|
-
if (t === "START") return;
|
|
1639
|
-
const isLastInDeliveredWave = delivery?.last ?? true;
|
|
1640
|
-
if (this._value.terminal !== void 0) {
|
|
1641
|
-
if (t === "TEARDOWN") this._down([["TEARDOWN"]]);
|
|
1642
|
-
return;
|
|
1643
|
-
}
|
|
1644
|
-
if (t === "INVALIDATE") {
|
|
1645
|
-
const projection = this._recordDepProjection(idx, delivery);
|
|
1646
|
-
projection.push(SENTINEL);
|
|
1647
|
-
if (projection.some((v) => v !== SENTINEL) && isLastInDeliveredWave) this._maybeRun();
|
|
1648
|
-
this._dep.prev[idx] = SENTINEL;
|
|
1649
|
-
this._dep.hasData[idx] = false;
|
|
1650
|
-
this._dep.batch[idx] = null;
|
|
1651
|
-
if (this._dep.dirty[idx]) {
|
|
1652
|
-
this._dep.dirty[idx] = false;
|
|
1653
|
-
this._wave.pending--;
|
|
1654
|
-
}
|
|
1655
|
-
if (this._control.pausedDepWaveOccurred && this._dep.batch.every((b) => b === null)) {
|
|
1656
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1657
|
-
}
|
|
1658
|
-
const hadData = this._value.hasData;
|
|
1659
|
-
this._invalidate();
|
|
1660
|
-
if (this._wave.pending === 0 && this._wave.emittedDirtyThisWave) {
|
|
1661
|
-
if (!hadData) this._down([["RESOLVED"]]);
|
|
1662
|
-
else this._wave.emittedDirtyThisWave = false;
|
|
1663
|
-
}
|
|
1664
|
-
this._fireOwedDemandIfReady();
|
|
1665
|
-
return;
|
|
1666
|
-
}
|
|
1667
|
-
if (isTerminal(t)) {
|
|
1668
|
-
const isError = t === "ERROR";
|
|
1669
|
-
const errPayload = isError ? msg[1] : void 0;
|
|
1670
|
-
this._dep.terminal[idx] = isError ? errPayload : true;
|
|
1671
|
-
this._dep.terminalInput[idx] = isError ? errPayload : true;
|
|
1672
|
-
this._releaseDepDirty(idx);
|
|
1673
|
-
const ranValueBeforeTerminal = this._depProjectionHasData(idx) && isLastInDeliveredWave;
|
|
1674
|
-
if (ranValueBeforeTerminal) this._maybeRun();
|
|
1675
|
-
if (isError && this._slot.errorWhenDepsError) {
|
|
1676
|
-
this._down([["ERROR", errPayload]]);
|
|
1677
|
-
} else if (this._slot.terminalAsRealInput) {
|
|
1678
|
-
if (ranValueBeforeTerminal) {
|
|
1679
|
-
this._fireOwedDemandIfReady();
|
|
1680
|
-
return;
|
|
1681
|
-
}
|
|
1682
|
-
this._maybeRun();
|
|
1683
|
-
} else if (this._slot.completeWhenDepsComplete && this._allDepsTerminal()) {
|
|
1684
|
-
this._down([["COMPLETE"]]);
|
|
1685
|
-
} else {
|
|
1686
|
-
this._settleAfterAbsorbedTerminal();
|
|
1687
|
-
}
|
|
1688
|
-
this._fireOwedDemandIfReady();
|
|
1689
|
-
return;
|
|
1690
|
-
}
|
|
1691
|
-
if (t === "TEARDOWN") {
|
|
1692
|
-
this._down([["TEARDOWN"]]);
|
|
1693
|
-
return;
|
|
1694
|
-
}
|
|
1695
|
-
if (t === "DIRTY") {
|
|
1696
|
-
if (!this._dep.dirty[idx]) {
|
|
1697
|
-
this._dep.dirty[idx] = true;
|
|
1698
|
-
this._wave.pending++;
|
|
1699
|
-
this._dep.tier[idx] = 2;
|
|
1700
|
-
this._markDirty();
|
|
1701
|
-
}
|
|
1702
|
-
return;
|
|
1703
|
-
}
|
|
1704
|
-
if (t === "DATA") {
|
|
1705
|
-
const v = msg[1];
|
|
1706
|
-
this._recordDepProjection(idx, delivery).push(v);
|
|
1707
|
-
const b = this._dep.batch[idx];
|
|
1708
|
-
if (b === null) this._dep.batch[idx] = [v];
|
|
1709
|
-
else b.push(v);
|
|
1710
|
-
this._dep.prev[idx] = v;
|
|
1711
|
-
this._dep.hasData[idx] = true;
|
|
1712
|
-
this._dep.tier[idx] = 3;
|
|
1713
|
-
if (this._dep.dirty[idx]) {
|
|
1714
|
-
this._dep.dirty[idx] = false;
|
|
1715
|
-
this._wave.pending--;
|
|
1716
|
-
}
|
|
1717
|
-
if (isLastInDeliveredWave) this._maybeRun();
|
|
1718
|
-
this._fireOwedDemandIfReady();
|
|
1719
|
-
return;
|
|
1720
|
-
}
|
|
1721
|
-
if (t === "RESOLVED") {
|
|
1722
|
-
this._recordDepProjection(idx, delivery);
|
|
1723
|
-
this._dep.tier[idx] = 3;
|
|
1724
|
-
if (this._dep.dirty[idx]) {
|
|
1725
|
-
this._dep.dirty[idx] = false;
|
|
1726
|
-
this._wave.pending--;
|
|
1727
|
-
}
|
|
1728
|
-
if (isLastInDeliveredWave) this._maybeRun();
|
|
1729
|
-
this._fireOwedDemandIfReady();
|
|
1730
|
-
return;
|
|
1731
|
-
}
|
|
2422
|
+
nodeReceiveFromDep(nodeRuntimeHost(this), idx, msg, delivery);
|
|
1732
2423
|
}
|
|
1733
|
-
/**
|
|
1734
|
-
* R-terminal-settles-dirty (B35): release a dep's outstanding in-wave DIRTY contribution.
|
|
1735
|
-
* A settle-class event for that dep (DATA/RESOLVED inline above, INVALIDATE, and now
|
|
1736
|
-
* COMPLETE/ERROR) clears its dirty flag + decrements _pending. No-op if the dep already
|
|
1737
|
-
* settled this wave (DATA/RESOLVED ran first) — so the normal DATA-then-COMPLETE flow is
|
|
1738
|
-
* unaffected. This makes the exactly-one-settle invariant a single, shared step.
|
|
1739
|
-
*/
|
|
1740
2424
|
_releaseDepDirty(idx) {
|
|
1741
|
-
|
|
1742
|
-
this._dep.dirty[idx] = false;
|
|
1743
|
-
this._wave.pending--;
|
|
1744
|
-
}
|
|
2425
|
+
nodeReleaseDepDirty(nodeRuntimeHost(this), idx);
|
|
1745
2426
|
}
|
|
1746
|
-
/**
|
|
1747
|
-
* R-terminal-settles-dirty (B35): settle a node whose dirtied dep was released by an ABSORBED
|
|
1748
|
-
* terminal that is NOT a real input (a plain derived/effect — the common default-node case when
|
|
1749
|
-
* one of several deps completes while others stay live). Runs only when the release drained
|
|
1750
|
-
* _pending while the node still owes a downstream settle (it broadcast DIRTY this wave):
|
|
1751
|
-
* - if some OTHER dep delivered real DATA this wave (a value occurred) → recompute (→ DATA);
|
|
1752
|
-
* - else the terminal's signalled change did not materialise (no value) → one undirty RESOLVED
|
|
1753
|
-
* (R-resolved-undirty), keeping the cache (a terminal, unlike INVALIDATE, leaves the value).
|
|
1754
|
-
* A terminalAsRealInput node instead recomputes unconditionally (its fn reads the terminal).
|
|
1755
|
-
*/
|
|
1756
2427
|
_settleAfterAbsorbedTerminal() {
|
|
1757
|
-
|
|
1758
|
-
const sawData = this._dep.batch.some((b) => b !== null && b.length > 0);
|
|
1759
|
-
if (sawData) this._maybeRun();
|
|
1760
|
-
if (this._wave.emittedDirtyThisWave) this._down([["RESOLVED"]]);
|
|
2428
|
+
nodeSettleAfterAbsorbedTerminal(nodeRuntimeHost(this));
|
|
1761
2429
|
}
|
|
1762
2430
|
_markDirty() {
|
|
1763
|
-
this
|
|
1764
|
-
if (this._isPullQuiet()) return;
|
|
1765
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
1766
|
-
this._wave.emittedDirtyThisWave = true;
|
|
1767
|
-
this._emitToSubs(["DIRTY"]);
|
|
1768
|
-
}
|
|
2431
|
+
nodeMarkDirty(nodeRuntimeHost(this));
|
|
1769
2432
|
}
|
|
1770
2433
|
_maybeRun() {
|
|
1771
|
-
|
|
1772
|
-
this._wave.rewireRunPending = true;
|
|
1773
|
-
return;
|
|
1774
|
-
}
|
|
1775
|
-
if (this._slot.pausable === true && this._isPaused()) {
|
|
1776
|
-
this._control.pausedDepWaveOccurred = true;
|
|
1777
|
-
return;
|
|
1778
|
-
}
|
|
1779
|
-
this._tryRun();
|
|
2434
|
+
nodeMaybeRun(nodeRuntimeHost(this));
|
|
1780
2435
|
}
|
|
1781
|
-
/**
|
|
1782
|
-
* R-rewire atomic settle (after a rewire that warrants a recompute): emit a proper
|
|
1783
|
-
* two-phase DIRTY→DATA wave (R-dirty-before-data — a rewire-triggered settle is a wave),
|
|
1784
|
-
* once, with every added dep already wired. Mirrors _maybeRun/_tryRun's pause + gate +
|
|
1785
|
-
* pending guards, then injects the phase-1 DIRTY the added dep's [START,DATA] handshake
|
|
1786
|
-
* did not carry.
|
|
1787
|
-
*/
|
|
1788
2436
|
_settleRewire() {
|
|
1789
|
-
|
|
1790
|
-
this._control.pausedDepWaveOccurred = true;
|
|
1791
|
-
return;
|
|
1792
|
-
}
|
|
1793
|
-
if (this._wave.pending > 0) return;
|
|
1794
|
-
if (this._slot.handle === null) {
|
|
1795
|
-
this._passthroughEmit();
|
|
1796
|
-
return;
|
|
1797
|
-
}
|
|
1798
|
-
if (!this._wave.hasCalledFnOnce && !(this._slot.partial || this._allDepsSettled())) return;
|
|
1799
|
-
this._markDirty();
|
|
1800
|
-
this._runWave();
|
|
2437
|
+
nodeSettleRewire(nodeRuntimeHost(this));
|
|
1801
2438
|
}
|
|
1802
2439
|
_tryRun() {
|
|
1803
|
-
|
|
1804
|
-
if (this._slot.handle === null) {
|
|
1805
|
-
this._passthroughEmit();
|
|
1806
|
-
return;
|
|
1807
|
-
}
|
|
1808
|
-
if (!this._wave.hasCalledFnOnce) {
|
|
1809
|
-
if (this._slot.partial || this._allDepsSettled()) this._runWave();
|
|
1810
|
-
return;
|
|
1811
|
-
}
|
|
1812
|
-
this._runWave();
|
|
2440
|
+
nodeTryRun(nodeRuntimeHost(this));
|
|
1813
2441
|
}
|
|
1814
2442
|
_allDepsSettled() {
|
|
1815
|
-
|
|
1816
|
-
if (this._dep.hasData[i]) continue;
|
|
1817
|
-
if (this._slot.terminalAsRealInput && this._dep.terminal[i] !== void 0) continue;
|
|
1818
|
-
return false;
|
|
1819
|
-
}
|
|
1820
|
-
return true;
|
|
2443
|
+
return nodeAllDepsSettled(nodeRuntimeHost(this));
|
|
1821
2444
|
}
|
|
1822
2445
|
_passthroughEmit() {
|
|
1823
|
-
|
|
1824
|
-
if (b !== null && b.length > 0) {
|
|
1825
|
-
this._down([["DATA", b[b.length - 1]]]);
|
|
1826
|
-
} else if (this._wave.emittedDirtyThisWave) {
|
|
1827
|
-
this._down([["RESOLVED"]]);
|
|
1828
|
-
}
|
|
1829
|
-
this._dep.batch[0] = null;
|
|
1830
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2446
|
+
nodePassthroughEmit(nodeRuntimeHost(this));
|
|
1831
2447
|
}
|
|
1832
2448
|
_runWave() {
|
|
1833
|
-
|
|
1834
|
-
throw new Error(
|
|
1835
|
-
"synchronous feedback cycle: node fn re-entered its own wave (R-reentrancy / D37)"
|
|
1836
|
-
);
|
|
1837
|
-
this._wave.hasCalledFnOnce = true;
|
|
1838
|
-
this._hooks.onInvalidate = [];
|
|
1839
|
-
this._hooks.onDeactivation = [];
|
|
1840
|
-
const ctx = this._buildCtx();
|
|
1841
|
-
const wasDirty = this._wave.emittedDirtyThisWave;
|
|
1842
|
-
this._wave.emittedSettleThisWave = false;
|
|
1843
|
-
this._wave.insideRunWave = true;
|
|
1844
|
-
try {
|
|
1845
|
-
this._slot.dispatcher.invoke(this._slot.handle, ctx);
|
|
1846
|
-
} finally {
|
|
1847
|
-
this._wave.insideRunWave = false;
|
|
1848
|
-
}
|
|
1849
|
-
if (wasDirty && !this._wave.emittedSettleThisWave && this._value.terminal === void 0 && !this._isAsyncPool()) {
|
|
1850
|
-
this._down([["RESOLVED"]]);
|
|
1851
|
-
}
|
|
1852
|
-
for (let i = 0; i < this._dep.batch.length; i++) {
|
|
1853
|
-
this._dep.batch[i] = null;
|
|
1854
|
-
this._dep.waveData[i] = [];
|
|
1855
|
-
this._dep.waveTokens[i] = void 0;
|
|
1856
|
-
this._dep.terminalInput[i] = void 0;
|
|
1857
|
-
}
|
|
1858
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2449
|
+
nodeRunWave(nodeRuntimeHost(this));
|
|
1859
2450
|
}
|
|
1860
|
-
// ── ctx construction (L3-Q5: sync = node-stable reused ctx; async = per-invocation) ──
|
|
1861
2451
|
_buildCtx() {
|
|
1862
|
-
|
|
1863
|
-
if (kind === "sync") {
|
|
1864
|
-
if (this._syncCtx === null) this._syncCtx = this._makeCtx();
|
|
1865
|
-
this._refreshCtx(this._syncCtx);
|
|
1866
|
-
return this._syncCtx;
|
|
1867
|
-
}
|
|
1868
|
-
return this._makeCtx({
|
|
1869
|
-
waveData: this._dep.waveData.map((waves) => waves.map((w) => [...w])),
|
|
1870
|
-
terminal: this._dep.terminalInput.map(terminalView),
|
|
1871
|
-
latest: [...this._dep.prev]
|
|
1872
|
-
});
|
|
2452
|
+
return nodeBuildCtx(nodeRuntimeHost(this));
|
|
1873
2453
|
}
|
|
1874
2454
|
_makeCtx(snapshot) {
|
|
1875
|
-
|
|
1876
|
-
// Wave-owner boundary (D47): a SYNC fn's emit nests under the public entry that drove
|
|
1877
|
-
// it (cheap inc/dec, no early drain); an ASYNC-pool fn re-enters here from its stashed
|
|
1878
|
-
// ctx at depth 0, so this is the boundary that drains any rewireNext it issued.
|
|
1879
|
-
up: (msgs, towardDep) => {
|
|
1880
|
-
if (this._released) return;
|
|
1881
|
-
enterWave();
|
|
1882
|
-
try {
|
|
1883
|
-
this._up(msgs, towardDep);
|
|
1884
|
-
} finally {
|
|
1885
|
-
exitWave();
|
|
1886
|
-
}
|
|
1887
|
-
},
|
|
1888
|
-
down: (msgs) => {
|
|
1889
|
-
if (this._released) return;
|
|
1890
|
-
enterWave();
|
|
1891
|
-
try {
|
|
1892
|
-
this._down(msgs);
|
|
1893
|
-
} finally {
|
|
1894
|
-
exitWave();
|
|
1895
|
-
}
|
|
1896
|
-
},
|
|
1897
|
-
waveData: snapshot?.waveData ?? this._dep.waveData,
|
|
1898
|
-
terminal: snapshot?.terminal ?? this._dep.terminalInput.map(terminalView),
|
|
1899
|
-
state: this._makeState(),
|
|
1900
|
-
onDeactivation: (fn) => {
|
|
1901
|
-
if (this._released) return;
|
|
1902
|
-
this._hooks.onDeactivation.push(fn);
|
|
1903
|
-
},
|
|
1904
|
-
onInvalidate: (fn) => {
|
|
1905
|
-
if (this._released) return;
|
|
1906
|
-
this._hooks.onInvalidate.push(fn);
|
|
1907
|
-
},
|
|
1908
|
-
environment: () => this._slot.environment,
|
|
1909
|
-
// R-rewire-deferred (D47): defer a self-dep-set mutation to the committed boundary.
|
|
1910
|
-
rewireNext: {
|
|
1911
|
-
subscribeDep: (dep, fn) => this._requestRewireNext({ kind: "add", dep, fn }),
|
|
1912
|
-
unsubscribeDep: (dep, fn) => this._requestRewireNext({ kind: "remove", dep, fn }),
|
|
1913
|
-
replaceDeps: (deps, fn) => this._requestRewireNext({ kind: "set", deps, fn })
|
|
1914
|
-
},
|
|
1915
|
-
// R-up-routing / R-pull (D59): deferred up — route a control wave (e.g. a RESUME pull
|
|
1916
|
-
// DEMAND) up the declared cone at the committed boundary. The SELF-demand path: an
|
|
1917
|
-
// immediate ctx.up whose delivery loops back re-enters this fn (D37 / R-reentrancy).
|
|
1918
|
-
upNext: (msgs, towardDep) => this._requestUpNext(msgs, towardDep),
|
|
1919
|
-
[CTX_DEP_CACHE]: { latest: snapshot?.latest ?? this._dep.prev },
|
|
1920
|
-
[CTX_NODE_BINDING]: {
|
|
1921
|
-
dispatcher: this._slot.dispatcher,
|
|
1922
|
-
create: (factory) => withEnvironmentDrivers(this._slot.environment, () => withNodeCore(this._core, factory))
|
|
1923
|
-
}
|
|
1924
|
-
};
|
|
1925
|
-
if (this._slot.dynamic) {
|
|
1926
|
-
ctx.track = (i) => ctx[CTX_DEP_CACHE]?.latest[i];
|
|
1927
|
-
}
|
|
1928
|
-
return ctx;
|
|
2455
|
+
return nodeMakeCtx(nodeRuntimeHost(this), snapshot);
|
|
1929
2456
|
}
|
|
1930
2457
|
_refreshCtx(ctx) {
|
|
1931
|
-
ctx
|
|
1932
|
-
ctx.terminal = this._dep.terminalInput.map(terminalView);
|
|
1933
|
-
ctx[CTX_DEP_CACHE] = { latest: this._dep.prev };
|
|
2458
|
+
nodeRefreshCtx(nodeRuntimeHost(this), ctx);
|
|
1934
2459
|
}
|
|
1935
2460
|
_makeState() {
|
|
1936
|
-
return
|
|
1937
|
-
get: () => this._privateState.value,
|
|
1938
|
-
set: (v) => {
|
|
1939
|
-
this._privateState.value = v;
|
|
1940
|
-
},
|
|
1941
|
-
persist: (on = true) => {
|
|
1942
|
-
this._privateState.persist = on;
|
|
1943
|
-
}
|
|
1944
|
-
};
|
|
2461
|
+
return nodeMakeState(nodeRuntimeHost(this));
|
|
1945
2462
|
}
|
|
1946
2463
|
// ── downstream emission pipeline (the unified waist) ──
|
|
1947
2464
|
_down(msgs) {
|
|
1948
|
-
|
|
1949
|
-
validateDownPayloads(msgs);
|
|
1950
|
-
const deliveryWave = {};
|
|
1951
|
-
const assertVersionDataCompatible = (wave) => {
|
|
1952
|
-
for (const m of wave) {
|
|
1953
|
-
if (m[0] === "DATA") assertNodeVersionDataCompatible(this._version.policy, m[1]);
|
|
1954
|
-
}
|
|
1955
|
-
};
|
|
1956
|
-
const snapshotVersionData = (wave) => wave.map(
|
|
1957
|
-
(m) => m[0] === "DATA" ? ["DATA", snapshotNodeVersionData(this._version.policy, m[1])] : m
|
|
1958
|
-
);
|
|
1959
|
-
assertVersionDataCompatible(msgs);
|
|
1960
|
-
if (this._value.terminal !== void 0) {
|
|
1961
|
-
if (!msgs.some((m) => m[0] === "TEARDOWN")) return;
|
|
1962
|
-
this._value.hasTorndown = true;
|
|
1963
|
-
if (this._slot.resetOnTeardown) {
|
|
1964
|
-
this._value.cache = SENTINEL;
|
|
1965
|
-
this._value.hasData = false;
|
|
1966
|
-
}
|
|
1967
|
-
this._emitToSubs(["TEARDOWN"], { wave: deliveryWave, last: true });
|
|
1968
|
-
return;
|
|
1969
|
-
}
|
|
1970
|
-
let sorted = [...msgs].sort((a, b) => messageTier(a[0]) - messageTier(b[0]));
|
|
1971
|
-
const firstInvalidate = sorted.findIndex((m) => m[0] === "INVALIDATE");
|
|
1972
|
-
if (firstInvalidate !== -1) {
|
|
1973
|
-
sorted = sorted.filter((m, i) => m[0] !== "INVALIDATE" || i === firstInvalidate);
|
|
1974
|
-
}
|
|
1975
|
-
const hasTeardown = sorted.some((m) => m[0] === "TEARDOWN");
|
|
1976
|
-
const hasTerminal = sorted.some((m) => m[0] === "COMPLETE" || m[0] === "ERROR");
|
|
1977
|
-
if (hasTeardown && !hasTerminal && this._value.terminal === void 0 && !this._value.hasTorndown) {
|
|
1978
|
-
sorted = [["COMPLETE"], ...sorted];
|
|
1979
|
-
}
|
|
1980
|
-
if (!this._wave.insideRunWave && currentBatch()) {
|
|
1981
|
-
const deferred = snapshotVersionData(sorted.filter((m) => isDeferredTier(m[0])));
|
|
1982
|
-
if (deferred.length > 0) {
|
|
1983
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
1984
|
-
this._wave.emittedDirtyThisWave = true;
|
|
1985
|
-
this._value.status = "dirty";
|
|
1986
|
-
this._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1987
|
-
}
|
|
1988
|
-
this._wave.batchDirtyOwed = true;
|
|
1989
|
-
deferToBatch(this, deferred);
|
|
1990
|
-
return;
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
if (this._shouldBufferOnPause()) {
|
|
1994
|
-
const buffered = snapshotVersionData(sorted.filter((m) => isPauseBufferedTier(m[0])));
|
|
1995
|
-
if (buffered.length > 0) {
|
|
1996
|
-
this._wave.emittedSettleThisWave = true;
|
|
1997
|
-
this._control.pauseBuffer.push(buffered);
|
|
1998
|
-
}
|
|
1999
|
-
sorted = sorted.filter((m) => !isPauseBufferedTier(m[0]));
|
|
2000
|
-
if (sorted.length === 0) return;
|
|
2001
|
-
}
|
|
2002
|
-
let dataCount = 0;
|
|
2003
|
-
let hasTier3 = false;
|
|
2004
|
-
let hasResolved = false;
|
|
2005
|
-
for (const m of sorted) {
|
|
2006
|
-
if (m[0] === "DATA") dataCount++;
|
|
2007
|
-
if (m[0] === "RESOLVED") hasResolved = true;
|
|
2008
|
-
if (isValueTier(m[0])) hasTier3 = true;
|
|
2009
|
-
}
|
|
2010
|
-
if (dataCount >= 1 && hasResolved) {
|
|
2011
|
-
throw new Error(
|
|
2012
|
-
"down: a wave cannot mix DATA and RESOLVED (tier-3 exclusivity, R-resolved-undirty)"
|
|
2013
|
-
);
|
|
2014
|
-
}
|
|
2015
|
-
const plannedVersions = new Array(sorted.length);
|
|
2016
|
-
if (dataCount > 0) {
|
|
2017
|
-
let plannedVersion = this._version.value;
|
|
2018
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
2019
|
-
const m = sorted[i];
|
|
2020
|
-
if (m[0] !== "DATA") continue;
|
|
2021
|
-
plannedVersion = advanceNodeVersion(plannedVersion, this._version.policy, m[1]);
|
|
2022
|
-
plannedVersions[i] = plannedVersion;
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
if (hasTier3 && !this._wave.insideRunWave && !this._wave.emittedDirtyThisWave) {
|
|
2026
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2027
|
-
this._value.status = "dirty";
|
|
2028
|
-
this._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
2029
|
-
}
|
|
2030
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
2031
|
-
const m = sorted[i];
|
|
2032
|
-
const delivery = { wave: deliveryWave, last: i === sorted.length - 1 };
|
|
2033
|
-
if (isDeferredTier(m[0])) this._wave.emittedSettleThisWave = true;
|
|
2034
|
-
if (m[0] === "DIRTY") {
|
|
2035
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
2036
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2037
|
-
this._value.status = "dirty";
|
|
2038
|
-
this._emitToSubs(["DIRTY"], delivery);
|
|
2039
|
-
}
|
|
2040
|
-
continue;
|
|
2041
|
-
}
|
|
2042
|
-
if (m[0] === "DATA") {
|
|
2043
|
-
const v = m[1];
|
|
2044
|
-
this._value.cache = v;
|
|
2045
|
-
this._value.hasData = true;
|
|
2046
|
-
this._value.status = "settled";
|
|
2047
|
-
this._version.value = plannedVersions[i];
|
|
2048
|
-
if (this._slot.replayN > 0) {
|
|
2049
|
-
this._value.replayRing.push(v);
|
|
2050
|
-
if (this._value.replayRing.length > this._slot.replayN) this._value.replayRing.shift();
|
|
2051
|
-
}
|
|
2052
|
-
this._emitToSubs(["DATA", v], delivery);
|
|
2053
|
-
continue;
|
|
2054
|
-
}
|
|
2055
|
-
if (m[0] === "RESOLVED") {
|
|
2056
|
-
this._value.status = this._value.hasData ? "resolved" : "sentinel";
|
|
2057
|
-
this._emitToSubs(["RESOLVED"], delivery);
|
|
2058
|
-
continue;
|
|
2059
|
-
}
|
|
2060
|
-
if (m[0] === "INVALIDATE") {
|
|
2061
|
-
this._invalidate(delivery);
|
|
2062
|
-
continue;
|
|
2063
|
-
}
|
|
2064
|
-
if (m[0] === "COMPLETE") {
|
|
2065
|
-
if (this._value.terminal !== void 0) continue;
|
|
2066
|
-
this._value.terminal = true;
|
|
2067
|
-
this._control.pauseBuffer = [];
|
|
2068
|
-
this._value.status = "completed";
|
|
2069
|
-
this._emitToSubs(["COMPLETE"], delivery);
|
|
2070
|
-
continue;
|
|
2071
|
-
}
|
|
2072
|
-
if (m[0] === "ERROR") {
|
|
2073
|
-
if (this._value.terminal !== void 0) continue;
|
|
2074
|
-
this._value.terminal = m[1];
|
|
2075
|
-
this._control.pauseBuffer = [];
|
|
2076
|
-
this._value.status = "errored";
|
|
2077
|
-
this._emitToSubs(["ERROR", m[1]], delivery);
|
|
2078
|
-
continue;
|
|
2079
|
-
}
|
|
2080
|
-
if (m[0] === "TEARDOWN") {
|
|
2081
|
-
this._value.hasTorndown = true;
|
|
2082
|
-
if (this._slot.resetOnTeardown) {
|
|
2083
|
-
this._value.cache = SENTINEL;
|
|
2084
|
-
this._value.hasData = false;
|
|
2085
|
-
}
|
|
2086
|
-
this._emitToSubs(["TEARDOWN"], delivery);
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2089
|
-
if (!this._wave.insideRunWave) this._wave.emittedDirtyThisWave = false;
|
|
2465
|
+
nodeDown(nodeRuntimeHost(this), msgs);
|
|
2090
2466
|
}
|
|
2091
2467
|
_up(msgs, towardDep, route) {
|
|
2092
|
-
|
|
2093
|
-
const routeState = route ?? { demandFired: /* @__PURE__ */ new Map() };
|
|
2094
|
-
for (const m of msgs) {
|
|
2095
|
-
if (!isUpAllowed(m[0])) {
|
|
2096
|
-
throw new Error(
|
|
2097
|
-
`ctx.up: ${m[0]} is down-only (tier ${messageTier(m[0])}); up carries control tiers only (R-ctx-up)`
|
|
2098
|
-
);
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
for (const m of msgs) {
|
|
2102
|
-
if (m[0] === "PAUSE") {
|
|
2103
|
-
this._pauseAcquire(m[1]);
|
|
2104
|
-
} else if (m[0] === "RESUME") {
|
|
2105
|
-
if (this._slot.pull && m[1] === this._slot.pullLock) {
|
|
2106
|
-
if (!this._markDemandRouted(m[1], routeState)) this._onDemand();
|
|
2107
|
-
} else if (this._control.pauseLockset.has(m[1])) {
|
|
2108
|
-
this._pauseRelease(m[1]);
|
|
2109
|
-
} else {
|
|
2110
|
-
this._forwardUp(m, towardDep, routeState);
|
|
2111
|
-
}
|
|
2112
|
-
} else if (this._slot.deps.length === 0) {
|
|
2113
|
-
if (m[0] === "INVALIDATE") this._down([["INVALIDATE"]]);
|
|
2114
|
-
} else {
|
|
2115
|
-
this._forwardUp(m, towardDep, routeState);
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2468
|
+
nodeUp(nodeRuntimeHost(this), msgs, towardDep, route);
|
|
2118
2469
|
}
|
|
2119
2470
|
_markDemandRouted(lockId, route) {
|
|
2120
|
-
|
|
2121
|
-
if (holders === void 0) {
|
|
2122
|
-
holders = /* @__PURE__ */ new Set();
|
|
2123
|
-
route.demandFired.set(lockId, holders);
|
|
2124
|
-
}
|
|
2125
|
-
if (holders.has(this)) return true;
|
|
2126
|
-
holders.add(this);
|
|
2127
|
-
return false;
|
|
2471
|
+
return nodeMarkDemandRouted(nodeRuntimeHost(this), lockId, route);
|
|
2128
2472
|
}
|
|
2129
|
-
/**
|
|
2130
|
-
* Forward one up-going control message toward deps (R-up-routing): up the single declared edge
|
|
2131
|
-
* `towardDep` (directed — prunes other branches; only meaningful on the issuer's FIRST hop) or
|
|
2132
|
-
* broadcast up ALL deps. A depless source has no deps → the message DROPS here (the terminus —
|
|
2133
|
-
* e.g. a cone-routed RESUME whose pullId no node up this cone holds, R-up-at-source). Recursive
|
|
2134
|
-
* forwarding carries the same per-wave route state and no `towardDep` → broadcast beyond the
|
|
2135
|
-
* first hop.
|
|
2136
|
-
*/
|
|
2137
2473
|
_forwardUp(m, towardDep, route) {
|
|
2138
|
-
|
|
2139
|
-
if (towardDep !== void 0) {
|
|
2140
|
-
const d = this._slot.deps[towardDep];
|
|
2141
|
-
if (d !== void 0) d._up([m], void 0, route);
|
|
2142
|
-
} else {
|
|
2143
|
-
for (const dep of this._slot.deps) dep._up([m], void 0, route);
|
|
2144
|
-
}
|
|
2474
|
+
nodeForwardUp(nodeRuntimeHost(this), m, towardDep, route);
|
|
2145
2475
|
}
|
|
2146
|
-
// ── PAUSE/RESUME lockset (R-pause-lockset) + modes (R-pause-modes) ──
|
|
2147
2476
|
_isPaused() {
|
|
2148
|
-
return this
|
|
2477
|
+
return nodeIsPaused(nodeRuntimeHost(this));
|
|
2149
2478
|
}
|
|
2150
2479
|
_hasBoundaryPauseLock() {
|
|
2151
|
-
|
|
2152
|
-
let locks = this._control.pauseLockset.size;
|
|
2153
|
-
if (this._slot.pull && this._control.pauseLockset.has(this._slot.pullLock)) locks--;
|
|
2154
|
-
return locks > 0;
|
|
2480
|
+
return nodeHasBoundaryPauseLock(nodeRuntimeHost(this));
|
|
2155
2481
|
}
|
|
2156
2482
|
_isAsyncPool() {
|
|
2157
|
-
return
|
|
2483
|
+
return nodeIsAsyncPool(nodeRuntimeHost(this));
|
|
2158
2484
|
}
|
|
2159
2485
|
_pauseAcquire(lockId) {
|
|
2160
|
-
this
|
|
2486
|
+
nodePauseAcquire(nodeRuntimeHost(this), lockId);
|
|
2161
2487
|
}
|
|
2162
2488
|
_pauseRelease(lockId) {
|
|
2163
|
-
|
|
2164
|
-
this._control.pauseLockset.delete(lockId);
|
|
2165
|
-
if (this._slot.pull && this._control.demandOwed) this._fireOwedDemandIfReady();
|
|
2166
|
-
if (this._hasBoundaryPauseLock()) return;
|
|
2167
|
-
scheduleBoundaryDrain(this._core);
|
|
2168
|
-
if (this._control.pauseLockset.size > 0) return;
|
|
2169
|
-
this._onResume();
|
|
2489
|
+
nodePauseRelease(nodeRuntimeHost(this), lockId);
|
|
2170
2490
|
}
|
|
2171
2491
|
_onResume() {
|
|
2172
|
-
|
|
2173
|
-
this._control.pauseBuffer = [];
|
|
2174
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2175
|
-
this._control.demandOwed = false;
|
|
2176
|
-
return;
|
|
2177
|
-
}
|
|
2178
|
-
if (this._control.pauseBuffer.length > 0) {
|
|
2179
|
-
const buf = this._control.pauseBuffer;
|
|
2180
|
-
this._control.pauseBuffer = [];
|
|
2181
|
-
for (const wave of buf) this._down(wave);
|
|
2182
|
-
}
|
|
2183
|
-
if (this._control.pausedDepWaveOccurred) {
|
|
2184
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2185
|
-
this._tryRun();
|
|
2186
|
-
}
|
|
2492
|
+
nodeOnResume(nodeRuntimeHost(this));
|
|
2187
2493
|
}
|
|
2188
|
-
/**
|
|
2189
|
-
* R-pull (D59): can this pull node fire a demand NOW? — not terminal, settle-ready (_pending===0),
|
|
2190
|
-
* and no OTHER (non-pullId) lock holds it paused. The gate that decides fire-now vs OWE.
|
|
2191
|
-
*/
|
|
2192
2494
|
_canFireDemand() {
|
|
2193
|
-
|
|
2194
|
-
const own = this._control.pauseLockset.has(this._slot.pullLock) ? 1 : 0;
|
|
2195
|
-
return this._control.pauseLockset.size <= own;
|
|
2495
|
+
return nodeCanFireDemand(nodeRuntimeHost(this));
|
|
2196
2496
|
}
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
* absorbed), fire it, then RE-QUIET (1:1). The pullId re-add + the re-entrancy flag are in a
|
|
2200
|
-
* `finally` so a throwing pull fn (graph-less node, no D30 catch) cannot leave the node
|
|
2201
|
-
* permanently non-quiet (the wedge-fix silently disabled) — QA-found robustness fix.
|
|
2202
|
-
*/
|
|
2203
|
-
_deliverPullDemand() {
|
|
2204
|
-
this._control.demandOwed = false;
|
|
2205
|
-
this._control.inDeliverDemand = true;
|
|
2206
|
-
this._control.pauseLockset.delete(this._slot.pullLock);
|
|
2207
|
-
try {
|
|
2208
|
-
this._firePullDemand();
|
|
2209
|
-
} finally {
|
|
2210
|
-
this._control.pauseLockset.add(this._slot.pullLock);
|
|
2211
|
-
this._control.inDeliverDemand = false;
|
|
2212
|
-
}
|
|
2497
|
+
_deliverPullDemand(demand) {
|
|
2498
|
+
nodeDeliverPullDemand(nodeRuntimeHost(this), demand);
|
|
2213
2499
|
}
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
* Fire immediately if able; else OWE it — pin-5 (a dep DIRTY in flight, _pending>0) or F4/F5 (an
|
|
2217
|
-
* external PAUSE lock co-holds the node) — and fire when the node next becomes able. A demand
|
|
2218
|
-
* arriving WHILE a delivery is in flight (synchronous re-entry) is DROPPED (1:1, QA guard).
|
|
2219
|
-
*/
|
|
2220
|
-
_onDemand() {
|
|
2221
|
-
if (this._control.inDeliverDemand) return;
|
|
2222
|
-
if (this._canFireDemand()) this._deliverPullDemand();
|
|
2223
|
-
else this._control.demandOwed = true;
|
|
2500
|
+
_onDemand(demand) {
|
|
2501
|
+
nodeOnDemand(nodeRuntimeHost(this), demand);
|
|
2224
2502
|
}
|
|
2225
|
-
/**
|
|
2226
|
-
* R-pull (D55): service ONE demand. Delivery content = the orthogonal pausable mode:
|
|
2227
|
-
* - 'resumeAll' → drain the buffered BACKLOG (each `_down` re-synthesizes a leading DIRTY, so
|
|
2228
|
-
* the per-entry replay is DIRTY-before-DATA — R-pause-modes per-entry arrival order);
|
|
2229
|
-
* - true → deliver the coalesced LATEST as ONE DIRTY-before-DATA wave (pin 2: the quiet absorb
|
|
2230
|
-
* suppressed the dep's original DIRTY, so the demand wave restores it before the value).
|
|
2231
|
-
* Neither branch fires when nothing changed since the last demand → the demand is SILENT.
|
|
2232
|
-
* Called by `_deliverPullDemand` only when settle-ready; the caller has released the pullId, so
|
|
2233
|
-
* `_markDirty` relays the leading DIRTY (not absorbed).
|
|
2234
|
-
*/
|
|
2235
2503
|
_firePullDemand() {
|
|
2236
|
-
|
|
2237
|
-
const buf = this._control.pauseBuffer;
|
|
2238
|
-
this._control.pauseBuffer = [];
|
|
2239
|
-
for (const wave of buf) this._down(wave);
|
|
2240
|
-
}
|
|
2241
|
-
if (this._control.pausedDepWaveOccurred) {
|
|
2242
|
-
const gated = this._slot.handle !== null && !this._wave.hasCalledFnOnce && !(this._slot.partial || this._allDepsSettled());
|
|
2243
|
-
if (this._wave.pending > 0 || gated) return;
|
|
2244
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2245
|
-
this._markDirty();
|
|
2246
|
-
this._tryRun();
|
|
2247
|
-
}
|
|
2504
|
+
nodeFirePullDemand(nodeRuntimeHost(this));
|
|
2248
2505
|
}
|
|
2249
|
-
/**
|
|
2250
|
-
* R-pull (D55/D59): fire a demand that was OWED (deferred at demand time) once the node becomes
|
|
2251
|
-
* able — called from the dep-settle arms (DATA/RESOLVED/INVALIDATE/terminal drain _pending, pin-5
|
|
2252
|
-
* + B1/F6) and from `_pauseRelease` (an external PAUSE lock releases, F4/F5).
|
|
2253
|
-
*/
|
|
2254
2506
|
_fireOwedDemandIfReady() {
|
|
2255
|
-
|
|
2256
|
-
if (this._slot.pull && this._control.demandOwed && this._canFireDemand())
|
|
2257
|
-
this._deliverPullDemand();
|
|
2507
|
+
nodeFireOwedDemandIfReady(nodeRuntimeHost(this));
|
|
2258
2508
|
}
|
|
2259
|
-
/** Should an outgoing settle slice be deferred into the pause buffer? */
|
|
2260
2509
|
_shouldBufferOnPause() {
|
|
2261
|
-
|
|
2262
|
-
if (!this._isPaused()) return false;
|
|
2263
|
-
if (this._slot.pausable === "resumeAll") return true;
|
|
2264
|
-
if (!this._wave.insideRunWave && this._isAsyncPool() && this._slot.deps.length > 0) return true;
|
|
2265
|
-
return false;
|
|
2510
|
+
return nodeShouldBufferOnPause(nodeRuntimeHost(this));
|
|
2266
2511
|
}
|
|
2267
|
-
/** R-invalidate-idempotent: clear cache + flush + cascade; no-op if nothing cached. */
|
|
2268
2512
|
_invalidate(delivery) {
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
this._value.hasData = false;
|
|
2272
|
-
this._value.status = "sentinel";
|
|
2273
|
-
this._value.replayRing = [];
|
|
2274
|
-
for (const fn of this._hooks.onInvalidate) fn();
|
|
2275
|
-
this._emitToSubs(["INVALIDATE"], delivery);
|
|
2276
|
-
}
|
|
2277
|
-
// B42 (R-deps-terminal): ALL deps TERMINAL = every dep has reached COMPLETE *or* an ABSORBED
|
|
2278
|
-
// ERROR. Block only on a LIVE dep (_depTerminal[i] === undefined); an errored dep (terminal = the
|
|
2279
|
-
// error payload, which R-data-payload guarantees is !== undefined and non-boolean) COUNTS as
|
|
2280
|
-
// terminal-done. Was
|
|
2281
|
-
// `tm !== true`, which wedged a node whose errorWhenDepsError:false dep ERRORed (it never
|
|
2282
|
-
// auto-completed even after every other dep completed). Drives the completeWhenDepsComplete cascade.
|
|
2513
|
+
nodeInvalidate(nodeRuntimeHost(this), delivery);
|
|
2514
|
+
}
|
|
2283
2515
|
_allDepsTerminal() {
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2516
|
+
return nodeAllDepsTerminal(nodeRuntimeHost(this));
|
|
2517
|
+
}
|
|
2518
|
+
_emitToSubs(msg, delivery) {
|
|
2519
|
+
nodeEmitToSubs(nodeRuntimeHost(this), msg, delivery);
|
|
2287
2520
|
}
|
|
2288
2521
|
/** R-terminal: resubscribable reset clears terminal + dep state + re-arms the gate. */
|
|
2289
2522
|
_resetLifecycle() {
|
|
2290
|
-
|
|
2291
|
-
this._dep.unsubs = [];
|
|
2292
|
-
this._dep.idxBoxes = [];
|
|
2293
|
-
this._lifecycle.subscribers.clear();
|
|
2294
|
-
this._lifecycle.activated = false;
|
|
2295
|
-
this._value.terminal = void 0;
|
|
2296
|
-
this._value.hasTorndown = false;
|
|
2297
|
-
this._wave.hasCalledFnOnce = false;
|
|
2298
|
-
this._resetDepState();
|
|
2299
|
-
this._control.pauseLockset.clear();
|
|
2300
|
-
this._control.pauseBuffer = [];
|
|
2301
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2302
|
-
this._control.demandOwed = false;
|
|
2303
|
-
this._value.replayRing = [];
|
|
2304
|
-
const isCompute = this._slot.handle !== null || this._slot.deps.length > 0;
|
|
2305
|
-
if (isCompute) {
|
|
2306
|
-
this._value.cache = SENTINEL;
|
|
2307
|
-
this._value.hasData = false;
|
|
2308
|
-
this._value.status = "sentinel";
|
|
2309
|
-
} else {
|
|
2310
|
-
this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
2311
|
-
}
|
|
2312
|
-
if (!this._privateState.persist) this._privateState.value = SENTINEL;
|
|
2313
|
-
}
|
|
2314
|
-
_emitToSubs(msg, delivery) {
|
|
2315
|
-
if (this._released) return;
|
|
2316
|
-
const subs = [...this._lifecycle.subscribers];
|
|
2317
|
-
for (const sink of subs) sink(msg, delivery);
|
|
2523
|
+
nodeResetLifecycle(nodeRuntimeHost(this));
|
|
2318
2524
|
}
|
|
2319
2525
|
/** Batch commit (R-batch-coalesce): deliver the deferred tier-3 wave now. */
|
|
2320
2526
|
__commitBatchedWave(wave) {
|
|
2321
|
-
this
|
|
2322
|
-
this._down(wave);
|
|
2527
|
+
nodeCommitBatchedWave(nodeRuntimeHost(this), wave);
|
|
2323
2528
|
}
|
|
2324
2529
|
/** Batch rollback: balance the immediate DIRTY with a RESOLVED so downstream un-dirties. */
|
|
2325
2530
|
__rollbackBatched() {
|
|
2326
|
-
|
|
2327
|
-
this._wave.batchDirtyOwed = false;
|
|
2328
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2329
|
-
this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
2330
|
-
this._emitToSubs(["RESOLVED"]);
|
|
2331
|
-
}
|
|
2531
|
+
nodeRollbackBatched(nodeRuntimeHost(this));
|
|
2332
2532
|
}
|
|
2333
2533
|
/** B49: enqueue a committed-boundary task on this node's graph-local core. */
|
|
2334
2534
|
__deferBoundary(fn, batchToken) {
|
|
2335
|
-
|
|
2336
|
-
batchToken,
|
|
2337
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
2338
|
-
});
|
|
2535
|
+
nodeDeferBoundary(nodeRuntimeHost(this), fn, batchToken);
|
|
2339
2536
|
}
|
|
2340
2537
|
};
|
|
2341
2538
|
function node(deps = [], handleOrFn = null, opts = {}) {
|
|
@@ -2478,7 +2675,10 @@ function collectionCore(backend, factory, opts = {}, restore) {
|
|
|
2478
2675
|
name: name ? `${name}.delta` : void 0
|
|
2479
2676
|
});
|
|
2480
2677
|
const pullId = /* @__PURE__ */ Symbol(name ? `${name}.snapshot` : `${factory}.snapshot`);
|
|
2678
|
+
let deliveredVersion = backend.version;
|
|
2481
2679
|
const snapFn = (ctx) => {
|
|
2680
|
+
if (ctx.pull !== void 0 && backend.version === deliveredVersion) return;
|
|
2681
|
+
deliveredVersion = backend.version;
|
|
2482
2682
|
ctx.down([["DATA", backend.snapshot()]]);
|
|
2483
2683
|
};
|
|
2484
2684
|
const snapshot = graph ? graph.node([delta], snapFn, {
|