@graphrefly/ts 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -0
- package/dist/actions-types-CSC3NMDl.d.ts +657 -0
- package/dist/actions-types-wl9Mgkmr.d.cts +657 -0
- package/dist/adapters/index.cjs +5219 -2974
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +204 -192
- package/dist/adapters/index.d.ts +204 -192
- package/dist/adapters/index.js +3685 -1833
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/nestjs/microservices.cjs +841 -0
- package/dist/adapters/nestjs/microservices.cjs.map +1 -0
- package/dist/adapters/nestjs/microservices.d.cts +45 -0
- package/dist/adapters/nestjs/microservices.d.ts +45 -0
- package/dist/adapters/nestjs/microservices.js +206 -0
- package/dist/adapters/nestjs/microservices.js.map +1 -0
- package/dist/adapters/nestjs/native.cjs +1391 -0
- package/dist/adapters/nestjs/native.cjs.map +1 -0
- package/dist/adapters/nestjs/native.d.cts +111 -0
- package/dist/adapters/nestjs/native.d.ts +111 -0
- package/dist/adapters/nestjs/native.js +577 -0
- package/dist/adapters/nestjs/native.js.map +1 -0
- package/dist/adapters/nestjs/websockets.cjs +924 -0
- package/dist/adapters/nestjs/websockets.cjs.map +1 -0
- package/dist/adapters/nestjs/websockets.d.cts +47 -0
- package/dist/adapters/nestjs/websockets.d.ts +47 -0
- package/dist/adapters/nestjs/websockets.js +286 -0
- package/dist/adapters/nestjs/websockets.js.map +1 -0
- package/dist/adapters/nestjs.cjs +1085 -0
- package/dist/adapters/nestjs.cjs.map +1 -0
- package/dist/adapters/nestjs.d.cts +385 -0
- package/dist/adapters/nestjs.d.ts +385 -0
- package/dist/adapters/nestjs.js +112 -0
- package/dist/adapters/nestjs.js.map +1 -0
- package/dist/adapters/observe-storage.d.cts +4 -4
- package/dist/adapters/observe-storage.d.ts +4 -4
- package/dist/adapters/observe-storage.js +5 -4
- package/dist/adapters/observe-storage.js.map +1 -1
- package/dist/adapters/react.cjs +166 -0
- package/dist/adapters/react.cjs.map +1 -0
- package/dist/adapters/react.d.cts +31 -0
- package/dist/adapters/react.d.ts +31 -0
- package/dist/adapters/react.js +51 -0
- package/dist/adapters/react.js.map +1 -0
- package/dist/adapters/solid.cjs +157 -0
- package/dist/adapters/solid.cjs.map +1 -0
- package/dist/adapters/solid.d.cts +26 -0
- package/dist/adapters/solid.d.ts +26 -0
- package/dist/adapters/solid.js +48 -0
- package/dist/adapters/solid.js.map +1 -0
- package/dist/adapters/svelte.cjs +148 -0
- package/dist/adapters/svelte.cjs.map +1 -0
- package/dist/adapters/svelte.d.cts +31 -0
- package/dist/adapters/svelte.d.ts +31 -0
- package/dist/adapters/svelte.js +46 -0
- package/dist/adapters/svelte.js.map +1 -0
- package/dist/adapters/vue.cjs +155 -0
- package/dist/adapters/vue.cjs.map +1 -0
- package/dist/adapters/vue.d.cts +26 -0
- package/dist/adapters/vue.d.ts +26 -0
- package/dist/adapters/vue.js +46 -0
- package/dist/adapters/vue.js.map +1 -0
- package/dist/agent-runtime-types-core-CaXfKNtY.d.cts +406 -0
- package/dist/agent-runtime-types-core-hU299uIC.d.ts +406 -0
- package/dist/agent-runtime-types-tool-BEpSINol.d.ts +695 -0
- package/dist/agent-runtime-types-tool-DninPEzk.d.cts +695 -0
- package/dist/agentic-memory-retention-BmGX368S.d.ts +14 -0
- package/dist/agentic-memory-retention-Ih1qhX9Z.d.cts +14 -0
- package/dist/agentic-memory-types-CVSUS6XR.d.ts +473 -0
- package/dist/agentic-memory-types-FnnYlVUs.d.cts +473 -0
- package/dist/capability-admission-BW2CziT6.d.ts +102 -0
- package/dist/capability-admission-lwSecxXs.d.cts +102 -0
- package/dist/chunk-2KUAG2GZ.js +9693 -0
- package/dist/chunk-2KUAG2GZ.js.map +1 -0
- package/dist/chunk-2NJP6GO4.js +1320 -0
- package/dist/chunk-2NJP6GO4.js.map +1 -0
- package/dist/{chunk-GDL26N2T.js → chunk-3KN7NJDR.js} +2 -2
- package/dist/{chunk-COHO25CZ.js → chunk-4NWSNI4K.js} +2232 -1672
- package/dist/chunk-4NWSNI4K.js.map +1 -0
- package/dist/{chunk-Z2ANQ6JW.js → chunk-4Q77MMJY.js} +2 -2
- package/dist/chunk-6E76H4OU.js +132 -0
- package/dist/chunk-6E76H4OU.js.map +1 -0
- package/dist/chunk-7GOTIIQ7.js +819 -0
- package/dist/chunk-7GOTIIQ7.js.map +1 -0
- package/dist/{chunk-D6BG7U6A.js → chunk-7HZRJMN6.js} +3 -3
- package/dist/{chunk-SCRFRCGR.js → chunk-BSQGE5PS.js} +1 -1
- package/dist/{chunk-PKVBHGBM.js → chunk-CJIFGJQG.js} +7 -7
- package/dist/{chunk-G4M3NHRJ.js → chunk-CX6B6PO2.js} +93 -10
- package/dist/chunk-CX6B6PO2.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/{chunk-JIMUDQN3.js → chunk-E4QCH32M.js} +449 -447
- package/dist/chunk-E4QCH32M.js.map +1 -0
- package/dist/{chunk-RIIOUTGM.js → chunk-ECURQ3HD.js} +19 -129
- package/dist/chunk-ECURQ3HD.js.map +1 -0
- package/dist/{chunk-2ILL7HQI.js → chunk-EOKT4QFF.js} +134 -128
- package/dist/chunk-EOKT4QFF.js.map +1 -0
- package/dist/{chunk-K3FXTC3I.js → chunk-HJACH5PU.js} +3 -3
- package/dist/{chunk-GTPCOEOZ.js → chunk-IDMLXLLG.js} +3 -3
- package/dist/{chunk-DKP56CSW.js → chunk-JKAYLDQV.js} +2 -2
- package/dist/{chunk-4VLAQHZI.js → chunk-K7FB3JTD.js} +17 -1
- package/dist/chunk-K7FB3JTD.js.map +1 -0
- package/dist/chunk-L6LDXRWE.js +219 -0
- package/dist/chunk-L6LDXRWE.js.map +1 -0
- package/dist/chunk-M7J6Z4IJ.js +1930 -0
- package/dist/chunk-M7J6Z4IJ.js.map +1 -0
- package/dist/chunk-MQEQMS7B.js +1009 -0
- package/dist/chunk-MQEQMS7B.js.map +1 -0
- package/dist/chunk-MTELVIYR.js +1421 -0
- package/dist/chunk-MTELVIYR.js.map +1 -0
- package/dist/chunk-PVC7WDKI.js +885 -0
- package/dist/chunk-PVC7WDKI.js.map +1 -0
- package/dist/chunk-RAHNUYA5.js +368 -0
- package/dist/chunk-RAHNUYA5.js.map +1 -0
- package/dist/{chunk-DK554R7P.js → chunk-S6HXABGL.js} +2 -1
- package/dist/chunk-S6HXABGL.js.map +1 -0
- package/dist/{chunk-I3IHOHCJ.js → chunk-SHZDP2MQ.js} +1181 -1001
- package/dist/chunk-SHZDP2MQ.js.map +1 -0
- package/dist/{chunk-Y3ZLRGHC.js → chunk-SIDJO2T4.js} +16 -16
- package/dist/chunk-STXRMPW4.js +4131 -0
- package/dist/chunk-STXRMPW4.js.map +1 -0
- package/dist/{chunk-JR4IKCR2.js → chunk-TPND5MJS.js} +5 -5
- package/dist/chunk-TQPCAIQI.js +612 -0
- package/dist/chunk-TQPCAIQI.js.map +1 -0
- package/dist/chunk-UT3MHJCW.js +49 -0
- package/dist/chunk-UT3MHJCW.js.map +1 -0
- package/dist/{chunk-TEW47IVR.js → chunk-VPEFSDME.js} +2 -2
- package/dist/{chunk-SWTLEQL6.js → chunk-WQIA3GFB.js} +2 -2
- package/dist/chunk-WQIA3GFB.js.map +1 -0
- package/dist/{chunk-DJC4CHLQ.js → chunk-YDWBXXQZ.js} +5 -5
- package/dist/{chunk-6PHB5CJS.js → chunk-ZLFRB6FI.js} +2 -2
- package/dist/composition/index.cjs +1256 -1059
- package/dist/composition/index.cjs.map +1 -1
- package/dist/composition/index.d.cts +4 -4
- package/dist/composition/index.d.ts +4 -4
- package/dist/composition/index.js +7 -6
- package/dist/core/index.cjs +1218 -1021
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +5 -4
- package/dist/cqrs/index.cjs.map +1 -1
- package/dist/cqrs/index.d.cts +4 -4
- package/dist/cqrs/index.d.ts +4 -4
- package/dist/cqrs/index.js +3 -2
- package/dist/cqrs/index.js.map +1 -1
- package/dist/cqrs/messaging.cjs +312 -0
- package/dist/cqrs/messaging.cjs.map +1 -0
- package/dist/cqrs/messaging.d.cts +57 -0
- package/dist/cqrs/messaging.d.ts +57 -0
- package/dist/cqrs/messaging.js +274 -0
- package/dist/cqrs/messaging.js.map +1 -0
- package/dist/cqrs/work-queue.cjs +329 -0
- package/dist/cqrs/work-queue.cjs.map +1 -0
- package/dist/cqrs/work-queue.d.cts +90 -0
- package/dist/cqrs/work-queue.d.ts +90 -0
- package/dist/cqrs/work-queue.js +292 -0
- package/dist/cqrs/work-queue.js.map +1 -0
- package/dist/data/index.cjs +19 -0
- package/dist/data/index.cjs.map +1 -0
- package/dist/data/index.d.cts +36 -0
- package/dist/data/index.d.ts +36 -0
- package/dist/data/index.js +1 -0
- package/dist/data/index.js.map +1 -0
- package/dist/data-structures/index.cjs +1252 -1052
- package/dist/data-structures/index.cjs.map +1 -1
- package/dist/data-structures/index.d.cts +9 -8
- package/dist/data-structures/index.d.ts +9 -8
- package/dist/data-structures/index.js +9 -7
- package/dist/{describe-BZb7AS2y.d.ts → describe-B_A5fbXH.d.ts} +1 -1
- package/dist/{describe-Ciu8SUnN.d.cts → describe-CQRrkv-Q.d.cts} +1 -1
- package/dist/executors/tool-provider-adapters.cjs +3091 -0
- package/dist/executors/tool-provider-adapters.cjs.map +1 -0
- package/dist/executors/tool-provider-adapters.d.cts +174 -0
- package/dist/executors/tool-provider-adapters.d.ts +174 -0
- package/dist/executors/tool-provider-adapters.js +1336 -0
- package/dist/executors/tool-provider-adapters.js.map +1 -0
- package/dist/executors/tool-provider-runtime.cjs +5178 -0
- package/dist/executors/tool-provider-runtime.cjs.map +1 -0
- package/dist/executors/tool-provider-runtime.d.cts +17 -0
- package/dist/executors/tool-provider-runtime.d.ts +17 -0
- package/dist/executors/tool-provider-runtime.js +15 -0
- package/dist/executors/tool-provider-runtime.js.map +1 -0
- package/dist/executors/tool-provider.cjs +6392 -0
- package/dist/executors/tool-provider.cjs.map +1 -0
- package/dist/executors/tool-provider.d.cts +60 -0
- package/dist/executors/tool-provider.d.ts +60 -0
- package/dist/executors/tool-provider.js +89 -0
- package/dist/executors/tool-provider.js.map +1 -0
- package/dist/executors/work-queue.cjs +342 -0
- package/dist/executors/work-queue.cjs.map +1 -0
- package/dist/executors/work-queue.d.cts +90 -0
- package/dist/executors/work-queue.d.ts +90 -0
- package/dist/executors/work-queue.js +306 -0
- package/dist/executors/work-queue.js.map +1 -0
- package/dist/graph/index.cjs +1536 -1324
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +10 -9
- package/dist/graph/index.d.ts +10 -9
- package/dist/graph/index.js +22 -20
- package/dist/{graph-s23RbbFO.d.cts → graph-CWK3HLPB.d.cts} +134 -132
- package/dist/{graph-DfdF9zy4.d.ts → graph-ho5sotHP.d.ts} +134 -132
- package/dist/{index-SnzZu3x7.d.ts → index-CQWcE0Dw.d.ts} +18 -4
- package/dist/{index-CAEmLCYF.d.cts → index-DHA1i67c.d.cts} +18 -4
- package/dist/index.cjs +3331 -3020
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -10
- package/dist/index.d.ts +14 -10
- package/dist/index.js +114 -108
- package/dist/inspection/boundary.cjs +98 -0
- package/dist/inspection/boundary.cjs.map +1 -0
- package/dist/inspection/boundary.d.cts +61 -0
- package/dist/inspection/boundary.d.ts +61 -0
- package/dist/inspection/boundary.js +75 -0
- package/dist/inspection/boundary.js.map +1 -0
- package/dist/measurements-C0mAvWU1.d.cts +164 -0
- package/dist/measurements-OMpCeBwh.d.ts +164 -0
- package/dist/{messages-BZqrGGm1.d.ts → messages-CAzUPPJM.d.cts} +10 -5
- package/dist/{messages-BZqrGGm1.d.cts → messages-CAzUPPJM.d.ts} +10 -5
- package/dist/messaging/index.cjs +756 -619
- package/dist/messaging/index.cjs.map +1 -1
- package/dist/messaging/index.d.cts +17 -226
- package/dist/messaging/index.d.ts +17 -226
- package/dist/messaging/index.js +19 -749
- package/dist/messaging/index.js.map +1 -1
- package/dist/operators/index.cjs +1256 -1059
- package/dist/operators/index.cjs.map +1 -1
- package/dist/operators/index.d.cts +6 -6
- package/dist/operators/index.d.ts +6 -6
- package/dist/operators/index.js +9 -8
- package/dist/orchestration/index.cjs +8664 -2617
- package/dist/orchestration/index.cjs.map +1 -1
- package/dist/orchestration/index.d.cts +171 -221
- package/dist/orchestration/index.d.ts +171 -221
- package/dist/orchestration/index.js +74 -982
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/messaging.cjs +314 -0
- package/dist/orchestration/messaging.cjs.map +1 -0
- package/dist/orchestration/messaging.d.cts +56 -0
- package/dist/orchestration/messaging.d.ts +56 -0
- package/dist/orchestration/messaging.js +276 -0
- package/dist/orchestration/messaging.js.map +1 -0
- package/dist/orchestration/work-queue.cjs +1500 -0
- package/dist/orchestration/work-queue.cjs.map +1 -0
- package/dist/orchestration/work-queue.d.cts +196 -0
- package/dist/orchestration/work-queue.d.ts +196 -0
- package/dist/orchestration/work-queue.js +1289 -0
- package/dist/orchestration/work-queue.js.map +1 -0
- package/dist/patterns/event-flow.cjs +433 -0
- package/dist/patterns/event-flow.cjs.map +1 -0
- package/dist/patterns/event-flow.d.cts +115 -0
- package/dist/patterns/event-flow.d.ts +115 -0
- package/dist/patterns/event-flow.js +14 -0
- package/dist/patterns/event-flow.js.map +1 -0
- package/dist/patterns/index.cjs +748 -355
- package/dist/patterns/index.cjs.map +1 -1
- package/dist/patterns/index.d.cts +9 -5
- package/dist/patterns/index.d.ts +9 -5
- package/dist/patterns/index.js +13 -4
- package/dist/process-types-C9uMYz3i.d.ts +200 -0
- package/dist/process-types-h3uRlzDc.d.cts +200 -0
- package/dist/{reactive-collection-BxBqtIOE.d.cts → reactive-collection-B9R0Bl1P.d.cts} +11 -41
- package/dist/{reactive-collection-Cb1II1Fi.d.ts → reactive-collection-BXFrH0U2.d.ts} +11 -41
- package/dist/{reactive-collection-storage-D-KmjE0J.d.cts → reactive-collection-storage-BLGv8Xp8.d.cts} +5 -5
- package/dist/{reactive-collection-storage-BNiEc-Gd.d.ts → reactive-collection-storage-a4zD3665.d.ts} +5 -5
- package/dist/{reactive-map-BcB4KsQR.d.ts → reactive-map-C_8sOfdS.d.cts} +7 -6
- package/dist/{reactive-map-D-g3dv8I.d.cts → reactive-map-jle5dnok.d.ts} +7 -6
- package/dist/render/index.d.cts +3 -3
- package/dist/render/index.d.ts +3 -3
- package/dist/render/index.js +1 -0
- package/dist/scheduled-readiness-5rwQlyjV.d.ts +91 -0
- package/dist/scheduled-readiness-DpRY8jI0.d.cts +91 -0
- package/dist/semantic-memory-graph-C2ZUwIlq.d.ts +30 -0
- package/dist/semantic-memory-graph-DlZBD_Eu.d.cts +30 -0
- package/dist/{semantic-memory-graph-BYoIlP35.d.cts → semantic-memory-graph-types-BvzdqmkY.d.cts} +2 -28
- package/dist/{semantic-memory-graph-CxyXLms3.d.ts → semantic-memory-graph-types-Ci-OtahO.d.ts} +2 -28
- package/dist/solutions/index.cjs +6788 -2128
- package/dist/solutions/index.cjs.map +1 -1
- package/dist/solutions/index.d.cts +15 -519
- package/dist/solutions/index.d.ts +15 -519
- package/dist/solutions/index.js +91 -7
- package/dist/solutions/reactive-layout/browser/index.cjs +457 -0
- package/dist/solutions/reactive-layout/browser/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/browser/index.d.cts +44 -0
- package/dist/solutions/reactive-layout/browser/index.d.ts +44 -0
- package/dist/solutions/reactive-layout/browser/index.js +69 -0
- package/dist/solutions/reactive-layout/browser/index.js.map +1 -0
- package/dist/solutions/reactive-layout/index.cjs +4494 -0
- package/dist/solutions/reactive-layout/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/index.d.cts +37 -0
- package/dist/solutions/reactive-layout/index.d.ts +37 -0
- package/dist/solutions/reactive-layout/index.js +146 -0
- package/dist/solutions/reactive-layout/index.js.map +1 -0
- package/dist/solutions/reactive-layout/node-canvas/index.cjs +555 -0
- package/dist/solutions/reactive-layout/node-canvas/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/node-canvas/index.d.cts +54 -0
- package/dist/solutions/reactive-layout/node-canvas/index.d.ts +54 -0
- package/dist/solutions/reactive-layout/node-canvas/index.js +131 -0
- package/dist/solutions/reactive-layout/node-canvas/index.js.map +1 -0
- package/dist/solutions/reactive-layout/react-native/index.cjs +504 -0
- package/dist/solutions/reactive-layout/react-native/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/react-native/index.d.cts +51 -0
- package/dist/solutions/reactive-layout/react-native/index.d.ts +51 -0
- package/dist/solutions/reactive-layout/react-native/index.js +77 -0
- package/dist/solutions/reactive-layout/react-native/index.js.map +1 -0
- package/dist/solutions/reactive-layout/skia/index.cjs +557 -0
- package/dist/solutions/reactive-layout/skia/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/skia/index.d.cts +64 -0
- package/dist/solutions/reactive-layout/skia/index.d.ts +64 -0
- package/dist/solutions/reactive-layout/skia/index.js +70 -0
- package/dist/solutions/reactive-layout/skia/index.js.map +1 -0
- package/dist/solutions/work-item/actions.cjs +2345 -0
- package/dist/solutions/work-item/actions.cjs.map +1 -0
- package/dist/solutions/work-item/actions.d.cts +40 -0
- package/dist/solutions/work-item/actions.d.ts +40 -0
- package/dist/solutions/work-item/actions.js +2078 -0
- package/dist/solutions/work-item/actions.js.map +1 -0
- package/dist/solutions/work-item/scheduling.cjs +9797 -0
- package/dist/solutions/work-item/scheduling.cjs.map +1 -0
- package/dist/solutions/work-item/scheduling.d.cts +1868 -0
- package/dist/solutions/work-item/scheduling.d.ts +1868 -0
- package/dist/solutions/work-item/scheduling.js +146 -0
- package/dist/solutions/work-item/scheduling.js.map +1 -0
- package/dist/solutions/work-item/work-queue.cjs +306 -0
- package/dist/solutions/work-item/work-queue.cjs.map +1 -0
- package/dist/solutions/work-item/work-queue.d.cts +71 -0
- package/dist/solutions/work-item/work-queue.d.ts +71 -0
- package/dist/solutions/work-item/work-queue.js +270 -0
- package/dist/solutions/work-item/work-queue.js.map +1 -0
- package/dist/sources/browser.cjs +1399 -1052
- package/dist/sources/browser.cjs.map +1 -1
- package/dist/sources/browser.d.cts +33 -6
- package/dist/sources/browser.d.ts +33 -6
- package/dist/sources/browser.js +73 -6
- package/dist/sources/browser.js.map +1 -1
- package/dist/sources/index.cjs +1345 -1065
- package/dist/sources/index.cjs.map +1 -1
- package/dist/sources/index.d.cts +5 -5
- package/dist/sources/index.d.ts +5 -5
- package/dist/sources/index.js +7 -6
- package/dist/sources/node.cjs.map +1 -1
- package/dist/sources/node.d.cts +4 -4
- package/dist/sources/node.d.ts +4 -4
- package/dist/sources/node.js +2 -1
- package/dist/sources/node.js.map +1 -1
- package/dist/storage/browser.cjs +16 -0
- package/dist/storage/browser.cjs.map +1 -1
- package/dist/storage/browser.js +4 -3
- package/dist/storage/browser.js.map +1 -1
- package/dist/storage/index.cjs +16 -0
- package/dist/storage/index.cjs.map +1 -1
- package/dist/storage/index.d.cts +6 -5
- package/dist/storage/index.d.ts +6 -5
- package/dist/storage/index.js +10 -9
- package/dist/storage/node.cjs +16 -0
- package/dist/storage/node.cjs.map +1 -1
- package/dist/storage/node.js +4 -3
- package/dist/storage/node.js.map +1 -1
- package/dist/store-BmtEs9mG.d.ts +123 -0
- package/dist/store-PAAsYvML.d.cts +123 -0
- package/dist/testing/index.cjs +1 -0
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +3 -2
- package/dist/types-BRNKoFHj.d.ts +357 -0
- package/dist/{types-h12mNYbq.d.ts → types-BS6CyR-x.d.cts} +49 -130
- package/dist/types-BWK2ay3e.d.cts +457 -0
- package/dist/types-BXKSAoE1.d.cts +357 -0
- package/dist/types-BaPpZItj.d.ts +457 -0
- package/dist/types-BhveCMg5.d.cts +274 -0
- package/dist/{types-bNMSWKqF.d.cts → types-C9NOgNJw.d.ts} +49 -130
- package/dist/types-CTsQ8Ww4.d.ts +274 -0
- package/dist/types-DL_05n2M.d.ts +34 -0
- package/dist/types-XDoqxYO9.d.cts +34 -0
- package/dist/work-item-runtime-types-BqtWnSCS.d.ts +138 -0
- package/dist/work-item-runtime-types-CHO03AKh.d.cts +138 -0
- package/dist/work-queue/index.cjs +1136 -0
- package/dist/work-queue/index.cjs.map +1 -0
- package/dist/work-queue/index.d.cts +21 -0
- package/dist/work-queue/index.d.ts +21 -0
- package/dist/work-queue/index.js +1082 -0
- package/dist/work-queue/index.js.map +1 -0
- package/package.json +603 -249
- package/dist/chunk-2ILL7HQI.js.map +0 -1
- package/dist/chunk-4VLAQHZI.js.map +0 -1
- package/dist/chunk-COHO25CZ.js.map +0 -1
- package/dist/chunk-DK554R7P.js.map +0 -1
- package/dist/chunk-G4M3NHRJ.js.map +0 -1
- package/dist/chunk-I3IHOHCJ.js.map +0 -1
- package/dist/chunk-JIMUDQN3.js.map +0 -1
- package/dist/chunk-RIIOUTGM.js.map +0 -1
- package/dist/chunk-SWTLEQL6.js.map +0 -1
- /package/dist/{chunk-GDL26N2T.js.map → chunk-3KN7NJDR.js.map} +0 -0
- /package/dist/{chunk-Z2ANQ6JW.js.map → chunk-4Q77MMJY.js.map} +0 -0
- /package/dist/{chunk-D6BG7U6A.js.map → chunk-7HZRJMN6.js.map} +0 -0
- /package/dist/{chunk-SCRFRCGR.js.map → chunk-BSQGE5PS.js.map} +0 -0
- /package/dist/{chunk-PKVBHGBM.js.map → chunk-CJIFGJQG.js.map} +0 -0
- /package/dist/{chunk-K3FXTC3I.js.map → chunk-HJACH5PU.js.map} +0 -0
- /package/dist/{chunk-GTPCOEOZ.js.map → chunk-IDMLXLLG.js.map} +0 -0
- /package/dist/{chunk-DKP56CSW.js.map → chunk-JKAYLDQV.js.map} +0 -0
- /package/dist/{chunk-Y3ZLRGHC.js.map → chunk-SIDJO2T4.js.map} +0 -0
- /package/dist/{chunk-JR4IKCR2.js.map → chunk-TPND5MJS.js.map} +0 -0
- /package/dist/{chunk-TEW47IVR.js.map → chunk-VPEFSDME.js.map} +0 -0
- /package/dist/{chunk-DJC4CHLQ.js.map → chunk-YDWBXXQZ.js.map} +0 -0
- /package/dist/{chunk-6PHB5CJS.js.map → chunk-ZLFRB6FI.js.map} +0 -0
package/dist/core/index.cjs
CHANGED
|
@@ -210,6 +210,7 @@ var TIER = {
|
|
|
210
210
|
START: TIER_START,
|
|
211
211
|
PAUSE: TIER_CONTROL,
|
|
212
212
|
RESUME: TIER_CONTROL,
|
|
213
|
+
PULL: TIER_CONTROL,
|
|
213
214
|
DIRTY: TIER_NOTIFICATION,
|
|
214
215
|
DATA: TIER_VALUE,
|
|
215
216
|
RESOLVED: TIER_VALUE,
|
|
@@ -580,6 +581,562 @@ function makeDepBookkeeping(depCount2) {
|
|
|
580
581
|
};
|
|
581
582
|
}
|
|
582
583
|
|
|
584
|
+
// src/node/protocol-guards.ts
|
|
585
|
+
function terminalView(t) {
|
|
586
|
+
return t === void 0 ? false : t;
|
|
587
|
+
}
|
|
588
|
+
function normalizePullDemand(demand) {
|
|
589
|
+
if (typeof demand !== "object" || demand === null || Array.isArray(demand)) {
|
|
590
|
+
throw new Error("ctx.up: PULL requires { pullId, params? } demand payload (D269)");
|
|
591
|
+
}
|
|
592
|
+
const pullId = demand.pullId;
|
|
593
|
+
if (typeof pullId !== "string" && typeof pullId !== "symbol") {
|
|
594
|
+
throw new Error("ctx.up: PULL demand requires a string or symbol pullId (D269)");
|
|
595
|
+
}
|
|
596
|
+
const params = demand.params;
|
|
597
|
+
return params === void 0 ? { pullId } : { pullId, params };
|
|
598
|
+
}
|
|
599
|
+
function validateDownPayloads(msgs) {
|
|
600
|
+
for (const m of msgs) {
|
|
601
|
+
if (m[0] === "DATA" && m[1] === void 0) {
|
|
602
|
+
throw new Error("down: DATA requires a non-SENTINEL payload (R-data-payload)");
|
|
603
|
+
}
|
|
604
|
+
if (m[0] === "ERROR" && isInvalidErrorPayload(m[1])) {
|
|
605
|
+
throw new Error("down: ERROR requires a non-SENTINEL, non-boolean payload (R-data-payload)");
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// src/node/runtime-accessors.ts
|
|
611
|
+
var constructingCore;
|
|
612
|
+
var constructingEnvironment;
|
|
613
|
+
var ownerTokens = /* @__PURE__ */ new WeakMap();
|
|
614
|
+
var topologyDepsChangedObservers = /* @__PURE__ */ new WeakMap();
|
|
615
|
+
var checkpointReaders = /* @__PURE__ */ new WeakMap();
|
|
616
|
+
var restoreWriters = /* @__PURE__ */ new WeakMap();
|
|
617
|
+
var runtimeReleasers = /* @__PURE__ */ new WeakMap();
|
|
618
|
+
var runtimeQuiescenceReaders = /* @__PURE__ */ new WeakMap();
|
|
619
|
+
var subscriberCountReaders = /* @__PURE__ */ new WeakMap();
|
|
620
|
+
var activationReaders = /* @__PURE__ */ new WeakMap();
|
|
621
|
+
var releasedNodes = /* @__PURE__ */ new WeakSet();
|
|
622
|
+
function withNodeCore(core, create) {
|
|
623
|
+
const prev = constructingCore;
|
|
624
|
+
constructingCore = core;
|
|
625
|
+
try {
|
|
626
|
+
return create();
|
|
627
|
+
} finally {
|
|
628
|
+
constructingCore = prev;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function takeConstructingNodeCore() {
|
|
632
|
+
const core = constructingCore;
|
|
633
|
+
constructingCore = void 0;
|
|
634
|
+
return core;
|
|
635
|
+
}
|
|
636
|
+
function withEnvironmentDrivers(environment, create) {
|
|
637
|
+
const prev = constructingEnvironment;
|
|
638
|
+
constructingEnvironment = environment;
|
|
639
|
+
try {
|
|
640
|
+
return create();
|
|
641
|
+
} finally {
|
|
642
|
+
constructingEnvironment = prev;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function takeConstructingEnvironmentDrivers() {
|
|
646
|
+
const environment = constructingEnvironment;
|
|
647
|
+
constructingEnvironment = void 0;
|
|
648
|
+
return environment;
|
|
649
|
+
}
|
|
650
|
+
function getNodeOwner(n) {
|
|
651
|
+
return ownerTokens.get(n);
|
|
652
|
+
}
|
|
653
|
+
function notifyTopologyDepsChanged(node2, prevDeps, deps) {
|
|
654
|
+
topologyDepsChangedObservers.get(node2)?.(node2, prevDeps, deps);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// src/node/node-context-runtime.ts
|
|
658
|
+
function nodeBuildCtx(self) {
|
|
659
|
+
const kind = self._slot.handle ? self._slot.dispatcher.poolKind(self._slot.handle.poolId) : "sync";
|
|
660
|
+
if (kind === "sync") {
|
|
661
|
+
if (self._syncCtx === null) self._syncCtx = self._makeCtx();
|
|
662
|
+
self._refreshCtx(self._syncCtx);
|
|
663
|
+
return self._syncCtx;
|
|
664
|
+
}
|
|
665
|
+
return self._makeCtx({
|
|
666
|
+
waveData: self._dep.waveData.map((waves) => waves.map((w) => [...w])),
|
|
667
|
+
terminal: self._dep.terminalInput.map(terminalView),
|
|
668
|
+
latest: [...self._dep.prev]
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
function nodeMakeCtx(self, snapshot) {
|
|
672
|
+
const ctx = {
|
|
673
|
+
// Wave-owner boundary (D47): a SYNC fn's emit nests under the public entry that drove
|
|
674
|
+
// it (cheap inc/dec, no early drain); an ASYNC-pool fn re-enters here from its stashed
|
|
675
|
+
// ctx at depth 0, so this is the boundary that drains any rewireNext it issued.
|
|
676
|
+
up: (msgs, towardDep) => {
|
|
677
|
+
if (self._released) return;
|
|
678
|
+
enterWave();
|
|
679
|
+
try {
|
|
680
|
+
self._up(msgs, towardDep);
|
|
681
|
+
} finally {
|
|
682
|
+
exitWave();
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
down: (msgs) => {
|
|
686
|
+
if (self._released) return;
|
|
687
|
+
enterWave();
|
|
688
|
+
try {
|
|
689
|
+
self._down(msgs);
|
|
690
|
+
} finally {
|
|
691
|
+
exitWave();
|
|
692
|
+
}
|
|
693
|
+
},
|
|
694
|
+
waveData: snapshot?.waveData ?? self._dep.waveData,
|
|
695
|
+
terminal: snapshot?.terminal ?? self._dep.terminalInput.map(terminalView),
|
|
696
|
+
state: self._makeState(),
|
|
697
|
+
onDeactivation: (fn) => {
|
|
698
|
+
if (self._released) return;
|
|
699
|
+
self._hooks.onDeactivation.push(fn);
|
|
700
|
+
},
|
|
701
|
+
onInvalidate: (fn) => {
|
|
702
|
+
if (self._released) return;
|
|
703
|
+
self._hooks.onInvalidate.push(fn);
|
|
704
|
+
},
|
|
705
|
+
environment: () => self._slot.environment,
|
|
706
|
+
// R-rewire-deferred (D47): defer a self-dep-set mutation to the committed boundary.
|
|
707
|
+
rewireNext: {
|
|
708
|
+
subscribeDep: (dep, fn) => self._requestRewireNext({ kind: "add", dep, fn }),
|
|
709
|
+
unsubscribeDep: (dep, fn) => self._requestRewireNext({ kind: "remove", dep, fn }),
|
|
710
|
+
replaceDeps: (deps, fn) => self._requestRewireNext({ kind: "set", deps, fn })
|
|
711
|
+
},
|
|
712
|
+
// R-up-routing / R-pull (D269): deferred up — route a control/demand wave (e.g. PULL)
|
|
713
|
+
// up the declared cone at the committed boundary. The SELF-demand path: an
|
|
714
|
+
// immediate ctx.up whose delivery loops back re-enters this fn (D37 / R-reentrancy).
|
|
715
|
+
upNext: (msgs, towardDep) => self._requestUpNext(msgs, towardDep),
|
|
716
|
+
...self._control.activePull === void 0 ? {} : { pull: self._control.activePull },
|
|
717
|
+
[CTX_DEP_CACHE]: { latest: snapshot?.latest ?? self._dep.prev },
|
|
718
|
+
[CTX_NODE_BINDING]: {
|
|
719
|
+
dispatcher: self._slot.dispatcher,
|
|
720
|
+
create: (factory) => withEnvironmentDrivers(self._slot.environment, () => withNodeCore(self._core, factory))
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
if (self._slot.dynamic) {
|
|
724
|
+
ctx.track = (i) => ctx[CTX_DEP_CACHE]?.latest[i];
|
|
725
|
+
}
|
|
726
|
+
return ctx;
|
|
727
|
+
}
|
|
728
|
+
function nodeRefreshCtx(self, ctx) {
|
|
729
|
+
ctx.waveData = self._dep.waveData;
|
|
730
|
+
ctx.terminal = self._dep.terminalInput.map(terminalView);
|
|
731
|
+
if (self._control.activePull === void 0) {
|
|
732
|
+
delete ctx.pull;
|
|
733
|
+
} else {
|
|
734
|
+
ctx.pull = self._control.activePull;
|
|
735
|
+
}
|
|
736
|
+
ctx[CTX_DEP_CACHE] = { latest: self._dep.prev };
|
|
737
|
+
}
|
|
738
|
+
function nodeMakeState(self) {
|
|
739
|
+
return {
|
|
740
|
+
get: () => self._privateState.value,
|
|
741
|
+
set: (v) => {
|
|
742
|
+
self._privateState.value = v;
|
|
743
|
+
},
|
|
744
|
+
persist: (on = true) => {
|
|
745
|
+
self._privateState.persist = on;
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// src/node/node-input-runtime.ts
|
|
751
|
+
function nodeRecordDepProjection(self, idx, delivery) {
|
|
752
|
+
const token = delivery?.wave ?? {};
|
|
753
|
+
if (self._dep.waveTokens[idx] !== token) {
|
|
754
|
+
self._dep.waveData[idx].push([]);
|
|
755
|
+
self._dep.waveTokens[idx] = token;
|
|
756
|
+
}
|
|
757
|
+
return self._dep.waveData[idx][self._dep.waveData[idx].length - 1];
|
|
758
|
+
}
|
|
759
|
+
function nodeDepProjectionHasData(self, idx) {
|
|
760
|
+
const projection = self._dep.waveData[idx][self._dep.waveData[idx].length - 1];
|
|
761
|
+
return projection?.some((v) => v !== SENTINEL) ?? false;
|
|
762
|
+
}
|
|
763
|
+
function nodeReceiveFromDep(self, idx, msg, delivery) {
|
|
764
|
+
if (self._released) return;
|
|
765
|
+
const t = msg[0];
|
|
766
|
+
if (t === "START") return;
|
|
767
|
+
const isLastInDeliveredWave = delivery?.last ?? true;
|
|
768
|
+
if (self._value.terminal !== void 0) {
|
|
769
|
+
if (t === "TEARDOWN") self._down([["TEARDOWN"]]);
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
if (t === "INVALIDATE") {
|
|
773
|
+
const projection = self._recordDepProjection(idx, delivery);
|
|
774
|
+
projection.push(SENTINEL);
|
|
775
|
+
if (projection.some((v) => v !== SENTINEL) && isLastInDeliveredWave) self._maybeRun();
|
|
776
|
+
self._dep.prev[idx] = SENTINEL;
|
|
777
|
+
self._dep.hasData[idx] = false;
|
|
778
|
+
self._dep.batch[idx] = null;
|
|
779
|
+
if (self._dep.dirty[idx]) {
|
|
780
|
+
self._dep.dirty[idx] = false;
|
|
781
|
+
self._wave.pending--;
|
|
782
|
+
}
|
|
783
|
+
if (self._control.pausedDepWaveOccurred && self._dep.batch.every((b) => b === null)) {
|
|
784
|
+
self._control.pausedDepWaveOccurred = false;
|
|
785
|
+
}
|
|
786
|
+
const hadData = self._value.hasData;
|
|
787
|
+
self._invalidate();
|
|
788
|
+
if (self._wave.pending === 0 && self._wave.emittedDirtyThisWave) {
|
|
789
|
+
if (!hadData) self._down([["RESOLVED"]]);
|
|
790
|
+
else self._wave.emittedDirtyThisWave = false;
|
|
791
|
+
}
|
|
792
|
+
self._fireOwedDemandIfReady();
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
if (isTerminal(t)) {
|
|
796
|
+
const isError = t === "ERROR";
|
|
797
|
+
const errPayload = isError ? msg[1] : void 0;
|
|
798
|
+
self._dep.terminal[idx] = isError ? errPayload : true;
|
|
799
|
+
self._dep.terminalInput[idx] = isError ? errPayload : true;
|
|
800
|
+
self._releaseDepDirty(idx);
|
|
801
|
+
const ranValueBeforeTerminal = self._depProjectionHasData(idx) && isLastInDeliveredWave;
|
|
802
|
+
if (ranValueBeforeTerminal) self._maybeRun();
|
|
803
|
+
if (isError && self._slot.errorWhenDepsError) {
|
|
804
|
+
self._down([["ERROR", errPayload]]);
|
|
805
|
+
} else if (self._slot.terminalAsRealInput) {
|
|
806
|
+
if (ranValueBeforeTerminal) {
|
|
807
|
+
self._fireOwedDemandIfReady();
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
self._maybeRun();
|
|
811
|
+
} else if (self._slot.completeWhenDepsComplete && self._allDepsTerminal()) {
|
|
812
|
+
self._down([["COMPLETE"]]);
|
|
813
|
+
} else {
|
|
814
|
+
self._settleAfterAbsorbedTerminal();
|
|
815
|
+
}
|
|
816
|
+
self._fireOwedDemandIfReady();
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
if (t === "TEARDOWN") {
|
|
820
|
+
self._down([["TEARDOWN"]]);
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
if (t === "DIRTY") {
|
|
824
|
+
if (!self._dep.dirty[idx]) {
|
|
825
|
+
self._dep.dirty[idx] = true;
|
|
826
|
+
self._wave.pending++;
|
|
827
|
+
self._dep.tier[idx] = 2;
|
|
828
|
+
self._markDirty();
|
|
829
|
+
}
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
if (t === "DATA") {
|
|
833
|
+
const v = msg[1];
|
|
834
|
+
self._recordDepProjection(idx, delivery).push(v);
|
|
835
|
+
const b = self._dep.batch[idx];
|
|
836
|
+
if (b === null) self._dep.batch[idx] = [v];
|
|
837
|
+
else b.push(v);
|
|
838
|
+
self._dep.prev[idx] = v;
|
|
839
|
+
self._dep.hasData[idx] = true;
|
|
840
|
+
self._dep.tier[idx] = 3;
|
|
841
|
+
if (self._dep.dirty[idx]) {
|
|
842
|
+
self._dep.dirty[idx] = false;
|
|
843
|
+
self._wave.pending--;
|
|
844
|
+
}
|
|
845
|
+
if (isLastInDeliveredWave) self._maybeRun();
|
|
846
|
+
self._fireOwedDemandIfReady();
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
if (t === "RESOLVED") {
|
|
850
|
+
self._recordDepProjection(idx, delivery);
|
|
851
|
+
self._dep.tier[idx] = 3;
|
|
852
|
+
if (self._dep.dirty[idx]) {
|
|
853
|
+
self._dep.dirty[idx] = false;
|
|
854
|
+
self._wave.pending--;
|
|
855
|
+
}
|
|
856
|
+
if (isLastInDeliveredWave) self._maybeRun();
|
|
857
|
+
self._fireOwedDemandIfReady();
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
function nodeReleaseDepDirty(self, idx) {
|
|
862
|
+
if (self._dep.dirty[idx]) {
|
|
863
|
+
self._dep.dirty[idx] = false;
|
|
864
|
+
self._wave.pending--;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
function nodeSettleAfterAbsorbedTerminal(self) {
|
|
868
|
+
if (self._wave.pending !== 0 || !self._wave.emittedDirtyThisWave) return;
|
|
869
|
+
const sawData = self._dep.batch.some((b) => b !== null && b.length > 0);
|
|
870
|
+
if (sawData) self._maybeRun();
|
|
871
|
+
if (self._wave.emittedDirtyThisWave) self._down([["RESOLVED"]]);
|
|
872
|
+
}
|
|
873
|
+
function nodeMarkDirty(self) {
|
|
874
|
+
self._value.status = "dirty";
|
|
875
|
+
if (self._isPullQuiet()) return;
|
|
876
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
877
|
+
self._wave.emittedDirtyThisWave = true;
|
|
878
|
+
self._emitToSubs(["DIRTY"]);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
function nodeMaybeRun(self) {
|
|
882
|
+
if (self._wave.inDepMutation) {
|
|
883
|
+
self._wave.rewireRunPending = true;
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
if (self._slot.pausable === true && (self._isPaused() || self._isPullQuiet())) {
|
|
887
|
+
self._control.pausedDepWaveOccurred = true;
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
self._tryRun();
|
|
891
|
+
}
|
|
892
|
+
function nodeSettleRewire(self) {
|
|
893
|
+
if (self._slot.pausable === true && self._isPaused()) {
|
|
894
|
+
self._control.pausedDepWaveOccurred = true;
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
if (self._wave.pending > 0) return;
|
|
898
|
+
if (self._slot.handle === null) {
|
|
899
|
+
self._passthroughEmit();
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
if (!self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled())) return;
|
|
903
|
+
self._markDirty();
|
|
904
|
+
self._runWave();
|
|
905
|
+
}
|
|
906
|
+
function nodeTryRun(self) {
|
|
907
|
+
if (self._wave.pending > 0) return;
|
|
908
|
+
if (self._slot.handle === null) {
|
|
909
|
+
self._passthroughEmit();
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
if (!self._wave.hasCalledFnOnce) {
|
|
913
|
+
if (self._slot.partial || self._allDepsSettled()) self._runWave();
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
self._runWave();
|
|
917
|
+
}
|
|
918
|
+
function nodeAllDepsSettled(self) {
|
|
919
|
+
for (let i = 0; i < self._slot.deps.length; i++) {
|
|
920
|
+
if (self._dep.hasData[i]) continue;
|
|
921
|
+
if (self._slot.terminalAsRealInput && self._dep.terminal[i] !== void 0) continue;
|
|
922
|
+
return false;
|
|
923
|
+
}
|
|
924
|
+
return true;
|
|
925
|
+
}
|
|
926
|
+
function nodePassthroughEmit(self) {
|
|
927
|
+
const b = self._dep.batch[0];
|
|
928
|
+
if (b !== null && b.length > 0) {
|
|
929
|
+
self._down([["DATA", b[b.length - 1]]]);
|
|
930
|
+
} else if (self._wave.emittedDirtyThisWave) {
|
|
931
|
+
self._down([["RESOLVED"]]);
|
|
932
|
+
}
|
|
933
|
+
self._dep.batch[0] = null;
|
|
934
|
+
self._wave.emittedDirtyThisWave = false;
|
|
935
|
+
}
|
|
936
|
+
function nodeRunWave(self) {
|
|
937
|
+
if (self._wave.insideRunWave)
|
|
938
|
+
throw new Error(
|
|
939
|
+
"synchronous feedback cycle: node fn re-entered its own wave (R-reentrancy / D37)"
|
|
940
|
+
);
|
|
941
|
+
self._wave.hasCalledFnOnce = true;
|
|
942
|
+
self._hooks.onInvalidate = [];
|
|
943
|
+
self._hooks.onDeactivation = [];
|
|
944
|
+
const ctx = self._buildCtx();
|
|
945
|
+
const wasDirty = self._wave.emittedDirtyThisWave;
|
|
946
|
+
self._wave.emittedSettleThisWave = false;
|
|
947
|
+
self._wave.insideRunWave = true;
|
|
948
|
+
try {
|
|
949
|
+
self._slot.dispatcher.invoke(self._slot.handle, ctx);
|
|
950
|
+
} finally {
|
|
951
|
+
self._wave.insideRunWave = false;
|
|
952
|
+
}
|
|
953
|
+
if (wasDirty && !self._wave.emittedSettleThisWave && self._value.terminal === void 0 && !self._isAsyncPool()) {
|
|
954
|
+
self._down([["RESOLVED"]]);
|
|
955
|
+
}
|
|
956
|
+
for (let i = 0; i < self._dep.batch.length; i++) {
|
|
957
|
+
self._dep.batch[i] = null;
|
|
958
|
+
self._dep.waveData[i] = [];
|
|
959
|
+
self._dep.waveTokens[i] = void 0;
|
|
960
|
+
self._dep.terminalInput[i] = void 0;
|
|
961
|
+
}
|
|
962
|
+
self._wave.emittedDirtyThisWave = false;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// src/node/node-runtime-host.ts
|
|
966
|
+
function nodeRuntimeHost(node2) {
|
|
967
|
+
return node2;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// src/node/node-lifecycle-runtime.ts
|
|
971
|
+
function nodeActivate(self) {
|
|
972
|
+
self._lifecycle.activated = true;
|
|
973
|
+
const seedRestoredDeps = self._restoredActivationPending;
|
|
974
|
+
self._restoredActivationPending = false;
|
|
975
|
+
self._dep.unsubs = new Array(self._slot.deps.length);
|
|
976
|
+
self._dep.idxBoxes = new Array(self._slot.deps.length);
|
|
977
|
+
for (const dep of self._slot.deps) self._subscribeDepAt(dep, { seedRestored: seedRestoredDeps });
|
|
978
|
+
if (self._slot.deps.length === 0 && self._slot.handle !== null && !self._wave.hasCalledFnOnce) {
|
|
979
|
+
self._runWave();
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
function nodeSubscribeDepAt(self, depNode, opts = {}) {
|
|
983
|
+
const idx0 = self._slot.deps.indexOf(depNode);
|
|
984
|
+
const box = { v: idx0 };
|
|
985
|
+
let ignoreInitialPush = opts.seedRestored === true;
|
|
986
|
+
if (ignoreInitialPush && idx0 !== -1) {
|
|
987
|
+
self._seedRestoredDepAt(idx0, depNode);
|
|
988
|
+
const dep = nodeRuntimeHost(depNode);
|
|
989
|
+
if (dep._value.terminal !== void 0 && !dep._slot.resubscribable) {
|
|
990
|
+
self._dep.unsubs[idx0] = () => {
|
|
991
|
+
};
|
|
992
|
+
self._dep.idxBoxes[idx0] = box;
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
const unsub = depNode.subscribe((msg, delivery) => {
|
|
997
|
+
if (ignoreInitialPush && delivery === void 0) return;
|
|
998
|
+
if (ignoreInitialPush) ignoreInitialPush = false;
|
|
999
|
+
if (box.v === -1) return;
|
|
1000
|
+
self._receiveFromDep(box.v, msg, delivery);
|
|
1001
|
+
});
|
|
1002
|
+
if (ignoreInitialPush && idx0 !== -1 && box.v !== -1) self._seedRestoredDepAt(idx0, depNode);
|
|
1003
|
+
ignoreInitialPush = false;
|
|
1004
|
+
if (idx0 !== -1) {
|
|
1005
|
+
self._dep.unsubs[idx0] = unsub;
|
|
1006
|
+
self._dep.idxBoxes[idx0] = box;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
function nodeSeedRestoredDepAt(self, idx, depNode) {
|
|
1010
|
+
const dep = nodeRuntimeHost(depNode);
|
|
1011
|
+
const seedData = dep._value.hasData && !dep._slot.pull;
|
|
1012
|
+
self._dep.batch[idx] = null;
|
|
1013
|
+
self._dep.waveData[idx] = [];
|
|
1014
|
+
self._dep.waveTokens[idx] = void 0;
|
|
1015
|
+
self._dep.prev[idx] = seedData ? dep._value.cache : SENTINEL;
|
|
1016
|
+
self._dep.hasData[idx] = seedData;
|
|
1017
|
+
self._dep.dirty[idx] = false;
|
|
1018
|
+
self._dep.tier[idx] = seedData ? 3 : 0;
|
|
1019
|
+
self._dep.terminal[idx] = dep._value.terminal;
|
|
1020
|
+
self._dep.terminalInput[idx] = void 0;
|
|
1021
|
+
}
|
|
1022
|
+
function nodeDeactivate(self) {
|
|
1023
|
+
self._lifecycle.activated = false;
|
|
1024
|
+
for (const u of self._dep.unsubs) if (u) u();
|
|
1025
|
+
self._dep.unsubs = [];
|
|
1026
|
+
self._dep.idxBoxes = [];
|
|
1027
|
+
for (const fn of self._hooks.onDeactivation) fn();
|
|
1028
|
+
self._hooks.onDeactivation = [];
|
|
1029
|
+
self._hooks.onInvalidate = [];
|
|
1030
|
+
const isCompute = self._slot.handle !== null || self._slot.deps.length > 0;
|
|
1031
|
+
if (isCompute) {
|
|
1032
|
+
self._value.cache = SENTINEL;
|
|
1033
|
+
self._value.hasData = false;
|
|
1034
|
+
self._value.status = "sentinel";
|
|
1035
|
+
}
|
|
1036
|
+
self._resetDepState();
|
|
1037
|
+
self._wave.hasCalledFnOnce = false;
|
|
1038
|
+
self._control.pauseLockset.clear();
|
|
1039
|
+
self._control.pauseBuffer = [];
|
|
1040
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1041
|
+
self._control.demandOwed = void 0;
|
|
1042
|
+
self._control.activePull = void 0;
|
|
1043
|
+
self._control.pullDirtyOwed = false;
|
|
1044
|
+
self._value.replayRing = [];
|
|
1045
|
+
if (!self._privateState.persist) self._privateState.value = SENTINEL;
|
|
1046
|
+
}
|
|
1047
|
+
function nodeSubscriberCount(self) {
|
|
1048
|
+
return self._lifecycle.subscribers.size;
|
|
1049
|
+
}
|
|
1050
|
+
function nodeIsRuntimeQuiescentForRelease(self) {
|
|
1051
|
+
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;
|
|
1052
|
+
}
|
|
1053
|
+
function nodeReleaseRuntime(self) {
|
|
1054
|
+
if (self._released) return;
|
|
1055
|
+
self._released = true;
|
|
1056
|
+
const node2 = self;
|
|
1057
|
+
releasedNodes.add(node2);
|
|
1058
|
+
let releaseError;
|
|
1059
|
+
const recordReleaseError = (error) => {
|
|
1060
|
+
if (releaseError === void 0) releaseError = error;
|
|
1061
|
+
};
|
|
1062
|
+
self._lifecycle.activated = false;
|
|
1063
|
+
for (const u of self._dep.unsubs) {
|
|
1064
|
+
try {
|
|
1065
|
+
u();
|
|
1066
|
+
} catch (error) {
|
|
1067
|
+
recordReleaseError(error);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
for (const fn of self._hooks.onDeactivation) {
|
|
1071
|
+
try {
|
|
1072
|
+
fn();
|
|
1073
|
+
} catch (error) {
|
|
1074
|
+
recordReleaseError(error);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
self._dep.unsubs = [];
|
|
1078
|
+
self._dep.idxBoxes = [];
|
|
1079
|
+
self._lifecycle.subscribers.clear();
|
|
1080
|
+
if (self._slot.handle !== null) {
|
|
1081
|
+
self._slot.dispatcher.unregister(self._slot.handle);
|
|
1082
|
+
self._slot.handle = null;
|
|
1083
|
+
}
|
|
1084
|
+
self._slot.deps = [];
|
|
1085
|
+
self._dep.batch = [];
|
|
1086
|
+
self._dep.waveData = [];
|
|
1087
|
+
self._dep.waveTokens = [];
|
|
1088
|
+
self._dep.prev = [];
|
|
1089
|
+
self._dep.hasData = [];
|
|
1090
|
+
self._dep.dirty = [];
|
|
1091
|
+
self._dep.tier = [];
|
|
1092
|
+
self._dep.terminal = [];
|
|
1093
|
+
self._dep.terminalInput = [];
|
|
1094
|
+
self._value.cache = SENTINEL;
|
|
1095
|
+
self._value.hasData = false;
|
|
1096
|
+
self._value.status = "sentinel";
|
|
1097
|
+
self._value.terminal = void 0;
|
|
1098
|
+
self._value.replayRing = [];
|
|
1099
|
+
self._privateState.value = SENTINEL;
|
|
1100
|
+
self._privateState.persist = false;
|
|
1101
|
+
self._syncCtx = null;
|
|
1102
|
+
self._resetDepState();
|
|
1103
|
+
self._hooks.onDeactivation = [];
|
|
1104
|
+
self._hooks.onInvalidate = [];
|
|
1105
|
+
self._control.pauseLockset.clear();
|
|
1106
|
+
self._control.pauseBuffer = [];
|
|
1107
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1108
|
+
self._control.demandOwed = void 0;
|
|
1109
|
+
self._control.activePull = void 0;
|
|
1110
|
+
self._control.pullDirtyOwed = false;
|
|
1111
|
+
self._restoredActivationPending = false;
|
|
1112
|
+
checkpointReaders.delete(node2);
|
|
1113
|
+
restoreWriters.delete(node2);
|
|
1114
|
+
runtimeReleasers.delete(node2);
|
|
1115
|
+
runtimeQuiescenceReaders.delete(node2);
|
|
1116
|
+
subscriberCountReaders.delete(node2);
|
|
1117
|
+
activationReaders.delete(node2);
|
|
1118
|
+
ownerTokens.delete(node2);
|
|
1119
|
+
topologyDepsChangedObservers.delete(node2);
|
|
1120
|
+
self._core.releaseSlot(self._id);
|
|
1121
|
+
if (releaseError !== void 0) throw releaseError;
|
|
1122
|
+
}
|
|
1123
|
+
function nodeResetDepState(self) {
|
|
1124
|
+
const n = self._slot.deps.length;
|
|
1125
|
+
for (let i = 0; i < n; i++) {
|
|
1126
|
+
self._dep.batch[i] = null;
|
|
1127
|
+
self._dep.waveData[i] = [];
|
|
1128
|
+
self._dep.waveTokens[i] = void 0;
|
|
1129
|
+
self._dep.prev[i] = SENTINEL;
|
|
1130
|
+
self._dep.hasData[i] = false;
|
|
1131
|
+
self._dep.dirty[i] = false;
|
|
1132
|
+
self._dep.tier[i] = 0;
|
|
1133
|
+
self._dep.terminal[i] = void 0;
|
|
1134
|
+
self._dep.terminalInput[i] = void 0;
|
|
1135
|
+
}
|
|
1136
|
+
self._wave.pending = 0;
|
|
1137
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
583
1140
|
// src/json/codec.ts
|
|
584
1141
|
var JS_MIN_NORMAL_NUMBER = 2 ** -1022;
|
|
585
1142
|
function assertStableJsonNumber(value, path) {
|
|
@@ -624,9 +1181,16 @@ function sortedJsonValue(value, seen = /* @__PURE__ */ new Set(), path = "$", st
|
|
|
624
1181
|
}
|
|
625
1182
|
for (const key of Object.getOwnPropertyNames(value)) {
|
|
626
1183
|
const isIndex = /^(0|[1-9]\d*)$/.test(key) && Number.isSafeInteger(Number(key)) && Number(key) < value.length;
|
|
1184
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1185
|
+
if (descriptor !== void 0 && ("get" in descriptor || "set" in descriptor)) {
|
|
1186
|
+
throw new TypeError(`stableJsonString: accessor property at ${path}.${key}`);
|
|
1187
|
+
}
|
|
627
1188
|
if (key !== "length" && !isIndex) {
|
|
628
1189
|
throw new TypeError(`stableJsonString: non-index array property at ${path}.${key}`);
|
|
629
1190
|
}
|
|
1191
|
+
if (key !== "length" && descriptor !== void 0 && !descriptor.enumerable) {
|
|
1192
|
+
throw new TypeError(`stableJsonString: non-enumerable array property at ${path}.${key}`);
|
|
1193
|
+
}
|
|
630
1194
|
}
|
|
631
1195
|
const out2 = [];
|
|
632
1196
|
for (let i = 0; i < value.length; i += 1) {
|
|
@@ -640,6 +1204,15 @@ function sortedJsonValue(value, seen = /* @__PURE__ */ new Set(), path = "$", st
|
|
|
640
1204
|
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
641
1205
|
throw new TypeError(`stableJsonString: symbol-keyed properties at ${path}`);
|
|
642
1206
|
}
|
|
1207
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
1208
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1209
|
+
if (descriptor !== void 0 && ("get" in descriptor || "set" in descriptor)) {
|
|
1210
|
+
throw new TypeError(`stableJsonString: accessor property at ${path}.${key}`);
|
|
1211
|
+
}
|
|
1212
|
+
if (descriptor !== void 0 && !descriptor.enumerable) {
|
|
1213
|
+
throw new TypeError(`stableJsonString: non-enumerable property at ${path}.${key}`);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
643
1216
|
const out = /* @__PURE__ */ Object.create(null);
|
|
644
1217
|
for (const key of Object.keys(value).sort()) {
|
|
645
1218
|
out[key] = sortedJsonValue(
|
|
@@ -962,56 +1535,532 @@ function restoredV1Cid(policy, hasData, cache) {
|
|
|
962
1535
|
return computeV1Cid(policy, hasData ? cache : ABSENT_V1_SEED);
|
|
963
1536
|
}
|
|
964
1537
|
|
|
965
|
-
// src/node/node.ts
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1538
|
+
// src/node/node-output-runtime.ts
|
|
1539
|
+
function nodeDown(self, msgs) {
|
|
1540
|
+
if (self._released) return;
|
|
1541
|
+
validateDownPayloads(msgs);
|
|
1542
|
+
const deliveryWave = {};
|
|
1543
|
+
const assertVersionDataCompatible = (wave) => {
|
|
1544
|
+
for (const m of wave) {
|
|
1545
|
+
if (m[0] === "DATA") assertNodeVersionDataCompatible(self._version.policy, m[1]);
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1548
|
+
const snapshotVersionData = (wave) => wave.map(
|
|
1549
|
+
(m) => m[0] === "DATA" ? ["DATA", snapshotNodeVersionData(self._version.policy, m[1])] : m
|
|
1550
|
+
);
|
|
1551
|
+
assertVersionDataCompatible(msgs);
|
|
1552
|
+
if (self._value.terminal !== void 0) {
|
|
1553
|
+
if (!msgs.some((m) => m[0] === "TEARDOWN")) return;
|
|
1554
|
+
self._value.hasTorndown = true;
|
|
1555
|
+
if (self._slot.resetOnTeardown) {
|
|
1556
|
+
self._value.cache = SENTINEL;
|
|
1557
|
+
self._value.hasData = false;
|
|
1558
|
+
}
|
|
1559
|
+
self._emitToSubs(["TEARDOWN"], { wave: deliveryWave, last: true });
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
let sorted = [...msgs].sort((a, b) => messageTier(a[0]) - messageTier(b[0]));
|
|
1563
|
+
const firstInvalidate = sorted.findIndex((m) => m[0] === "INVALIDATE");
|
|
1564
|
+
if (firstInvalidate !== -1) {
|
|
1565
|
+
sorted = sorted.filter((m, i) => m[0] !== "INVALIDATE" || i === firstInvalidate);
|
|
1566
|
+
}
|
|
1567
|
+
const hasTeardown = sorted.some((m) => m[0] === "TEARDOWN");
|
|
1568
|
+
const hasTerminal = sorted.some((m) => m[0] === "COMPLETE" || m[0] === "ERROR");
|
|
1569
|
+
if (hasTeardown && !hasTerminal && self._value.terminal === void 0 && !self._value.hasTorndown) {
|
|
1570
|
+
sorted = [["COMPLETE"], ...sorted];
|
|
1571
|
+
}
|
|
1572
|
+
if (!self._wave.insideRunWave && currentBatch()) {
|
|
1573
|
+
const deferred = snapshotVersionData(sorted.filter((m) => isDeferredTier(m[0])));
|
|
1574
|
+
if (deferred.length > 0) {
|
|
1575
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1576
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1577
|
+
self._value.status = "dirty";
|
|
1578
|
+
self._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1579
|
+
}
|
|
1580
|
+
self._wave.batchDirtyOwed = true;
|
|
1581
|
+
deferToBatch(self, deferred);
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
if (self._shouldBufferOnPause()) {
|
|
1586
|
+
const buffered = snapshotVersionData(sorted.filter((m) => isPauseBufferedTier(m[0])));
|
|
1587
|
+
if (buffered.length > 0) {
|
|
1588
|
+
self._wave.emittedSettleThisWave = true;
|
|
1589
|
+
self._control.pauseBuffer.push(buffered);
|
|
1590
|
+
}
|
|
1591
|
+
sorted = sorted.filter((m) => !isPauseBufferedTier(m[0]));
|
|
1592
|
+
if (sorted.length === 0) return;
|
|
1593
|
+
}
|
|
1594
|
+
let dataCount = 0;
|
|
1595
|
+
let hasTier3 = false;
|
|
1596
|
+
let hasResolved = false;
|
|
1597
|
+
for (const m of sorted) {
|
|
1598
|
+
if (m[0] === "DATA") dataCount++;
|
|
1599
|
+
if (m[0] === "RESOLVED") hasResolved = true;
|
|
1600
|
+
if (isValueTier(m[0])) hasTier3 = true;
|
|
984
1601
|
}
|
|
1602
|
+
if (dataCount >= 1 && hasResolved) {
|
|
1603
|
+
throw new Error(
|
|
1604
|
+
"down: a wave cannot mix DATA and RESOLVED (tier-3 exclusivity, R-resolved-undirty)"
|
|
1605
|
+
);
|
|
1606
|
+
}
|
|
1607
|
+
const plannedVersions = new Array(sorted.length);
|
|
1608
|
+
if (dataCount > 0) {
|
|
1609
|
+
let plannedVersion = self._version.value;
|
|
1610
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1611
|
+
const m = sorted[i];
|
|
1612
|
+
if (m[0] !== "DATA") continue;
|
|
1613
|
+
plannedVersion = advanceNodeVersion(plannedVersion, self._version.policy, m[1]);
|
|
1614
|
+
plannedVersions[i] = plannedVersion;
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
if (hasTier3 && (!self._wave.insideRunWave || self._control.pullDirtyOwed) && !self._wave.emittedDirtyThisWave) {
|
|
1618
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1619
|
+
self._value.status = "dirty";
|
|
1620
|
+
self._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1621
|
+
}
|
|
1622
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1623
|
+
const m = sorted[i];
|
|
1624
|
+
const delivery = { wave: deliveryWave, last: i === sorted.length - 1 };
|
|
1625
|
+
if (isDeferredTier(m[0])) self._wave.emittedSettleThisWave = true;
|
|
1626
|
+
if (m[0] === "DIRTY") {
|
|
1627
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1628
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1629
|
+
self._value.status = "dirty";
|
|
1630
|
+
self._emitToSubs(["DIRTY"], delivery);
|
|
1631
|
+
}
|
|
1632
|
+
continue;
|
|
1633
|
+
}
|
|
1634
|
+
if (m[0] === "DATA") {
|
|
1635
|
+
const v = m[1];
|
|
1636
|
+
self._value.cache = v;
|
|
1637
|
+
self._value.hasData = true;
|
|
1638
|
+
self._value.status = "settled";
|
|
1639
|
+
self._version.value = plannedVersions[i];
|
|
1640
|
+
if (self._slot.replayN > 0) {
|
|
1641
|
+
self._value.replayRing.push(v);
|
|
1642
|
+
if (self._value.replayRing.length > self._slot.replayN) self._value.replayRing.shift();
|
|
1643
|
+
}
|
|
1644
|
+
self._emitToSubs(["DATA", v], delivery);
|
|
1645
|
+
continue;
|
|
1646
|
+
}
|
|
1647
|
+
if (m[0] === "RESOLVED") {
|
|
1648
|
+
self._value.status = self._value.hasData ? "resolved" : "sentinel";
|
|
1649
|
+
self._emitToSubs(["RESOLVED"], delivery);
|
|
1650
|
+
continue;
|
|
1651
|
+
}
|
|
1652
|
+
if (m[0] === "INVALIDATE") {
|
|
1653
|
+
self._invalidate(delivery);
|
|
1654
|
+
continue;
|
|
1655
|
+
}
|
|
1656
|
+
if (m[0] === "COMPLETE") {
|
|
1657
|
+
if (self._value.terminal !== void 0) continue;
|
|
1658
|
+
self._value.terminal = true;
|
|
1659
|
+
self._control.pauseBuffer = [];
|
|
1660
|
+
self._value.status = "completed";
|
|
1661
|
+
self._emitToSubs(["COMPLETE"], delivery);
|
|
1662
|
+
continue;
|
|
1663
|
+
}
|
|
1664
|
+
if (m[0] === "ERROR") {
|
|
1665
|
+
if (self._value.terminal !== void 0) continue;
|
|
1666
|
+
self._value.terminal = m[1];
|
|
1667
|
+
self._control.pauseBuffer = [];
|
|
1668
|
+
self._value.status = "errored";
|
|
1669
|
+
self._emitToSubs(["ERROR", m[1]], delivery);
|
|
1670
|
+
continue;
|
|
1671
|
+
}
|
|
1672
|
+
if (m[0] === "TEARDOWN") {
|
|
1673
|
+
self._value.hasTorndown = true;
|
|
1674
|
+
if (self._slot.resetOnTeardown) {
|
|
1675
|
+
self._value.cache = SENTINEL;
|
|
1676
|
+
self._value.hasData = false;
|
|
1677
|
+
}
|
|
1678
|
+
self._emitToSubs(["TEARDOWN"], delivery);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
if (!self._wave.insideRunWave) self._wave.emittedDirtyThisWave = false;
|
|
985
1682
|
}
|
|
986
|
-
function
|
|
987
|
-
|
|
988
|
-
|
|
1683
|
+
function nodeUp(self, msgs, towardDep, route) {
|
|
1684
|
+
if (self._released) return;
|
|
1685
|
+
const routeState = route ?? { demandFired: /* @__PURE__ */ new Map() };
|
|
1686
|
+
for (const m of msgs) {
|
|
1687
|
+
if (!isUpAllowed(m[0])) {
|
|
1688
|
+
throw new Error(
|
|
1689
|
+
`ctx.up: ${m[0]} is down-only (tier ${messageTier(m[0])}); up carries control tiers only (R-ctx-up)`
|
|
1690
|
+
);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
for (const m of msgs) {
|
|
1694
|
+
if (m[0] === "PAUSE") {
|
|
1695
|
+
self._pauseAcquire(m[1]);
|
|
1696
|
+
} else if (m[0] === "RESUME") {
|
|
1697
|
+
if (self._control.pauseLockset.has(m[1])) {
|
|
1698
|
+
self._pauseRelease(m[1]);
|
|
1699
|
+
} else {
|
|
1700
|
+
self._forwardUp(m, towardDep, routeState);
|
|
1701
|
+
}
|
|
1702
|
+
} else if (m[0] === "PULL") {
|
|
1703
|
+
const demand = normalizePullDemand(m[1]);
|
|
1704
|
+
if (self._slot.pull && demand.pullId === self._slot.pullLock) {
|
|
1705
|
+
if (!self._markDemandRouted(demand.pullId, routeState)) self._onDemand(demand);
|
|
1706
|
+
} else {
|
|
1707
|
+
self._forwardUp(["PULL", demand], towardDep, routeState);
|
|
1708
|
+
}
|
|
1709
|
+
} else if (self._slot.deps.length === 0) {
|
|
1710
|
+
if (m[0] === "INVALIDATE") self._down([["INVALIDATE"]]);
|
|
1711
|
+
} else {
|
|
1712
|
+
self._forwardUp(m, towardDep, routeState);
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
function nodeMarkDemandRouted(self, lockId, route) {
|
|
1717
|
+
let holders = route.demandFired.get(lockId);
|
|
1718
|
+
if (holders === void 0) {
|
|
1719
|
+
holders = /* @__PURE__ */ new Set();
|
|
1720
|
+
route.demandFired.set(lockId, holders);
|
|
1721
|
+
}
|
|
1722
|
+
const node2 = self;
|
|
1723
|
+
if (holders.has(node2)) return true;
|
|
1724
|
+
holders.add(node2);
|
|
1725
|
+
return false;
|
|
1726
|
+
}
|
|
1727
|
+
function nodeForwardUp(self, m, towardDep, route) {
|
|
1728
|
+
if (self._slot.deps.length === 0) return;
|
|
1729
|
+
if (towardDep !== void 0) {
|
|
1730
|
+
const d = self._slot.deps[towardDep];
|
|
1731
|
+
if (d !== void 0) nodeRuntimeHost(d)._up([m], void 0, route);
|
|
1732
|
+
} else {
|
|
1733
|
+
for (const dep of self._slot.deps) nodeRuntimeHost(dep)._up([m], void 0, route);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
function nodeIsPaused(self) {
|
|
1737
|
+
return self._control.pauseLockset.size > 0;
|
|
1738
|
+
}
|
|
1739
|
+
function nodeHasBoundaryPauseLock(self) {
|
|
1740
|
+
if (self._slot.pausable === false) return false;
|
|
1741
|
+
return self._control.pauseLockset.size > 0;
|
|
1742
|
+
}
|
|
1743
|
+
function nodeIsAsyncPool(self) {
|
|
1744
|
+
return self._slot.handle !== null && self._slot.dispatcher.poolKind(self._slot.handle.poolId) === "async";
|
|
1745
|
+
}
|
|
1746
|
+
function nodePauseAcquire(self, lockId) {
|
|
1747
|
+
self._control.pauseLockset.add(lockId);
|
|
1748
|
+
}
|
|
1749
|
+
function nodePauseRelease(self, lockId) {
|
|
1750
|
+
if (!self._control.pauseLockset.has(lockId)) return;
|
|
1751
|
+
self._control.pauseLockset.delete(lockId);
|
|
1752
|
+
if (self._slot.pull && self._control.demandOwed !== void 0) self._fireOwedDemandIfReady();
|
|
1753
|
+
if (self._hasBoundaryPauseLock()) return;
|
|
1754
|
+
scheduleBoundaryDrain(self._core);
|
|
1755
|
+
if (self._slot.pull) return;
|
|
1756
|
+
self._onResume();
|
|
1757
|
+
}
|
|
1758
|
+
function nodeOnResume(self) {
|
|
1759
|
+
if (self._value.terminal !== void 0) {
|
|
1760
|
+
self._control.pauseBuffer = [];
|
|
1761
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1762
|
+
self._control.demandOwed = void 0;
|
|
1763
|
+
self._control.activePull = void 0;
|
|
1764
|
+
self._control.pullDirtyOwed = false;
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
if (self._control.pauseBuffer.length > 0) {
|
|
1768
|
+
const buf = self._control.pauseBuffer;
|
|
1769
|
+
self._control.pauseBuffer = [];
|
|
1770
|
+
for (const wave of buf) self._down(wave);
|
|
1771
|
+
}
|
|
1772
|
+
if (self._control.pausedDepWaveOccurred) {
|
|
1773
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1774
|
+
self._tryRun();
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
function nodeCanFireDemand(self) {
|
|
1778
|
+
if (self._value.terminal !== void 0 || self._wave.pending > 0) return false;
|
|
1779
|
+
return self._control.pauseLockset.size === 0;
|
|
1780
|
+
}
|
|
1781
|
+
function nodeDeliverPullDemand(self, demand) {
|
|
1782
|
+
self._control.demandOwed = void 0;
|
|
1783
|
+
self._control.activePull = demand;
|
|
1784
|
+
self._control.inDeliverDemand = true;
|
|
989
1785
|
try {
|
|
990
|
-
|
|
1786
|
+
self._firePullDemand();
|
|
991
1787
|
} finally {
|
|
992
|
-
|
|
1788
|
+
self._control.activePull = void 0;
|
|
1789
|
+
self._control.inDeliverDemand = false;
|
|
993
1790
|
}
|
|
994
1791
|
}
|
|
995
|
-
function
|
|
996
|
-
|
|
1792
|
+
function nodeOnDemand(self, demand) {
|
|
1793
|
+
if (self._control.inDeliverDemand) return;
|
|
1794
|
+
if (self._canFireDemand()) self._deliverPullDemand(demand);
|
|
1795
|
+
else self._control.demandOwed = demand;
|
|
997
1796
|
}
|
|
998
|
-
function
|
|
999
|
-
|
|
1797
|
+
function nodeFirePullDemand(self) {
|
|
1798
|
+
let drainedBuffer = false;
|
|
1799
|
+
if (self._control.pauseBuffer.length > 0) {
|
|
1800
|
+
const buf = self._control.pauseBuffer;
|
|
1801
|
+
self._control.pauseBuffer = [];
|
|
1802
|
+
for (const wave of buf) self._down(wave);
|
|
1803
|
+
drainedBuffer = true;
|
|
1804
|
+
}
|
|
1805
|
+
if (drainedBuffer) return;
|
|
1806
|
+
if (self._control.pausedDepWaveOccurred) {
|
|
1807
|
+
const gated = self._slot.handle !== null && !self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled());
|
|
1808
|
+
if (self._wave.pending > 0 || gated) return;
|
|
1809
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1810
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1811
|
+
self._control.pullDirtyOwed = true;
|
|
1812
|
+
try {
|
|
1813
|
+
self._tryRun();
|
|
1814
|
+
} finally {
|
|
1815
|
+
self._control.pullDirtyOwed = false;
|
|
1816
|
+
}
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
if (self._slot.handle !== null) {
|
|
1820
|
+
if (!self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled())) return;
|
|
1821
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1822
|
+
self._control.pullDirtyOwed = true;
|
|
1823
|
+
try {
|
|
1824
|
+
self._runWave();
|
|
1825
|
+
} finally {
|
|
1826
|
+
self._control.pullDirtyOwed = false;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1000
1829
|
}
|
|
1001
|
-
function
|
|
1002
|
-
|
|
1830
|
+
function nodeFireOwedDemandIfReady(self) {
|
|
1831
|
+
if (self._control.inDeliverDemand) return;
|
|
1832
|
+
if (self._slot.pull && self._control.demandOwed !== void 0 && self._canFireDemand()) {
|
|
1833
|
+
self._deliverPullDemand(self._control.demandOwed);
|
|
1834
|
+
}
|
|
1003
1835
|
}
|
|
1004
|
-
function
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1836
|
+
function nodeShouldBufferOnPause(self) {
|
|
1837
|
+
if (self._slot.pausable === false) return false;
|
|
1838
|
+
if (!self._isPaused() && !self._isPullQuiet()) return false;
|
|
1839
|
+
if (self._slot.pausable === "resumeAll") return true;
|
|
1840
|
+
if (!self._wave.insideRunWave && self._isAsyncPool() && self._slot.deps.length > 0) return true;
|
|
1841
|
+
return false;
|
|
1842
|
+
}
|
|
1843
|
+
function nodeInvalidate(self, delivery) {
|
|
1844
|
+
if (!self._value.hasData) return;
|
|
1845
|
+
self._value.cache = SENTINEL;
|
|
1846
|
+
self._value.hasData = false;
|
|
1847
|
+
self._value.status = "sentinel";
|
|
1848
|
+
self._value.replayRing = [];
|
|
1849
|
+
for (const fn of self._hooks.onInvalidate) fn();
|
|
1850
|
+
self._emitToSubs(["INVALIDATE"], delivery);
|
|
1851
|
+
}
|
|
1852
|
+
function nodeAllDepsTerminal(self) {
|
|
1853
|
+
if (self._slot.deps.length === 0) return false;
|
|
1854
|
+
for (const tm of self._dep.terminal) if (tm === void 0) return false;
|
|
1855
|
+
return true;
|
|
1856
|
+
}
|
|
1857
|
+
function nodeResetLifecycle(self) {
|
|
1858
|
+
for (const u of self._dep.unsubs) if (u) u();
|
|
1859
|
+
self._dep.unsubs = [];
|
|
1860
|
+
self._dep.idxBoxes = [];
|
|
1861
|
+
self._lifecycle.subscribers.clear();
|
|
1862
|
+
self._lifecycle.activated = false;
|
|
1863
|
+
self._value.terminal = void 0;
|
|
1864
|
+
self._value.hasTorndown = false;
|
|
1865
|
+
self._wave.hasCalledFnOnce = false;
|
|
1866
|
+
self._resetDepState();
|
|
1867
|
+
self._control.pauseLockset.clear();
|
|
1868
|
+
self._control.pauseBuffer = [];
|
|
1869
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1870
|
+
self._control.demandOwed = void 0;
|
|
1871
|
+
self._control.activePull = void 0;
|
|
1872
|
+
self._control.pullDirtyOwed = false;
|
|
1873
|
+
self._value.replayRing = [];
|
|
1874
|
+
const isCompute = self._slot.handle !== null || self._slot.deps.length > 0;
|
|
1875
|
+
if (isCompute) {
|
|
1876
|
+
self._value.cache = SENTINEL;
|
|
1877
|
+
self._value.hasData = false;
|
|
1878
|
+
self._value.status = "sentinel";
|
|
1879
|
+
} else {
|
|
1880
|
+
self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1881
|
+
}
|
|
1882
|
+
if (!self._privateState.persist) self._privateState.value = SENTINEL;
|
|
1883
|
+
}
|
|
1884
|
+
function nodeEmitToSubs(self, msg, delivery) {
|
|
1885
|
+
if (self._released) return;
|
|
1886
|
+
const subs = [...self._lifecycle.subscribers];
|
|
1887
|
+
for (const sink of subs) sink(msg, delivery);
|
|
1888
|
+
}
|
|
1889
|
+
function nodeCommitBatchedWave(self, wave) {
|
|
1890
|
+
self._wave.batchDirtyOwed = false;
|
|
1891
|
+
self._down(wave);
|
|
1892
|
+
}
|
|
1893
|
+
function nodeRollbackBatched(self) {
|
|
1894
|
+
if (self._wave.batchDirtyOwed) {
|
|
1895
|
+
self._wave.batchDirtyOwed = false;
|
|
1896
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1897
|
+
self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1898
|
+
self._emitToSubs(["RESOLVED"]);
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
function nodeDeferBoundary(self, fn, batchToken) {
|
|
1902
|
+
deferRewire(self._core, fn, {
|
|
1903
|
+
batchToken,
|
|
1904
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1905
|
+
});
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
// src/node/node-rewire-runtime.ts
|
|
1909
|
+
function nodeRequestRewireNext(self, op) {
|
|
1910
|
+
deferRewire(self._core, () => self._applyRewireNext(op), {
|
|
1911
|
+
batchToken: currentBoundaryBatchToken(),
|
|
1912
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1913
|
+
});
|
|
1914
|
+
}
|
|
1915
|
+
function nodeRequestUpNext(self, msgs, towardDep) {
|
|
1916
|
+
deferRewire(
|
|
1917
|
+
self._core,
|
|
1918
|
+
() => {
|
|
1919
|
+
if (!self._released) self._up(msgs, towardDep);
|
|
1920
|
+
},
|
|
1921
|
+
{
|
|
1922
|
+
batchToken: currentBoundaryBatchToken(),
|
|
1923
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1924
|
+
}
|
|
1925
|
+
);
|
|
1926
|
+
}
|
|
1927
|
+
function nodeApplyRewireNext(self, op) {
|
|
1928
|
+
if (self._released) return;
|
|
1929
|
+
try {
|
|
1930
|
+
if (op.kind === "add") {
|
|
1931
|
+
const next = self._slot.deps.includes(op.dep) ? [...self._slot.deps] : [...self._slot.deps, op.dep];
|
|
1932
|
+
self._rewire(next, op.fn, { allowTerminalOwner: true });
|
|
1933
|
+
} else if (op.kind === "remove") {
|
|
1934
|
+
self._rewire(
|
|
1935
|
+
self._slot.deps.filter((d) => d !== op.dep),
|
|
1936
|
+
op.fn,
|
|
1937
|
+
{ allowTerminalOwner: true }
|
|
1938
|
+
);
|
|
1939
|
+
} else {
|
|
1940
|
+
self._rewire(self._dedupDeps(op.deps), op.fn, { allowTerminalOwner: true });
|
|
1941
|
+
}
|
|
1942
|
+
} catch (e) {
|
|
1943
|
+
self._down([["ERROR", errorPayload(e, "rewireNext op failed")]]);
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
function nodeRewire(self, newDeps, fn, opts = {}) {
|
|
1947
|
+
const node2 = self;
|
|
1948
|
+
if (self._value.terminal !== void 0 && !opts.allowTerminalOwner)
|
|
1949
|
+
throw new Error(
|
|
1950
|
+
"rewire: node is terminal (completed/errored) \u2014 cannot rewire (R-rewire / D42)"
|
|
1951
|
+
);
|
|
1952
|
+
if (self._wave.insideRunWave)
|
|
1953
|
+
throw new Error(
|
|
1954
|
+
"rewire: mid-fn topology mutation \u2014 a fn mutating its own deps mid-wave is the feedback cycle (R-rewire / D37)"
|
|
1955
|
+
);
|
|
1956
|
+
if (self._wave.inDepMutation)
|
|
1957
|
+
throw new Error(
|
|
1958
|
+
"rewire: reentrant dep mutation \u2014 another replaceDeps/subscribeDep/unsubscribeDep is in flight (R-rewire)"
|
|
1959
|
+
);
|
|
1960
|
+
if (newDeps.includes(node2)) throw new Error("rewire: self-dependency rejected (R-rewire / D42)");
|
|
1961
|
+
const oldDeps = self._slot.deps;
|
|
1962
|
+
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
1963
|
+
for (const d of added) {
|
|
1964
|
+
if (self._reachableUpstream(d, node2))
|
|
1965
|
+
throw new Error(
|
|
1966
|
+
"rewire: would create a cycle \u2014 dep already transitively depends on this node (R-rewire / D42)"
|
|
1967
|
+
);
|
|
1968
|
+
const dep = nodeRuntimeHost(d);
|
|
1969
|
+
if (dep._value.terminal !== void 0 && !dep._slot.resubscribable)
|
|
1970
|
+
throw new Error(
|
|
1971
|
+
"rewire: cannot add a non-resubscribable terminal dep \u2014 would wedge (R-rewire / D42)"
|
|
1972
|
+
);
|
|
1973
|
+
self._assertRewireDepOwner(d);
|
|
1974
|
+
}
|
|
1975
|
+
if (deferAfterBatchForTarget(node2, () => {
|
|
1976
|
+
self._rewire(newDeps, fn, { ...opts, allowTerminalOwner: true });
|
|
1977
|
+
})) {
|
|
1978
|
+
return true;
|
|
1979
|
+
}
|
|
1980
|
+
if (!self._lifecycle.activated) self._restoredActivationPending = false;
|
|
1981
|
+
self._wave.inDepMutation = true;
|
|
1982
|
+
self._wave.rewireRunPending = false;
|
|
1983
|
+
let zeroDepUnDirty = false;
|
|
1984
|
+
try {
|
|
1985
|
+
const oldHandle = self._slot.handle;
|
|
1986
|
+
self._slot.handle = self._slot.dispatcher.register(fn, self._slot.pool);
|
|
1987
|
+
if (oldHandle !== null) self._slot.dispatcher.unregister(oldHandle);
|
|
1988
|
+
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
1989
|
+
let removedDirtyContributor = false;
|
|
1990
|
+
for (const d of removed) {
|
|
1991
|
+
const oldIdx = oldDeps.indexOf(d);
|
|
1992
|
+
if (self._dep.dirty[oldIdx]) {
|
|
1993
|
+
removedDirtyContributor = true;
|
|
1994
|
+
self._wave.pending--;
|
|
1995
|
+
}
|
|
1996
|
+
if (self._lifecycle.activated) {
|
|
1997
|
+
const box = self._dep.idxBoxes[oldIdx];
|
|
1998
|
+
if (box) box.v = -1;
|
|
1999
|
+
const unsub = self._dep.unsubs[oldIdx];
|
|
2000
|
+
if (unsub) unsub();
|
|
2001
|
+
}
|
|
1008
2002
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
2003
|
+
const n = newDeps.length;
|
|
2004
|
+
const newBatch = new Array(n).fill(null);
|
|
2005
|
+
const newPrev = new Array(n).fill(SENTINEL);
|
|
2006
|
+
const newHasData = new Array(n).fill(false);
|
|
2007
|
+
const newDirty = new Array(n).fill(false);
|
|
2008
|
+
const newTier = new Array(n).fill(0);
|
|
2009
|
+
const newTerminal = new Array(n).fill(void 0);
|
|
2010
|
+
const newTerminalInput = new Array(n).fill(void 0);
|
|
2011
|
+
const newUnsubs = new Array(n);
|
|
2012
|
+
const newBoxes = new Array(n);
|
|
2013
|
+
for (let j = 0; j < n; j++) {
|
|
2014
|
+
const oldIdx = oldDeps.indexOf(newDeps[j]);
|
|
2015
|
+
if (oldIdx !== -1) {
|
|
2016
|
+
newBatch[j] = self._dep.batch[oldIdx];
|
|
2017
|
+
newPrev[j] = self._dep.prev[oldIdx];
|
|
2018
|
+
newHasData[j] = self._dep.hasData[oldIdx];
|
|
2019
|
+
newDirty[j] = self._dep.dirty[oldIdx];
|
|
2020
|
+
newTier[j] = self._dep.tier[oldIdx];
|
|
2021
|
+
newTerminal[j] = self._dep.terminal[oldIdx];
|
|
2022
|
+
newUnsubs[j] = self._dep.unsubs[oldIdx];
|
|
2023
|
+
const box = self._dep.idxBoxes[oldIdx];
|
|
2024
|
+
if (box) box.v = j;
|
|
2025
|
+
newBoxes[j] = box;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
self._slot.deps = newDeps;
|
|
2029
|
+
self._dep.batch = newBatch;
|
|
2030
|
+
self._dep.prev = newPrev;
|
|
2031
|
+
self._dep.hasData = newHasData;
|
|
2032
|
+
self._dep.dirty = newDirty;
|
|
2033
|
+
self._dep.tier = newTier;
|
|
2034
|
+
self._dep.terminal = newTerminal;
|
|
2035
|
+
self._dep.terminalInput = newTerminalInput;
|
|
2036
|
+
self._dep.unsubs = newUnsubs;
|
|
2037
|
+
self._dep.idxBoxes = newBoxes;
|
|
2038
|
+
self._dep.waveData = newDeps.map(() => []);
|
|
2039
|
+
self._dep.waveTokens = new Array(newDeps.length).fill(void 0);
|
|
2040
|
+
self._syncCtx = null;
|
|
2041
|
+
if (self._lifecycle.activated) {
|
|
2042
|
+
for (const d of added) self._subscribeDepAt(d);
|
|
2043
|
+
}
|
|
2044
|
+
notifyTopologyDepsChanged(node2, oldDeps, newDeps);
|
|
2045
|
+
if (removedDirtyContributor && self._wave.pending === 0 && self._value.status === "dirty") {
|
|
2046
|
+
if (newDeps.length > 0) self._wave.rewireRunPending = true;
|
|
2047
|
+
else zeroDepUnDirty = true;
|
|
1011
2048
|
}
|
|
2049
|
+
} finally {
|
|
2050
|
+
self._wave.inDepMutation = false;
|
|
2051
|
+
}
|
|
2052
|
+
if (self._wave.rewireRunPending) {
|
|
2053
|
+
self._wave.rewireRunPending = false;
|
|
2054
|
+
self._settleRewire();
|
|
2055
|
+
} else if (zeroDepUnDirty) {
|
|
2056
|
+
if (self._wave.emittedDirtyThisWave) self._down([["RESOLVED"]]);
|
|
2057
|
+
else self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1012
2058
|
}
|
|
2059
|
+
return false;
|
|
1013
2060
|
}
|
|
1014
|
-
|
|
2061
|
+
|
|
2062
|
+
// src/node/node.ts
|
|
2063
|
+
var Node = class _Node {
|
|
1015
2064
|
_core;
|
|
1016
2065
|
_id;
|
|
1017
2066
|
_slot;
|
|
@@ -1032,19 +2081,63 @@ var Node = class {
|
|
|
1032
2081
|
set _syncCtx(ctx) {
|
|
1033
2082
|
this._syncCtxState.value = ctx;
|
|
1034
2083
|
}
|
|
2084
|
+
static _retainIndirectRuntimeMethods(node2) {
|
|
2085
|
+
void node2._dep;
|
|
2086
|
+
void node2._hooks;
|
|
2087
|
+
void node2._restoredActivationPending;
|
|
2088
|
+
void node2._requestRewireNext;
|
|
2089
|
+
void node2._requestUpNext;
|
|
2090
|
+
void node2._applyRewireNext;
|
|
2091
|
+
void node2._reachableUpstream;
|
|
2092
|
+
void node2._assertRewireDepOwner;
|
|
2093
|
+
void node2._subscribeDepAt;
|
|
2094
|
+
void node2._seedRestoredDepAt;
|
|
2095
|
+
void node2._recordDepProjection;
|
|
2096
|
+
void node2._depProjectionHasData;
|
|
2097
|
+
void node2._receiveFromDep;
|
|
2098
|
+
void node2._releaseDepDirty;
|
|
2099
|
+
void node2._settleAfterAbsorbedTerminal;
|
|
2100
|
+
void node2._markDirty;
|
|
2101
|
+
void node2._maybeRun;
|
|
2102
|
+
void node2._settleRewire;
|
|
2103
|
+
void node2._tryRun;
|
|
2104
|
+
void node2._allDepsSettled;
|
|
2105
|
+
void node2._passthroughEmit;
|
|
2106
|
+
void node2._runWave;
|
|
2107
|
+
void node2._buildCtx;
|
|
2108
|
+
void node2._makeCtx;
|
|
2109
|
+
void node2._refreshCtx;
|
|
2110
|
+
void node2._makeState;
|
|
2111
|
+
void node2._markDemandRouted;
|
|
2112
|
+
void node2._forwardUp;
|
|
2113
|
+
void node2._isPullQuiet;
|
|
2114
|
+
void node2._isPaused;
|
|
2115
|
+
void node2._hasBoundaryPauseLock;
|
|
2116
|
+
void node2._isAsyncPool;
|
|
2117
|
+
void node2._pauseAcquire;
|
|
2118
|
+
void node2._pauseRelease;
|
|
2119
|
+
void node2._onResume;
|
|
2120
|
+
void node2._canFireDemand;
|
|
2121
|
+
void node2._deliverPullDemand;
|
|
2122
|
+
void node2._onDemand;
|
|
2123
|
+
void node2._firePullDemand;
|
|
2124
|
+
void node2._fireOwedDemandIfReady;
|
|
2125
|
+
void node2._shouldBufferOnPause;
|
|
2126
|
+
void node2._invalidate;
|
|
2127
|
+
void node2._allDepsTerminal;
|
|
2128
|
+
void node2._emitToSubs;
|
|
2129
|
+
}
|
|
1035
2130
|
constructor(deps, handleOrFn, opts = {}) {
|
|
1036
|
-
const core =
|
|
1037
|
-
constructingCore = void 0;
|
|
2131
|
+
const core = takeConstructingNodeCore();
|
|
1038
2132
|
const dispatcher = opts.dispatcher ?? defaultDispatcher;
|
|
1039
|
-
const environment =
|
|
1040
|
-
constructingEnvironment = void 0;
|
|
2133
|
+
const environment = takeConstructingEnvironmentDrivers() ?? EnvironmentDrivers.empty();
|
|
1041
2134
|
const pool = opts.pool ?? "sync";
|
|
1042
2135
|
const pausable = opts.pausable ?? true;
|
|
1043
2136
|
const pullLock = opts.pullId;
|
|
1044
2137
|
const pull = opts.pullId !== void 0;
|
|
1045
2138
|
if (pull && pausable === false)
|
|
1046
2139
|
throw new Error(
|
|
1047
|
-
"node: pullId is incompatible with pausable:false \u2014 a pull node
|
|
2140
|
+
"node: pullId is incompatible with pausable:false \u2014 a pull node uses the pausable delivery-content axis (R-pull / R-pause-modes / D55,D269)"
|
|
1048
2141
|
);
|
|
1049
2142
|
let handle;
|
|
1050
2143
|
if (handleOrFn === null) handle = null;
|
|
@@ -1067,7 +2160,6 @@ var Node = class {
|
|
|
1067
2160
|
value.status = "settled";
|
|
1068
2161
|
}
|
|
1069
2162
|
const pauseLockset = /* @__PURE__ */ new Set();
|
|
1070
|
-
if (pull) pauseLockset.add(pullLock);
|
|
1071
2163
|
this._core = core ?? new NodeCore();
|
|
1072
2164
|
const created = this._core.createSlot(
|
|
1073
2165
|
{
|
|
@@ -1108,7 +2200,9 @@ var Node = class {
|
|
|
1108
2200
|
pauseLockset,
|
|
1109
2201
|
pausedDepWaveOccurred: false,
|
|
1110
2202
|
pauseBuffer: [],
|
|
1111
|
-
demandOwed:
|
|
2203
|
+
demandOwed: void 0,
|
|
2204
|
+
activePull: void 0,
|
|
2205
|
+
pullDirtyOwed: false,
|
|
1112
2206
|
inDeliverDemand: false
|
|
1113
2207
|
},
|
|
1114
2208
|
privateState: { value: SENTINEL, persist: false },
|
|
@@ -1165,10 +2259,11 @@ var Node = class {
|
|
|
1165
2259
|
this._wave.batchDirtyOwed = false;
|
|
1166
2260
|
this._control.pauseBuffer = [];
|
|
1167
2261
|
this._control.pausedDepWaveOccurred = false;
|
|
1168
|
-
this._control.demandOwed =
|
|
2262
|
+
this._control.demandOwed = void 0;
|
|
2263
|
+
this._control.activePull = void 0;
|
|
2264
|
+
this._control.pullDirtyOwed = false;
|
|
1169
2265
|
this._control.inDeliverDemand = false;
|
|
1170
2266
|
this._control.pauseLockset.clear();
|
|
1171
|
-
if (this._slot.pull) this._control.pauseLockset.add(this._slot.pullLock);
|
|
1172
2267
|
this._privateState.value = state.ctxState.value;
|
|
1173
2268
|
this._privateState.persist = state.ctxState.persist;
|
|
1174
2269
|
if (state.version === false) {
|
|
@@ -1206,18 +2301,18 @@ var Node = class {
|
|
|
1206
2301
|
runtimeQuiescenceReaders.set(this, () => this._isRuntimeQuiescentForRelease());
|
|
1207
2302
|
subscriberCountReaders.set(this, () => this._subscriberCount());
|
|
1208
2303
|
activationReaders.set(this, () => this._lifecycle.activated);
|
|
2304
|
+
_Node._retainIndirectRuntimeMethods(this);
|
|
1209
2305
|
}
|
|
1210
|
-
/** R-pull (D55): true while a pull node is
|
|
2306
|
+
/** R-pull (D55/D272): true while a pull node is not serving a PULL demand pulse. */
|
|
1211
2307
|
_isPullQuiet() {
|
|
1212
|
-
return this._slot.pull && this._control.
|
|
2308
|
+
return this._slot.pull && this._control.activePull === void 0;
|
|
1213
2309
|
}
|
|
1214
2310
|
/**
|
|
1215
|
-
* R-pull (
|
|
1216
|
-
* triggers computation). A consumer demands one delivery by cone-routing
|
|
1217
|
-
* reference): `ctx.up([["
|
|
1218
|
-
* `ctx.upNext([["
|
|
1219
|
-
*
|
|
1220
|
-
* for inspection/describe; routing matches by the pullId value carried in the RESUME, by identity.
|
|
2311
|
+
* R-pull (D269/D272): this pull node's pullId (pure data, like {@link cache}/{@link handle} —
|
|
2312
|
+
* never triggers computation). A consumer demands one delivery by cone-routing PULL of it (no
|
|
2313
|
+
* node reference): `ctx.up([["PULL", { pullId }]])` (immediate; loops back → D37 for a self-read
|
|
2314
|
+
* dep) or `ctx.upNext([["PULL", { pullId }]])` (boundary-deferred self-demand). Undefined for a
|
|
2315
|
+
* non-pull node. The author writes the pullId verbatim; routing matches by identity.
|
|
1221
2316
|
*/
|
|
1222
2317
|
get pullId() {
|
|
1223
2318
|
return this._slot.pullLock;
|
|
@@ -1311,58 +2406,6 @@ var Node = class {
|
|
|
1311
2406
|
exitWave();
|
|
1312
2407
|
}
|
|
1313
2408
|
}
|
|
1314
|
-
// ── deferred self-rewire (R-rewire-deferred / D47): ctx.rewireNext drain support ──
|
|
1315
|
-
/**
|
|
1316
|
-
* Enqueue a deferred self-rewire op (issued from this node's fn via `ctx.rewireNext`).
|
|
1317
|
-
* Applied at the committed wave boundary (boundary.ts drain), never in place — the in-fn
|
|
1318
|
-
* immediate path (`subscribeDep`/`replaceDeps`/`unsubscribeDep`) still throws mid-run (D37/R-reentrancy).
|
|
1319
|
-
*/
|
|
1320
|
-
_requestRewireNext(op) {
|
|
1321
|
-
deferRewire(this._core, () => this._applyRewireNext(op), {
|
|
1322
|
-
batchToken: currentBoundaryBatchToken(),
|
|
1323
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
1324
|
-
});
|
|
1325
|
-
}
|
|
1326
|
-
/**
|
|
1327
|
-
* Enqueue a deferred up-going control wave (R-up-routing / R-pull / D59): at the committed wave
|
|
1328
|
-
* boundary, route `msgs` up from THIS node (broadcast, or up the single `towardDep` edge). The
|
|
1329
|
-
* deferred form of `ctx.up` — the SELF-demand path: a consumer issues `ctx.upNext([[RESUME,
|
|
1330
|
-
* pullId]])` to demand a dep it ALSO reads; the demand applies at the boundary (not mid-fn), so
|
|
1331
|
-
* the pull node's delivery loops back as a FRESH wave rather than re-entering the consumer (D37 /
|
|
1332
|
-
* R-reentrancy). Rides the same R-rewire-deferred (D47) drain as ctx.rewireNext.
|
|
1333
|
-
*/
|
|
1334
|
-
_requestUpNext(msgs, towardDep) {
|
|
1335
|
-
deferRewire(
|
|
1336
|
-
this._core,
|
|
1337
|
-
() => {
|
|
1338
|
-
if (!this._released) this._up(msgs, towardDep);
|
|
1339
|
-
},
|
|
1340
|
-
{
|
|
1341
|
-
batchToken: currentBoundaryBatchToken(),
|
|
1342
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
1343
|
-
}
|
|
1344
|
-
);
|
|
1345
|
-
}
|
|
1346
|
-
/** Apply one queued self-rewire at the boundary (drain thunk). */
|
|
1347
|
-
_applyRewireNext(op) {
|
|
1348
|
-
if (this._released) return;
|
|
1349
|
-
try {
|
|
1350
|
-
if (op.kind === "add") {
|
|
1351
|
-
const next = this._slot.deps.includes(op.dep) ? [...this._slot.deps] : [...this._slot.deps, op.dep];
|
|
1352
|
-
this._rewire(next, op.fn, { allowTerminalOwner: true });
|
|
1353
|
-
} else if (op.kind === "remove") {
|
|
1354
|
-
this._rewire(
|
|
1355
|
-
this._slot.deps.filter((d) => d !== op.dep),
|
|
1356
|
-
op.fn,
|
|
1357
|
-
{ allowTerminalOwner: true }
|
|
1358
|
-
);
|
|
1359
|
-
} else {
|
|
1360
|
-
this._rewire(this._dedupDeps(op.deps), op.fn, { allowTerminalOwner: true });
|
|
1361
|
-
}
|
|
1362
|
-
} catch (e) {
|
|
1363
|
-
this._down([["ERROR", errorPayload(e, "rewireNext op failed")]]);
|
|
1364
|
-
}
|
|
1365
|
-
}
|
|
1366
2409
|
// ── rewire (R-rewire / D42): intra-graph runtime topology mutation ──
|
|
1367
2410
|
/**
|
|
1368
2411
|
* Replace this node's deps atomically (surgical, Option-C). Requires an explicit
|
|
@@ -1390,6 +2433,15 @@ var Node = class {
|
|
|
1390
2433
|
fn
|
|
1391
2434
|
);
|
|
1392
2435
|
}
|
|
2436
|
+
_requestRewireNext(op) {
|
|
2437
|
+
nodeRequestRewireNext(nodeRuntimeHost(this), op);
|
|
2438
|
+
}
|
|
2439
|
+
_requestUpNext(msgs, towardDep) {
|
|
2440
|
+
nodeRequestUpNext(nodeRuntimeHost(this), msgs, towardDep);
|
|
2441
|
+
}
|
|
2442
|
+
_applyRewireNext(op) {
|
|
2443
|
+
nodeApplyRewireNext(nodeRuntimeHost(this), op);
|
|
2444
|
+
}
|
|
1393
2445
|
_dedupDeps(deps) {
|
|
1394
2446
|
const seen = /* @__PURE__ */ new Set();
|
|
1395
2447
|
const out = [];
|
|
@@ -1400,7 +2452,6 @@ var Node = class {
|
|
|
1400
2452
|
}
|
|
1401
2453
|
return out;
|
|
1402
2454
|
}
|
|
1403
|
-
/** Is `target` reachable upstream from `from` (following deps)? Cycle-prevention DFS. */
|
|
1404
2455
|
_reachableUpstream(from, target) {
|
|
1405
2456
|
const seen = /* @__PURE__ */ new Set();
|
|
1406
2457
|
const stack = [from];
|
|
@@ -1410,1025 +2461,171 @@ var Node = class {
|
|
|
1410
2461
|
if (n === target) return true;
|
|
1411
2462
|
if (seen.has(n)) continue;
|
|
1412
2463
|
seen.add(n);
|
|
1413
|
-
for (const d of n._slot.deps) stack.push(d);
|
|
2464
|
+
for (const d of nodeRuntimeHost(n)._slot.deps) stack.push(d);
|
|
1414
2465
|
}
|
|
1415
2466
|
return false;
|
|
1416
2467
|
}
|
|
1417
2468
|
_assertRewireDepOwner(dep) {
|
|
1418
2469
|
const selfOwner = getNodeOwner(this);
|
|
1419
2470
|
const depOwner = getNodeOwner(dep);
|
|
1420
|
-
if (selfOwner !== void 0 && depOwner !== void 0 && selfOwner !== depOwner)
|
|
2471
|
+
if (selfOwner !== void 0 && depOwner !== void 0 && selfOwner !== depOwner)
|
|
1421
2472
|
throw new Error(
|
|
1422
2473
|
"rewire: dep belongs to a different graph; cross-graph deps require a wire bridge (D22 / R-graph-domain)"
|
|
1423
2474
|
);
|
|
1424
|
-
}
|
|
1425
2475
|
}
|
|
1426
2476
|
_rewire(newDeps, fn, opts = {}) {
|
|
1427
|
-
|
|
1428
|
-
throw new Error(
|
|
1429
|
-
"rewire: node is terminal (completed/errored) \u2014 cannot rewire (R-rewire / D42)"
|
|
1430
|
-
);
|
|
1431
|
-
if (this._wave.insideRunWave)
|
|
1432
|
-
throw new Error(
|
|
1433
|
-
"rewire: mid-fn topology mutation \u2014 a fn mutating its own deps mid-wave is the feedback cycle (R-rewire / D37)"
|
|
1434
|
-
);
|
|
1435
|
-
if (this._wave.inDepMutation)
|
|
1436
|
-
throw new Error(
|
|
1437
|
-
"rewire: reentrant dep mutation \u2014 another replaceDeps/subscribeDep/unsubscribeDep is in flight (R-rewire)"
|
|
1438
|
-
);
|
|
1439
|
-
if (newDeps.includes(this))
|
|
1440
|
-
throw new Error("rewire: self-dependency rejected (R-rewire / D42)");
|
|
1441
|
-
const oldDeps = this._slot.deps;
|
|
1442
|
-
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
1443
|
-
for (const d of added) {
|
|
1444
|
-
if (this._reachableUpstream(d, this))
|
|
1445
|
-
throw new Error(
|
|
1446
|
-
"rewire: would create a cycle \u2014 dep already transitively depends on this node (R-rewire / D42)"
|
|
1447
|
-
);
|
|
1448
|
-
if (d._value.terminal !== void 0 && !d._slot.resubscribable)
|
|
1449
|
-
throw new Error(
|
|
1450
|
-
"rewire: cannot add a non-resubscribable terminal dep \u2014 would wedge (R-rewire / D42)"
|
|
1451
|
-
);
|
|
1452
|
-
this._assertRewireDepOwner(d);
|
|
1453
|
-
}
|
|
1454
|
-
if (deferAfterBatchForTarget(this, () => {
|
|
1455
|
-
this._rewire(newDeps, fn, { ...opts, allowTerminalOwner: true });
|
|
1456
|
-
})) {
|
|
1457
|
-
return true;
|
|
1458
|
-
}
|
|
1459
|
-
if (!this._lifecycle.activated) this._restoredActivationPending = false;
|
|
1460
|
-
this._wave.inDepMutation = true;
|
|
1461
|
-
this._wave.rewireRunPending = false;
|
|
1462
|
-
let zeroDepUnDirty = false;
|
|
1463
|
-
try {
|
|
1464
|
-
const oldHandle = this._slot.handle;
|
|
1465
|
-
this._slot.handle = this._slot.dispatcher.register(fn, this._slot.pool);
|
|
1466
|
-
if (oldHandle !== null) this._slot.dispatcher.unregister(oldHandle);
|
|
1467
|
-
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
1468
|
-
let removedDirtyContributor = false;
|
|
1469
|
-
for (const d of removed) {
|
|
1470
|
-
const oldIdx = oldDeps.indexOf(d);
|
|
1471
|
-
if (this._dep.dirty[oldIdx]) {
|
|
1472
|
-
removedDirtyContributor = true;
|
|
1473
|
-
this._wave.pending--;
|
|
1474
|
-
}
|
|
1475
|
-
if (this._lifecycle.activated) {
|
|
1476
|
-
const box = this._dep.idxBoxes[oldIdx];
|
|
1477
|
-
if (box) box.v = -1;
|
|
1478
|
-
const unsub = this._dep.unsubs[oldIdx];
|
|
1479
|
-
if (unsub) unsub();
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
const n = newDeps.length;
|
|
1483
|
-
const newBatch = new Array(n).fill(null);
|
|
1484
|
-
const newPrev = new Array(n).fill(SENTINEL);
|
|
1485
|
-
const newHasData = new Array(n).fill(false);
|
|
1486
|
-
const newDirty = new Array(n).fill(false);
|
|
1487
|
-
const newTier = new Array(n).fill(0);
|
|
1488
|
-
const newTerminal = new Array(n).fill(void 0);
|
|
1489
|
-
const newTerminalInput = new Array(n).fill(void 0);
|
|
1490
|
-
const newUnsubs = new Array(n);
|
|
1491
|
-
const newBoxes = new Array(n);
|
|
1492
|
-
for (let j = 0; j < n; j++) {
|
|
1493
|
-
const oldIdx = oldDeps.indexOf(newDeps[j]);
|
|
1494
|
-
if (oldIdx !== -1) {
|
|
1495
|
-
newBatch[j] = this._dep.batch[oldIdx];
|
|
1496
|
-
newPrev[j] = this._dep.prev[oldIdx];
|
|
1497
|
-
newHasData[j] = this._dep.hasData[oldIdx];
|
|
1498
|
-
newDirty[j] = this._dep.dirty[oldIdx];
|
|
1499
|
-
newTier[j] = this._dep.tier[oldIdx];
|
|
1500
|
-
newTerminal[j] = this._dep.terminal[oldIdx];
|
|
1501
|
-
newUnsubs[j] = this._dep.unsubs[oldIdx];
|
|
1502
|
-
const box = this._dep.idxBoxes[oldIdx];
|
|
1503
|
-
if (box) box.v = j;
|
|
1504
|
-
newBoxes[j] = box;
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
this._slot.deps = newDeps;
|
|
1508
|
-
this._dep.batch = newBatch;
|
|
1509
|
-
this._dep.prev = newPrev;
|
|
1510
|
-
this._dep.hasData = newHasData;
|
|
1511
|
-
this._dep.dirty = newDirty;
|
|
1512
|
-
this._dep.tier = newTier;
|
|
1513
|
-
this._dep.terminal = newTerminal;
|
|
1514
|
-
this._dep.terminalInput = newTerminalInput;
|
|
1515
|
-
this._dep.unsubs = newUnsubs;
|
|
1516
|
-
this._dep.idxBoxes = newBoxes;
|
|
1517
|
-
this._dep.waveData = newDeps.map(() => []);
|
|
1518
|
-
this._dep.waveTokens = new Array(newDeps.length).fill(void 0);
|
|
1519
|
-
this._syncCtx = null;
|
|
1520
|
-
if (this._lifecycle.activated) {
|
|
1521
|
-
for (const d of added) this._subscribeDepAt(d);
|
|
1522
|
-
}
|
|
1523
|
-
notifyTopologyDepsChanged(this, oldDeps, newDeps);
|
|
1524
|
-
if (removedDirtyContributor && this._wave.pending === 0 && this._value.status === "dirty") {
|
|
1525
|
-
if (newDeps.length > 0) this._wave.rewireRunPending = true;
|
|
1526
|
-
else zeroDepUnDirty = true;
|
|
1527
|
-
}
|
|
1528
|
-
} finally {
|
|
1529
|
-
this._wave.inDepMutation = false;
|
|
1530
|
-
}
|
|
1531
|
-
if (this._wave.rewireRunPending) {
|
|
1532
|
-
this._wave.rewireRunPending = false;
|
|
1533
|
-
this._settleRewire();
|
|
1534
|
-
} else if (zeroDepUnDirty) {
|
|
1535
|
-
if (this._wave.emittedDirtyThisWave) this._down([["RESOLVED"]]);
|
|
1536
|
-
else this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
1537
|
-
}
|
|
1538
|
-
return false;
|
|
2477
|
+
return nodeRewire(nodeRuntimeHost(this), newDeps, fn, opts);
|
|
1539
2478
|
}
|
|
1540
2479
|
// ── activation / deactivation (lazy; R-rom-ram) ──
|
|
1541
2480
|
_activate() {
|
|
1542
|
-
this
|
|
1543
|
-
const seedRestoredDeps = this._restoredActivationPending;
|
|
1544
|
-
this._restoredActivationPending = false;
|
|
1545
|
-
if (this._slot.pull) this._control.pauseLockset.add(this._slot.pullLock);
|
|
1546
|
-
this._dep.unsubs = new Array(this._slot.deps.length);
|
|
1547
|
-
this._dep.idxBoxes = new Array(this._slot.deps.length);
|
|
1548
|
-
for (const dep of this._slot.deps)
|
|
1549
|
-
this._subscribeDepAt(dep, { seedRestored: seedRestoredDeps });
|
|
1550
|
-
if (this._slot.deps.length === 0 && this._slot.handle !== null && !this._wave.hasCalledFnOnce) {
|
|
1551
|
-
this._runWave();
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
/**
|
|
1555
|
-
* Subscribe to a dep. The dispatch callback reads the dep's CURRENT index from a
|
|
1556
|
-
* mutable box (O(1)); a surgical rewire that reorders kept deps just updates the box
|
|
1557
|
-
* (R-rewire Option-C / D42) — no re-subscribe, no per-message indexOf scan. A removed
|
|
1558
|
-
* dep's box is set to -1 so any stale in-flight callback drops (drain).
|
|
1559
|
-
*/
|
|
1560
|
-
_subscribeDepAt(depNode, opts = {}) {
|
|
1561
|
-
const idx0 = this._slot.deps.indexOf(depNode);
|
|
1562
|
-
const box = { v: idx0 };
|
|
1563
|
-
let ignoreInitialPush = opts.seedRestored === true;
|
|
1564
|
-
if (ignoreInitialPush && idx0 !== -1) {
|
|
1565
|
-
this._seedRestoredDepAt(idx0, depNode);
|
|
1566
|
-
if (depNode._value.terminal !== void 0 && !depNode._slot.resubscribable) {
|
|
1567
|
-
this._dep.unsubs[idx0] = () => {
|
|
1568
|
-
};
|
|
1569
|
-
this._dep.idxBoxes[idx0] = box;
|
|
1570
|
-
return;
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
const unsub = depNode.subscribe((msg, delivery) => {
|
|
1574
|
-
if (ignoreInitialPush && delivery === void 0) return;
|
|
1575
|
-
if (ignoreInitialPush) ignoreInitialPush = false;
|
|
1576
|
-
if (box.v === -1) return;
|
|
1577
|
-
this._receiveFromDep(box.v, msg, delivery);
|
|
1578
|
-
});
|
|
1579
|
-
if (ignoreInitialPush && idx0 !== -1 && box.v !== -1) this._seedRestoredDepAt(idx0, depNode);
|
|
1580
|
-
ignoreInitialPush = false;
|
|
1581
|
-
if (idx0 !== -1) {
|
|
1582
|
-
this._dep.unsubs[idx0] = unsub;
|
|
1583
|
-
this._dep.idxBoxes[idx0] = box;
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
_seedRestoredDepAt(idx, depNode) {
|
|
1587
|
-
const seedData = depNode._value.hasData && !depNode._slot.pull;
|
|
1588
|
-
this._dep.batch[idx] = null;
|
|
1589
|
-
this._dep.waveData[idx] = [];
|
|
1590
|
-
this._dep.waveTokens[idx] = void 0;
|
|
1591
|
-
this._dep.prev[idx] = seedData ? depNode._value.cache : SENTINEL;
|
|
1592
|
-
this._dep.hasData[idx] = seedData;
|
|
1593
|
-
this._dep.dirty[idx] = false;
|
|
1594
|
-
this._dep.tier[idx] = seedData ? 3 : 0;
|
|
1595
|
-
this._dep.terminal[idx] = depNode._value.terminal;
|
|
1596
|
-
this._dep.terminalInput[idx] = void 0;
|
|
2481
|
+
nodeActivate(nodeRuntimeHost(this));
|
|
1597
2482
|
}
|
|
1598
2483
|
_deactivate() {
|
|
1599
|
-
this
|
|
1600
|
-
for (const u of this._dep.unsubs) if (u) u();
|
|
1601
|
-
this._dep.unsubs = [];
|
|
1602
|
-
this._dep.idxBoxes = [];
|
|
1603
|
-
for (const fn of this._hooks.onDeactivation) fn();
|
|
1604
|
-
this._hooks.onDeactivation = [];
|
|
1605
|
-
this._hooks.onInvalidate = [];
|
|
1606
|
-
const isCompute = this._slot.handle !== null || this._slot.deps.length > 0;
|
|
1607
|
-
if (isCompute) {
|
|
1608
|
-
this._value.cache = SENTINEL;
|
|
1609
|
-
this._value.hasData = false;
|
|
1610
|
-
this._value.status = "sentinel";
|
|
1611
|
-
}
|
|
1612
|
-
this._resetDepState();
|
|
1613
|
-
this._wave.hasCalledFnOnce = false;
|
|
1614
|
-
this._control.pauseLockset.clear();
|
|
1615
|
-
this._control.pauseBuffer = [];
|
|
1616
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1617
|
-
this._control.demandOwed = false;
|
|
1618
|
-
this._value.replayRing = [];
|
|
1619
|
-
if (!this._privateState.persist) this._privateState.value = SENTINEL;
|
|
2484
|
+
nodeDeactivate(nodeRuntimeHost(this));
|
|
1620
2485
|
}
|
|
1621
2486
|
_assertNotReleased(op) {
|
|
1622
2487
|
if (this._released)
|
|
1623
2488
|
throw new Error(`${op}: node has been released from its graph lifecycle (D122)`);
|
|
1624
2489
|
}
|
|
1625
2490
|
_subscriberCount() {
|
|
1626
|
-
return this
|
|
2491
|
+
return nodeSubscriberCount(nodeRuntimeHost(this));
|
|
1627
2492
|
}
|
|
1628
2493
|
_isRuntimeQuiescentForRelease() {
|
|
1629
|
-
|
|
1630
|
-
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);
|
|
2494
|
+
return nodeIsRuntimeQuiescentForRelease(nodeRuntimeHost(this));
|
|
1631
2495
|
}
|
|
1632
2496
|
_releaseRuntime() {
|
|
1633
|
-
|
|
1634
|
-
this._released = true;
|
|
1635
|
-
releasedNodes.add(this);
|
|
1636
|
-
let releaseError;
|
|
1637
|
-
const recordReleaseError = (error) => {
|
|
1638
|
-
if (releaseError === void 0) releaseError = error;
|
|
1639
|
-
};
|
|
1640
|
-
this._lifecycle.activated = false;
|
|
1641
|
-
for (const u of this._dep.unsubs) {
|
|
1642
|
-
try {
|
|
1643
|
-
u();
|
|
1644
|
-
} catch (error) {
|
|
1645
|
-
recordReleaseError(error);
|
|
1646
|
-
}
|
|
1647
|
-
}
|
|
1648
|
-
for (const fn of this._hooks.onDeactivation) {
|
|
1649
|
-
try {
|
|
1650
|
-
fn();
|
|
1651
|
-
} catch (error) {
|
|
1652
|
-
recordReleaseError(error);
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
this._dep.unsubs = [];
|
|
1656
|
-
this._dep.idxBoxes = [];
|
|
1657
|
-
this._lifecycle.subscribers.clear();
|
|
1658
|
-
if (this._slot.handle !== null) {
|
|
1659
|
-
this._slot.dispatcher.unregister(this._slot.handle);
|
|
1660
|
-
this._slot.handle = null;
|
|
1661
|
-
}
|
|
1662
|
-
this._slot.deps = [];
|
|
1663
|
-
this._dep.batch = [];
|
|
1664
|
-
this._dep.waveData = [];
|
|
1665
|
-
this._dep.waveTokens = [];
|
|
1666
|
-
this._dep.prev = [];
|
|
1667
|
-
this._dep.hasData = [];
|
|
1668
|
-
this._dep.dirty = [];
|
|
1669
|
-
this._dep.tier = [];
|
|
1670
|
-
this._dep.terminal = [];
|
|
1671
|
-
this._dep.terminalInput = [];
|
|
1672
|
-
this._value.cache = SENTINEL;
|
|
1673
|
-
this._value.hasData = false;
|
|
1674
|
-
this._value.status = "sentinel";
|
|
1675
|
-
this._value.terminal = void 0;
|
|
1676
|
-
this._value.replayRing = [];
|
|
1677
|
-
this._privateState.value = SENTINEL;
|
|
1678
|
-
this._privateState.persist = false;
|
|
1679
|
-
this._syncCtx = null;
|
|
1680
|
-
this._resetDepState();
|
|
1681
|
-
this._hooks.onDeactivation = [];
|
|
1682
|
-
this._hooks.onInvalidate = [];
|
|
1683
|
-
this._control.pauseLockset.clear();
|
|
1684
|
-
this._control.pauseBuffer = [];
|
|
1685
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1686
|
-
this._control.demandOwed = false;
|
|
1687
|
-
this._restoredActivationPending = false;
|
|
1688
|
-
checkpointReaders.delete(this);
|
|
1689
|
-
restoreWriters.delete(this);
|
|
1690
|
-
runtimeReleasers.delete(this);
|
|
1691
|
-
runtimeQuiescenceReaders.delete(this);
|
|
1692
|
-
subscriberCountReaders.delete(this);
|
|
1693
|
-
activationReaders.delete(this);
|
|
1694
|
-
ownerTokens.delete(this);
|
|
1695
|
-
topologyDepsChangedObservers.delete(this);
|
|
1696
|
-
this._core.releaseSlot(this._id);
|
|
1697
|
-
if (releaseError !== void 0) throw releaseError;
|
|
2497
|
+
nodeReleaseRuntime(nodeRuntimeHost(this));
|
|
1698
2498
|
}
|
|
1699
2499
|
_resetDepState() {
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
this._dep.tier[i] = 0;
|
|
1709
|
-
this._dep.terminal[i] = void 0;
|
|
1710
|
-
this._dep.terminalInput[i] = void 0;
|
|
1711
|
-
}
|
|
1712
|
-
this._wave.pending = 0;
|
|
1713
|
-
this._wave.emittedDirtyThisWave = false;
|
|
1714
|
-
}
|
|
1715
|
-
// ── upstream wave receive (two-phase + diamond) ──
|
|
2500
|
+
nodeResetDepState(nodeRuntimeHost(this));
|
|
2501
|
+
}
|
|
2502
|
+
_subscribeDepAt(depNode, opts = {}) {
|
|
2503
|
+
nodeSubscribeDepAt(nodeRuntimeHost(this), depNode, opts);
|
|
2504
|
+
}
|
|
2505
|
+
_seedRestoredDepAt(idx, depNode) {
|
|
2506
|
+
nodeSeedRestoredDepAt(nodeRuntimeHost(this), idx, depNode);
|
|
2507
|
+
}
|
|
1716
2508
|
_recordDepProjection(idx, delivery) {
|
|
1717
|
-
|
|
1718
|
-
if (this._dep.waveTokens[idx] !== token) {
|
|
1719
|
-
this._dep.waveData[idx].push([]);
|
|
1720
|
-
this._dep.waveTokens[idx] = token;
|
|
1721
|
-
}
|
|
1722
|
-
return this._dep.waveData[idx][this._dep.waveData[idx].length - 1];
|
|
2509
|
+
return nodeRecordDepProjection(nodeRuntimeHost(this), idx, delivery);
|
|
1723
2510
|
}
|
|
1724
2511
|
_depProjectionHasData(idx) {
|
|
1725
|
-
|
|
1726
|
-
return projection?.some((v) => v !== SENTINEL) ?? false;
|
|
2512
|
+
return nodeDepProjectionHasData(nodeRuntimeHost(this), idx);
|
|
1727
2513
|
}
|
|
1728
2514
|
_receiveFromDep(idx, msg, delivery) {
|
|
1729
|
-
|
|
1730
|
-
const t = msg[0];
|
|
1731
|
-
if (t === "START") return;
|
|
1732
|
-
const isLastInDeliveredWave = delivery?.last ?? true;
|
|
1733
|
-
if (this._value.terminal !== void 0) {
|
|
1734
|
-
if (t === "TEARDOWN") this._down([["TEARDOWN"]]);
|
|
1735
|
-
return;
|
|
1736
|
-
}
|
|
1737
|
-
if (t === "INVALIDATE") {
|
|
1738
|
-
const projection = this._recordDepProjection(idx, delivery);
|
|
1739
|
-
projection.push(SENTINEL);
|
|
1740
|
-
if (projection.some((v) => v !== SENTINEL) && isLastInDeliveredWave) this._maybeRun();
|
|
1741
|
-
this._dep.prev[idx] = SENTINEL;
|
|
1742
|
-
this._dep.hasData[idx] = false;
|
|
1743
|
-
this._dep.batch[idx] = null;
|
|
1744
|
-
if (this._dep.dirty[idx]) {
|
|
1745
|
-
this._dep.dirty[idx] = false;
|
|
1746
|
-
this._wave.pending--;
|
|
1747
|
-
}
|
|
1748
|
-
if (this._control.pausedDepWaveOccurred && this._dep.batch.every((b) => b === null)) {
|
|
1749
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1750
|
-
}
|
|
1751
|
-
const hadData = this._value.hasData;
|
|
1752
|
-
this._invalidate();
|
|
1753
|
-
if (this._wave.pending === 0 && this._wave.emittedDirtyThisWave) {
|
|
1754
|
-
if (!hadData) this._down([["RESOLVED"]]);
|
|
1755
|
-
else this._wave.emittedDirtyThisWave = false;
|
|
1756
|
-
}
|
|
1757
|
-
this._fireOwedDemandIfReady();
|
|
1758
|
-
return;
|
|
1759
|
-
}
|
|
1760
|
-
if (isTerminal(t)) {
|
|
1761
|
-
const isError = t === "ERROR";
|
|
1762
|
-
const errPayload = isError ? msg[1] : void 0;
|
|
1763
|
-
this._dep.terminal[idx] = isError ? errPayload : true;
|
|
1764
|
-
this._dep.terminalInput[idx] = isError ? errPayload : true;
|
|
1765
|
-
this._releaseDepDirty(idx);
|
|
1766
|
-
const ranValueBeforeTerminal = this._depProjectionHasData(idx) && isLastInDeliveredWave;
|
|
1767
|
-
if (ranValueBeforeTerminal) this._maybeRun();
|
|
1768
|
-
if (isError && this._slot.errorWhenDepsError) {
|
|
1769
|
-
this._down([["ERROR", errPayload]]);
|
|
1770
|
-
} else if (this._slot.terminalAsRealInput) {
|
|
1771
|
-
if (ranValueBeforeTerminal) {
|
|
1772
|
-
this._fireOwedDemandIfReady();
|
|
1773
|
-
return;
|
|
1774
|
-
}
|
|
1775
|
-
this._maybeRun();
|
|
1776
|
-
} else if (this._slot.completeWhenDepsComplete && this._allDepsTerminal()) {
|
|
1777
|
-
this._down([["COMPLETE"]]);
|
|
1778
|
-
} else {
|
|
1779
|
-
this._settleAfterAbsorbedTerminal();
|
|
1780
|
-
}
|
|
1781
|
-
this._fireOwedDemandIfReady();
|
|
1782
|
-
return;
|
|
1783
|
-
}
|
|
1784
|
-
if (t === "TEARDOWN") {
|
|
1785
|
-
this._down([["TEARDOWN"]]);
|
|
1786
|
-
return;
|
|
1787
|
-
}
|
|
1788
|
-
if (t === "DIRTY") {
|
|
1789
|
-
if (!this._dep.dirty[idx]) {
|
|
1790
|
-
this._dep.dirty[idx] = true;
|
|
1791
|
-
this._wave.pending++;
|
|
1792
|
-
this._dep.tier[idx] = 2;
|
|
1793
|
-
this._markDirty();
|
|
1794
|
-
}
|
|
1795
|
-
return;
|
|
1796
|
-
}
|
|
1797
|
-
if (t === "DATA") {
|
|
1798
|
-
const v = msg[1];
|
|
1799
|
-
this._recordDepProjection(idx, delivery).push(v);
|
|
1800
|
-
const b = this._dep.batch[idx];
|
|
1801
|
-
if (b === null) this._dep.batch[idx] = [v];
|
|
1802
|
-
else b.push(v);
|
|
1803
|
-
this._dep.prev[idx] = v;
|
|
1804
|
-
this._dep.hasData[idx] = true;
|
|
1805
|
-
this._dep.tier[idx] = 3;
|
|
1806
|
-
if (this._dep.dirty[idx]) {
|
|
1807
|
-
this._dep.dirty[idx] = false;
|
|
1808
|
-
this._wave.pending--;
|
|
1809
|
-
}
|
|
1810
|
-
if (isLastInDeliveredWave) this._maybeRun();
|
|
1811
|
-
this._fireOwedDemandIfReady();
|
|
1812
|
-
return;
|
|
1813
|
-
}
|
|
1814
|
-
if (t === "RESOLVED") {
|
|
1815
|
-
this._recordDepProjection(idx, delivery);
|
|
1816
|
-
this._dep.tier[idx] = 3;
|
|
1817
|
-
if (this._dep.dirty[idx]) {
|
|
1818
|
-
this._dep.dirty[idx] = false;
|
|
1819
|
-
this._wave.pending--;
|
|
1820
|
-
}
|
|
1821
|
-
if (isLastInDeliveredWave) this._maybeRun();
|
|
1822
|
-
this._fireOwedDemandIfReady();
|
|
1823
|
-
return;
|
|
1824
|
-
}
|
|
2515
|
+
nodeReceiveFromDep(nodeRuntimeHost(this), idx, msg, delivery);
|
|
1825
2516
|
}
|
|
1826
|
-
/**
|
|
1827
|
-
* R-terminal-settles-dirty (B35): release a dep's outstanding in-wave DIRTY contribution.
|
|
1828
|
-
* A settle-class event for that dep (DATA/RESOLVED inline above, INVALIDATE, and now
|
|
1829
|
-
* COMPLETE/ERROR) clears its dirty flag + decrements _pending. No-op if the dep already
|
|
1830
|
-
* settled this wave (DATA/RESOLVED ran first) — so the normal DATA-then-COMPLETE flow is
|
|
1831
|
-
* unaffected. This makes the exactly-one-settle invariant a single, shared step.
|
|
1832
|
-
*/
|
|
1833
2517
|
_releaseDepDirty(idx) {
|
|
1834
|
-
|
|
1835
|
-
this._dep.dirty[idx] = false;
|
|
1836
|
-
this._wave.pending--;
|
|
1837
|
-
}
|
|
2518
|
+
nodeReleaseDepDirty(nodeRuntimeHost(this), idx);
|
|
1838
2519
|
}
|
|
1839
|
-
/**
|
|
1840
|
-
* R-terminal-settles-dirty (B35): settle a node whose dirtied dep was released by an ABSORBED
|
|
1841
|
-
* terminal that is NOT a real input (a plain derived/effect — the common default-node case when
|
|
1842
|
-
* one of several deps completes while others stay live). Runs only when the release drained
|
|
1843
|
-
* _pending while the node still owes a downstream settle (it broadcast DIRTY this wave):
|
|
1844
|
-
* - if some OTHER dep delivered real DATA this wave (a value occurred) → recompute (→ DATA);
|
|
1845
|
-
* - else the terminal's signalled change did not materialise (no value) → one undirty RESOLVED
|
|
1846
|
-
* (R-resolved-undirty), keeping the cache (a terminal, unlike INVALIDATE, leaves the value).
|
|
1847
|
-
* A terminalAsRealInput node instead recomputes unconditionally (its fn reads the terminal).
|
|
1848
|
-
*/
|
|
1849
2520
|
_settleAfterAbsorbedTerminal() {
|
|
1850
|
-
|
|
1851
|
-
const sawData = this._dep.batch.some((b) => b !== null && b.length > 0);
|
|
1852
|
-
if (sawData) this._maybeRun();
|
|
1853
|
-
if (this._wave.emittedDirtyThisWave) this._down([["RESOLVED"]]);
|
|
2521
|
+
nodeSettleAfterAbsorbedTerminal(nodeRuntimeHost(this));
|
|
1854
2522
|
}
|
|
1855
2523
|
_markDirty() {
|
|
1856
|
-
this
|
|
1857
|
-
if (this._isPullQuiet()) return;
|
|
1858
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
1859
|
-
this._wave.emittedDirtyThisWave = true;
|
|
1860
|
-
this._emitToSubs(["DIRTY"]);
|
|
1861
|
-
}
|
|
2524
|
+
nodeMarkDirty(nodeRuntimeHost(this));
|
|
1862
2525
|
}
|
|
1863
2526
|
_maybeRun() {
|
|
1864
|
-
|
|
1865
|
-
this._wave.rewireRunPending = true;
|
|
1866
|
-
return;
|
|
1867
|
-
}
|
|
1868
|
-
if (this._slot.pausable === true && this._isPaused()) {
|
|
1869
|
-
this._control.pausedDepWaveOccurred = true;
|
|
1870
|
-
return;
|
|
1871
|
-
}
|
|
1872
|
-
this._tryRun();
|
|
2527
|
+
nodeMaybeRun(nodeRuntimeHost(this));
|
|
1873
2528
|
}
|
|
1874
|
-
/**
|
|
1875
|
-
* R-rewire atomic settle (after a rewire that warrants a recompute): emit a proper
|
|
1876
|
-
* two-phase DIRTY→DATA wave (R-dirty-before-data — a rewire-triggered settle is a wave),
|
|
1877
|
-
* once, with every added dep already wired. Mirrors _maybeRun/_tryRun's pause + gate +
|
|
1878
|
-
* pending guards, then injects the phase-1 DIRTY the added dep's [START,DATA] handshake
|
|
1879
|
-
* did not carry.
|
|
1880
|
-
*/
|
|
1881
2529
|
_settleRewire() {
|
|
1882
|
-
|
|
1883
|
-
this._control.pausedDepWaveOccurred = true;
|
|
1884
|
-
return;
|
|
1885
|
-
}
|
|
1886
|
-
if (this._wave.pending > 0) return;
|
|
1887
|
-
if (this._slot.handle === null) {
|
|
1888
|
-
this._passthroughEmit();
|
|
1889
|
-
return;
|
|
1890
|
-
}
|
|
1891
|
-
if (!this._wave.hasCalledFnOnce && !(this._slot.partial || this._allDepsSettled())) return;
|
|
1892
|
-
this._markDirty();
|
|
1893
|
-
this._runWave();
|
|
2530
|
+
nodeSettleRewire(nodeRuntimeHost(this));
|
|
1894
2531
|
}
|
|
1895
2532
|
_tryRun() {
|
|
1896
|
-
|
|
1897
|
-
if (this._slot.handle === null) {
|
|
1898
|
-
this._passthroughEmit();
|
|
1899
|
-
return;
|
|
1900
|
-
}
|
|
1901
|
-
if (!this._wave.hasCalledFnOnce) {
|
|
1902
|
-
if (this._slot.partial || this._allDepsSettled()) this._runWave();
|
|
1903
|
-
return;
|
|
1904
|
-
}
|
|
1905
|
-
this._runWave();
|
|
2533
|
+
nodeTryRun(nodeRuntimeHost(this));
|
|
1906
2534
|
}
|
|
1907
2535
|
_allDepsSettled() {
|
|
1908
|
-
|
|
1909
|
-
if (this._dep.hasData[i]) continue;
|
|
1910
|
-
if (this._slot.terminalAsRealInput && this._dep.terminal[i] !== void 0) continue;
|
|
1911
|
-
return false;
|
|
1912
|
-
}
|
|
1913
|
-
return true;
|
|
2536
|
+
return nodeAllDepsSettled(nodeRuntimeHost(this));
|
|
1914
2537
|
}
|
|
1915
2538
|
_passthroughEmit() {
|
|
1916
|
-
|
|
1917
|
-
if (b !== null && b.length > 0) {
|
|
1918
|
-
this._down([["DATA", b[b.length - 1]]]);
|
|
1919
|
-
} else if (this._wave.emittedDirtyThisWave) {
|
|
1920
|
-
this._down([["RESOLVED"]]);
|
|
1921
|
-
}
|
|
1922
|
-
this._dep.batch[0] = null;
|
|
1923
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2539
|
+
nodePassthroughEmit(nodeRuntimeHost(this));
|
|
1924
2540
|
}
|
|
1925
2541
|
_runWave() {
|
|
1926
|
-
|
|
1927
|
-
throw new Error(
|
|
1928
|
-
"synchronous feedback cycle: node fn re-entered its own wave (R-reentrancy / D37)"
|
|
1929
|
-
);
|
|
1930
|
-
this._wave.hasCalledFnOnce = true;
|
|
1931
|
-
this._hooks.onInvalidate = [];
|
|
1932
|
-
this._hooks.onDeactivation = [];
|
|
1933
|
-
const ctx = this._buildCtx();
|
|
1934
|
-
const wasDirty = this._wave.emittedDirtyThisWave;
|
|
1935
|
-
this._wave.emittedSettleThisWave = false;
|
|
1936
|
-
this._wave.insideRunWave = true;
|
|
1937
|
-
try {
|
|
1938
|
-
this._slot.dispatcher.invoke(this._slot.handle, ctx);
|
|
1939
|
-
} finally {
|
|
1940
|
-
this._wave.insideRunWave = false;
|
|
1941
|
-
}
|
|
1942
|
-
if (wasDirty && !this._wave.emittedSettleThisWave && this._value.terminal === void 0 && !this._isAsyncPool()) {
|
|
1943
|
-
this._down([["RESOLVED"]]);
|
|
1944
|
-
}
|
|
1945
|
-
for (let i = 0; i < this._dep.batch.length; i++) {
|
|
1946
|
-
this._dep.batch[i] = null;
|
|
1947
|
-
this._dep.waveData[i] = [];
|
|
1948
|
-
this._dep.waveTokens[i] = void 0;
|
|
1949
|
-
this._dep.terminalInput[i] = void 0;
|
|
1950
|
-
}
|
|
1951
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2542
|
+
nodeRunWave(nodeRuntimeHost(this));
|
|
1952
2543
|
}
|
|
1953
|
-
// ── ctx construction (L3-Q5: sync = node-stable reused ctx; async = per-invocation) ──
|
|
1954
2544
|
_buildCtx() {
|
|
1955
|
-
|
|
1956
|
-
if (kind === "sync") {
|
|
1957
|
-
if (this._syncCtx === null) this._syncCtx = this._makeCtx();
|
|
1958
|
-
this._refreshCtx(this._syncCtx);
|
|
1959
|
-
return this._syncCtx;
|
|
1960
|
-
}
|
|
1961
|
-
return this._makeCtx({
|
|
1962
|
-
waveData: this._dep.waveData.map((waves) => waves.map((w) => [...w])),
|
|
1963
|
-
terminal: this._dep.terminalInput.map(terminalView),
|
|
1964
|
-
latest: [...this._dep.prev]
|
|
1965
|
-
});
|
|
2545
|
+
return nodeBuildCtx(nodeRuntimeHost(this));
|
|
1966
2546
|
}
|
|
1967
2547
|
_makeCtx(snapshot) {
|
|
1968
|
-
|
|
1969
|
-
// Wave-owner boundary (D47): a SYNC fn's emit nests under the public entry that drove
|
|
1970
|
-
// it (cheap inc/dec, no early drain); an ASYNC-pool fn re-enters here from its stashed
|
|
1971
|
-
// ctx at depth 0, so this is the boundary that drains any rewireNext it issued.
|
|
1972
|
-
up: (msgs, towardDep) => {
|
|
1973
|
-
if (this._released) return;
|
|
1974
|
-
enterWave();
|
|
1975
|
-
try {
|
|
1976
|
-
this._up(msgs, towardDep);
|
|
1977
|
-
} finally {
|
|
1978
|
-
exitWave();
|
|
1979
|
-
}
|
|
1980
|
-
},
|
|
1981
|
-
down: (msgs) => {
|
|
1982
|
-
if (this._released) return;
|
|
1983
|
-
enterWave();
|
|
1984
|
-
try {
|
|
1985
|
-
this._down(msgs);
|
|
1986
|
-
} finally {
|
|
1987
|
-
exitWave();
|
|
1988
|
-
}
|
|
1989
|
-
},
|
|
1990
|
-
waveData: snapshot?.waveData ?? this._dep.waveData,
|
|
1991
|
-
terminal: snapshot?.terminal ?? this._dep.terminalInput.map(terminalView),
|
|
1992
|
-
state: this._makeState(),
|
|
1993
|
-
onDeactivation: (fn) => {
|
|
1994
|
-
if (this._released) return;
|
|
1995
|
-
this._hooks.onDeactivation.push(fn);
|
|
1996
|
-
},
|
|
1997
|
-
onInvalidate: (fn) => {
|
|
1998
|
-
if (this._released) return;
|
|
1999
|
-
this._hooks.onInvalidate.push(fn);
|
|
2000
|
-
},
|
|
2001
|
-
environment: () => this._slot.environment,
|
|
2002
|
-
// R-rewire-deferred (D47): defer a self-dep-set mutation to the committed boundary.
|
|
2003
|
-
rewireNext: {
|
|
2004
|
-
subscribeDep: (dep, fn) => this._requestRewireNext({ kind: "add", dep, fn }),
|
|
2005
|
-
unsubscribeDep: (dep, fn) => this._requestRewireNext({ kind: "remove", dep, fn }),
|
|
2006
|
-
replaceDeps: (deps, fn) => this._requestRewireNext({ kind: "set", deps, fn })
|
|
2007
|
-
},
|
|
2008
|
-
// R-up-routing / R-pull (D59): deferred up — route a control wave (e.g. a RESUME pull
|
|
2009
|
-
// DEMAND) up the declared cone at the committed boundary. The SELF-demand path: an
|
|
2010
|
-
// immediate ctx.up whose delivery loops back re-enters this fn (D37 / R-reentrancy).
|
|
2011
|
-
upNext: (msgs, towardDep) => this._requestUpNext(msgs, towardDep),
|
|
2012
|
-
[CTX_DEP_CACHE]: { latest: snapshot?.latest ?? this._dep.prev },
|
|
2013
|
-
[CTX_NODE_BINDING]: {
|
|
2014
|
-
dispatcher: this._slot.dispatcher,
|
|
2015
|
-
create: (factory) => withEnvironmentDrivers(this._slot.environment, () => withNodeCore(this._core, factory))
|
|
2016
|
-
}
|
|
2017
|
-
};
|
|
2018
|
-
if (this._slot.dynamic) {
|
|
2019
|
-
ctx.track = (i) => ctx[CTX_DEP_CACHE]?.latest[i];
|
|
2020
|
-
}
|
|
2021
|
-
return ctx;
|
|
2548
|
+
return nodeMakeCtx(nodeRuntimeHost(this), snapshot);
|
|
2022
2549
|
}
|
|
2023
2550
|
_refreshCtx(ctx) {
|
|
2024
|
-
ctx
|
|
2025
|
-
ctx.terminal = this._dep.terminalInput.map(terminalView);
|
|
2026
|
-
ctx[CTX_DEP_CACHE] = { latest: this._dep.prev };
|
|
2551
|
+
nodeRefreshCtx(nodeRuntimeHost(this), ctx);
|
|
2027
2552
|
}
|
|
2028
2553
|
_makeState() {
|
|
2029
|
-
return
|
|
2030
|
-
get: () => this._privateState.value,
|
|
2031
|
-
set: (v) => {
|
|
2032
|
-
this._privateState.value = v;
|
|
2033
|
-
},
|
|
2034
|
-
persist: (on = true) => {
|
|
2035
|
-
this._privateState.persist = on;
|
|
2036
|
-
}
|
|
2037
|
-
};
|
|
2554
|
+
return nodeMakeState(nodeRuntimeHost(this));
|
|
2038
2555
|
}
|
|
2039
2556
|
// ── downstream emission pipeline (the unified waist) ──
|
|
2040
2557
|
_down(msgs) {
|
|
2041
|
-
|
|
2042
|
-
validateDownPayloads(msgs);
|
|
2043
|
-
const deliveryWave = {};
|
|
2044
|
-
const assertVersionDataCompatible = (wave) => {
|
|
2045
|
-
for (const m of wave) {
|
|
2046
|
-
if (m[0] === "DATA") assertNodeVersionDataCompatible(this._version.policy, m[1]);
|
|
2047
|
-
}
|
|
2048
|
-
};
|
|
2049
|
-
const snapshotVersionData = (wave) => wave.map(
|
|
2050
|
-
(m) => m[0] === "DATA" ? ["DATA", snapshotNodeVersionData(this._version.policy, m[1])] : m
|
|
2051
|
-
);
|
|
2052
|
-
assertVersionDataCompatible(msgs);
|
|
2053
|
-
if (this._value.terminal !== void 0) {
|
|
2054
|
-
if (!msgs.some((m) => m[0] === "TEARDOWN")) return;
|
|
2055
|
-
this._value.hasTorndown = true;
|
|
2056
|
-
if (this._slot.resetOnTeardown) {
|
|
2057
|
-
this._value.cache = SENTINEL;
|
|
2058
|
-
this._value.hasData = false;
|
|
2059
|
-
}
|
|
2060
|
-
this._emitToSubs(["TEARDOWN"], { wave: deliveryWave, last: true });
|
|
2061
|
-
return;
|
|
2062
|
-
}
|
|
2063
|
-
let sorted = [...msgs].sort((a, b) => messageTier(a[0]) - messageTier(b[0]));
|
|
2064
|
-
const firstInvalidate = sorted.findIndex((m) => m[0] === "INVALIDATE");
|
|
2065
|
-
if (firstInvalidate !== -1) {
|
|
2066
|
-
sorted = sorted.filter((m, i) => m[0] !== "INVALIDATE" || i === firstInvalidate);
|
|
2067
|
-
}
|
|
2068
|
-
const hasTeardown = sorted.some((m) => m[0] === "TEARDOWN");
|
|
2069
|
-
const hasTerminal = sorted.some((m) => m[0] === "COMPLETE" || m[0] === "ERROR");
|
|
2070
|
-
if (hasTeardown && !hasTerminal && this._value.terminal === void 0 && !this._value.hasTorndown) {
|
|
2071
|
-
sorted = [["COMPLETE"], ...sorted];
|
|
2072
|
-
}
|
|
2073
|
-
if (!this._wave.insideRunWave && currentBatch()) {
|
|
2074
|
-
const deferred = snapshotVersionData(sorted.filter((m) => isDeferredTier(m[0])));
|
|
2075
|
-
if (deferred.length > 0) {
|
|
2076
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
2077
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2078
|
-
this._value.status = "dirty";
|
|
2079
|
-
this._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
2080
|
-
}
|
|
2081
|
-
this._wave.batchDirtyOwed = true;
|
|
2082
|
-
deferToBatch(this, deferred);
|
|
2083
|
-
return;
|
|
2084
|
-
}
|
|
2085
|
-
}
|
|
2086
|
-
if (this._shouldBufferOnPause()) {
|
|
2087
|
-
const buffered = snapshotVersionData(sorted.filter((m) => isPauseBufferedTier(m[0])));
|
|
2088
|
-
if (buffered.length > 0) {
|
|
2089
|
-
this._wave.emittedSettleThisWave = true;
|
|
2090
|
-
this._control.pauseBuffer.push(buffered);
|
|
2091
|
-
}
|
|
2092
|
-
sorted = sorted.filter((m) => !isPauseBufferedTier(m[0]));
|
|
2093
|
-
if (sorted.length === 0) return;
|
|
2094
|
-
}
|
|
2095
|
-
let dataCount = 0;
|
|
2096
|
-
let hasTier3 = false;
|
|
2097
|
-
let hasResolved = false;
|
|
2098
|
-
for (const m of sorted) {
|
|
2099
|
-
if (m[0] === "DATA") dataCount++;
|
|
2100
|
-
if (m[0] === "RESOLVED") hasResolved = true;
|
|
2101
|
-
if (isValueTier(m[0])) hasTier3 = true;
|
|
2102
|
-
}
|
|
2103
|
-
if (dataCount >= 1 && hasResolved) {
|
|
2104
|
-
throw new Error(
|
|
2105
|
-
"down: a wave cannot mix DATA and RESOLVED (tier-3 exclusivity, R-resolved-undirty)"
|
|
2106
|
-
);
|
|
2107
|
-
}
|
|
2108
|
-
const plannedVersions = new Array(sorted.length);
|
|
2109
|
-
if (dataCount > 0) {
|
|
2110
|
-
let plannedVersion = this._version.value;
|
|
2111
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
2112
|
-
const m = sorted[i];
|
|
2113
|
-
if (m[0] !== "DATA") continue;
|
|
2114
|
-
plannedVersion = advanceNodeVersion(plannedVersion, this._version.policy, m[1]);
|
|
2115
|
-
plannedVersions[i] = plannedVersion;
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2118
|
-
if (hasTier3 && !this._wave.insideRunWave && !this._wave.emittedDirtyThisWave) {
|
|
2119
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2120
|
-
this._value.status = "dirty";
|
|
2121
|
-
this._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
2122
|
-
}
|
|
2123
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
2124
|
-
const m = sorted[i];
|
|
2125
|
-
const delivery = { wave: deliveryWave, last: i === sorted.length - 1 };
|
|
2126
|
-
if (isDeferredTier(m[0])) this._wave.emittedSettleThisWave = true;
|
|
2127
|
-
if (m[0] === "DIRTY") {
|
|
2128
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
2129
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2130
|
-
this._value.status = "dirty";
|
|
2131
|
-
this._emitToSubs(["DIRTY"], delivery);
|
|
2132
|
-
}
|
|
2133
|
-
continue;
|
|
2134
|
-
}
|
|
2135
|
-
if (m[0] === "DATA") {
|
|
2136
|
-
const v = m[1];
|
|
2137
|
-
this._value.cache = v;
|
|
2138
|
-
this._value.hasData = true;
|
|
2139
|
-
this._value.status = "settled";
|
|
2140
|
-
this._version.value = plannedVersions[i];
|
|
2141
|
-
if (this._slot.replayN > 0) {
|
|
2142
|
-
this._value.replayRing.push(v);
|
|
2143
|
-
if (this._value.replayRing.length > this._slot.replayN) this._value.replayRing.shift();
|
|
2144
|
-
}
|
|
2145
|
-
this._emitToSubs(["DATA", v], delivery);
|
|
2146
|
-
continue;
|
|
2147
|
-
}
|
|
2148
|
-
if (m[0] === "RESOLVED") {
|
|
2149
|
-
this._value.status = this._value.hasData ? "resolved" : "sentinel";
|
|
2150
|
-
this._emitToSubs(["RESOLVED"], delivery);
|
|
2151
|
-
continue;
|
|
2152
|
-
}
|
|
2153
|
-
if (m[0] === "INVALIDATE") {
|
|
2154
|
-
this._invalidate(delivery);
|
|
2155
|
-
continue;
|
|
2156
|
-
}
|
|
2157
|
-
if (m[0] === "COMPLETE") {
|
|
2158
|
-
if (this._value.terminal !== void 0) continue;
|
|
2159
|
-
this._value.terminal = true;
|
|
2160
|
-
this._control.pauseBuffer = [];
|
|
2161
|
-
this._value.status = "completed";
|
|
2162
|
-
this._emitToSubs(["COMPLETE"], delivery);
|
|
2163
|
-
continue;
|
|
2164
|
-
}
|
|
2165
|
-
if (m[0] === "ERROR") {
|
|
2166
|
-
if (this._value.terminal !== void 0) continue;
|
|
2167
|
-
this._value.terminal = m[1];
|
|
2168
|
-
this._control.pauseBuffer = [];
|
|
2169
|
-
this._value.status = "errored";
|
|
2170
|
-
this._emitToSubs(["ERROR", m[1]], delivery);
|
|
2171
|
-
continue;
|
|
2172
|
-
}
|
|
2173
|
-
if (m[0] === "TEARDOWN") {
|
|
2174
|
-
this._value.hasTorndown = true;
|
|
2175
|
-
if (this._slot.resetOnTeardown) {
|
|
2176
|
-
this._value.cache = SENTINEL;
|
|
2177
|
-
this._value.hasData = false;
|
|
2178
|
-
}
|
|
2179
|
-
this._emitToSubs(["TEARDOWN"], delivery);
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
if (!this._wave.insideRunWave) this._wave.emittedDirtyThisWave = false;
|
|
2558
|
+
nodeDown(nodeRuntimeHost(this), msgs);
|
|
2183
2559
|
}
|
|
2184
2560
|
_up(msgs, towardDep, route) {
|
|
2185
|
-
|
|
2186
|
-
const routeState = route ?? { demandFired: /* @__PURE__ */ new Map() };
|
|
2187
|
-
for (const m of msgs) {
|
|
2188
|
-
if (!isUpAllowed(m[0])) {
|
|
2189
|
-
throw new Error(
|
|
2190
|
-
`ctx.up: ${m[0]} is down-only (tier ${messageTier(m[0])}); up carries control tiers only (R-ctx-up)`
|
|
2191
|
-
);
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
2194
|
-
for (const m of msgs) {
|
|
2195
|
-
if (m[0] === "PAUSE") {
|
|
2196
|
-
this._pauseAcquire(m[1]);
|
|
2197
|
-
} else if (m[0] === "RESUME") {
|
|
2198
|
-
if (this._slot.pull && m[1] === this._slot.pullLock) {
|
|
2199
|
-
if (!this._markDemandRouted(m[1], routeState)) this._onDemand();
|
|
2200
|
-
} else if (this._control.pauseLockset.has(m[1])) {
|
|
2201
|
-
this._pauseRelease(m[1]);
|
|
2202
|
-
} else {
|
|
2203
|
-
this._forwardUp(m, towardDep, routeState);
|
|
2204
|
-
}
|
|
2205
|
-
} else if (this._slot.deps.length === 0) {
|
|
2206
|
-
if (m[0] === "INVALIDATE") this._down([["INVALIDATE"]]);
|
|
2207
|
-
} else {
|
|
2208
|
-
this._forwardUp(m, towardDep, routeState);
|
|
2209
|
-
}
|
|
2210
|
-
}
|
|
2561
|
+
nodeUp(nodeRuntimeHost(this), msgs, towardDep, route);
|
|
2211
2562
|
}
|
|
2212
2563
|
_markDemandRouted(lockId, route) {
|
|
2213
|
-
|
|
2214
|
-
if (holders === void 0) {
|
|
2215
|
-
holders = /* @__PURE__ */ new Set();
|
|
2216
|
-
route.demandFired.set(lockId, holders);
|
|
2217
|
-
}
|
|
2218
|
-
if (holders.has(this)) return true;
|
|
2219
|
-
holders.add(this);
|
|
2220
|
-
return false;
|
|
2564
|
+
return nodeMarkDemandRouted(nodeRuntimeHost(this), lockId, route);
|
|
2221
2565
|
}
|
|
2222
|
-
/**
|
|
2223
|
-
* Forward one up-going control message toward deps (R-up-routing): up the single declared edge
|
|
2224
|
-
* `towardDep` (directed — prunes other branches; only meaningful on the issuer's FIRST hop) or
|
|
2225
|
-
* broadcast up ALL deps. A depless source has no deps → the message DROPS here (the terminus —
|
|
2226
|
-
* e.g. a cone-routed RESUME whose pullId no node up this cone holds, R-up-at-source). Recursive
|
|
2227
|
-
* forwarding carries the same per-wave route state and no `towardDep` → broadcast beyond the
|
|
2228
|
-
* first hop.
|
|
2229
|
-
*/
|
|
2230
2566
|
_forwardUp(m, towardDep, route) {
|
|
2231
|
-
|
|
2232
|
-
if (towardDep !== void 0) {
|
|
2233
|
-
const d = this._slot.deps[towardDep];
|
|
2234
|
-
if (d !== void 0) d._up([m], void 0, route);
|
|
2235
|
-
} else {
|
|
2236
|
-
for (const dep of this._slot.deps) dep._up([m], void 0, route);
|
|
2237
|
-
}
|
|
2567
|
+
nodeForwardUp(nodeRuntimeHost(this), m, towardDep, route);
|
|
2238
2568
|
}
|
|
2239
|
-
// ── PAUSE/RESUME lockset (R-pause-lockset) + modes (R-pause-modes) ──
|
|
2240
2569
|
_isPaused() {
|
|
2241
|
-
return this
|
|
2570
|
+
return nodeIsPaused(nodeRuntimeHost(this));
|
|
2242
2571
|
}
|
|
2243
2572
|
_hasBoundaryPauseLock() {
|
|
2244
|
-
|
|
2245
|
-
let locks = this._control.pauseLockset.size;
|
|
2246
|
-
if (this._slot.pull && this._control.pauseLockset.has(this._slot.pullLock)) locks--;
|
|
2247
|
-
return locks > 0;
|
|
2573
|
+
return nodeHasBoundaryPauseLock(nodeRuntimeHost(this));
|
|
2248
2574
|
}
|
|
2249
2575
|
_isAsyncPool() {
|
|
2250
|
-
return
|
|
2576
|
+
return nodeIsAsyncPool(nodeRuntimeHost(this));
|
|
2251
2577
|
}
|
|
2252
2578
|
_pauseAcquire(lockId) {
|
|
2253
|
-
this
|
|
2579
|
+
nodePauseAcquire(nodeRuntimeHost(this), lockId);
|
|
2254
2580
|
}
|
|
2255
2581
|
_pauseRelease(lockId) {
|
|
2256
|
-
|
|
2257
|
-
this._control.pauseLockset.delete(lockId);
|
|
2258
|
-
if (this._slot.pull && this._control.demandOwed) this._fireOwedDemandIfReady();
|
|
2259
|
-
if (this._hasBoundaryPauseLock()) return;
|
|
2260
|
-
scheduleBoundaryDrain(this._core);
|
|
2261
|
-
if (this._control.pauseLockset.size > 0) return;
|
|
2262
|
-
this._onResume();
|
|
2582
|
+
nodePauseRelease(nodeRuntimeHost(this), lockId);
|
|
2263
2583
|
}
|
|
2264
2584
|
_onResume() {
|
|
2265
|
-
|
|
2266
|
-
this._control.pauseBuffer = [];
|
|
2267
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2268
|
-
this._control.demandOwed = false;
|
|
2269
|
-
return;
|
|
2270
|
-
}
|
|
2271
|
-
if (this._control.pauseBuffer.length > 0) {
|
|
2272
|
-
const buf = this._control.pauseBuffer;
|
|
2273
|
-
this._control.pauseBuffer = [];
|
|
2274
|
-
for (const wave of buf) this._down(wave);
|
|
2275
|
-
}
|
|
2276
|
-
if (this._control.pausedDepWaveOccurred) {
|
|
2277
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2278
|
-
this._tryRun();
|
|
2279
|
-
}
|
|
2585
|
+
nodeOnResume(nodeRuntimeHost(this));
|
|
2280
2586
|
}
|
|
2281
|
-
/**
|
|
2282
|
-
* R-pull (D59): can this pull node fire a demand NOW? — not terminal, settle-ready (_pending===0),
|
|
2283
|
-
* and no OTHER (non-pullId) lock holds it paused. The gate that decides fire-now vs OWE.
|
|
2284
|
-
*/
|
|
2285
2587
|
_canFireDemand() {
|
|
2286
|
-
|
|
2287
|
-
const own = this._control.pauseLockset.has(this._slot.pullLock) ? 1 : 0;
|
|
2288
|
-
return this._control.pauseLockset.size <= own;
|
|
2588
|
+
return nodeCanFireDemand(nodeRuntimeHost(this));
|
|
2289
2589
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
* absorbed), fire it, then RE-QUIET (1:1). The pullId re-add + the re-entrancy flag are in a
|
|
2293
|
-
* `finally` so a throwing pull fn (graph-less node, no D30 catch) cannot leave the node
|
|
2294
|
-
* permanently non-quiet (the wedge-fix silently disabled) — QA-found robustness fix.
|
|
2295
|
-
*/
|
|
2296
|
-
_deliverPullDemand() {
|
|
2297
|
-
this._control.demandOwed = false;
|
|
2298
|
-
this._control.inDeliverDemand = true;
|
|
2299
|
-
this._control.pauseLockset.delete(this._slot.pullLock);
|
|
2300
|
-
try {
|
|
2301
|
-
this._firePullDemand();
|
|
2302
|
-
} finally {
|
|
2303
|
-
this._control.pauseLockset.add(this._slot.pullLock);
|
|
2304
|
-
this._control.inDeliverDemand = false;
|
|
2305
|
-
}
|
|
2590
|
+
_deliverPullDemand(demand) {
|
|
2591
|
+
nodeDeliverPullDemand(nodeRuntimeHost(this), demand);
|
|
2306
2592
|
}
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
* Fire immediately if able; else OWE it — pin-5 (a dep DIRTY in flight, _pending>0) or F4/F5 (an
|
|
2310
|
-
* external PAUSE lock co-holds the node) — and fire when the node next becomes able. A demand
|
|
2311
|
-
* arriving WHILE a delivery is in flight (synchronous re-entry) is DROPPED (1:1, QA guard).
|
|
2312
|
-
*/
|
|
2313
|
-
_onDemand() {
|
|
2314
|
-
if (this._control.inDeliverDemand) return;
|
|
2315
|
-
if (this._canFireDemand()) this._deliverPullDemand();
|
|
2316
|
-
else this._control.demandOwed = true;
|
|
2593
|
+
_onDemand(demand) {
|
|
2594
|
+
nodeOnDemand(nodeRuntimeHost(this), demand);
|
|
2317
2595
|
}
|
|
2318
|
-
/**
|
|
2319
|
-
* R-pull (D55): service ONE demand. Delivery content = the orthogonal pausable mode:
|
|
2320
|
-
* - 'resumeAll' → drain the buffered BACKLOG (each `_down` re-synthesizes a leading DIRTY, so
|
|
2321
|
-
* the per-entry replay is DIRTY-before-DATA — R-pause-modes per-entry arrival order);
|
|
2322
|
-
* - true → deliver the coalesced LATEST as ONE DIRTY-before-DATA wave (pin 2: the quiet absorb
|
|
2323
|
-
* suppressed the dep's original DIRTY, so the demand wave restores it before the value).
|
|
2324
|
-
* Neither branch fires when nothing changed since the last demand → the demand is SILENT.
|
|
2325
|
-
* Called by `_deliverPullDemand` only when settle-ready; the caller has released the pullId, so
|
|
2326
|
-
* `_markDirty` relays the leading DIRTY (not absorbed).
|
|
2327
|
-
*/
|
|
2328
2596
|
_firePullDemand() {
|
|
2329
|
-
|
|
2330
|
-
const buf = this._control.pauseBuffer;
|
|
2331
|
-
this._control.pauseBuffer = [];
|
|
2332
|
-
for (const wave of buf) this._down(wave);
|
|
2333
|
-
}
|
|
2334
|
-
if (this._control.pausedDepWaveOccurred) {
|
|
2335
|
-
const gated = this._slot.handle !== null && !this._wave.hasCalledFnOnce && !(this._slot.partial || this._allDepsSettled());
|
|
2336
|
-
if (this._wave.pending > 0 || gated) return;
|
|
2337
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2338
|
-
this._markDirty();
|
|
2339
|
-
this._tryRun();
|
|
2340
|
-
}
|
|
2597
|
+
nodeFirePullDemand(nodeRuntimeHost(this));
|
|
2341
2598
|
}
|
|
2342
|
-
/**
|
|
2343
|
-
* R-pull (D55/D59): fire a demand that was OWED (deferred at demand time) once the node becomes
|
|
2344
|
-
* able — called from the dep-settle arms (DATA/RESOLVED/INVALIDATE/terminal drain _pending, pin-5
|
|
2345
|
-
* + B1/F6) and from `_pauseRelease` (an external PAUSE lock releases, F4/F5).
|
|
2346
|
-
*/
|
|
2347
2599
|
_fireOwedDemandIfReady() {
|
|
2348
|
-
|
|
2349
|
-
if (this._slot.pull && this._control.demandOwed && this._canFireDemand())
|
|
2350
|
-
this._deliverPullDemand();
|
|
2600
|
+
nodeFireOwedDemandIfReady(nodeRuntimeHost(this));
|
|
2351
2601
|
}
|
|
2352
|
-
/** Should an outgoing settle slice be deferred into the pause buffer? */
|
|
2353
2602
|
_shouldBufferOnPause() {
|
|
2354
|
-
|
|
2355
|
-
if (!this._isPaused()) return false;
|
|
2356
|
-
if (this._slot.pausable === "resumeAll") return true;
|
|
2357
|
-
if (!this._wave.insideRunWave && this._isAsyncPool() && this._slot.deps.length > 0) return true;
|
|
2358
|
-
return false;
|
|
2603
|
+
return nodeShouldBufferOnPause(nodeRuntimeHost(this));
|
|
2359
2604
|
}
|
|
2360
|
-
/** R-invalidate-idempotent: clear cache + flush + cascade; no-op if nothing cached. */
|
|
2361
2605
|
_invalidate(delivery) {
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
this._value.hasData = false;
|
|
2365
|
-
this._value.status = "sentinel";
|
|
2366
|
-
this._value.replayRing = [];
|
|
2367
|
-
for (const fn of this._hooks.onInvalidate) fn();
|
|
2368
|
-
this._emitToSubs(["INVALIDATE"], delivery);
|
|
2369
|
-
}
|
|
2370
|
-
// B42 (R-deps-terminal): ALL deps TERMINAL = every dep has reached COMPLETE *or* an ABSORBED
|
|
2371
|
-
// ERROR. Block only on a LIVE dep (_depTerminal[i] === undefined); an errored dep (terminal = the
|
|
2372
|
-
// error payload, which R-data-payload guarantees is !== undefined and non-boolean) COUNTS as
|
|
2373
|
-
// terminal-done. Was
|
|
2374
|
-
// `tm !== true`, which wedged a node whose errorWhenDepsError:false dep ERRORed (it never
|
|
2375
|
-
// auto-completed even after every other dep completed). Drives the completeWhenDepsComplete cascade.
|
|
2606
|
+
nodeInvalidate(nodeRuntimeHost(this), delivery);
|
|
2607
|
+
}
|
|
2376
2608
|
_allDepsTerminal() {
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2609
|
+
return nodeAllDepsTerminal(nodeRuntimeHost(this));
|
|
2610
|
+
}
|
|
2611
|
+
_emitToSubs(msg, delivery) {
|
|
2612
|
+
nodeEmitToSubs(nodeRuntimeHost(this), msg, delivery);
|
|
2380
2613
|
}
|
|
2381
2614
|
/** R-terminal: resubscribable reset clears terminal + dep state + re-arms the gate. */
|
|
2382
2615
|
_resetLifecycle() {
|
|
2383
|
-
|
|
2384
|
-
this._dep.unsubs = [];
|
|
2385
|
-
this._dep.idxBoxes = [];
|
|
2386
|
-
this._lifecycle.subscribers.clear();
|
|
2387
|
-
this._lifecycle.activated = false;
|
|
2388
|
-
this._value.terminal = void 0;
|
|
2389
|
-
this._value.hasTorndown = false;
|
|
2390
|
-
this._wave.hasCalledFnOnce = false;
|
|
2391
|
-
this._resetDepState();
|
|
2392
|
-
this._control.pauseLockset.clear();
|
|
2393
|
-
this._control.pauseBuffer = [];
|
|
2394
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2395
|
-
this._control.demandOwed = false;
|
|
2396
|
-
this._value.replayRing = [];
|
|
2397
|
-
const isCompute = this._slot.handle !== null || this._slot.deps.length > 0;
|
|
2398
|
-
if (isCompute) {
|
|
2399
|
-
this._value.cache = SENTINEL;
|
|
2400
|
-
this._value.hasData = false;
|
|
2401
|
-
this._value.status = "sentinel";
|
|
2402
|
-
} else {
|
|
2403
|
-
this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
2404
|
-
}
|
|
2405
|
-
if (!this._privateState.persist) this._privateState.value = SENTINEL;
|
|
2406
|
-
}
|
|
2407
|
-
_emitToSubs(msg, delivery) {
|
|
2408
|
-
if (this._released) return;
|
|
2409
|
-
const subs = [...this._lifecycle.subscribers];
|
|
2410
|
-
for (const sink of subs) sink(msg, delivery);
|
|
2616
|
+
nodeResetLifecycle(nodeRuntimeHost(this));
|
|
2411
2617
|
}
|
|
2412
2618
|
/** Batch commit (R-batch-coalesce): deliver the deferred tier-3 wave now. */
|
|
2413
2619
|
__commitBatchedWave(wave) {
|
|
2414
|
-
this
|
|
2415
|
-
this._down(wave);
|
|
2620
|
+
nodeCommitBatchedWave(nodeRuntimeHost(this), wave);
|
|
2416
2621
|
}
|
|
2417
2622
|
/** Batch rollback: balance the immediate DIRTY with a RESOLVED so downstream un-dirties. */
|
|
2418
2623
|
__rollbackBatched() {
|
|
2419
|
-
|
|
2420
|
-
this._wave.batchDirtyOwed = false;
|
|
2421
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2422
|
-
this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
2423
|
-
this._emitToSubs(["RESOLVED"]);
|
|
2424
|
-
}
|
|
2624
|
+
nodeRollbackBatched(nodeRuntimeHost(this));
|
|
2425
2625
|
}
|
|
2426
2626
|
/** B49: enqueue a committed-boundary task on this node's graph-local core. */
|
|
2427
2627
|
__deferBoundary(fn, batchToken) {
|
|
2428
|
-
|
|
2429
|
-
batchToken,
|
|
2430
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
2431
|
-
});
|
|
2628
|
+
nodeDeferBoundary(nodeRuntimeHost(this), fn, batchToken);
|
|
2432
2629
|
}
|
|
2433
2630
|
};
|
|
2434
2631
|
function node(deps = [], handleOrFn = null, opts = {}) {
|