@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/sources/index.cjs
CHANGED
|
@@ -68,6 +68,7 @@ var TIER = {
|
|
|
68
68
|
START: TIER_START,
|
|
69
69
|
PAUSE: TIER_CONTROL,
|
|
70
70
|
RESUME: TIER_CONTROL,
|
|
71
|
+
PULL: TIER_CONTROL,
|
|
71
72
|
DIRTY: TIER_NOTIFICATION,
|
|
72
73
|
DATA: TIER_VALUE,
|
|
73
74
|
RESOLVED: TIER_VALUE,
|
|
@@ -141,9 +142,16 @@ function sortedJsonValue(value, seen = /* @__PURE__ */ new Set(), path = "$", st
|
|
|
141
142
|
}
|
|
142
143
|
for (const key of Object.getOwnPropertyNames(value)) {
|
|
143
144
|
const isIndex = /^(0|[1-9]\d*)$/.test(key) && Number.isSafeInteger(Number(key)) && Number(key) < value.length;
|
|
145
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
146
|
+
if (descriptor !== void 0 && ("get" in descriptor || "set" in descriptor)) {
|
|
147
|
+
throw new TypeError(`stableJsonString: accessor property at ${path}.${key}`);
|
|
148
|
+
}
|
|
144
149
|
if (key !== "length" && !isIndex) {
|
|
145
150
|
throw new TypeError(`stableJsonString: non-index array property at ${path}.${key}`);
|
|
146
151
|
}
|
|
152
|
+
if (key !== "length" && descriptor !== void 0 && !descriptor.enumerable) {
|
|
153
|
+
throw new TypeError(`stableJsonString: non-enumerable array property at ${path}.${key}`);
|
|
154
|
+
}
|
|
147
155
|
}
|
|
148
156
|
const out2 = [];
|
|
149
157
|
for (let i = 0; i < value.length; i += 1) {
|
|
@@ -157,6 +165,15 @@ function sortedJsonValue(value, seen = /* @__PURE__ */ new Set(), path = "$", st
|
|
|
157
165
|
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
158
166
|
throw new TypeError(`stableJsonString: symbol-keyed properties at ${path}`);
|
|
159
167
|
}
|
|
168
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
169
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
170
|
+
if (descriptor !== void 0 && ("get" in descriptor || "set" in descriptor)) {
|
|
171
|
+
throw new TypeError(`stableJsonString: accessor property at ${path}.${key}`);
|
|
172
|
+
}
|
|
173
|
+
if (descriptor !== void 0 && !descriptor.enumerable) {
|
|
174
|
+
throw new TypeError(`stableJsonString: non-enumerable property at ${path}.${key}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
160
177
|
const out = /* @__PURE__ */ Object.create(null);
|
|
161
178
|
for (const key of Object.keys(value).sort()) {
|
|
162
179
|
out[key] = sortedJsonValue(
|
|
@@ -463,30 +480,6 @@ function drain() {
|
|
|
463
480
|
if (escaped !== null) throw escaped.e;
|
|
464
481
|
}
|
|
465
482
|
|
|
466
|
-
// src/batch/batch.ts
|
|
467
|
-
var active = null;
|
|
468
|
-
var boundaryOwner = null;
|
|
469
|
-
function currentBatch() {
|
|
470
|
-
return active !== null;
|
|
471
|
-
}
|
|
472
|
-
function currentBoundaryBatchToken() {
|
|
473
|
-
return active ?? boundaryOwner ?? void 0;
|
|
474
|
-
}
|
|
475
|
-
function deferToBatch(target, tier3Wave) {
|
|
476
|
-
if (active === null) return false;
|
|
477
|
-
if (!active.deferred.has(target)) active.order.push(target);
|
|
478
|
-
active.deferred.set(target, tier3Wave);
|
|
479
|
-
return true;
|
|
480
|
-
}
|
|
481
|
-
function deferAfterBatchForTarget(target, fn) {
|
|
482
|
-
if (active === null || !active.deferred.has(target)) return false;
|
|
483
|
-
const owner = active;
|
|
484
|
-
target.__deferBoundary(() => {
|
|
485
|
-
if (owner.committed) fn();
|
|
486
|
-
}, owner);
|
|
487
|
-
return true;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
483
|
// src/dispatcher/index.ts
|
|
491
484
|
var PoolTable = class {
|
|
492
485
|
constructor(kind) {
|
|
@@ -793,6 +786,586 @@ function makeDepBookkeeping(depCount) {
|
|
|
793
786
|
};
|
|
794
787
|
}
|
|
795
788
|
|
|
789
|
+
// src/node/protocol-guards.ts
|
|
790
|
+
function terminalView(t) {
|
|
791
|
+
return t === void 0 ? false : t;
|
|
792
|
+
}
|
|
793
|
+
function normalizePullDemand(demand) {
|
|
794
|
+
if (typeof demand !== "object" || demand === null || Array.isArray(demand)) {
|
|
795
|
+
throw new Error("ctx.up: PULL requires { pullId, params? } demand payload (D269)");
|
|
796
|
+
}
|
|
797
|
+
const pullId = demand.pullId;
|
|
798
|
+
if (typeof pullId !== "string" && typeof pullId !== "symbol") {
|
|
799
|
+
throw new Error("ctx.up: PULL demand requires a string or symbol pullId (D269)");
|
|
800
|
+
}
|
|
801
|
+
const params = demand.params;
|
|
802
|
+
return params === void 0 ? { pullId } : { pullId, params };
|
|
803
|
+
}
|
|
804
|
+
function validateDownPayloads(msgs) {
|
|
805
|
+
for (const m of msgs) {
|
|
806
|
+
if (m[0] === "DATA" && m[1] === void 0) {
|
|
807
|
+
throw new Error("down: DATA requires a non-SENTINEL payload (R-data-payload)");
|
|
808
|
+
}
|
|
809
|
+
if (m[0] === "ERROR" && isInvalidErrorPayload(m[1])) {
|
|
810
|
+
throw new Error("down: ERROR requires a non-SENTINEL, non-boolean payload (R-data-payload)");
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// src/node/runtime-accessors.ts
|
|
816
|
+
var constructingCore;
|
|
817
|
+
var constructingEnvironment;
|
|
818
|
+
var ownerTokens = /* @__PURE__ */ new WeakMap();
|
|
819
|
+
var topologyDepsChangedObservers = /* @__PURE__ */ new WeakMap();
|
|
820
|
+
var checkpointReaders = /* @__PURE__ */ new WeakMap();
|
|
821
|
+
var restoreWriters = /* @__PURE__ */ new WeakMap();
|
|
822
|
+
var runtimeReleasers = /* @__PURE__ */ new WeakMap();
|
|
823
|
+
var runtimeQuiescenceReaders = /* @__PURE__ */ new WeakMap();
|
|
824
|
+
var subscriberCountReaders = /* @__PURE__ */ new WeakMap();
|
|
825
|
+
var activationReaders = /* @__PURE__ */ new WeakMap();
|
|
826
|
+
var releasedNodes = /* @__PURE__ */ new WeakSet();
|
|
827
|
+
function withNodeCore(core, create) {
|
|
828
|
+
const prev = constructingCore;
|
|
829
|
+
constructingCore = core;
|
|
830
|
+
try {
|
|
831
|
+
return create();
|
|
832
|
+
} finally {
|
|
833
|
+
constructingCore = prev;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
function takeConstructingNodeCore() {
|
|
837
|
+
const core = constructingCore;
|
|
838
|
+
constructingCore = void 0;
|
|
839
|
+
return core;
|
|
840
|
+
}
|
|
841
|
+
function withEnvironmentDrivers(environment, create) {
|
|
842
|
+
const prev = constructingEnvironment;
|
|
843
|
+
constructingEnvironment = environment;
|
|
844
|
+
try {
|
|
845
|
+
return create();
|
|
846
|
+
} finally {
|
|
847
|
+
constructingEnvironment = prev;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
function takeConstructingEnvironmentDrivers() {
|
|
851
|
+
const environment = constructingEnvironment;
|
|
852
|
+
constructingEnvironment = void 0;
|
|
853
|
+
return environment;
|
|
854
|
+
}
|
|
855
|
+
function getNodeOwner(n) {
|
|
856
|
+
return ownerTokens.get(n);
|
|
857
|
+
}
|
|
858
|
+
function notifyTopologyDepsChanged(node, prevDeps, deps) {
|
|
859
|
+
topologyDepsChangedObservers.get(node)?.(node, prevDeps, deps);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// src/node/node-context-runtime.ts
|
|
863
|
+
function nodeBuildCtx(self) {
|
|
864
|
+
const kind = self._slot.handle ? self._slot.dispatcher.poolKind(self._slot.handle.poolId) : "sync";
|
|
865
|
+
if (kind === "sync") {
|
|
866
|
+
if (self._syncCtx === null) self._syncCtx = self._makeCtx();
|
|
867
|
+
self._refreshCtx(self._syncCtx);
|
|
868
|
+
return self._syncCtx;
|
|
869
|
+
}
|
|
870
|
+
return self._makeCtx({
|
|
871
|
+
waveData: self._dep.waveData.map((waves) => waves.map((w) => [...w])),
|
|
872
|
+
terminal: self._dep.terminalInput.map(terminalView),
|
|
873
|
+
latest: [...self._dep.prev]
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
function nodeMakeCtx(self, snapshot) {
|
|
877
|
+
const ctx = {
|
|
878
|
+
// Wave-owner boundary (D47): a SYNC fn's emit nests under the public entry that drove
|
|
879
|
+
// it (cheap inc/dec, no early drain); an ASYNC-pool fn re-enters here from its stashed
|
|
880
|
+
// ctx at depth 0, so this is the boundary that drains any rewireNext it issued.
|
|
881
|
+
up: (msgs, towardDep) => {
|
|
882
|
+
if (self._released) return;
|
|
883
|
+
enterWave();
|
|
884
|
+
try {
|
|
885
|
+
self._up(msgs, towardDep);
|
|
886
|
+
} finally {
|
|
887
|
+
exitWave();
|
|
888
|
+
}
|
|
889
|
+
},
|
|
890
|
+
down: (msgs) => {
|
|
891
|
+
if (self._released) return;
|
|
892
|
+
enterWave();
|
|
893
|
+
try {
|
|
894
|
+
self._down(msgs);
|
|
895
|
+
} finally {
|
|
896
|
+
exitWave();
|
|
897
|
+
}
|
|
898
|
+
},
|
|
899
|
+
waveData: snapshot?.waveData ?? self._dep.waveData,
|
|
900
|
+
terminal: snapshot?.terminal ?? self._dep.terminalInput.map(terminalView),
|
|
901
|
+
state: self._makeState(),
|
|
902
|
+
onDeactivation: (fn) => {
|
|
903
|
+
if (self._released) return;
|
|
904
|
+
self._hooks.onDeactivation.push(fn);
|
|
905
|
+
},
|
|
906
|
+
onInvalidate: (fn) => {
|
|
907
|
+
if (self._released) return;
|
|
908
|
+
self._hooks.onInvalidate.push(fn);
|
|
909
|
+
},
|
|
910
|
+
environment: () => self._slot.environment,
|
|
911
|
+
// R-rewire-deferred (D47): defer a self-dep-set mutation to the committed boundary.
|
|
912
|
+
rewireNext: {
|
|
913
|
+
subscribeDep: (dep, fn) => self._requestRewireNext({ kind: "add", dep, fn }),
|
|
914
|
+
unsubscribeDep: (dep, fn) => self._requestRewireNext({ kind: "remove", dep, fn }),
|
|
915
|
+
replaceDeps: (deps, fn) => self._requestRewireNext({ kind: "set", deps, fn })
|
|
916
|
+
},
|
|
917
|
+
// R-up-routing / R-pull (D269): deferred up — route a control/demand wave (e.g. PULL)
|
|
918
|
+
// up the declared cone at the committed boundary. The SELF-demand path: an
|
|
919
|
+
// immediate ctx.up whose delivery loops back re-enters this fn (D37 / R-reentrancy).
|
|
920
|
+
upNext: (msgs, towardDep) => self._requestUpNext(msgs, towardDep),
|
|
921
|
+
...self._control.activePull === void 0 ? {} : { pull: self._control.activePull },
|
|
922
|
+
[CTX_DEP_CACHE]: { latest: snapshot?.latest ?? self._dep.prev },
|
|
923
|
+
[CTX_NODE_BINDING]: {
|
|
924
|
+
dispatcher: self._slot.dispatcher,
|
|
925
|
+
create: (factory) => withEnvironmentDrivers(self._slot.environment, () => withNodeCore(self._core, factory))
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
if (self._slot.dynamic) {
|
|
929
|
+
ctx.track = (i) => ctx[CTX_DEP_CACHE]?.latest[i];
|
|
930
|
+
}
|
|
931
|
+
return ctx;
|
|
932
|
+
}
|
|
933
|
+
function nodeRefreshCtx(self, ctx) {
|
|
934
|
+
ctx.waveData = self._dep.waveData;
|
|
935
|
+
ctx.terminal = self._dep.terminalInput.map(terminalView);
|
|
936
|
+
if (self._control.activePull === void 0) {
|
|
937
|
+
delete ctx.pull;
|
|
938
|
+
} else {
|
|
939
|
+
ctx.pull = self._control.activePull;
|
|
940
|
+
}
|
|
941
|
+
ctx[CTX_DEP_CACHE] = { latest: self._dep.prev };
|
|
942
|
+
}
|
|
943
|
+
function nodeMakeState(self) {
|
|
944
|
+
return {
|
|
945
|
+
get: () => self._privateState.value,
|
|
946
|
+
set: (v) => {
|
|
947
|
+
self._privateState.value = v;
|
|
948
|
+
},
|
|
949
|
+
persist: (on = true) => {
|
|
950
|
+
self._privateState.persist = on;
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
// src/node/node-input-runtime.ts
|
|
956
|
+
function nodeRecordDepProjection(self, idx, delivery) {
|
|
957
|
+
const token = delivery?.wave ?? {};
|
|
958
|
+
if (self._dep.waveTokens[idx] !== token) {
|
|
959
|
+
self._dep.waveData[idx].push([]);
|
|
960
|
+
self._dep.waveTokens[idx] = token;
|
|
961
|
+
}
|
|
962
|
+
return self._dep.waveData[idx][self._dep.waveData[idx].length - 1];
|
|
963
|
+
}
|
|
964
|
+
function nodeDepProjectionHasData(self, idx) {
|
|
965
|
+
const projection = self._dep.waveData[idx][self._dep.waveData[idx].length - 1];
|
|
966
|
+
return projection?.some((v) => v !== SENTINEL) ?? false;
|
|
967
|
+
}
|
|
968
|
+
function nodeReceiveFromDep(self, idx, msg, delivery) {
|
|
969
|
+
if (self._released) return;
|
|
970
|
+
const t = msg[0];
|
|
971
|
+
if (t === "START") return;
|
|
972
|
+
const isLastInDeliveredWave = delivery?.last ?? true;
|
|
973
|
+
if (self._value.terminal !== void 0) {
|
|
974
|
+
if (t === "TEARDOWN") self._down([["TEARDOWN"]]);
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
if (t === "INVALIDATE") {
|
|
978
|
+
const projection = self._recordDepProjection(idx, delivery);
|
|
979
|
+
projection.push(SENTINEL);
|
|
980
|
+
if (projection.some((v) => v !== SENTINEL) && isLastInDeliveredWave) self._maybeRun();
|
|
981
|
+
self._dep.prev[idx] = SENTINEL;
|
|
982
|
+
self._dep.hasData[idx] = false;
|
|
983
|
+
self._dep.batch[idx] = null;
|
|
984
|
+
if (self._dep.dirty[idx]) {
|
|
985
|
+
self._dep.dirty[idx] = false;
|
|
986
|
+
self._wave.pending--;
|
|
987
|
+
}
|
|
988
|
+
if (self._control.pausedDepWaveOccurred && self._dep.batch.every((b) => b === null)) {
|
|
989
|
+
self._control.pausedDepWaveOccurred = false;
|
|
990
|
+
}
|
|
991
|
+
const hadData = self._value.hasData;
|
|
992
|
+
self._invalidate();
|
|
993
|
+
if (self._wave.pending === 0 && self._wave.emittedDirtyThisWave) {
|
|
994
|
+
if (!hadData) self._down([["RESOLVED"]]);
|
|
995
|
+
else self._wave.emittedDirtyThisWave = false;
|
|
996
|
+
}
|
|
997
|
+
self._fireOwedDemandIfReady();
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
if (isTerminal(t)) {
|
|
1001
|
+
const isError = t === "ERROR";
|
|
1002
|
+
const errPayload = isError ? msg[1] : void 0;
|
|
1003
|
+
self._dep.terminal[idx] = isError ? errPayload : true;
|
|
1004
|
+
self._dep.terminalInput[idx] = isError ? errPayload : true;
|
|
1005
|
+
self._releaseDepDirty(idx);
|
|
1006
|
+
const ranValueBeforeTerminal = self._depProjectionHasData(idx) && isLastInDeliveredWave;
|
|
1007
|
+
if (ranValueBeforeTerminal) self._maybeRun();
|
|
1008
|
+
if (isError && self._slot.errorWhenDepsError) {
|
|
1009
|
+
self._down([["ERROR", errPayload]]);
|
|
1010
|
+
} else if (self._slot.terminalAsRealInput) {
|
|
1011
|
+
if (ranValueBeforeTerminal) {
|
|
1012
|
+
self._fireOwedDemandIfReady();
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
self._maybeRun();
|
|
1016
|
+
} else if (self._slot.completeWhenDepsComplete && self._allDepsTerminal()) {
|
|
1017
|
+
self._down([["COMPLETE"]]);
|
|
1018
|
+
} else {
|
|
1019
|
+
self._settleAfterAbsorbedTerminal();
|
|
1020
|
+
}
|
|
1021
|
+
self._fireOwedDemandIfReady();
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
if (t === "TEARDOWN") {
|
|
1025
|
+
self._down([["TEARDOWN"]]);
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
if (t === "DIRTY") {
|
|
1029
|
+
if (!self._dep.dirty[idx]) {
|
|
1030
|
+
self._dep.dirty[idx] = true;
|
|
1031
|
+
self._wave.pending++;
|
|
1032
|
+
self._dep.tier[idx] = 2;
|
|
1033
|
+
self._markDirty();
|
|
1034
|
+
}
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
if (t === "DATA") {
|
|
1038
|
+
const v = msg[1];
|
|
1039
|
+
self._recordDepProjection(idx, delivery).push(v);
|
|
1040
|
+
const b = self._dep.batch[idx];
|
|
1041
|
+
if (b === null) self._dep.batch[idx] = [v];
|
|
1042
|
+
else b.push(v);
|
|
1043
|
+
self._dep.prev[idx] = v;
|
|
1044
|
+
self._dep.hasData[idx] = true;
|
|
1045
|
+
self._dep.tier[idx] = 3;
|
|
1046
|
+
if (self._dep.dirty[idx]) {
|
|
1047
|
+
self._dep.dirty[idx] = false;
|
|
1048
|
+
self._wave.pending--;
|
|
1049
|
+
}
|
|
1050
|
+
if (isLastInDeliveredWave) self._maybeRun();
|
|
1051
|
+
self._fireOwedDemandIfReady();
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
if (t === "RESOLVED") {
|
|
1055
|
+
self._recordDepProjection(idx, delivery);
|
|
1056
|
+
self._dep.tier[idx] = 3;
|
|
1057
|
+
if (self._dep.dirty[idx]) {
|
|
1058
|
+
self._dep.dirty[idx] = false;
|
|
1059
|
+
self._wave.pending--;
|
|
1060
|
+
}
|
|
1061
|
+
if (isLastInDeliveredWave) self._maybeRun();
|
|
1062
|
+
self._fireOwedDemandIfReady();
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
function nodeReleaseDepDirty(self, idx) {
|
|
1067
|
+
if (self._dep.dirty[idx]) {
|
|
1068
|
+
self._dep.dirty[idx] = false;
|
|
1069
|
+
self._wave.pending--;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
function nodeSettleAfterAbsorbedTerminal(self) {
|
|
1073
|
+
if (self._wave.pending !== 0 || !self._wave.emittedDirtyThisWave) return;
|
|
1074
|
+
const sawData = self._dep.batch.some((b) => b !== null && b.length > 0);
|
|
1075
|
+
if (sawData) self._maybeRun();
|
|
1076
|
+
if (self._wave.emittedDirtyThisWave) self._down([["RESOLVED"]]);
|
|
1077
|
+
}
|
|
1078
|
+
function nodeMarkDirty(self) {
|
|
1079
|
+
self._value.status = "dirty";
|
|
1080
|
+
if (self._isPullQuiet()) return;
|
|
1081
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1082
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1083
|
+
self._emitToSubs(["DIRTY"]);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
function nodeMaybeRun(self) {
|
|
1087
|
+
if (self._wave.inDepMutation) {
|
|
1088
|
+
self._wave.rewireRunPending = true;
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
if (self._slot.pausable === true && (self._isPaused() || self._isPullQuiet())) {
|
|
1092
|
+
self._control.pausedDepWaveOccurred = true;
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
self._tryRun();
|
|
1096
|
+
}
|
|
1097
|
+
function nodeSettleRewire(self) {
|
|
1098
|
+
if (self._slot.pausable === true && self._isPaused()) {
|
|
1099
|
+
self._control.pausedDepWaveOccurred = true;
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
if (self._wave.pending > 0) return;
|
|
1103
|
+
if (self._slot.handle === null) {
|
|
1104
|
+
self._passthroughEmit();
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
if (!self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled())) return;
|
|
1108
|
+
self._markDirty();
|
|
1109
|
+
self._runWave();
|
|
1110
|
+
}
|
|
1111
|
+
function nodeTryRun(self) {
|
|
1112
|
+
if (self._wave.pending > 0) return;
|
|
1113
|
+
if (self._slot.handle === null) {
|
|
1114
|
+
self._passthroughEmit();
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
if (!self._wave.hasCalledFnOnce) {
|
|
1118
|
+
if (self._slot.partial || self._allDepsSettled()) self._runWave();
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
self._runWave();
|
|
1122
|
+
}
|
|
1123
|
+
function nodeAllDepsSettled(self) {
|
|
1124
|
+
for (let i = 0; i < self._slot.deps.length; i++) {
|
|
1125
|
+
if (self._dep.hasData[i]) continue;
|
|
1126
|
+
if (self._slot.terminalAsRealInput && self._dep.terminal[i] !== void 0) continue;
|
|
1127
|
+
return false;
|
|
1128
|
+
}
|
|
1129
|
+
return true;
|
|
1130
|
+
}
|
|
1131
|
+
function nodePassthroughEmit(self) {
|
|
1132
|
+
const b = self._dep.batch[0];
|
|
1133
|
+
if (b !== null && b.length > 0) {
|
|
1134
|
+
self._down([["DATA", b[b.length - 1]]]);
|
|
1135
|
+
} else if (self._wave.emittedDirtyThisWave) {
|
|
1136
|
+
self._down([["RESOLVED"]]);
|
|
1137
|
+
}
|
|
1138
|
+
self._dep.batch[0] = null;
|
|
1139
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1140
|
+
}
|
|
1141
|
+
function nodeRunWave(self) {
|
|
1142
|
+
if (self._wave.insideRunWave)
|
|
1143
|
+
throw new Error(
|
|
1144
|
+
"synchronous feedback cycle: node fn re-entered its own wave (R-reentrancy / D37)"
|
|
1145
|
+
);
|
|
1146
|
+
self._wave.hasCalledFnOnce = true;
|
|
1147
|
+
self._hooks.onInvalidate = [];
|
|
1148
|
+
self._hooks.onDeactivation = [];
|
|
1149
|
+
const ctx = self._buildCtx();
|
|
1150
|
+
const wasDirty = self._wave.emittedDirtyThisWave;
|
|
1151
|
+
self._wave.emittedSettleThisWave = false;
|
|
1152
|
+
self._wave.insideRunWave = true;
|
|
1153
|
+
try {
|
|
1154
|
+
self._slot.dispatcher.invoke(self._slot.handle, ctx);
|
|
1155
|
+
} finally {
|
|
1156
|
+
self._wave.insideRunWave = false;
|
|
1157
|
+
}
|
|
1158
|
+
if (wasDirty && !self._wave.emittedSettleThisWave && self._value.terminal === void 0 && !self._isAsyncPool()) {
|
|
1159
|
+
self._down([["RESOLVED"]]);
|
|
1160
|
+
}
|
|
1161
|
+
for (let i = 0; i < self._dep.batch.length; i++) {
|
|
1162
|
+
self._dep.batch[i] = null;
|
|
1163
|
+
self._dep.waveData[i] = [];
|
|
1164
|
+
self._dep.waveTokens[i] = void 0;
|
|
1165
|
+
self._dep.terminalInput[i] = void 0;
|
|
1166
|
+
}
|
|
1167
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
// src/node/node-runtime-host.ts
|
|
1171
|
+
function nodeRuntimeHost(node) {
|
|
1172
|
+
return node;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
// src/node/node-lifecycle-runtime.ts
|
|
1176
|
+
function nodeActivate(self) {
|
|
1177
|
+
self._lifecycle.activated = true;
|
|
1178
|
+
const seedRestoredDeps = self._restoredActivationPending;
|
|
1179
|
+
self._restoredActivationPending = false;
|
|
1180
|
+
self._dep.unsubs = new Array(self._slot.deps.length);
|
|
1181
|
+
self._dep.idxBoxes = new Array(self._slot.deps.length);
|
|
1182
|
+
for (const dep of self._slot.deps) self._subscribeDepAt(dep, { seedRestored: seedRestoredDeps });
|
|
1183
|
+
if (self._slot.deps.length === 0 && self._slot.handle !== null && !self._wave.hasCalledFnOnce) {
|
|
1184
|
+
self._runWave();
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
function nodeSubscribeDepAt(self, depNode, opts = {}) {
|
|
1188
|
+
const idx0 = self._slot.deps.indexOf(depNode);
|
|
1189
|
+
const box = { v: idx0 };
|
|
1190
|
+
let ignoreInitialPush = opts.seedRestored === true;
|
|
1191
|
+
if (ignoreInitialPush && idx0 !== -1) {
|
|
1192
|
+
self._seedRestoredDepAt(idx0, depNode);
|
|
1193
|
+
const dep = nodeRuntimeHost(depNode);
|
|
1194
|
+
if (dep._value.terminal !== void 0 && !dep._slot.resubscribable) {
|
|
1195
|
+
self._dep.unsubs[idx0] = () => {
|
|
1196
|
+
};
|
|
1197
|
+
self._dep.idxBoxes[idx0] = box;
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
const unsub = depNode.subscribe((msg, delivery) => {
|
|
1202
|
+
if (ignoreInitialPush && delivery === void 0) return;
|
|
1203
|
+
if (ignoreInitialPush) ignoreInitialPush = false;
|
|
1204
|
+
if (box.v === -1) return;
|
|
1205
|
+
self._receiveFromDep(box.v, msg, delivery);
|
|
1206
|
+
});
|
|
1207
|
+
if (ignoreInitialPush && idx0 !== -1 && box.v !== -1) self._seedRestoredDepAt(idx0, depNode);
|
|
1208
|
+
ignoreInitialPush = false;
|
|
1209
|
+
if (idx0 !== -1) {
|
|
1210
|
+
self._dep.unsubs[idx0] = unsub;
|
|
1211
|
+
self._dep.idxBoxes[idx0] = box;
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
function nodeSeedRestoredDepAt(self, idx, depNode) {
|
|
1215
|
+
const dep = nodeRuntimeHost(depNode);
|
|
1216
|
+
const seedData = dep._value.hasData && !dep._slot.pull;
|
|
1217
|
+
self._dep.batch[idx] = null;
|
|
1218
|
+
self._dep.waveData[idx] = [];
|
|
1219
|
+
self._dep.waveTokens[idx] = void 0;
|
|
1220
|
+
self._dep.prev[idx] = seedData ? dep._value.cache : SENTINEL;
|
|
1221
|
+
self._dep.hasData[idx] = seedData;
|
|
1222
|
+
self._dep.dirty[idx] = false;
|
|
1223
|
+
self._dep.tier[idx] = seedData ? 3 : 0;
|
|
1224
|
+
self._dep.terminal[idx] = dep._value.terminal;
|
|
1225
|
+
self._dep.terminalInput[idx] = void 0;
|
|
1226
|
+
}
|
|
1227
|
+
function nodeDeactivate(self) {
|
|
1228
|
+
self._lifecycle.activated = false;
|
|
1229
|
+
for (const u of self._dep.unsubs) if (u) u();
|
|
1230
|
+
self._dep.unsubs = [];
|
|
1231
|
+
self._dep.idxBoxes = [];
|
|
1232
|
+
for (const fn of self._hooks.onDeactivation) fn();
|
|
1233
|
+
self._hooks.onDeactivation = [];
|
|
1234
|
+
self._hooks.onInvalidate = [];
|
|
1235
|
+
const isCompute = self._slot.handle !== null || self._slot.deps.length > 0;
|
|
1236
|
+
if (isCompute) {
|
|
1237
|
+
self._value.cache = SENTINEL;
|
|
1238
|
+
self._value.hasData = false;
|
|
1239
|
+
self._value.status = "sentinel";
|
|
1240
|
+
}
|
|
1241
|
+
self._resetDepState();
|
|
1242
|
+
self._wave.hasCalledFnOnce = false;
|
|
1243
|
+
self._control.pauseLockset.clear();
|
|
1244
|
+
self._control.pauseBuffer = [];
|
|
1245
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1246
|
+
self._control.demandOwed = void 0;
|
|
1247
|
+
self._control.activePull = void 0;
|
|
1248
|
+
self._control.pullDirtyOwed = false;
|
|
1249
|
+
self._value.replayRing = [];
|
|
1250
|
+
if (!self._privateState.persist) self._privateState.value = SENTINEL;
|
|
1251
|
+
}
|
|
1252
|
+
function nodeSubscriberCount(self) {
|
|
1253
|
+
return self._lifecycle.subscribers.size;
|
|
1254
|
+
}
|
|
1255
|
+
function nodeIsRuntimeQuiescentForRelease(self) {
|
|
1256
|
+
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;
|
|
1257
|
+
}
|
|
1258
|
+
function nodeReleaseRuntime(self) {
|
|
1259
|
+
if (self._released) return;
|
|
1260
|
+
self._released = true;
|
|
1261
|
+
const node = self;
|
|
1262
|
+
releasedNodes.add(node);
|
|
1263
|
+
let releaseError;
|
|
1264
|
+
const recordReleaseError = (error) => {
|
|
1265
|
+
if (releaseError === void 0) releaseError = error;
|
|
1266
|
+
};
|
|
1267
|
+
self._lifecycle.activated = false;
|
|
1268
|
+
for (const u of self._dep.unsubs) {
|
|
1269
|
+
try {
|
|
1270
|
+
u();
|
|
1271
|
+
} catch (error) {
|
|
1272
|
+
recordReleaseError(error);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
for (const fn of self._hooks.onDeactivation) {
|
|
1276
|
+
try {
|
|
1277
|
+
fn();
|
|
1278
|
+
} catch (error) {
|
|
1279
|
+
recordReleaseError(error);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
self._dep.unsubs = [];
|
|
1283
|
+
self._dep.idxBoxes = [];
|
|
1284
|
+
self._lifecycle.subscribers.clear();
|
|
1285
|
+
if (self._slot.handle !== null) {
|
|
1286
|
+
self._slot.dispatcher.unregister(self._slot.handle);
|
|
1287
|
+
self._slot.handle = null;
|
|
1288
|
+
}
|
|
1289
|
+
self._slot.deps = [];
|
|
1290
|
+
self._dep.batch = [];
|
|
1291
|
+
self._dep.waveData = [];
|
|
1292
|
+
self._dep.waveTokens = [];
|
|
1293
|
+
self._dep.prev = [];
|
|
1294
|
+
self._dep.hasData = [];
|
|
1295
|
+
self._dep.dirty = [];
|
|
1296
|
+
self._dep.tier = [];
|
|
1297
|
+
self._dep.terminal = [];
|
|
1298
|
+
self._dep.terminalInput = [];
|
|
1299
|
+
self._value.cache = SENTINEL;
|
|
1300
|
+
self._value.hasData = false;
|
|
1301
|
+
self._value.status = "sentinel";
|
|
1302
|
+
self._value.terminal = void 0;
|
|
1303
|
+
self._value.replayRing = [];
|
|
1304
|
+
self._privateState.value = SENTINEL;
|
|
1305
|
+
self._privateState.persist = false;
|
|
1306
|
+
self._syncCtx = null;
|
|
1307
|
+
self._resetDepState();
|
|
1308
|
+
self._hooks.onDeactivation = [];
|
|
1309
|
+
self._hooks.onInvalidate = [];
|
|
1310
|
+
self._control.pauseLockset.clear();
|
|
1311
|
+
self._control.pauseBuffer = [];
|
|
1312
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1313
|
+
self._control.demandOwed = void 0;
|
|
1314
|
+
self._control.activePull = void 0;
|
|
1315
|
+
self._control.pullDirtyOwed = false;
|
|
1316
|
+
self._restoredActivationPending = false;
|
|
1317
|
+
checkpointReaders.delete(node);
|
|
1318
|
+
restoreWriters.delete(node);
|
|
1319
|
+
runtimeReleasers.delete(node);
|
|
1320
|
+
runtimeQuiescenceReaders.delete(node);
|
|
1321
|
+
subscriberCountReaders.delete(node);
|
|
1322
|
+
activationReaders.delete(node);
|
|
1323
|
+
ownerTokens.delete(node);
|
|
1324
|
+
topologyDepsChangedObservers.delete(node);
|
|
1325
|
+
self._core.releaseSlot(self._id);
|
|
1326
|
+
if (releaseError !== void 0) throw releaseError;
|
|
1327
|
+
}
|
|
1328
|
+
function nodeResetDepState(self) {
|
|
1329
|
+
const n = self._slot.deps.length;
|
|
1330
|
+
for (let i = 0; i < n; i++) {
|
|
1331
|
+
self._dep.batch[i] = null;
|
|
1332
|
+
self._dep.waveData[i] = [];
|
|
1333
|
+
self._dep.waveTokens[i] = void 0;
|
|
1334
|
+
self._dep.prev[i] = SENTINEL;
|
|
1335
|
+
self._dep.hasData[i] = false;
|
|
1336
|
+
self._dep.dirty[i] = false;
|
|
1337
|
+
self._dep.tier[i] = 0;
|
|
1338
|
+
self._dep.terminal[i] = void 0;
|
|
1339
|
+
self._dep.terminalInput[i] = void 0;
|
|
1340
|
+
}
|
|
1341
|
+
self._wave.pending = 0;
|
|
1342
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
// src/batch/batch.ts
|
|
1346
|
+
var active = null;
|
|
1347
|
+
var boundaryOwner = null;
|
|
1348
|
+
function currentBatch() {
|
|
1349
|
+
return active !== null;
|
|
1350
|
+
}
|
|
1351
|
+
function currentBoundaryBatchToken() {
|
|
1352
|
+
return active ?? boundaryOwner ?? void 0;
|
|
1353
|
+
}
|
|
1354
|
+
function deferToBatch(target, tier3Wave) {
|
|
1355
|
+
if (active === null) return false;
|
|
1356
|
+
if (!active.deferred.has(target)) active.order.push(target);
|
|
1357
|
+
active.deferred.set(target, tier3Wave);
|
|
1358
|
+
return true;
|
|
1359
|
+
}
|
|
1360
|
+
function deferAfterBatchForTarget(target, fn) {
|
|
1361
|
+
if (active === null || !active.deferred.has(target)) return false;
|
|
1362
|
+
const owner = active;
|
|
1363
|
+
target.__deferBoundary(() => {
|
|
1364
|
+
if (owner.committed) fn();
|
|
1365
|
+
}, owner);
|
|
1366
|
+
return true;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
796
1369
|
// src/node/versioning.ts
|
|
797
1370
|
var ABSENT_V1_SEED = Object.freeze({
|
|
798
1371
|
"@graphrefly/node-version": "v1-absent"
|
|
@@ -871,60 +1444,536 @@ function restoredV1Cid(policy, hasData, cache) {
|
|
|
871
1444
|
return computeV1Cid(policy, hasData ? cache : ABSENT_V1_SEED);
|
|
872
1445
|
}
|
|
873
1446
|
|
|
874
|
-
// src/node/node.ts
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
constructingEnvironment = environment;
|
|
898
|
-
try {
|
|
899
|
-
return create();
|
|
900
|
-
} finally {
|
|
901
|
-
constructingEnvironment = prev;
|
|
1447
|
+
// src/node/node-output-runtime.ts
|
|
1448
|
+
function nodeDown(self, msgs) {
|
|
1449
|
+
if (self._released) return;
|
|
1450
|
+
validateDownPayloads(msgs);
|
|
1451
|
+
const deliveryWave = {};
|
|
1452
|
+
const assertVersionDataCompatible = (wave) => {
|
|
1453
|
+
for (const m of wave) {
|
|
1454
|
+
if (m[0] === "DATA") assertNodeVersionDataCompatible(self._version.policy, m[1]);
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
const snapshotVersionData = (wave) => wave.map(
|
|
1458
|
+
(m) => m[0] === "DATA" ? ["DATA", snapshotNodeVersionData(self._version.policy, m[1])] : m
|
|
1459
|
+
);
|
|
1460
|
+
assertVersionDataCompatible(msgs);
|
|
1461
|
+
if (self._value.terminal !== void 0) {
|
|
1462
|
+
if (!msgs.some((m) => m[0] === "TEARDOWN")) return;
|
|
1463
|
+
self._value.hasTorndown = true;
|
|
1464
|
+
if (self._slot.resetOnTeardown) {
|
|
1465
|
+
self._value.cache = SENTINEL;
|
|
1466
|
+
self._value.hasData = false;
|
|
1467
|
+
}
|
|
1468
|
+
self._emitToSubs(["TEARDOWN"], { wave: deliveryWave, last: true });
|
|
1469
|
+
return;
|
|
902
1470
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
if (
|
|
916
|
-
|
|
1471
|
+
let sorted = [...msgs].sort((a, b) => messageTier(a[0]) - messageTier(b[0]));
|
|
1472
|
+
const firstInvalidate = sorted.findIndex((m) => m[0] === "INVALIDATE");
|
|
1473
|
+
if (firstInvalidate !== -1) {
|
|
1474
|
+
sorted = sorted.filter((m, i) => m[0] !== "INVALIDATE" || i === firstInvalidate);
|
|
1475
|
+
}
|
|
1476
|
+
const hasTeardown = sorted.some((m) => m[0] === "TEARDOWN");
|
|
1477
|
+
const hasTerminal = sorted.some((m) => m[0] === "COMPLETE" || m[0] === "ERROR");
|
|
1478
|
+
if (hasTeardown && !hasTerminal && self._value.terminal === void 0 && !self._value.hasTorndown) {
|
|
1479
|
+
sorted = [["COMPLETE"], ...sorted];
|
|
1480
|
+
}
|
|
1481
|
+
if (!self._wave.insideRunWave && currentBatch()) {
|
|
1482
|
+
const deferred = snapshotVersionData(sorted.filter((m) => isDeferredTier(m[0])));
|
|
1483
|
+
if (deferred.length > 0) {
|
|
1484
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1485
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1486
|
+
self._value.status = "dirty";
|
|
1487
|
+
self._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1488
|
+
}
|
|
1489
|
+
self._wave.batchDirtyOwed = true;
|
|
1490
|
+
deferToBatch(self, deferred);
|
|
1491
|
+
return;
|
|
917
1492
|
}
|
|
918
|
-
|
|
919
|
-
|
|
1493
|
+
}
|
|
1494
|
+
if (self._shouldBufferOnPause()) {
|
|
1495
|
+
const buffered = snapshotVersionData(sorted.filter((m) => isPauseBufferedTier(m[0])));
|
|
1496
|
+
if (buffered.length > 0) {
|
|
1497
|
+
self._wave.emittedSettleThisWave = true;
|
|
1498
|
+
self._control.pauseBuffer.push(buffered);
|
|
920
1499
|
}
|
|
1500
|
+
sorted = sorted.filter((m) => !isPauseBufferedTier(m[0]));
|
|
1501
|
+
if (sorted.length === 0) return;
|
|
921
1502
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
1503
|
+
let dataCount = 0;
|
|
1504
|
+
let hasTier3 = false;
|
|
1505
|
+
let hasResolved = false;
|
|
1506
|
+
for (const m of sorted) {
|
|
1507
|
+
if (m[0] === "DATA") dataCount++;
|
|
1508
|
+
if (m[0] === "RESOLVED") hasResolved = true;
|
|
1509
|
+
if (isValueTier(m[0])) hasTier3 = true;
|
|
1510
|
+
}
|
|
1511
|
+
if (dataCount >= 1 && hasResolved) {
|
|
1512
|
+
throw new Error(
|
|
1513
|
+
"down: a wave cannot mix DATA and RESOLVED (tier-3 exclusivity, R-resolved-undirty)"
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1516
|
+
const plannedVersions = new Array(sorted.length);
|
|
1517
|
+
if (dataCount > 0) {
|
|
1518
|
+
let plannedVersion = self._version.value;
|
|
1519
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1520
|
+
const m = sorted[i];
|
|
1521
|
+
if (m[0] !== "DATA") continue;
|
|
1522
|
+
plannedVersion = advanceNodeVersion(plannedVersion, self._version.policy, m[1]);
|
|
1523
|
+
plannedVersions[i] = plannedVersion;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
if (hasTier3 && (!self._wave.insideRunWave || self._control.pullDirtyOwed) && !self._wave.emittedDirtyThisWave) {
|
|
1527
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1528
|
+
self._value.status = "dirty";
|
|
1529
|
+
self._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1530
|
+
}
|
|
1531
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1532
|
+
const m = sorted[i];
|
|
1533
|
+
const delivery = { wave: deliveryWave, last: i === sorted.length - 1 };
|
|
1534
|
+
if (isDeferredTier(m[0])) self._wave.emittedSettleThisWave = true;
|
|
1535
|
+
if (m[0] === "DIRTY") {
|
|
1536
|
+
if (!self._wave.emittedDirtyThisWave) {
|
|
1537
|
+
self._wave.emittedDirtyThisWave = true;
|
|
1538
|
+
self._value.status = "dirty";
|
|
1539
|
+
self._emitToSubs(["DIRTY"], delivery);
|
|
1540
|
+
}
|
|
1541
|
+
continue;
|
|
1542
|
+
}
|
|
1543
|
+
if (m[0] === "DATA") {
|
|
1544
|
+
const v = m[1];
|
|
1545
|
+
self._value.cache = v;
|
|
1546
|
+
self._value.hasData = true;
|
|
1547
|
+
self._value.status = "settled";
|
|
1548
|
+
self._version.value = plannedVersions[i];
|
|
1549
|
+
if (self._slot.replayN > 0) {
|
|
1550
|
+
self._value.replayRing.push(v);
|
|
1551
|
+
if (self._value.replayRing.length > self._slot.replayN) self._value.replayRing.shift();
|
|
1552
|
+
}
|
|
1553
|
+
self._emitToSubs(["DATA", v], delivery);
|
|
1554
|
+
continue;
|
|
1555
|
+
}
|
|
1556
|
+
if (m[0] === "RESOLVED") {
|
|
1557
|
+
self._value.status = self._value.hasData ? "resolved" : "sentinel";
|
|
1558
|
+
self._emitToSubs(["RESOLVED"], delivery);
|
|
1559
|
+
continue;
|
|
1560
|
+
}
|
|
1561
|
+
if (m[0] === "INVALIDATE") {
|
|
1562
|
+
self._invalidate(delivery);
|
|
1563
|
+
continue;
|
|
1564
|
+
}
|
|
1565
|
+
if (m[0] === "COMPLETE") {
|
|
1566
|
+
if (self._value.terminal !== void 0) continue;
|
|
1567
|
+
self._value.terminal = true;
|
|
1568
|
+
self._control.pauseBuffer = [];
|
|
1569
|
+
self._value.status = "completed";
|
|
1570
|
+
self._emitToSubs(["COMPLETE"], delivery);
|
|
1571
|
+
continue;
|
|
1572
|
+
}
|
|
1573
|
+
if (m[0] === "ERROR") {
|
|
1574
|
+
if (self._value.terminal !== void 0) continue;
|
|
1575
|
+
self._value.terminal = m[1];
|
|
1576
|
+
self._control.pauseBuffer = [];
|
|
1577
|
+
self._value.status = "errored";
|
|
1578
|
+
self._emitToSubs(["ERROR", m[1]], delivery);
|
|
1579
|
+
continue;
|
|
1580
|
+
}
|
|
1581
|
+
if (m[0] === "TEARDOWN") {
|
|
1582
|
+
self._value.hasTorndown = true;
|
|
1583
|
+
if (self._slot.resetOnTeardown) {
|
|
1584
|
+
self._value.cache = SENTINEL;
|
|
1585
|
+
self._value.hasData = false;
|
|
1586
|
+
}
|
|
1587
|
+
self._emitToSubs(["TEARDOWN"], delivery);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
if (!self._wave.insideRunWave) self._wave.emittedDirtyThisWave = false;
|
|
1591
|
+
}
|
|
1592
|
+
function nodeUp(self, msgs, towardDep, route) {
|
|
1593
|
+
if (self._released) return;
|
|
1594
|
+
const routeState = route ?? { demandFired: /* @__PURE__ */ new Map() };
|
|
1595
|
+
for (const m of msgs) {
|
|
1596
|
+
if (!isUpAllowed(m[0])) {
|
|
1597
|
+
throw new Error(
|
|
1598
|
+
`ctx.up: ${m[0]} is down-only (tier ${messageTier(m[0])}); up carries control tiers only (R-ctx-up)`
|
|
1599
|
+
);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
for (const m of msgs) {
|
|
1603
|
+
if (m[0] === "PAUSE") {
|
|
1604
|
+
self._pauseAcquire(m[1]);
|
|
1605
|
+
} else if (m[0] === "RESUME") {
|
|
1606
|
+
if (self._control.pauseLockset.has(m[1])) {
|
|
1607
|
+
self._pauseRelease(m[1]);
|
|
1608
|
+
} else {
|
|
1609
|
+
self._forwardUp(m, towardDep, routeState);
|
|
1610
|
+
}
|
|
1611
|
+
} else if (m[0] === "PULL") {
|
|
1612
|
+
const demand = normalizePullDemand(m[1]);
|
|
1613
|
+
if (self._slot.pull && demand.pullId === self._slot.pullLock) {
|
|
1614
|
+
if (!self._markDemandRouted(demand.pullId, routeState)) self._onDemand(demand);
|
|
1615
|
+
} else {
|
|
1616
|
+
self._forwardUp(["PULL", demand], towardDep, routeState);
|
|
1617
|
+
}
|
|
1618
|
+
} else if (self._slot.deps.length === 0) {
|
|
1619
|
+
if (m[0] === "INVALIDATE") self._down([["INVALIDATE"]]);
|
|
1620
|
+
} else {
|
|
1621
|
+
self._forwardUp(m, towardDep, routeState);
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
function nodeMarkDemandRouted(self, lockId, route) {
|
|
1626
|
+
let holders = route.demandFired.get(lockId);
|
|
1627
|
+
if (holders === void 0) {
|
|
1628
|
+
holders = /* @__PURE__ */ new Set();
|
|
1629
|
+
route.demandFired.set(lockId, holders);
|
|
1630
|
+
}
|
|
1631
|
+
const node = self;
|
|
1632
|
+
if (holders.has(node)) return true;
|
|
1633
|
+
holders.add(node);
|
|
1634
|
+
return false;
|
|
1635
|
+
}
|
|
1636
|
+
function nodeForwardUp(self, m, towardDep, route) {
|
|
1637
|
+
if (self._slot.deps.length === 0) return;
|
|
1638
|
+
if (towardDep !== void 0) {
|
|
1639
|
+
const d = self._slot.deps[towardDep];
|
|
1640
|
+
if (d !== void 0) nodeRuntimeHost(d)._up([m], void 0, route);
|
|
1641
|
+
} else {
|
|
1642
|
+
for (const dep of self._slot.deps) nodeRuntimeHost(dep)._up([m], void 0, route);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
function nodeIsPaused(self) {
|
|
1646
|
+
return self._control.pauseLockset.size > 0;
|
|
1647
|
+
}
|
|
1648
|
+
function nodeHasBoundaryPauseLock(self) {
|
|
1649
|
+
if (self._slot.pausable === false) return false;
|
|
1650
|
+
return self._control.pauseLockset.size > 0;
|
|
1651
|
+
}
|
|
1652
|
+
function nodeIsAsyncPool(self) {
|
|
1653
|
+
return self._slot.handle !== null && self._slot.dispatcher.poolKind(self._slot.handle.poolId) === "async";
|
|
1654
|
+
}
|
|
1655
|
+
function nodePauseAcquire(self, lockId) {
|
|
1656
|
+
self._control.pauseLockset.add(lockId);
|
|
1657
|
+
}
|
|
1658
|
+
function nodePauseRelease(self, lockId) {
|
|
1659
|
+
if (!self._control.pauseLockset.has(lockId)) return;
|
|
1660
|
+
self._control.pauseLockset.delete(lockId);
|
|
1661
|
+
if (self._slot.pull && self._control.demandOwed !== void 0) self._fireOwedDemandIfReady();
|
|
1662
|
+
if (self._hasBoundaryPauseLock()) return;
|
|
1663
|
+
scheduleBoundaryDrain(self._core);
|
|
1664
|
+
if (self._slot.pull) return;
|
|
1665
|
+
self._onResume();
|
|
1666
|
+
}
|
|
1667
|
+
function nodeOnResume(self) {
|
|
1668
|
+
if (self._value.terminal !== void 0) {
|
|
1669
|
+
self._control.pauseBuffer = [];
|
|
1670
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1671
|
+
self._control.demandOwed = void 0;
|
|
1672
|
+
self._control.activePull = void 0;
|
|
1673
|
+
self._control.pullDirtyOwed = false;
|
|
1674
|
+
return;
|
|
1675
|
+
}
|
|
1676
|
+
if (self._control.pauseBuffer.length > 0) {
|
|
1677
|
+
const buf = self._control.pauseBuffer;
|
|
1678
|
+
self._control.pauseBuffer = [];
|
|
1679
|
+
for (const wave of buf) self._down(wave);
|
|
1680
|
+
}
|
|
1681
|
+
if (self._control.pausedDepWaveOccurred) {
|
|
1682
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1683
|
+
self._tryRun();
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
function nodeCanFireDemand(self) {
|
|
1687
|
+
if (self._value.terminal !== void 0 || self._wave.pending > 0) return false;
|
|
1688
|
+
return self._control.pauseLockset.size === 0;
|
|
1689
|
+
}
|
|
1690
|
+
function nodeDeliverPullDemand(self, demand) {
|
|
1691
|
+
self._control.demandOwed = void 0;
|
|
1692
|
+
self._control.activePull = demand;
|
|
1693
|
+
self._control.inDeliverDemand = true;
|
|
1694
|
+
try {
|
|
1695
|
+
self._firePullDemand();
|
|
1696
|
+
} finally {
|
|
1697
|
+
self._control.activePull = void 0;
|
|
1698
|
+
self._control.inDeliverDemand = false;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
function nodeOnDemand(self, demand) {
|
|
1702
|
+
if (self._control.inDeliverDemand) return;
|
|
1703
|
+
if (self._canFireDemand()) self._deliverPullDemand(demand);
|
|
1704
|
+
else self._control.demandOwed = demand;
|
|
1705
|
+
}
|
|
1706
|
+
function nodeFirePullDemand(self) {
|
|
1707
|
+
let drainedBuffer = false;
|
|
1708
|
+
if (self._control.pauseBuffer.length > 0) {
|
|
1709
|
+
const buf = self._control.pauseBuffer;
|
|
1710
|
+
self._control.pauseBuffer = [];
|
|
1711
|
+
for (const wave of buf) self._down(wave);
|
|
1712
|
+
drainedBuffer = true;
|
|
1713
|
+
}
|
|
1714
|
+
if (drainedBuffer) return;
|
|
1715
|
+
if (self._control.pausedDepWaveOccurred) {
|
|
1716
|
+
const gated = self._slot.handle !== null && !self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled());
|
|
1717
|
+
if (self._wave.pending > 0 || gated) return;
|
|
1718
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1719
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1720
|
+
self._control.pullDirtyOwed = true;
|
|
1721
|
+
try {
|
|
1722
|
+
self._tryRun();
|
|
1723
|
+
} finally {
|
|
1724
|
+
self._control.pullDirtyOwed = false;
|
|
1725
|
+
}
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
if (self._slot.handle !== null) {
|
|
1729
|
+
if (!self._wave.hasCalledFnOnce && !(self._slot.partial || self._allDepsSettled())) return;
|
|
1730
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1731
|
+
self._control.pullDirtyOwed = true;
|
|
1732
|
+
try {
|
|
1733
|
+
self._runWave();
|
|
1734
|
+
} finally {
|
|
1735
|
+
self._control.pullDirtyOwed = false;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
function nodeFireOwedDemandIfReady(self) {
|
|
1740
|
+
if (self._control.inDeliverDemand) return;
|
|
1741
|
+
if (self._slot.pull && self._control.demandOwed !== void 0 && self._canFireDemand()) {
|
|
1742
|
+
self._deliverPullDemand(self._control.demandOwed);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
function nodeShouldBufferOnPause(self) {
|
|
1746
|
+
if (self._slot.pausable === false) return false;
|
|
1747
|
+
if (!self._isPaused() && !self._isPullQuiet()) return false;
|
|
1748
|
+
if (self._slot.pausable === "resumeAll") return true;
|
|
1749
|
+
if (!self._wave.insideRunWave && self._isAsyncPool() && self._slot.deps.length > 0) return true;
|
|
1750
|
+
return false;
|
|
1751
|
+
}
|
|
1752
|
+
function nodeInvalidate(self, delivery) {
|
|
1753
|
+
if (!self._value.hasData) return;
|
|
1754
|
+
self._value.cache = SENTINEL;
|
|
1755
|
+
self._value.hasData = false;
|
|
1756
|
+
self._value.status = "sentinel";
|
|
1757
|
+
self._value.replayRing = [];
|
|
1758
|
+
for (const fn of self._hooks.onInvalidate) fn();
|
|
1759
|
+
self._emitToSubs(["INVALIDATE"], delivery);
|
|
1760
|
+
}
|
|
1761
|
+
function nodeAllDepsTerminal(self) {
|
|
1762
|
+
if (self._slot.deps.length === 0) return false;
|
|
1763
|
+
for (const tm of self._dep.terminal) if (tm === void 0) return false;
|
|
1764
|
+
return true;
|
|
1765
|
+
}
|
|
1766
|
+
function nodeResetLifecycle(self) {
|
|
1767
|
+
for (const u of self._dep.unsubs) if (u) u();
|
|
1768
|
+
self._dep.unsubs = [];
|
|
1769
|
+
self._dep.idxBoxes = [];
|
|
1770
|
+
self._lifecycle.subscribers.clear();
|
|
1771
|
+
self._lifecycle.activated = false;
|
|
1772
|
+
self._value.terminal = void 0;
|
|
1773
|
+
self._value.hasTorndown = false;
|
|
1774
|
+
self._wave.hasCalledFnOnce = false;
|
|
1775
|
+
self._resetDepState();
|
|
1776
|
+
self._control.pauseLockset.clear();
|
|
1777
|
+
self._control.pauseBuffer = [];
|
|
1778
|
+
self._control.pausedDepWaveOccurred = false;
|
|
1779
|
+
self._control.demandOwed = void 0;
|
|
1780
|
+
self._control.activePull = void 0;
|
|
1781
|
+
self._control.pullDirtyOwed = false;
|
|
1782
|
+
self._value.replayRing = [];
|
|
1783
|
+
const isCompute = self._slot.handle !== null || self._slot.deps.length > 0;
|
|
1784
|
+
if (isCompute) {
|
|
1785
|
+
self._value.cache = SENTINEL;
|
|
1786
|
+
self._value.hasData = false;
|
|
1787
|
+
self._value.status = "sentinel";
|
|
1788
|
+
} else {
|
|
1789
|
+
self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1790
|
+
}
|
|
1791
|
+
if (!self._privateState.persist) self._privateState.value = SENTINEL;
|
|
1792
|
+
}
|
|
1793
|
+
function nodeEmitToSubs(self, msg, delivery) {
|
|
1794
|
+
if (self._released) return;
|
|
1795
|
+
const subs = [...self._lifecycle.subscribers];
|
|
1796
|
+
for (const sink of subs) sink(msg, delivery);
|
|
1797
|
+
}
|
|
1798
|
+
function nodeCommitBatchedWave(self, wave) {
|
|
1799
|
+
self._wave.batchDirtyOwed = false;
|
|
1800
|
+
self._down(wave);
|
|
1801
|
+
}
|
|
1802
|
+
function nodeRollbackBatched(self) {
|
|
1803
|
+
if (self._wave.batchDirtyOwed) {
|
|
1804
|
+
self._wave.batchDirtyOwed = false;
|
|
1805
|
+
self._wave.emittedDirtyThisWave = false;
|
|
1806
|
+
self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1807
|
+
self._emitToSubs(["RESOLVED"]);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
function nodeDeferBoundary(self, fn, batchToken) {
|
|
1811
|
+
deferRewire(self._core, fn, {
|
|
1812
|
+
batchToken,
|
|
1813
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
// src/node/node-rewire-runtime.ts
|
|
1818
|
+
function nodeRequestRewireNext(self, op) {
|
|
1819
|
+
deferRewire(self._core, () => self._applyRewireNext(op), {
|
|
1820
|
+
batchToken: currentBoundaryBatchToken(),
|
|
1821
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1824
|
+
function nodeRequestUpNext(self, msgs, towardDep) {
|
|
1825
|
+
deferRewire(
|
|
1826
|
+
self._core,
|
|
1827
|
+
() => {
|
|
1828
|
+
if (!self._released) self._up(msgs, towardDep);
|
|
1829
|
+
},
|
|
1830
|
+
{
|
|
1831
|
+
batchToken: currentBoundaryBatchToken(),
|
|
1832
|
+
isReady: () => !self._hasBoundaryPauseLock()
|
|
1833
|
+
}
|
|
1834
|
+
);
|
|
1835
|
+
}
|
|
1836
|
+
function nodeApplyRewireNext(self, op) {
|
|
1837
|
+
if (self._released) return;
|
|
1838
|
+
try {
|
|
1839
|
+
if (op.kind === "add") {
|
|
1840
|
+
const next = self._slot.deps.includes(op.dep) ? [...self._slot.deps] : [...self._slot.deps, op.dep];
|
|
1841
|
+
self._rewire(next, op.fn, { allowTerminalOwner: true });
|
|
1842
|
+
} else if (op.kind === "remove") {
|
|
1843
|
+
self._rewire(
|
|
1844
|
+
self._slot.deps.filter((d) => d !== op.dep),
|
|
1845
|
+
op.fn,
|
|
1846
|
+
{ allowTerminalOwner: true }
|
|
1847
|
+
);
|
|
1848
|
+
} else {
|
|
1849
|
+
self._rewire(self._dedupDeps(op.deps), op.fn, { allowTerminalOwner: true });
|
|
1850
|
+
}
|
|
1851
|
+
} catch (e) {
|
|
1852
|
+
self._down([["ERROR", errorPayload(e, "rewireNext op failed")]]);
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
function nodeRewire(self, newDeps, fn, opts = {}) {
|
|
1856
|
+
const node = self;
|
|
1857
|
+
if (self._value.terminal !== void 0 && !opts.allowTerminalOwner)
|
|
1858
|
+
throw new Error(
|
|
1859
|
+
"rewire: node is terminal (completed/errored) \u2014 cannot rewire (R-rewire / D42)"
|
|
1860
|
+
);
|
|
1861
|
+
if (self._wave.insideRunWave)
|
|
1862
|
+
throw new Error(
|
|
1863
|
+
"rewire: mid-fn topology mutation \u2014 a fn mutating its own deps mid-wave is the feedback cycle (R-rewire / D37)"
|
|
1864
|
+
);
|
|
1865
|
+
if (self._wave.inDepMutation)
|
|
1866
|
+
throw new Error(
|
|
1867
|
+
"rewire: reentrant dep mutation \u2014 another replaceDeps/subscribeDep/unsubscribeDep is in flight (R-rewire)"
|
|
1868
|
+
);
|
|
1869
|
+
if (newDeps.includes(node)) throw new Error("rewire: self-dependency rejected (R-rewire / D42)");
|
|
1870
|
+
const oldDeps = self._slot.deps;
|
|
1871
|
+
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
1872
|
+
for (const d of added) {
|
|
1873
|
+
if (self._reachableUpstream(d, node))
|
|
1874
|
+
throw new Error(
|
|
1875
|
+
"rewire: would create a cycle \u2014 dep already transitively depends on this node (R-rewire / D42)"
|
|
1876
|
+
);
|
|
1877
|
+
const dep = nodeRuntimeHost(d);
|
|
1878
|
+
if (dep._value.terminal !== void 0 && !dep._slot.resubscribable)
|
|
1879
|
+
throw new Error(
|
|
1880
|
+
"rewire: cannot add a non-resubscribable terminal dep \u2014 would wedge (R-rewire / D42)"
|
|
1881
|
+
);
|
|
1882
|
+
self._assertRewireDepOwner(d);
|
|
1883
|
+
}
|
|
1884
|
+
if (deferAfterBatchForTarget(node, () => {
|
|
1885
|
+
self._rewire(newDeps, fn, { ...opts, allowTerminalOwner: true });
|
|
1886
|
+
})) {
|
|
1887
|
+
return true;
|
|
1888
|
+
}
|
|
1889
|
+
if (!self._lifecycle.activated) self._restoredActivationPending = false;
|
|
1890
|
+
self._wave.inDepMutation = true;
|
|
1891
|
+
self._wave.rewireRunPending = false;
|
|
1892
|
+
let zeroDepUnDirty = false;
|
|
1893
|
+
try {
|
|
1894
|
+
const oldHandle = self._slot.handle;
|
|
1895
|
+
self._slot.handle = self._slot.dispatcher.register(fn, self._slot.pool);
|
|
1896
|
+
if (oldHandle !== null) self._slot.dispatcher.unregister(oldHandle);
|
|
1897
|
+
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
1898
|
+
let removedDirtyContributor = false;
|
|
1899
|
+
for (const d of removed) {
|
|
1900
|
+
const oldIdx = oldDeps.indexOf(d);
|
|
1901
|
+
if (self._dep.dirty[oldIdx]) {
|
|
1902
|
+
removedDirtyContributor = true;
|
|
1903
|
+
self._wave.pending--;
|
|
1904
|
+
}
|
|
1905
|
+
if (self._lifecycle.activated) {
|
|
1906
|
+
const box = self._dep.idxBoxes[oldIdx];
|
|
1907
|
+
if (box) box.v = -1;
|
|
1908
|
+
const unsub = self._dep.unsubs[oldIdx];
|
|
1909
|
+
if (unsub) unsub();
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
const n = newDeps.length;
|
|
1913
|
+
const newBatch = new Array(n).fill(null);
|
|
1914
|
+
const newPrev = new Array(n).fill(SENTINEL);
|
|
1915
|
+
const newHasData = new Array(n).fill(false);
|
|
1916
|
+
const newDirty = new Array(n).fill(false);
|
|
1917
|
+
const newTier = new Array(n).fill(0);
|
|
1918
|
+
const newTerminal = new Array(n).fill(void 0);
|
|
1919
|
+
const newTerminalInput = new Array(n).fill(void 0);
|
|
1920
|
+
const newUnsubs = new Array(n);
|
|
1921
|
+
const newBoxes = new Array(n);
|
|
1922
|
+
for (let j = 0; j < n; j++) {
|
|
1923
|
+
const oldIdx = oldDeps.indexOf(newDeps[j]);
|
|
1924
|
+
if (oldIdx !== -1) {
|
|
1925
|
+
newBatch[j] = self._dep.batch[oldIdx];
|
|
1926
|
+
newPrev[j] = self._dep.prev[oldIdx];
|
|
1927
|
+
newHasData[j] = self._dep.hasData[oldIdx];
|
|
1928
|
+
newDirty[j] = self._dep.dirty[oldIdx];
|
|
1929
|
+
newTier[j] = self._dep.tier[oldIdx];
|
|
1930
|
+
newTerminal[j] = self._dep.terminal[oldIdx];
|
|
1931
|
+
newUnsubs[j] = self._dep.unsubs[oldIdx];
|
|
1932
|
+
const box = self._dep.idxBoxes[oldIdx];
|
|
1933
|
+
if (box) box.v = j;
|
|
1934
|
+
newBoxes[j] = box;
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
self._slot.deps = newDeps;
|
|
1938
|
+
self._dep.batch = newBatch;
|
|
1939
|
+
self._dep.prev = newPrev;
|
|
1940
|
+
self._dep.hasData = newHasData;
|
|
1941
|
+
self._dep.dirty = newDirty;
|
|
1942
|
+
self._dep.tier = newTier;
|
|
1943
|
+
self._dep.terminal = newTerminal;
|
|
1944
|
+
self._dep.terminalInput = newTerminalInput;
|
|
1945
|
+
self._dep.unsubs = newUnsubs;
|
|
1946
|
+
self._dep.idxBoxes = newBoxes;
|
|
1947
|
+
self._dep.waveData = newDeps.map(() => []);
|
|
1948
|
+
self._dep.waveTokens = new Array(newDeps.length).fill(void 0);
|
|
1949
|
+
self._syncCtx = null;
|
|
1950
|
+
if (self._lifecycle.activated) {
|
|
1951
|
+
for (const d of added) self._subscribeDepAt(d);
|
|
1952
|
+
}
|
|
1953
|
+
notifyTopologyDepsChanged(node, oldDeps, newDeps);
|
|
1954
|
+
if (removedDirtyContributor && self._wave.pending === 0 && self._value.status === "dirty") {
|
|
1955
|
+
if (newDeps.length > 0) self._wave.rewireRunPending = true;
|
|
1956
|
+
else zeroDepUnDirty = true;
|
|
1957
|
+
}
|
|
1958
|
+
} finally {
|
|
1959
|
+
self._wave.inDepMutation = false;
|
|
1960
|
+
}
|
|
1961
|
+
if (self._wave.rewireRunPending) {
|
|
1962
|
+
self._wave.rewireRunPending = false;
|
|
1963
|
+
self._settleRewire();
|
|
1964
|
+
} else if (zeroDepUnDirty) {
|
|
1965
|
+
if (self._wave.emittedDirtyThisWave) self._down([["RESOLVED"]]);
|
|
1966
|
+
else self._value.status = self._value.hasData ? "settled" : "sentinel";
|
|
1967
|
+
}
|
|
1968
|
+
return false;
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
// src/node/node.ts
|
|
1972
|
+
var Node = class _Node {
|
|
1973
|
+
_core;
|
|
1974
|
+
_id;
|
|
1975
|
+
_slot;
|
|
1976
|
+
_dep;
|
|
928
1977
|
_value;
|
|
929
1978
|
_wave;
|
|
930
1979
|
_control;
|
|
@@ -941,19 +1990,63 @@ var Node = class {
|
|
|
941
1990
|
set _syncCtx(ctx) {
|
|
942
1991
|
this._syncCtxState.value = ctx;
|
|
943
1992
|
}
|
|
1993
|
+
static _retainIndirectRuntimeMethods(node) {
|
|
1994
|
+
void node._dep;
|
|
1995
|
+
void node._hooks;
|
|
1996
|
+
void node._restoredActivationPending;
|
|
1997
|
+
void node._requestRewireNext;
|
|
1998
|
+
void node._requestUpNext;
|
|
1999
|
+
void node._applyRewireNext;
|
|
2000
|
+
void node._reachableUpstream;
|
|
2001
|
+
void node._assertRewireDepOwner;
|
|
2002
|
+
void node._subscribeDepAt;
|
|
2003
|
+
void node._seedRestoredDepAt;
|
|
2004
|
+
void node._recordDepProjection;
|
|
2005
|
+
void node._depProjectionHasData;
|
|
2006
|
+
void node._receiveFromDep;
|
|
2007
|
+
void node._releaseDepDirty;
|
|
2008
|
+
void node._settleAfterAbsorbedTerminal;
|
|
2009
|
+
void node._markDirty;
|
|
2010
|
+
void node._maybeRun;
|
|
2011
|
+
void node._settleRewire;
|
|
2012
|
+
void node._tryRun;
|
|
2013
|
+
void node._allDepsSettled;
|
|
2014
|
+
void node._passthroughEmit;
|
|
2015
|
+
void node._runWave;
|
|
2016
|
+
void node._buildCtx;
|
|
2017
|
+
void node._makeCtx;
|
|
2018
|
+
void node._refreshCtx;
|
|
2019
|
+
void node._makeState;
|
|
2020
|
+
void node._markDemandRouted;
|
|
2021
|
+
void node._forwardUp;
|
|
2022
|
+
void node._isPullQuiet;
|
|
2023
|
+
void node._isPaused;
|
|
2024
|
+
void node._hasBoundaryPauseLock;
|
|
2025
|
+
void node._isAsyncPool;
|
|
2026
|
+
void node._pauseAcquire;
|
|
2027
|
+
void node._pauseRelease;
|
|
2028
|
+
void node._onResume;
|
|
2029
|
+
void node._canFireDemand;
|
|
2030
|
+
void node._deliverPullDemand;
|
|
2031
|
+
void node._onDemand;
|
|
2032
|
+
void node._firePullDemand;
|
|
2033
|
+
void node._fireOwedDemandIfReady;
|
|
2034
|
+
void node._shouldBufferOnPause;
|
|
2035
|
+
void node._invalidate;
|
|
2036
|
+
void node._allDepsTerminal;
|
|
2037
|
+
void node._emitToSubs;
|
|
2038
|
+
}
|
|
944
2039
|
constructor(deps, handleOrFn, opts = {}) {
|
|
945
|
-
const core =
|
|
946
|
-
constructingCore = void 0;
|
|
2040
|
+
const core = takeConstructingNodeCore();
|
|
947
2041
|
const dispatcher = opts.dispatcher ?? defaultDispatcher;
|
|
948
|
-
const environment =
|
|
949
|
-
constructingEnvironment = void 0;
|
|
2042
|
+
const environment = takeConstructingEnvironmentDrivers() ?? EnvironmentDrivers.empty();
|
|
950
2043
|
const pool = opts.pool ?? "sync";
|
|
951
2044
|
const pausable = opts.pausable ?? true;
|
|
952
2045
|
const pullLock = opts.pullId;
|
|
953
2046
|
const pull = opts.pullId !== void 0;
|
|
954
2047
|
if (pull && pausable === false)
|
|
955
2048
|
throw new Error(
|
|
956
|
-
"node: pullId is incompatible with pausable:false \u2014 a pull node
|
|
2049
|
+
"node: pullId is incompatible with pausable:false \u2014 a pull node uses the pausable delivery-content axis (R-pull / R-pause-modes / D55,D269)"
|
|
957
2050
|
);
|
|
958
2051
|
let handle;
|
|
959
2052
|
if (handleOrFn === null) handle = null;
|
|
@@ -976,7 +2069,6 @@ var Node = class {
|
|
|
976
2069
|
value.status = "settled";
|
|
977
2070
|
}
|
|
978
2071
|
const pauseLockset = /* @__PURE__ */ new Set();
|
|
979
|
-
if (pull) pauseLockset.add(pullLock);
|
|
980
2072
|
this._core = core ?? new NodeCore();
|
|
981
2073
|
const created = this._core.createSlot(
|
|
982
2074
|
{
|
|
@@ -1017,7 +2109,9 @@ var Node = class {
|
|
|
1017
2109
|
pauseLockset,
|
|
1018
2110
|
pausedDepWaveOccurred: false,
|
|
1019
2111
|
pauseBuffer: [],
|
|
1020
|
-
demandOwed:
|
|
2112
|
+
demandOwed: void 0,
|
|
2113
|
+
activePull: void 0,
|
|
2114
|
+
pullDirtyOwed: false,
|
|
1021
2115
|
inDeliverDemand: false
|
|
1022
2116
|
},
|
|
1023
2117
|
privateState: { value: SENTINEL, persist: false },
|
|
@@ -1074,10 +2168,11 @@ var Node = class {
|
|
|
1074
2168
|
this._wave.batchDirtyOwed = false;
|
|
1075
2169
|
this._control.pauseBuffer = [];
|
|
1076
2170
|
this._control.pausedDepWaveOccurred = false;
|
|
1077
|
-
this._control.demandOwed =
|
|
2171
|
+
this._control.demandOwed = void 0;
|
|
2172
|
+
this._control.activePull = void 0;
|
|
2173
|
+
this._control.pullDirtyOwed = false;
|
|
1078
2174
|
this._control.inDeliverDemand = false;
|
|
1079
2175
|
this._control.pauseLockset.clear();
|
|
1080
|
-
if (this._slot.pull) this._control.pauseLockset.add(this._slot.pullLock);
|
|
1081
2176
|
this._privateState.value = state.ctxState.value;
|
|
1082
2177
|
this._privateState.persist = state.ctxState.persist;
|
|
1083
2178
|
if (state.version === false) {
|
|
@@ -1115,18 +2210,18 @@ var Node = class {
|
|
|
1115
2210
|
runtimeQuiescenceReaders.set(this, () => this._isRuntimeQuiescentForRelease());
|
|
1116
2211
|
subscriberCountReaders.set(this, () => this._subscriberCount());
|
|
1117
2212
|
activationReaders.set(this, () => this._lifecycle.activated);
|
|
2213
|
+
_Node._retainIndirectRuntimeMethods(this);
|
|
1118
2214
|
}
|
|
1119
|
-
/** R-pull (D55): true while a pull node is
|
|
2215
|
+
/** R-pull (D55/D272): true while a pull node is not serving a PULL demand pulse. */
|
|
1120
2216
|
_isPullQuiet() {
|
|
1121
|
-
return this._slot.pull && this._control.
|
|
2217
|
+
return this._slot.pull && this._control.activePull === void 0;
|
|
1122
2218
|
}
|
|
1123
2219
|
/**
|
|
1124
|
-
* R-pull (
|
|
1125
|
-
* triggers computation). A consumer demands one delivery by cone-routing
|
|
1126
|
-
* reference): `ctx.up([["
|
|
1127
|
-
* `ctx.upNext([["
|
|
1128
|
-
*
|
|
1129
|
-
* for inspection/describe; routing matches by the pullId value carried in the RESUME, by identity.
|
|
2220
|
+
* R-pull (D269/D272): this pull node's pullId (pure data, like {@link cache}/{@link handle} —
|
|
2221
|
+
* never triggers computation). A consumer demands one delivery by cone-routing PULL of it (no
|
|
2222
|
+
* node reference): `ctx.up([["PULL", { pullId }]])` (immediate; loops back → D37 for a self-read
|
|
2223
|
+
* dep) or `ctx.upNext([["PULL", { pullId }]])` (boundary-deferred self-demand). Undefined for a
|
|
2224
|
+
* non-pull node. The author writes the pullId verbatim; routing matches by identity.
|
|
1130
2225
|
*/
|
|
1131
2226
|
get pullId() {
|
|
1132
2227
|
return this._slot.pullLock;
|
|
@@ -1220,58 +2315,6 @@ var Node = class {
|
|
|
1220
2315
|
exitWave();
|
|
1221
2316
|
}
|
|
1222
2317
|
}
|
|
1223
|
-
// ── deferred self-rewire (R-rewire-deferred / D47): ctx.rewireNext drain support ──
|
|
1224
|
-
/**
|
|
1225
|
-
* Enqueue a deferred self-rewire op (issued from this node's fn via `ctx.rewireNext`).
|
|
1226
|
-
* Applied at the committed wave boundary (boundary.ts drain), never in place — the in-fn
|
|
1227
|
-
* immediate path (`subscribeDep`/`replaceDeps`/`unsubscribeDep`) still throws mid-run (D37/R-reentrancy).
|
|
1228
|
-
*/
|
|
1229
|
-
_requestRewireNext(op) {
|
|
1230
|
-
deferRewire(this._core, () => this._applyRewireNext(op), {
|
|
1231
|
-
batchToken: currentBoundaryBatchToken(),
|
|
1232
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
1233
|
-
});
|
|
1234
|
-
}
|
|
1235
|
-
/**
|
|
1236
|
-
* Enqueue a deferred up-going control wave (R-up-routing / R-pull / D59): at the committed wave
|
|
1237
|
-
* boundary, route `msgs` up from THIS node (broadcast, or up the single `towardDep` edge). The
|
|
1238
|
-
* deferred form of `ctx.up` — the SELF-demand path: a consumer issues `ctx.upNext([[RESUME,
|
|
1239
|
-
* pullId]])` to demand a dep it ALSO reads; the demand applies at the boundary (not mid-fn), so
|
|
1240
|
-
* the pull node's delivery loops back as a FRESH wave rather than re-entering the consumer (D37 /
|
|
1241
|
-
* R-reentrancy). Rides the same R-rewire-deferred (D47) drain as ctx.rewireNext.
|
|
1242
|
-
*/
|
|
1243
|
-
_requestUpNext(msgs, towardDep) {
|
|
1244
|
-
deferRewire(
|
|
1245
|
-
this._core,
|
|
1246
|
-
() => {
|
|
1247
|
-
if (!this._released) this._up(msgs, towardDep);
|
|
1248
|
-
},
|
|
1249
|
-
{
|
|
1250
|
-
batchToken: currentBoundaryBatchToken(),
|
|
1251
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
1252
|
-
}
|
|
1253
|
-
);
|
|
1254
|
-
}
|
|
1255
|
-
/** Apply one queued self-rewire at the boundary (drain thunk). */
|
|
1256
|
-
_applyRewireNext(op) {
|
|
1257
|
-
if (this._released) return;
|
|
1258
|
-
try {
|
|
1259
|
-
if (op.kind === "add") {
|
|
1260
|
-
const next = this._slot.deps.includes(op.dep) ? [...this._slot.deps] : [...this._slot.deps, op.dep];
|
|
1261
|
-
this._rewire(next, op.fn, { allowTerminalOwner: true });
|
|
1262
|
-
} else if (op.kind === "remove") {
|
|
1263
|
-
this._rewire(
|
|
1264
|
-
this._slot.deps.filter((d) => d !== op.dep),
|
|
1265
|
-
op.fn,
|
|
1266
|
-
{ allowTerminalOwner: true }
|
|
1267
|
-
);
|
|
1268
|
-
} else {
|
|
1269
|
-
this._rewire(this._dedupDeps(op.deps), op.fn, { allowTerminalOwner: true });
|
|
1270
|
-
}
|
|
1271
|
-
} catch (e) {
|
|
1272
|
-
this._down([["ERROR", errorPayload(e, "rewireNext op failed")]]);
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
2318
|
// ── rewire (R-rewire / D42): intra-graph runtime topology mutation ──
|
|
1276
2319
|
/**
|
|
1277
2320
|
* Replace this node's deps atomically (surgical, Option-C). Requires an explicit
|
|
@@ -1299,6 +2342,15 @@ var Node = class {
|
|
|
1299
2342
|
fn
|
|
1300
2343
|
);
|
|
1301
2344
|
}
|
|
2345
|
+
_requestRewireNext(op) {
|
|
2346
|
+
nodeRequestRewireNext(nodeRuntimeHost(this), op);
|
|
2347
|
+
}
|
|
2348
|
+
_requestUpNext(msgs, towardDep) {
|
|
2349
|
+
nodeRequestUpNext(nodeRuntimeHost(this), msgs, towardDep);
|
|
2350
|
+
}
|
|
2351
|
+
_applyRewireNext(op) {
|
|
2352
|
+
nodeApplyRewireNext(nodeRuntimeHost(this), op);
|
|
2353
|
+
}
|
|
1302
2354
|
_dedupDeps(deps) {
|
|
1303
2355
|
const seen = /* @__PURE__ */ new Set();
|
|
1304
2356
|
const out = [];
|
|
@@ -1309,7 +2361,6 @@ var Node = class {
|
|
|
1309
2361
|
}
|
|
1310
2362
|
return out;
|
|
1311
2363
|
}
|
|
1312
|
-
/** Is `target` reachable upstream from `from` (following deps)? Cycle-prevention DFS. */
|
|
1313
2364
|
_reachableUpstream(from, target) {
|
|
1314
2365
|
const seen = /* @__PURE__ */ new Set();
|
|
1315
2366
|
const stack = [from];
|
|
@@ -1319,1025 +2370,171 @@ var Node = class {
|
|
|
1319
2370
|
if (n === target) return true;
|
|
1320
2371
|
if (seen.has(n)) continue;
|
|
1321
2372
|
seen.add(n);
|
|
1322
|
-
for (const d of n._slot.deps) stack.push(d);
|
|
2373
|
+
for (const d of nodeRuntimeHost(n)._slot.deps) stack.push(d);
|
|
1323
2374
|
}
|
|
1324
2375
|
return false;
|
|
1325
2376
|
}
|
|
1326
2377
|
_assertRewireDepOwner(dep) {
|
|
1327
2378
|
const selfOwner = getNodeOwner(this);
|
|
1328
2379
|
const depOwner = getNodeOwner(dep);
|
|
1329
|
-
if (selfOwner !== void 0 && depOwner !== void 0 && selfOwner !== depOwner)
|
|
2380
|
+
if (selfOwner !== void 0 && depOwner !== void 0 && selfOwner !== depOwner)
|
|
1330
2381
|
throw new Error(
|
|
1331
2382
|
"rewire: dep belongs to a different graph; cross-graph deps require a wire bridge (D22 / R-graph-domain)"
|
|
1332
2383
|
);
|
|
1333
|
-
}
|
|
1334
2384
|
}
|
|
1335
2385
|
_rewire(newDeps, fn, opts = {}) {
|
|
1336
|
-
|
|
1337
|
-
throw new Error(
|
|
1338
|
-
"rewire: node is terminal (completed/errored) \u2014 cannot rewire (R-rewire / D42)"
|
|
1339
|
-
);
|
|
1340
|
-
if (this._wave.insideRunWave)
|
|
1341
|
-
throw new Error(
|
|
1342
|
-
"rewire: mid-fn topology mutation \u2014 a fn mutating its own deps mid-wave is the feedback cycle (R-rewire / D37)"
|
|
1343
|
-
);
|
|
1344
|
-
if (this._wave.inDepMutation)
|
|
1345
|
-
throw new Error(
|
|
1346
|
-
"rewire: reentrant dep mutation \u2014 another replaceDeps/subscribeDep/unsubscribeDep is in flight (R-rewire)"
|
|
1347
|
-
);
|
|
1348
|
-
if (newDeps.includes(this))
|
|
1349
|
-
throw new Error("rewire: self-dependency rejected (R-rewire / D42)");
|
|
1350
|
-
const oldDeps = this._slot.deps;
|
|
1351
|
-
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
1352
|
-
for (const d of added) {
|
|
1353
|
-
if (this._reachableUpstream(d, this))
|
|
1354
|
-
throw new Error(
|
|
1355
|
-
"rewire: would create a cycle \u2014 dep already transitively depends on this node (R-rewire / D42)"
|
|
1356
|
-
);
|
|
1357
|
-
if (d._value.terminal !== void 0 && !d._slot.resubscribable)
|
|
1358
|
-
throw new Error(
|
|
1359
|
-
"rewire: cannot add a non-resubscribable terminal dep \u2014 would wedge (R-rewire / D42)"
|
|
1360
|
-
);
|
|
1361
|
-
this._assertRewireDepOwner(d);
|
|
1362
|
-
}
|
|
1363
|
-
if (deferAfterBatchForTarget(this, () => {
|
|
1364
|
-
this._rewire(newDeps, fn, { ...opts, allowTerminalOwner: true });
|
|
1365
|
-
})) {
|
|
1366
|
-
return true;
|
|
1367
|
-
}
|
|
1368
|
-
if (!this._lifecycle.activated) this._restoredActivationPending = false;
|
|
1369
|
-
this._wave.inDepMutation = true;
|
|
1370
|
-
this._wave.rewireRunPending = false;
|
|
1371
|
-
let zeroDepUnDirty = false;
|
|
1372
|
-
try {
|
|
1373
|
-
const oldHandle = this._slot.handle;
|
|
1374
|
-
this._slot.handle = this._slot.dispatcher.register(fn, this._slot.pool);
|
|
1375
|
-
if (oldHandle !== null) this._slot.dispatcher.unregister(oldHandle);
|
|
1376
|
-
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
1377
|
-
let removedDirtyContributor = false;
|
|
1378
|
-
for (const d of removed) {
|
|
1379
|
-
const oldIdx = oldDeps.indexOf(d);
|
|
1380
|
-
if (this._dep.dirty[oldIdx]) {
|
|
1381
|
-
removedDirtyContributor = true;
|
|
1382
|
-
this._wave.pending--;
|
|
1383
|
-
}
|
|
1384
|
-
if (this._lifecycle.activated) {
|
|
1385
|
-
const box = this._dep.idxBoxes[oldIdx];
|
|
1386
|
-
if (box) box.v = -1;
|
|
1387
|
-
const unsub = this._dep.unsubs[oldIdx];
|
|
1388
|
-
if (unsub) unsub();
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
const n = newDeps.length;
|
|
1392
|
-
const newBatch = new Array(n).fill(null);
|
|
1393
|
-
const newPrev = new Array(n).fill(SENTINEL);
|
|
1394
|
-
const newHasData = new Array(n).fill(false);
|
|
1395
|
-
const newDirty = new Array(n).fill(false);
|
|
1396
|
-
const newTier = new Array(n).fill(0);
|
|
1397
|
-
const newTerminal = new Array(n).fill(void 0);
|
|
1398
|
-
const newTerminalInput = new Array(n).fill(void 0);
|
|
1399
|
-
const newUnsubs = new Array(n);
|
|
1400
|
-
const newBoxes = new Array(n);
|
|
1401
|
-
for (let j = 0; j < n; j++) {
|
|
1402
|
-
const oldIdx = oldDeps.indexOf(newDeps[j]);
|
|
1403
|
-
if (oldIdx !== -1) {
|
|
1404
|
-
newBatch[j] = this._dep.batch[oldIdx];
|
|
1405
|
-
newPrev[j] = this._dep.prev[oldIdx];
|
|
1406
|
-
newHasData[j] = this._dep.hasData[oldIdx];
|
|
1407
|
-
newDirty[j] = this._dep.dirty[oldIdx];
|
|
1408
|
-
newTier[j] = this._dep.tier[oldIdx];
|
|
1409
|
-
newTerminal[j] = this._dep.terminal[oldIdx];
|
|
1410
|
-
newUnsubs[j] = this._dep.unsubs[oldIdx];
|
|
1411
|
-
const box = this._dep.idxBoxes[oldIdx];
|
|
1412
|
-
if (box) box.v = j;
|
|
1413
|
-
newBoxes[j] = box;
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
this._slot.deps = newDeps;
|
|
1417
|
-
this._dep.batch = newBatch;
|
|
1418
|
-
this._dep.prev = newPrev;
|
|
1419
|
-
this._dep.hasData = newHasData;
|
|
1420
|
-
this._dep.dirty = newDirty;
|
|
1421
|
-
this._dep.tier = newTier;
|
|
1422
|
-
this._dep.terminal = newTerminal;
|
|
1423
|
-
this._dep.terminalInput = newTerminalInput;
|
|
1424
|
-
this._dep.unsubs = newUnsubs;
|
|
1425
|
-
this._dep.idxBoxes = newBoxes;
|
|
1426
|
-
this._dep.waveData = newDeps.map(() => []);
|
|
1427
|
-
this._dep.waveTokens = new Array(newDeps.length).fill(void 0);
|
|
1428
|
-
this._syncCtx = null;
|
|
1429
|
-
if (this._lifecycle.activated) {
|
|
1430
|
-
for (const d of added) this._subscribeDepAt(d);
|
|
1431
|
-
}
|
|
1432
|
-
notifyTopologyDepsChanged(this, oldDeps, newDeps);
|
|
1433
|
-
if (removedDirtyContributor && this._wave.pending === 0 && this._value.status === "dirty") {
|
|
1434
|
-
if (newDeps.length > 0) this._wave.rewireRunPending = true;
|
|
1435
|
-
else zeroDepUnDirty = true;
|
|
1436
|
-
}
|
|
1437
|
-
} finally {
|
|
1438
|
-
this._wave.inDepMutation = false;
|
|
1439
|
-
}
|
|
1440
|
-
if (this._wave.rewireRunPending) {
|
|
1441
|
-
this._wave.rewireRunPending = false;
|
|
1442
|
-
this._settleRewire();
|
|
1443
|
-
} else if (zeroDepUnDirty) {
|
|
1444
|
-
if (this._wave.emittedDirtyThisWave) this._down([["RESOLVED"]]);
|
|
1445
|
-
else this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
1446
|
-
}
|
|
1447
|
-
return false;
|
|
2386
|
+
return nodeRewire(nodeRuntimeHost(this), newDeps, fn, opts);
|
|
1448
2387
|
}
|
|
1449
2388
|
// ── activation / deactivation (lazy; R-rom-ram) ──
|
|
1450
2389
|
_activate() {
|
|
1451
|
-
this
|
|
1452
|
-
const seedRestoredDeps = this._restoredActivationPending;
|
|
1453
|
-
this._restoredActivationPending = false;
|
|
1454
|
-
if (this._slot.pull) this._control.pauseLockset.add(this._slot.pullLock);
|
|
1455
|
-
this._dep.unsubs = new Array(this._slot.deps.length);
|
|
1456
|
-
this._dep.idxBoxes = new Array(this._slot.deps.length);
|
|
1457
|
-
for (const dep of this._slot.deps)
|
|
1458
|
-
this._subscribeDepAt(dep, { seedRestored: seedRestoredDeps });
|
|
1459
|
-
if (this._slot.deps.length === 0 && this._slot.handle !== null && !this._wave.hasCalledFnOnce) {
|
|
1460
|
-
this._runWave();
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
/**
|
|
1464
|
-
* Subscribe to a dep. The dispatch callback reads the dep's CURRENT index from a
|
|
1465
|
-
* mutable box (O(1)); a surgical rewire that reorders kept deps just updates the box
|
|
1466
|
-
* (R-rewire Option-C / D42) — no re-subscribe, no per-message indexOf scan. A removed
|
|
1467
|
-
* dep's box is set to -1 so any stale in-flight callback drops (drain).
|
|
1468
|
-
*/
|
|
1469
|
-
_subscribeDepAt(depNode, opts = {}) {
|
|
1470
|
-
const idx0 = this._slot.deps.indexOf(depNode);
|
|
1471
|
-
const box = { v: idx0 };
|
|
1472
|
-
let ignoreInitialPush = opts.seedRestored === true;
|
|
1473
|
-
if (ignoreInitialPush && idx0 !== -1) {
|
|
1474
|
-
this._seedRestoredDepAt(idx0, depNode);
|
|
1475
|
-
if (depNode._value.terminal !== void 0 && !depNode._slot.resubscribable) {
|
|
1476
|
-
this._dep.unsubs[idx0] = () => {
|
|
1477
|
-
};
|
|
1478
|
-
this._dep.idxBoxes[idx0] = box;
|
|
1479
|
-
return;
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
const unsub = depNode.subscribe((msg, delivery) => {
|
|
1483
|
-
if (ignoreInitialPush && delivery === void 0) return;
|
|
1484
|
-
if (ignoreInitialPush) ignoreInitialPush = false;
|
|
1485
|
-
if (box.v === -1) return;
|
|
1486
|
-
this._receiveFromDep(box.v, msg, delivery);
|
|
1487
|
-
});
|
|
1488
|
-
if (ignoreInitialPush && idx0 !== -1 && box.v !== -1) this._seedRestoredDepAt(idx0, depNode);
|
|
1489
|
-
ignoreInitialPush = false;
|
|
1490
|
-
if (idx0 !== -1) {
|
|
1491
|
-
this._dep.unsubs[idx0] = unsub;
|
|
1492
|
-
this._dep.idxBoxes[idx0] = box;
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
1495
|
-
_seedRestoredDepAt(idx, depNode) {
|
|
1496
|
-
const seedData = depNode._value.hasData && !depNode._slot.pull;
|
|
1497
|
-
this._dep.batch[idx] = null;
|
|
1498
|
-
this._dep.waveData[idx] = [];
|
|
1499
|
-
this._dep.waveTokens[idx] = void 0;
|
|
1500
|
-
this._dep.prev[idx] = seedData ? depNode._value.cache : SENTINEL;
|
|
1501
|
-
this._dep.hasData[idx] = seedData;
|
|
1502
|
-
this._dep.dirty[idx] = false;
|
|
1503
|
-
this._dep.tier[idx] = seedData ? 3 : 0;
|
|
1504
|
-
this._dep.terminal[idx] = depNode._value.terminal;
|
|
1505
|
-
this._dep.terminalInput[idx] = void 0;
|
|
2390
|
+
nodeActivate(nodeRuntimeHost(this));
|
|
1506
2391
|
}
|
|
1507
2392
|
_deactivate() {
|
|
1508
|
-
this
|
|
1509
|
-
for (const u of this._dep.unsubs) if (u) u();
|
|
1510
|
-
this._dep.unsubs = [];
|
|
1511
|
-
this._dep.idxBoxes = [];
|
|
1512
|
-
for (const fn of this._hooks.onDeactivation) fn();
|
|
1513
|
-
this._hooks.onDeactivation = [];
|
|
1514
|
-
this._hooks.onInvalidate = [];
|
|
1515
|
-
const isCompute = this._slot.handle !== null || this._slot.deps.length > 0;
|
|
1516
|
-
if (isCompute) {
|
|
1517
|
-
this._value.cache = SENTINEL;
|
|
1518
|
-
this._value.hasData = false;
|
|
1519
|
-
this._value.status = "sentinel";
|
|
1520
|
-
}
|
|
1521
|
-
this._resetDepState();
|
|
1522
|
-
this._wave.hasCalledFnOnce = false;
|
|
1523
|
-
this._control.pauseLockset.clear();
|
|
1524
|
-
this._control.pauseBuffer = [];
|
|
1525
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1526
|
-
this._control.demandOwed = false;
|
|
1527
|
-
this._value.replayRing = [];
|
|
1528
|
-
if (!this._privateState.persist) this._privateState.value = SENTINEL;
|
|
2393
|
+
nodeDeactivate(nodeRuntimeHost(this));
|
|
1529
2394
|
}
|
|
1530
2395
|
_assertNotReleased(op) {
|
|
1531
2396
|
if (this._released)
|
|
1532
2397
|
throw new Error(`${op}: node has been released from its graph lifecycle (D122)`);
|
|
1533
2398
|
}
|
|
1534
2399
|
_subscriberCount() {
|
|
1535
|
-
return this
|
|
2400
|
+
return nodeSubscriberCount(nodeRuntimeHost(this));
|
|
1536
2401
|
}
|
|
1537
2402
|
_isRuntimeQuiescentForRelease() {
|
|
1538
|
-
|
|
1539
|
-
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);
|
|
2403
|
+
return nodeIsRuntimeQuiescentForRelease(nodeRuntimeHost(this));
|
|
1540
2404
|
}
|
|
1541
2405
|
_releaseRuntime() {
|
|
1542
|
-
|
|
1543
|
-
this._released = true;
|
|
1544
|
-
releasedNodes.add(this);
|
|
1545
|
-
let releaseError;
|
|
1546
|
-
const recordReleaseError = (error) => {
|
|
1547
|
-
if (releaseError === void 0) releaseError = error;
|
|
1548
|
-
};
|
|
1549
|
-
this._lifecycle.activated = false;
|
|
1550
|
-
for (const u of this._dep.unsubs) {
|
|
1551
|
-
try {
|
|
1552
|
-
u();
|
|
1553
|
-
} catch (error) {
|
|
1554
|
-
recordReleaseError(error);
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
for (const fn of this._hooks.onDeactivation) {
|
|
1558
|
-
try {
|
|
1559
|
-
fn();
|
|
1560
|
-
} catch (error) {
|
|
1561
|
-
recordReleaseError(error);
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
this._dep.unsubs = [];
|
|
1565
|
-
this._dep.idxBoxes = [];
|
|
1566
|
-
this._lifecycle.subscribers.clear();
|
|
1567
|
-
if (this._slot.handle !== null) {
|
|
1568
|
-
this._slot.dispatcher.unregister(this._slot.handle);
|
|
1569
|
-
this._slot.handle = null;
|
|
1570
|
-
}
|
|
1571
|
-
this._slot.deps = [];
|
|
1572
|
-
this._dep.batch = [];
|
|
1573
|
-
this._dep.waveData = [];
|
|
1574
|
-
this._dep.waveTokens = [];
|
|
1575
|
-
this._dep.prev = [];
|
|
1576
|
-
this._dep.hasData = [];
|
|
1577
|
-
this._dep.dirty = [];
|
|
1578
|
-
this._dep.tier = [];
|
|
1579
|
-
this._dep.terminal = [];
|
|
1580
|
-
this._dep.terminalInput = [];
|
|
1581
|
-
this._value.cache = SENTINEL;
|
|
1582
|
-
this._value.hasData = false;
|
|
1583
|
-
this._value.status = "sentinel";
|
|
1584
|
-
this._value.terminal = void 0;
|
|
1585
|
-
this._value.replayRing = [];
|
|
1586
|
-
this._privateState.value = SENTINEL;
|
|
1587
|
-
this._privateState.persist = false;
|
|
1588
|
-
this._syncCtx = null;
|
|
1589
|
-
this._resetDepState();
|
|
1590
|
-
this._hooks.onDeactivation = [];
|
|
1591
|
-
this._hooks.onInvalidate = [];
|
|
1592
|
-
this._control.pauseLockset.clear();
|
|
1593
|
-
this._control.pauseBuffer = [];
|
|
1594
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1595
|
-
this._control.demandOwed = false;
|
|
1596
|
-
this._restoredActivationPending = false;
|
|
1597
|
-
checkpointReaders.delete(this);
|
|
1598
|
-
restoreWriters.delete(this);
|
|
1599
|
-
runtimeReleasers.delete(this);
|
|
1600
|
-
runtimeQuiescenceReaders.delete(this);
|
|
1601
|
-
subscriberCountReaders.delete(this);
|
|
1602
|
-
activationReaders.delete(this);
|
|
1603
|
-
ownerTokens.delete(this);
|
|
1604
|
-
topologyDepsChangedObservers.delete(this);
|
|
1605
|
-
this._core.releaseSlot(this._id);
|
|
1606
|
-
if (releaseError !== void 0) throw releaseError;
|
|
2406
|
+
nodeReleaseRuntime(nodeRuntimeHost(this));
|
|
1607
2407
|
}
|
|
1608
2408
|
_resetDepState() {
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
this._dep.tier[i] = 0;
|
|
1618
|
-
this._dep.terminal[i] = void 0;
|
|
1619
|
-
this._dep.terminalInput[i] = void 0;
|
|
1620
|
-
}
|
|
1621
|
-
this._wave.pending = 0;
|
|
1622
|
-
this._wave.emittedDirtyThisWave = false;
|
|
1623
|
-
}
|
|
1624
|
-
// ── upstream wave receive (two-phase + diamond) ──
|
|
2409
|
+
nodeResetDepState(nodeRuntimeHost(this));
|
|
2410
|
+
}
|
|
2411
|
+
_subscribeDepAt(depNode, opts = {}) {
|
|
2412
|
+
nodeSubscribeDepAt(nodeRuntimeHost(this), depNode, opts);
|
|
2413
|
+
}
|
|
2414
|
+
_seedRestoredDepAt(idx, depNode) {
|
|
2415
|
+
nodeSeedRestoredDepAt(nodeRuntimeHost(this), idx, depNode);
|
|
2416
|
+
}
|
|
1625
2417
|
_recordDepProjection(idx, delivery) {
|
|
1626
|
-
|
|
1627
|
-
if (this._dep.waveTokens[idx] !== token) {
|
|
1628
|
-
this._dep.waveData[idx].push([]);
|
|
1629
|
-
this._dep.waveTokens[idx] = token;
|
|
1630
|
-
}
|
|
1631
|
-
return this._dep.waveData[idx][this._dep.waveData[idx].length - 1];
|
|
2418
|
+
return nodeRecordDepProjection(nodeRuntimeHost(this), idx, delivery);
|
|
1632
2419
|
}
|
|
1633
2420
|
_depProjectionHasData(idx) {
|
|
1634
|
-
|
|
1635
|
-
return projection?.some((v) => v !== SENTINEL) ?? false;
|
|
2421
|
+
return nodeDepProjectionHasData(nodeRuntimeHost(this), idx);
|
|
1636
2422
|
}
|
|
1637
2423
|
_receiveFromDep(idx, msg, delivery) {
|
|
1638
|
-
|
|
1639
|
-
const t = msg[0];
|
|
1640
|
-
if (t === "START") return;
|
|
1641
|
-
const isLastInDeliveredWave = delivery?.last ?? true;
|
|
1642
|
-
if (this._value.terminal !== void 0) {
|
|
1643
|
-
if (t === "TEARDOWN") this._down([["TEARDOWN"]]);
|
|
1644
|
-
return;
|
|
1645
|
-
}
|
|
1646
|
-
if (t === "INVALIDATE") {
|
|
1647
|
-
const projection = this._recordDepProjection(idx, delivery);
|
|
1648
|
-
projection.push(SENTINEL);
|
|
1649
|
-
if (projection.some((v) => v !== SENTINEL) && isLastInDeliveredWave) this._maybeRun();
|
|
1650
|
-
this._dep.prev[idx] = SENTINEL;
|
|
1651
|
-
this._dep.hasData[idx] = false;
|
|
1652
|
-
this._dep.batch[idx] = null;
|
|
1653
|
-
if (this._dep.dirty[idx]) {
|
|
1654
|
-
this._dep.dirty[idx] = false;
|
|
1655
|
-
this._wave.pending--;
|
|
1656
|
-
}
|
|
1657
|
-
if (this._control.pausedDepWaveOccurred && this._dep.batch.every((b) => b === null)) {
|
|
1658
|
-
this._control.pausedDepWaveOccurred = false;
|
|
1659
|
-
}
|
|
1660
|
-
const hadData = this._value.hasData;
|
|
1661
|
-
this._invalidate();
|
|
1662
|
-
if (this._wave.pending === 0 && this._wave.emittedDirtyThisWave) {
|
|
1663
|
-
if (!hadData) this._down([["RESOLVED"]]);
|
|
1664
|
-
else this._wave.emittedDirtyThisWave = false;
|
|
1665
|
-
}
|
|
1666
|
-
this._fireOwedDemandIfReady();
|
|
1667
|
-
return;
|
|
1668
|
-
}
|
|
1669
|
-
if (isTerminal(t)) {
|
|
1670
|
-
const isError = t === "ERROR";
|
|
1671
|
-
const errPayload = isError ? msg[1] : void 0;
|
|
1672
|
-
this._dep.terminal[idx] = isError ? errPayload : true;
|
|
1673
|
-
this._dep.terminalInput[idx] = isError ? errPayload : true;
|
|
1674
|
-
this._releaseDepDirty(idx);
|
|
1675
|
-
const ranValueBeforeTerminal = this._depProjectionHasData(idx) && isLastInDeliveredWave;
|
|
1676
|
-
if (ranValueBeforeTerminal) this._maybeRun();
|
|
1677
|
-
if (isError && this._slot.errorWhenDepsError) {
|
|
1678
|
-
this._down([["ERROR", errPayload]]);
|
|
1679
|
-
} else if (this._slot.terminalAsRealInput) {
|
|
1680
|
-
if (ranValueBeforeTerminal) {
|
|
1681
|
-
this._fireOwedDemandIfReady();
|
|
1682
|
-
return;
|
|
1683
|
-
}
|
|
1684
|
-
this._maybeRun();
|
|
1685
|
-
} else if (this._slot.completeWhenDepsComplete && this._allDepsTerminal()) {
|
|
1686
|
-
this._down([["COMPLETE"]]);
|
|
1687
|
-
} else {
|
|
1688
|
-
this._settleAfterAbsorbedTerminal();
|
|
1689
|
-
}
|
|
1690
|
-
this._fireOwedDemandIfReady();
|
|
1691
|
-
return;
|
|
1692
|
-
}
|
|
1693
|
-
if (t === "TEARDOWN") {
|
|
1694
|
-
this._down([["TEARDOWN"]]);
|
|
1695
|
-
return;
|
|
1696
|
-
}
|
|
1697
|
-
if (t === "DIRTY") {
|
|
1698
|
-
if (!this._dep.dirty[idx]) {
|
|
1699
|
-
this._dep.dirty[idx] = true;
|
|
1700
|
-
this._wave.pending++;
|
|
1701
|
-
this._dep.tier[idx] = 2;
|
|
1702
|
-
this._markDirty();
|
|
1703
|
-
}
|
|
1704
|
-
return;
|
|
1705
|
-
}
|
|
1706
|
-
if (t === "DATA") {
|
|
1707
|
-
const v = msg[1];
|
|
1708
|
-
this._recordDepProjection(idx, delivery).push(v);
|
|
1709
|
-
const b = this._dep.batch[idx];
|
|
1710
|
-
if (b === null) this._dep.batch[idx] = [v];
|
|
1711
|
-
else b.push(v);
|
|
1712
|
-
this._dep.prev[idx] = v;
|
|
1713
|
-
this._dep.hasData[idx] = true;
|
|
1714
|
-
this._dep.tier[idx] = 3;
|
|
1715
|
-
if (this._dep.dirty[idx]) {
|
|
1716
|
-
this._dep.dirty[idx] = false;
|
|
1717
|
-
this._wave.pending--;
|
|
1718
|
-
}
|
|
1719
|
-
if (isLastInDeliveredWave) this._maybeRun();
|
|
1720
|
-
this._fireOwedDemandIfReady();
|
|
1721
|
-
return;
|
|
1722
|
-
}
|
|
1723
|
-
if (t === "RESOLVED") {
|
|
1724
|
-
this._recordDepProjection(idx, delivery);
|
|
1725
|
-
this._dep.tier[idx] = 3;
|
|
1726
|
-
if (this._dep.dirty[idx]) {
|
|
1727
|
-
this._dep.dirty[idx] = false;
|
|
1728
|
-
this._wave.pending--;
|
|
1729
|
-
}
|
|
1730
|
-
if (isLastInDeliveredWave) this._maybeRun();
|
|
1731
|
-
this._fireOwedDemandIfReady();
|
|
1732
|
-
return;
|
|
1733
|
-
}
|
|
2424
|
+
nodeReceiveFromDep(nodeRuntimeHost(this), idx, msg, delivery);
|
|
1734
2425
|
}
|
|
1735
|
-
/**
|
|
1736
|
-
* R-terminal-settles-dirty (B35): release a dep's outstanding in-wave DIRTY contribution.
|
|
1737
|
-
* A settle-class event for that dep (DATA/RESOLVED inline above, INVALIDATE, and now
|
|
1738
|
-
* COMPLETE/ERROR) clears its dirty flag + decrements _pending. No-op if the dep already
|
|
1739
|
-
* settled this wave (DATA/RESOLVED ran first) — so the normal DATA-then-COMPLETE flow is
|
|
1740
|
-
* unaffected. This makes the exactly-one-settle invariant a single, shared step.
|
|
1741
|
-
*/
|
|
1742
2426
|
_releaseDepDirty(idx) {
|
|
1743
|
-
|
|
1744
|
-
this._dep.dirty[idx] = false;
|
|
1745
|
-
this._wave.pending--;
|
|
1746
|
-
}
|
|
2427
|
+
nodeReleaseDepDirty(nodeRuntimeHost(this), idx);
|
|
1747
2428
|
}
|
|
1748
|
-
/**
|
|
1749
|
-
* R-terminal-settles-dirty (B35): settle a node whose dirtied dep was released by an ABSORBED
|
|
1750
|
-
* terminal that is NOT a real input (a plain derived/effect — the common default-node case when
|
|
1751
|
-
* one of several deps completes while others stay live). Runs only when the release drained
|
|
1752
|
-
* _pending while the node still owes a downstream settle (it broadcast DIRTY this wave):
|
|
1753
|
-
* - if some OTHER dep delivered real DATA this wave (a value occurred) → recompute (→ DATA);
|
|
1754
|
-
* - else the terminal's signalled change did not materialise (no value) → one undirty RESOLVED
|
|
1755
|
-
* (R-resolved-undirty), keeping the cache (a terminal, unlike INVALIDATE, leaves the value).
|
|
1756
|
-
* A terminalAsRealInput node instead recomputes unconditionally (its fn reads the terminal).
|
|
1757
|
-
*/
|
|
1758
2429
|
_settleAfterAbsorbedTerminal() {
|
|
1759
|
-
|
|
1760
|
-
const sawData = this._dep.batch.some((b) => b !== null && b.length > 0);
|
|
1761
|
-
if (sawData) this._maybeRun();
|
|
1762
|
-
if (this._wave.emittedDirtyThisWave) this._down([["RESOLVED"]]);
|
|
2430
|
+
nodeSettleAfterAbsorbedTerminal(nodeRuntimeHost(this));
|
|
1763
2431
|
}
|
|
1764
2432
|
_markDirty() {
|
|
1765
|
-
this
|
|
1766
|
-
if (this._isPullQuiet()) return;
|
|
1767
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
1768
|
-
this._wave.emittedDirtyThisWave = true;
|
|
1769
|
-
this._emitToSubs(["DIRTY"]);
|
|
1770
|
-
}
|
|
2433
|
+
nodeMarkDirty(nodeRuntimeHost(this));
|
|
1771
2434
|
}
|
|
1772
2435
|
_maybeRun() {
|
|
1773
|
-
|
|
1774
|
-
this._wave.rewireRunPending = true;
|
|
1775
|
-
return;
|
|
1776
|
-
}
|
|
1777
|
-
if (this._slot.pausable === true && this._isPaused()) {
|
|
1778
|
-
this._control.pausedDepWaveOccurred = true;
|
|
1779
|
-
return;
|
|
1780
|
-
}
|
|
1781
|
-
this._tryRun();
|
|
2436
|
+
nodeMaybeRun(nodeRuntimeHost(this));
|
|
1782
2437
|
}
|
|
1783
|
-
/**
|
|
1784
|
-
* R-rewire atomic settle (after a rewire that warrants a recompute): emit a proper
|
|
1785
|
-
* two-phase DIRTY→DATA wave (R-dirty-before-data — a rewire-triggered settle is a wave),
|
|
1786
|
-
* once, with every added dep already wired. Mirrors _maybeRun/_tryRun's pause + gate +
|
|
1787
|
-
* pending guards, then injects the phase-1 DIRTY the added dep's [START,DATA] handshake
|
|
1788
|
-
* did not carry.
|
|
1789
|
-
*/
|
|
1790
2438
|
_settleRewire() {
|
|
1791
|
-
|
|
1792
|
-
this._control.pausedDepWaveOccurred = true;
|
|
1793
|
-
return;
|
|
1794
|
-
}
|
|
1795
|
-
if (this._wave.pending > 0) return;
|
|
1796
|
-
if (this._slot.handle === null) {
|
|
1797
|
-
this._passthroughEmit();
|
|
1798
|
-
return;
|
|
1799
|
-
}
|
|
1800
|
-
if (!this._wave.hasCalledFnOnce && !(this._slot.partial || this._allDepsSettled())) return;
|
|
1801
|
-
this._markDirty();
|
|
1802
|
-
this._runWave();
|
|
2439
|
+
nodeSettleRewire(nodeRuntimeHost(this));
|
|
1803
2440
|
}
|
|
1804
2441
|
_tryRun() {
|
|
1805
|
-
|
|
1806
|
-
if (this._slot.handle === null) {
|
|
1807
|
-
this._passthroughEmit();
|
|
1808
|
-
return;
|
|
1809
|
-
}
|
|
1810
|
-
if (!this._wave.hasCalledFnOnce) {
|
|
1811
|
-
if (this._slot.partial || this._allDepsSettled()) this._runWave();
|
|
1812
|
-
return;
|
|
1813
|
-
}
|
|
1814
|
-
this._runWave();
|
|
2442
|
+
nodeTryRun(nodeRuntimeHost(this));
|
|
1815
2443
|
}
|
|
1816
2444
|
_allDepsSettled() {
|
|
1817
|
-
|
|
1818
|
-
if (this._dep.hasData[i]) continue;
|
|
1819
|
-
if (this._slot.terminalAsRealInput && this._dep.terminal[i] !== void 0) continue;
|
|
1820
|
-
return false;
|
|
1821
|
-
}
|
|
1822
|
-
return true;
|
|
2445
|
+
return nodeAllDepsSettled(nodeRuntimeHost(this));
|
|
1823
2446
|
}
|
|
1824
2447
|
_passthroughEmit() {
|
|
1825
|
-
|
|
1826
|
-
if (b !== null && b.length > 0) {
|
|
1827
|
-
this._down([["DATA", b[b.length - 1]]]);
|
|
1828
|
-
} else if (this._wave.emittedDirtyThisWave) {
|
|
1829
|
-
this._down([["RESOLVED"]]);
|
|
1830
|
-
}
|
|
1831
|
-
this._dep.batch[0] = null;
|
|
1832
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2448
|
+
nodePassthroughEmit(nodeRuntimeHost(this));
|
|
1833
2449
|
}
|
|
1834
2450
|
_runWave() {
|
|
1835
|
-
|
|
1836
|
-
throw new Error(
|
|
1837
|
-
"synchronous feedback cycle: node fn re-entered its own wave (R-reentrancy / D37)"
|
|
1838
|
-
);
|
|
1839
|
-
this._wave.hasCalledFnOnce = true;
|
|
1840
|
-
this._hooks.onInvalidate = [];
|
|
1841
|
-
this._hooks.onDeactivation = [];
|
|
1842
|
-
const ctx = this._buildCtx();
|
|
1843
|
-
const wasDirty = this._wave.emittedDirtyThisWave;
|
|
1844
|
-
this._wave.emittedSettleThisWave = false;
|
|
1845
|
-
this._wave.insideRunWave = true;
|
|
1846
|
-
try {
|
|
1847
|
-
this._slot.dispatcher.invoke(this._slot.handle, ctx);
|
|
1848
|
-
} finally {
|
|
1849
|
-
this._wave.insideRunWave = false;
|
|
1850
|
-
}
|
|
1851
|
-
if (wasDirty && !this._wave.emittedSettleThisWave && this._value.terminal === void 0 && !this._isAsyncPool()) {
|
|
1852
|
-
this._down([["RESOLVED"]]);
|
|
1853
|
-
}
|
|
1854
|
-
for (let i = 0; i < this._dep.batch.length; i++) {
|
|
1855
|
-
this._dep.batch[i] = null;
|
|
1856
|
-
this._dep.waveData[i] = [];
|
|
1857
|
-
this._dep.waveTokens[i] = void 0;
|
|
1858
|
-
this._dep.terminalInput[i] = void 0;
|
|
1859
|
-
}
|
|
1860
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2451
|
+
nodeRunWave(nodeRuntimeHost(this));
|
|
1861
2452
|
}
|
|
1862
|
-
// ── ctx construction (L3-Q5: sync = node-stable reused ctx; async = per-invocation) ──
|
|
1863
2453
|
_buildCtx() {
|
|
1864
|
-
|
|
1865
|
-
if (kind === "sync") {
|
|
1866
|
-
if (this._syncCtx === null) this._syncCtx = this._makeCtx();
|
|
1867
|
-
this._refreshCtx(this._syncCtx);
|
|
1868
|
-
return this._syncCtx;
|
|
1869
|
-
}
|
|
1870
|
-
return this._makeCtx({
|
|
1871
|
-
waveData: this._dep.waveData.map((waves) => waves.map((w) => [...w])),
|
|
1872
|
-
terminal: this._dep.terminalInput.map(terminalView),
|
|
1873
|
-
latest: [...this._dep.prev]
|
|
1874
|
-
});
|
|
2454
|
+
return nodeBuildCtx(nodeRuntimeHost(this));
|
|
1875
2455
|
}
|
|
1876
2456
|
_makeCtx(snapshot) {
|
|
1877
|
-
|
|
1878
|
-
// Wave-owner boundary (D47): a SYNC fn's emit nests under the public entry that drove
|
|
1879
|
-
// it (cheap inc/dec, no early drain); an ASYNC-pool fn re-enters here from its stashed
|
|
1880
|
-
// ctx at depth 0, so this is the boundary that drains any rewireNext it issued.
|
|
1881
|
-
up: (msgs, towardDep) => {
|
|
1882
|
-
if (this._released) return;
|
|
1883
|
-
enterWave();
|
|
1884
|
-
try {
|
|
1885
|
-
this._up(msgs, towardDep);
|
|
1886
|
-
} finally {
|
|
1887
|
-
exitWave();
|
|
1888
|
-
}
|
|
1889
|
-
},
|
|
1890
|
-
down: (msgs) => {
|
|
1891
|
-
if (this._released) return;
|
|
1892
|
-
enterWave();
|
|
1893
|
-
try {
|
|
1894
|
-
this._down(msgs);
|
|
1895
|
-
} finally {
|
|
1896
|
-
exitWave();
|
|
1897
|
-
}
|
|
1898
|
-
},
|
|
1899
|
-
waveData: snapshot?.waveData ?? this._dep.waveData,
|
|
1900
|
-
terminal: snapshot?.terminal ?? this._dep.terminalInput.map(terminalView),
|
|
1901
|
-
state: this._makeState(),
|
|
1902
|
-
onDeactivation: (fn) => {
|
|
1903
|
-
if (this._released) return;
|
|
1904
|
-
this._hooks.onDeactivation.push(fn);
|
|
1905
|
-
},
|
|
1906
|
-
onInvalidate: (fn) => {
|
|
1907
|
-
if (this._released) return;
|
|
1908
|
-
this._hooks.onInvalidate.push(fn);
|
|
1909
|
-
},
|
|
1910
|
-
environment: () => this._slot.environment,
|
|
1911
|
-
// R-rewire-deferred (D47): defer a self-dep-set mutation to the committed boundary.
|
|
1912
|
-
rewireNext: {
|
|
1913
|
-
subscribeDep: (dep, fn) => this._requestRewireNext({ kind: "add", dep, fn }),
|
|
1914
|
-
unsubscribeDep: (dep, fn) => this._requestRewireNext({ kind: "remove", dep, fn }),
|
|
1915
|
-
replaceDeps: (deps, fn) => this._requestRewireNext({ kind: "set", deps, fn })
|
|
1916
|
-
},
|
|
1917
|
-
// R-up-routing / R-pull (D59): deferred up — route a control wave (e.g. a RESUME pull
|
|
1918
|
-
// DEMAND) up the declared cone at the committed boundary. The SELF-demand path: an
|
|
1919
|
-
// immediate ctx.up whose delivery loops back re-enters this fn (D37 / R-reentrancy).
|
|
1920
|
-
upNext: (msgs, towardDep) => this._requestUpNext(msgs, towardDep),
|
|
1921
|
-
[CTX_DEP_CACHE]: { latest: snapshot?.latest ?? this._dep.prev },
|
|
1922
|
-
[CTX_NODE_BINDING]: {
|
|
1923
|
-
dispatcher: this._slot.dispatcher,
|
|
1924
|
-
create: (factory) => withEnvironmentDrivers(this._slot.environment, () => withNodeCore(this._core, factory))
|
|
1925
|
-
}
|
|
1926
|
-
};
|
|
1927
|
-
if (this._slot.dynamic) {
|
|
1928
|
-
ctx.track = (i) => ctx[CTX_DEP_CACHE]?.latest[i];
|
|
1929
|
-
}
|
|
1930
|
-
return ctx;
|
|
2457
|
+
return nodeMakeCtx(nodeRuntimeHost(this), snapshot);
|
|
1931
2458
|
}
|
|
1932
2459
|
_refreshCtx(ctx) {
|
|
1933
|
-
ctx
|
|
1934
|
-
ctx.terminal = this._dep.terminalInput.map(terminalView);
|
|
1935
|
-
ctx[CTX_DEP_CACHE] = { latest: this._dep.prev };
|
|
2460
|
+
nodeRefreshCtx(nodeRuntimeHost(this), ctx);
|
|
1936
2461
|
}
|
|
1937
2462
|
_makeState() {
|
|
1938
|
-
return
|
|
1939
|
-
get: () => this._privateState.value,
|
|
1940
|
-
set: (v) => {
|
|
1941
|
-
this._privateState.value = v;
|
|
1942
|
-
},
|
|
1943
|
-
persist: (on = true) => {
|
|
1944
|
-
this._privateState.persist = on;
|
|
1945
|
-
}
|
|
1946
|
-
};
|
|
2463
|
+
return nodeMakeState(nodeRuntimeHost(this));
|
|
1947
2464
|
}
|
|
1948
2465
|
// ── downstream emission pipeline (the unified waist) ──
|
|
1949
2466
|
_down(msgs) {
|
|
1950
|
-
|
|
1951
|
-
validateDownPayloads(msgs);
|
|
1952
|
-
const deliveryWave = {};
|
|
1953
|
-
const assertVersionDataCompatible = (wave) => {
|
|
1954
|
-
for (const m of wave) {
|
|
1955
|
-
if (m[0] === "DATA") assertNodeVersionDataCompatible(this._version.policy, m[1]);
|
|
1956
|
-
}
|
|
1957
|
-
};
|
|
1958
|
-
const snapshotVersionData = (wave) => wave.map(
|
|
1959
|
-
(m) => m[0] === "DATA" ? ["DATA", snapshotNodeVersionData(this._version.policy, m[1])] : m
|
|
1960
|
-
);
|
|
1961
|
-
assertVersionDataCompatible(msgs);
|
|
1962
|
-
if (this._value.terminal !== void 0) {
|
|
1963
|
-
if (!msgs.some((m) => m[0] === "TEARDOWN")) return;
|
|
1964
|
-
this._value.hasTorndown = true;
|
|
1965
|
-
if (this._slot.resetOnTeardown) {
|
|
1966
|
-
this._value.cache = SENTINEL;
|
|
1967
|
-
this._value.hasData = false;
|
|
1968
|
-
}
|
|
1969
|
-
this._emitToSubs(["TEARDOWN"], { wave: deliveryWave, last: true });
|
|
1970
|
-
return;
|
|
1971
|
-
}
|
|
1972
|
-
let sorted = [...msgs].sort((a, b) => messageTier(a[0]) - messageTier(b[0]));
|
|
1973
|
-
const firstInvalidate = sorted.findIndex((m) => m[0] === "INVALIDATE");
|
|
1974
|
-
if (firstInvalidate !== -1) {
|
|
1975
|
-
sorted = sorted.filter((m, i) => m[0] !== "INVALIDATE" || i === firstInvalidate);
|
|
1976
|
-
}
|
|
1977
|
-
const hasTeardown = sorted.some((m) => m[0] === "TEARDOWN");
|
|
1978
|
-
const hasTerminal = sorted.some((m) => m[0] === "COMPLETE" || m[0] === "ERROR");
|
|
1979
|
-
if (hasTeardown && !hasTerminal && this._value.terminal === void 0 && !this._value.hasTorndown) {
|
|
1980
|
-
sorted = [["COMPLETE"], ...sorted];
|
|
1981
|
-
}
|
|
1982
|
-
if (!this._wave.insideRunWave && currentBatch()) {
|
|
1983
|
-
const deferred = snapshotVersionData(sorted.filter((m) => isDeferredTier(m[0])));
|
|
1984
|
-
if (deferred.length > 0) {
|
|
1985
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
1986
|
-
this._wave.emittedDirtyThisWave = true;
|
|
1987
|
-
this._value.status = "dirty";
|
|
1988
|
-
this._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
1989
|
-
}
|
|
1990
|
-
this._wave.batchDirtyOwed = true;
|
|
1991
|
-
deferToBatch(this, deferred);
|
|
1992
|
-
return;
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
if (this._shouldBufferOnPause()) {
|
|
1996
|
-
const buffered = snapshotVersionData(sorted.filter((m) => isPauseBufferedTier(m[0])));
|
|
1997
|
-
if (buffered.length > 0) {
|
|
1998
|
-
this._wave.emittedSettleThisWave = true;
|
|
1999
|
-
this._control.pauseBuffer.push(buffered);
|
|
2000
|
-
}
|
|
2001
|
-
sorted = sorted.filter((m) => !isPauseBufferedTier(m[0]));
|
|
2002
|
-
if (sorted.length === 0) return;
|
|
2003
|
-
}
|
|
2004
|
-
let dataCount = 0;
|
|
2005
|
-
let hasTier3 = false;
|
|
2006
|
-
let hasResolved = false;
|
|
2007
|
-
for (const m of sorted) {
|
|
2008
|
-
if (m[0] === "DATA") dataCount++;
|
|
2009
|
-
if (m[0] === "RESOLVED") hasResolved = true;
|
|
2010
|
-
if (isValueTier(m[0])) hasTier3 = true;
|
|
2011
|
-
}
|
|
2012
|
-
if (dataCount >= 1 && hasResolved) {
|
|
2013
|
-
throw new Error(
|
|
2014
|
-
"down: a wave cannot mix DATA and RESOLVED (tier-3 exclusivity, R-resolved-undirty)"
|
|
2015
|
-
);
|
|
2016
|
-
}
|
|
2017
|
-
const plannedVersions = new Array(sorted.length);
|
|
2018
|
-
if (dataCount > 0) {
|
|
2019
|
-
let plannedVersion = this._version.value;
|
|
2020
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
2021
|
-
const m = sorted[i];
|
|
2022
|
-
if (m[0] !== "DATA") continue;
|
|
2023
|
-
plannedVersion = advanceNodeVersion(plannedVersion, this._version.policy, m[1]);
|
|
2024
|
-
plannedVersions[i] = plannedVersion;
|
|
2025
|
-
}
|
|
2026
|
-
}
|
|
2027
|
-
if (hasTier3 && !this._wave.insideRunWave && !this._wave.emittedDirtyThisWave) {
|
|
2028
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2029
|
-
this._value.status = "dirty";
|
|
2030
|
-
this._emitToSubs(["DIRTY"], { wave: deliveryWave, last: false });
|
|
2031
|
-
}
|
|
2032
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
2033
|
-
const m = sorted[i];
|
|
2034
|
-
const delivery = { wave: deliveryWave, last: i === sorted.length - 1 };
|
|
2035
|
-
if (isDeferredTier(m[0])) this._wave.emittedSettleThisWave = true;
|
|
2036
|
-
if (m[0] === "DIRTY") {
|
|
2037
|
-
if (!this._wave.emittedDirtyThisWave) {
|
|
2038
|
-
this._wave.emittedDirtyThisWave = true;
|
|
2039
|
-
this._value.status = "dirty";
|
|
2040
|
-
this._emitToSubs(["DIRTY"], delivery);
|
|
2041
|
-
}
|
|
2042
|
-
continue;
|
|
2043
|
-
}
|
|
2044
|
-
if (m[0] === "DATA") {
|
|
2045
|
-
const v = m[1];
|
|
2046
|
-
this._value.cache = v;
|
|
2047
|
-
this._value.hasData = true;
|
|
2048
|
-
this._value.status = "settled";
|
|
2049
|
-
this._version.value = plannedVersions[i];
|
|
2050
|
-
if (this._slot.replayN > 0) {
|
|
2051
|
-
this._value.replayRing.push(v);
|
|
2052
|
-
if (this._value.replayRing.length > this._slot.replayN) this._value.replayRing.shift();
|
|
2053
|
-
}
|
|
2054
|
-
this._emitToSubs(["DATA", v], delivery);
|
|
2055
|
-
continue;
|
|
2056
|
-
}
|
|
2057
|
-
if (m[0] === "RESOLVED") {
|
|
2058
|
-
this._value.status = this._value.hasData ? "resolved" : "sentinel";
|
|
2059
|
-
this._emitToSubs(["RESOLVED"], delivery);
|
|
2060
|
-
continue;
|
|
2061
|
-
}
|
|
2062
|
-
if (m[0] === "INVALIDATE") {
|
|
2063
|
-
this._invalidate(delivery);
|
|
2064
|
-
continue;
|
|
2065
|
-
}
|
|
2066
|
-
if (m[0] === "COMPLETE") {
|
|
2067
|
-
if (this._value.terminal !== void 0) continue;
|
|
2068
|
-
this._value.terminal = true;
|
|
2069
|
-
this._control.pauseBuffer = [];
|
|
2070
|
-
this._value.status = "completed";
|
|
2071
|
-
this._emitToSubs(["COMPLETE"], delivery);
|
|
2072
|
-
continue;
|
|
2073
|
-
}
|
|
2074
|
-
if (m[0] === "ERROR") {
|
|
2075
|
-
if (this._value.terminal !== void 0) continue;
|
|
2076
|
-
this._value.terminal = m[1];
|
|
2077
|
-
this._control.pauseBuffer = [];
|
|
2078
|
-
this._value.status = "errored";
|
|
2079
|
-
this._emitToSubs(["ERROR", m[1]], delivery);
|
|
2080
|
-
continue;
|
|
2081
|
-
}
|
|
2082
|
-
if (m[0] === "TEARDOWN") {
|
|
2083
|
-
this._value.hasTorndown = true;
|
|
2084
|
-
if (this._slot.resetOnTeardown) {
|
|
2085
|
-
this._value.cache = SENTINEL;
|
|
2086
|
-
this._value.hasData = false;
|
|
2087
|
-
}
|
|
2088
|
-
this._emitToSubs(["TEARDOWN"], delivery);
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2091
|
-
if (!this._wave.insideRunWave) this._wave.emittedDirtyThisWave = false;
|
|
2467
|
+
nodeDown(nodeRuntimeHost(this), msgs);
|
|
2092
2468
|
}
|
|
2093
2469
|
_up(msgs, towardDep, route) {
|
|
2094
|
-
|
|
2095
|
-
const routeState = route ?? { demandFired: /* @__PURE__ */ new Map() };
|
|
2096
|
-
for (const m of msgs) {
|
|
2097
|
-
if (!isUpAllowed(m[0])) {
|
|
2098
|
-
throw new Error(
|
|
2099
|
-
`ctx.up: ${m[0]} is down-only (tier ${messageTier(m[0])}); up carries control tiers only (R-ctx-up)`
|
|
2100
|
-
);
|
|
2101
|
-
}
|
|
2102
|
-
}
|
|
2103
|
-
for (const m of msgs) {
|
|
2104
|
-
if (m[0] === "PAUSE") {
|
|
2105
|
-
this._pauseAcquire(m[1]);
|
|
2106
|
-
} else if (m[0] === "RESUME") {
|
|
2107
|
-
if (this._slot.pull && m[1] === this._slot.pullLock) {
|
|
2108
|
-
if (!this._markDemandRouted(m[1], routeState)) this._onDemand();
|
|
2109
|
-
} else if (this._control.pauseLockset.has(m[1])) {
|
|
2110
|
-
this._pauseRelease(m[1]);
|
|
2111
|
-
} else {
|
|
2112
|
-
this._forwardUp(m, towardDep, routeState);
|
|
2113
|
-
}
|
|
2114
|
-
} else if (this._slot.deps.length === 0) {
|
|
2115
|
-
if (m[0] === "INVALIDATE") this._down([["INVALIDATE"]]);
|
|
2116
|
-
} else {
|
|
2117
|
-
this._forwardUp(m, towardDep, routeState);
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
2470
|
+
nodeUp(nodeRuntimeHost(this), msgs, towardDep, route);
|
|
2120
2471
|
}
|
|
2121
2472
|
_markDemandRouted(lockId, route) {
|
|
2122
|
-
|
|
2123
|
-
if (holders === void 0) {
|
|
2124
|
-
holders = /* @__PURE__ */ new Set();
|
|
2125
|
-
route.demandFired.set(lockId, holders);
|
|
2126
|
-
}
|
|
2127
|
-
if (holders.has(this)) return true;
|
|
2128
|
-
holders.add(this);
|
|
2129
|
-
return false;
|
|
2473
|
+
return nodeMarkDemandRouted(nodeRuntimeHost(this), lockId, route);
|
|
2130
2474
|
}
|
|
2131
|
-
/**
|
|
2132
|
-
* Forward one up-going control message toward deps (R-up-routing): up the single declared edge
|
|
2133
|
-
* `towardDep` (directed — prunes other branches; only meaningful on the issuer's FIRST hop) or
|
|
2134
|
-
* broadcast up ALL deps. A depless source has no deps → the message DROPS here (the terminus —
|
|
2135
|
-
* e.g. a cone-routed RESUME whose pullId no node up this cone holds, R-up-at-source). Recursive
|
|
2136
|
-
* forwarding carries the same per-wave route state and no `towardDep` → broadcast beyond the
|
|
2137
|
-
* first hop.
|
|
2138
|
-
*/
|
|
2139
2475
|
_forwardUp(m, towardDep, route) {
|
|
2140
|
-
|
|
2141
|
-
if (towardDep !== void 0) {
|
|
2142
|
-
const d = this._slot.deps[towardDep];
|
|
2143
|
-
if (d !== void 0) d._up([m], void 0, route);
|
|
2144
|
-
} else {
|
|
2145
|
-
for (const dep of this._slot.deps) dep._up([m], void 0, route);
|
|
2146
|
-
}
|
|
2476
|
+
nodeForwardUp(nodeRuntimeHost(this), m, towardDep, route);
|
|
2147
2477
|
}
|
|
2148
|
-
// ── PAUSE/RESUME lockset (R-pause-lockset) + modes (R-pause-modes) ──
|
|
2149
2478
|
_isPaused() {
|
|
2150
|
-
return this
|
|
2479
|
+
return nodeIsPaused(nodeRuntimeHost(this));
|
|
2151
2480
|
}
|
|
2152
2481
|
_hasBoundaryPauseLock() {
|
|
2153
|
-
|
|
2154
|
-
let locks = this._control.pauseLockset.size;
|
|
2155
|
-
if (this._slot.pull && this._control.pauseLockset.has(this._slot.pullLock)) locks--;
|
|
2156
|
-
return locks > 0;
|
|
2482
|
+
return nodeHasBoundaryPauseLock(nodeRuntimeHost(this));
|
|
2157
2483
|
}
|
|
2158
2484
|
_isAsyncPool() {
|
|
2159
|
-
return
|
|
2485
|
+
return nodeIsAsyncPool(nodeRuntimeHost(this));
|
|
2160
2486
|
}
|
|
2161
2487
|
_pauseAcquire(lockId) {
|
|
2162
|
-
this
|
|
2488
|
+
nodePauseAcquire(nodeRuntimeHost(this), lockId);
|
|
2163
2489
|
}
|
|
2164
2490
|
_pauseRelease(lockId) {
|
|
2165
|
-
|
|
2166
|
-
this._control.pauseLockset.delete(lockId);
|
|
2167
|
-
if (this._slot.pull && this._control.demandOwed) this._fireOwedDemandIfReady();
|
|
2168
|
-
if (this._hasBoundaryPauseLock()) return;
|
|
2169
|
-
scheduleBoundaryDrain(this._core);
|
|
2170
|
-
if (this._control.pauseLockset.size > 0) return;
|
|
2171
|
-
this._onResume();
|
|
2491
|
+
nodePauseRelease(nodeRuntimeHost(this), lockId);
|
|
2172
2492
|
}
|
|
2173
2493
|
_onResume() {
|
|
2174
|
-
|
|
2175
|
-
this._control.pauseBuffer = [];
|
|
2176
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2177
|
-
this._control.demandOwed = false;
|
|
2178
|
-
return;
|
|
2179
|
-
}
|
|
2180
|
-
if (this._control.pauseBuffer.length > 0) {
|
|
2181
|
-
const buf = this._control.pauseBuffer;
|
|
2182
|
-
this._control.pauseBuffer = [];
|
|
2183
|
-
for (const wave of buf) this._down(wave);
|
|
2184
|
-
}
|
|
2185
|
-
if (this._control.pausedDepWaveOccurred) {
|
|
2186
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2187
|
-
this._tryRun();
|
|
2188
|
-
}
|
|
2494
|
+
nodeOnResume(nodeRuntimeHost(this));
|
|
2189
2495
|
}
|
|
2190
|
-
/**
|
|
2191
|
-
* R-pull (D59): can this pull node fire a demand NOW? — not terminal, settle-ready (_pending===0),
|
|
2192
|
-
* and no OTHER (non-pullId) lock holds it paused. The gate that decides fire-now vs OWE.
|
|
2193
|
-
*/
|
|
2194
2496
|
_canFireDemand() {
|
|
2195
|
-
|
|
2196
|
-
const own = this._control.pauseLockset.has(this._slot.pullLock) ? 1 : 0;
|
|
2197
|
-
return this._control.pauseLockset.size <= own;
|
|
2497
|
+
return nodeCanFireDemand(nodeRuntimeHost(this));
|
|
2198
2498
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
* absorbed), fire it, then RE-QUIET (1:1). The pullId re-add + the re-entrancy flag are in a
|
|
2202
|
-
* `finally` so a throwing pull fn (graph-less node, no D30 catch) cannot leave the node
|
|
2203
|
-
* permanently non-quiet (the wedge-fix silently disabled) — QA-found robustness fix.
|
|
2204
|
-
*/
|
|
2205
|
-
_deliverPullDemand() {
|
|
2206
|
-
this._control.demandOwed = false;
|
|
2207
|
-
this._control.inDeliverDemand = true;
|
|
2208
|
-
this._control.pauseLockset.delete(this._slot.pullLock);
|
|
2209
|
-
try {
|
|
2210
|
-
this._firePullDemand();
|
|
2211
|
-
} finally {
|
|
2212
|
-
this._control.pauseLockset.add(this._slot.pullLock);
|
|
2213
|
-
this._control.inDeliverDemand = false;
|
|
2214
|
-
}
|
|
2499
|
+
_deliverPullDemand(demand) {
|
|
2500
|
+
nodeDeliverPullDemand(nodeRuntimeHost(this), demand);
|
|
2215
2501
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
* Fire immediately if able; else OWE it — pin-5 (a dep DIRTY in flight, _pending>0) or F4/F5 (an
|
|
2219
|
-
* external PAUSE lock co-holds the node) — and fire when the node next becomes able. A demand
|
|
2220
|
-
* arriving WHILE a delivery is in flight (synchronous re-entry) is DROPPED (1:1, QA guard).
|
|
2221
|
-
*/
|
|
2222
|
-
_onDemand() {
|
|
2223
|
-
if (this._control.inDeliverDemand) return;
|
|
2224
|
-
if (this._canFireDemand()) this._deliverPullDemand();
|
|
2225
|
-
else this._control.demandOwed = true;
|
|
2502
|
+
_onDemand(demand) {
|
|
2503
|
+
nodeOnDemand(nodeRuntimeHost(this), demand);
|
|
2226
2504
|
}
|
|
2227
|
-
/**
|
|
2228
|
-
* R-pull (D55): service ONE demand. Delivery content = the orthogonal pausable mode:
|
|
2229
|
-
* - 'resumeAll' → drain the buffered BACKLOG (each `_down` re-synthesizes a leading DIRTY, so
|
|
2230
|
-
* the per-entry replay is DIRTY-before-DATA — R-pause-modes per-entry arrival order);
|
|
2231
|
-
* - true → deliver the coalesced LATEST as ONE DIRTY-before-DATA wave (pin 2: the quiet absorb
|
|
2232
|
-
* suppressed the dep's original DIRTY, so the demand wave restores it before the value).
|
|
2233
|
-
* Neither branch fires when nothing changed since the last demand → the demand is SILENT.
|
|
2234
|
-
* Called by `_deliverPullDemand` only when settle-ready; the caller has released the pullId, so
|
|
2235
|
-
* `_markDirty` relays the leading DIRTY (not absorbed).
|
|
2236
|
-
*/
|
|
2237
2505
|
_firePullDemand() {
|
|
2238
|
-
|
|
2239
|
-
const buf = this._control.pauseBuffer;
|
|
2240
|
-
this._control.pauseBuffer = [];
|
|
2241
|
-
for (const wave of buf) this._down(wave);
|
|
2242
|
-
}
|
|
2243
|
-
if (this._control.pausedDepWaveOccurred) {
|
|
2244
|
-
const gated = this._slot.handle !== null && !this._wave.hasCalledFnOnce && !(this._slot.partial || this._allDepsSettled());
|
|
2245
|
-
if (this._wave.pending > 0 || gated) return;
|
|
2246
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2247
|
-
this._markDirty();
|
|
2248
|
-
this._tryRun();
|
|
2249
|
-
}
|
|
2506
|
+
nodeFirePullDemand(nodeRuntimeHost(this));
|
|
2250
2507
|
}
|
|
2251
|
-
/**
|
|
2252
|
-
* R-pull (D55/D59): fire a demand that was OWED (deferred at demand time) once the node becomes
|
|
2253
|
-
* able — called from the dep-settle arms (DATA/RESOLVED/INVALIDATE/terminal drain _pending, pin-5
|
|
2254
|
-
* + B1/F6) and from `_pauseRelease` (an external PAUSE lock releases, F4/F5).
|
|
2255
|
-
*/
|
|
2256
2508
|
_fireOwedDemandIfReady() {
|
|
2257
|
-
|
|
2258
|
-
if (this._slot.pull && this._control.demandOwed && this._canFireDemand())
|
|
2259
|
-
this._deliverPullDemand();
|
|
2509
|
+
nodeFireOwedDemandIfReady(nodeRuntimeHost(this));
|
|
2260
2510
|
}
|
|
2261
|
-
/** Should an outgoing settle slice be deferred into the pause buffer? */
|
|
2262
2511
|
_shouldBufferOnPause() {
|
|
2263
|
-
|
|
2264
|
-
if (!this._isPaused()) return false;
|
|
2265
|
-
if (this._slot.pausable === "resumeAll") return true;
|
|
2266
|
-
if (!this._wave.insideRunWave && this._isAsyncPool() && this._slot.deps.length > 0) return true;
|
|
2267
|
-
return false;
|
|
2512
|
+
return nodeShouldBufferOnPause(nodeRuntimeHost(this));
|
|
2268
2513
|
}
|
|
2269
|
-
/** R-invalidate-idempotent: clear cache + flush + cascade; no-op if nothing cached. */
|
|
2270
2514
|
_invalidate(delivery) {
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
this._value.hasData = false;
|
|
2274
|
-
this._value.status = "sentinel";
|
|
2275
|
-
this._value.replayRing = [];
|
|
2276
|
-
for (const fn of this._hooks.onInvalidate) fn();
|
|
2277
|
-
this._emitToSubs(["INVALIDATE"], delivery);
|
|
2278
|
-
}
|
|
2279
|
-
// B42 (R-deps-terminal): ALL deps TERMINAL = every dep has reached COMPLETE *or* an ABSORBED
|
|
2280
|
-
// ERROR. Block only on a LIVE dep (_depTerminal[i] === undefined); an errored dep (terminal = the
|
|
2281
|
-
// error payload, which R-data-payload guarantees is !== undefined and non-boolean) COUNTS as
|
|
2282
|
-
// terminal-done. Was
|
|
2283
|
-
// `tm !== true`, which wedged a node whose errorWhenDepsError:false dep ERRORed (it never
|
|
2284
|
-
// auto-completed even after every other dep completed). Drives the completeWhenDepsComplete cascade.
|
|
2515
|
+
nodeInvalidate(nodeRuntimeHost(this), delivery);
|
|
2516
|
+
}
|
|
2285
2517
|
_allDepsTerminal() {
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2518
|
+
return nodeAllDepsTerminal(nodeRuntimeHost(this));
|
|
2519
|
+
}
|
|
2520
|
+
_emitToSubs(msg, delivery) {
|
|
2521
|
+
nodeEmitToSubs(nodeRuntimeHost(this), msg, delivery);
|
|
2289
2522
|
}
|
|
2290
2523
|
/** R-terminal: resubscribable reset clears terminal + dep state + re-arms the gate. */
|
|
2291
2524
|
_resetLifecycle() {
|
|
2292
|
-
|
|
2293
|
-
this._dep.unsubs = [];
|
|
2294
|
-
this._dep.idxBoxes = [];
|
|
2295
|
-
this._lifecycle.subscribers.clear();
|
|
2296
|
-
this._lifecycle.activated = false;
|
|
2297
|
-
this._value.terminal = void 0;
|
|
2298
|
-
this._value.hasTorndown = false;
|
|
2299
|
-
this._wave.hasCalledFnOnce = false;
|
|
2300
|
-
this._resetDepState();
|
|
2301
|
-
this._control.pauseLockset.clear();
|
|
2302
|
-
this._control.pauseBuffer = [];
|
|
2303
|
-
this._control.pausedDepWaveOccurred = false;
|
|
2304
|
-
this._control.demandOwed = false;
|
|
2305
|
-
this._value.replayRing = [];
|
|
2306
|
-
const isCompute = this._slot.handle !== null || this._slot.deps.length > 0;
|
|
2307
|
-
if (isCompute) {
|
|
2308
|
-
this._value.cache = SENTINEL;
|
|
2309
|
-
this._value.hasData = false;
|
|
2310
|
-
this._value.status = "sentinel";
|
|
2311
|
-
} else {
|
|
2312
|
-
this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
2313
|
-
}
|
|
2314
|
-
if (!this._privateState.persist) this._privateState.value = SENTINEL;
|
|
2315
|
-
}
|
|
2316
|
-
_emitToSubs(msg, delivery) {
|
|
2317
|
-
if (this._released) return;
|
|
2318
|
-
const subs = [...this._lifecycle.subscribers];
|
|
2319
|
-
for (const sink of subs) sink(msg, delivery);
|
|
2525
|
+
nodeResetLifecycle(nodeRuntimeHost(this));
|
|
2320
2526
|
}
|
|
2321
2527
|
/** Batch commit (R-batch-coalesce): deliver the deferred tier-3 wave now. */
|
|
2322
2528
|
__commitBatchedWave(wave) {
|
|
2323
|
-
this
|
|
2324
|
-
this._down(wave);
|
|
2529
|
+
nodeCommitBatchedWave(nodeRuntimeHost(this), wave);
|
|
2325
2530
|
}
|
|
2326
2531
|
/** Batch rollback: balance the immediate DIRTY with a RESOLVED so downstream un-dirties. */
|
|
2327
2532
|
__rollbackBatched() {
|
|
2328
|
-
|
|
2329
|
-
this._wave.batchDirtyOwed = false;
|
|
2330
|
-
this._wave.emittedDirtyThisWave = false;
|
|
2331
|
-
this._value.status = this._value.hasData ? "settled" : "sentinel";
|
|
2332
|
-
this._emitToSubs(["RESOLVED"]);
|
|
2333
|
-
}
|
|
2533
|
+
nodeRollbackBatched(nodeRuntimeHost(this));
|
|
2334
2534
|
}
|
|
2335
2535
|
/** B49: enqueue a committed-boundary task on this node's graph-local core. */
|
|
2336
2536
|
__deferBoundary(fn, batchToken) {
|
|
2337
|
-
|
|
2338
|
-
batchToken,
|
|
2339
|
-
isReady: () => !this._hasBoundaryPauseLock()
|
|
2340
|
-
});
|
|
2537
|
+
nodeDeferBoundary(nodeRuntimeHost(this), fn, batchToken);
|
|
2341
2538
|
}
|
|
2342
2539
|
};
|
|
2343
2540
|
|
|
@@ -2536,18 +2733,90 @@ function parseCron(expr) {
|
|
|
2536
2733
|
daysOfWeek: parseCronField(parts[4], 0, 6)
|
|
2537
2734
|
};
|
|
2538
2735
|
}
|
|
2539
|
-
function matchesCron(schedule, date) {
|
|
2540
|
-
|
|
2736
|
+
function matchesCron(schedule, date, opts = {}) {
|
|
2737
|
+
const fields = cronWallClockFields(date, opts.timezone);
|
|
2738
|
+
return schedule.minutes.has(fields.minute) && schedule.hours.has(fields.hour) && schedule.daysOfMonth.has(fields.day) && schedule.months.has(fields.month) && schedule.daysOfWeek.has(fields.dayOfWeek);
|
|
2739
|
+
}
|
|
2740
|
+
function cronMinuteKey(date, timezone) {
|
|
2741
|
+
const fields = cronWallClockFields(date, timezone);
|
|
2742
|
+
return `${fields.year}-${fields.month}-${fields.day}-${fields.hour}-${fields.minute}`;
|
|
2541
2743
|
}
|
|
2542
|
-
function
|
|
2543
|
-
|
|
2744
|
+
function cronDayKey(date, timezone) {
|
|
2745
|
+
const fields = cronWallClockFields(date, timezone);
|
|
2746
|
+
return `${fields.year}-${fields.month}-${fields.day}`;
|
|
2747
|
+
}
|
|
2748
|
+
function cronWallClockFields(date, timezone) {
|
|
2749
|
+
if (timezone === void 0) {
|
|
2750
|
+
return {
|
|
2751
|
+
year: date.getFullYear(),
|
|
2752
|
+
month: date.getMonth() + 1,
|
|
2753
|
+
day: date.getDate(),
|
|
2754
|
+
hour: date.getHours(),
|
|
2755
|
+
minute: date.getMinutes(),
|
|
2756
|
+
dayOfWeek: date.getDay()
|
|
2757
|
+
};
|
|
2758
|
+
}
|
|
2759
|
+
const parts = timezoneFormatter(timezone).formatToParts(date);
|
|
2760
|
+
const values = {};
|
|
2761
|
+
for (const part of parts) {
|
|
2762
|
+
if (part.type === "year" || part.type === "month" || part.type === "day" || part.type === "hour" || part.type === "minute") {
|
|
2763
|
+
values[part.type] = Number.parseInt(part.value, 10);
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
const year = values.year;
|
|
2767
|
+
const month = values.month;
|
|
2768
|
+
const day = values.day;
|
|
2769
|
+
const hour = values.hour;
|
|
2770
|
+
const minute = values.minute;
|
|
2771
|
+
if (year === void 0 || month === void 0 || day === void 0 || hour === void 0 || minute === void 0) {
|
|
2772
|
+
throw new Error(`fromCron: timezone projection failed for ${timezone}`);
|
|
2773
|
+
}
|
|
2774
|
+
return {
|
|
2775
|
+
year,
|
|
2776
|
+
month,
|
|
2777
|
+
day,
|
|
2778
|
+
hour,
|
|
2779
|
+
minute,
|
|
2780
|
+
dayOfWeek: new Date(Date.UTC(year, month - 1, day)).getUTCDay()
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
var TIMEZONE_FORMATTERS = /* @__PURE__ */ new Map();
|
|
2784
|
+
function timezoneFormatter(timezone) {
|
|
2785
|
+
const existing = TIMEZONE_FORMATTERS.get(timezone);
|
|
2786
|
+
if (existing !== void 0) return existing;
|
|
2787
|
+
assertNonEmptyString(timezone, "fromCron: timezone");
|
|
2788
|
+
try {
|
|
2789
|
+
const formatter = new Intl.DateTimeFormat("en-US-u-ca-gregory-nu-latn", {
|
|
2790
|
+
timeZone: timezone,
|
|
2791
|
+
year: "numeric",
|
|
2792
|
+
month: "2-digit",
|
|
2793
|
+
day: "2-digit",
|
|
2794
|
+
hour: "2-digit",
|
|
2795
|
+
minute: "2-digit",
|
|
2796
|
+
hourCycle: "h23"
|
|
2797
|
+
});
|
|
2798
|
+
formatter.format(/* @__PURE__ */ new Date(0));
|
|
2799
|
+
TIMEZONE_FORMATTERS.set(timezone, formatter);
|
|
2800
|
+
return formatter;
|
|
2801
|
+
} catch (error) {
|
|
2802
|
+
throw new RangeError(
|
|
2803
|
+
`fromCron: unsupported IANA timezone '${timezone}' (${error instanceof Error ? error.message : String(error)})`
|
|
2804
|
+
);
|
|
2805
|
+
}
|
|
2544
2806
|
}
|
|
2545
2807
|
function dateToTimestampNs(date) {
|
|
2546
2808
|
return (BigInt(date.getTime()) * 1000000n).toString();
|
|
2547
2809
|
}
|
|
2548
2810
|
function fromCron(expr, opts = {}) {
|
|
2549
2811
|
const schedule = parseCron(expr);
|
|
2550
|
-
const { tickMs = 6e4, output = "timestamp_ns", signal } = opts;
|
|
2812
|
+
const { tickMs = 6e4, output = "timestamp_ns", signal, timezone } = opts;
|
|
2813
|
+
if (opts.dst?.nonexistent !== void 0 && opts.dst.nonexistent !== "skip") {
|
|
2814
|
+
throw new RangeError("fromCron: dst.nonexistent currently supports only 'skip'");
|
|
2815
|
+
}
|
|
2816
|
+
if (opts.dst?.repeated !== void 0 && opts.dst.repeated !== "once") {
|
|
2817
|
+
throw new RangeError("fromCron: dst.repeated currently supports only 'once'");
|
|
2818
|
+
}
|
|
2819
|
+
if (timezone !== void 0) timezoneFormatter(timezone);
|
|
2551
2820
|
if (!Number.isFinite(tickMs) || tickMs <= 0) {
|
|
2552
2821
|
throw new RangeError("fromCron: tickMs must be a positive finite number");
|
|
2553
2822
|
}
|
|
@@ -2556,6 +2825,8 @@ function fromCron(expr, opts = {}) {
|
|
|
2556
2825
|
(ctx) => {
|
|
2557
2826
|
let done = false;
|
|
2558
2827
|
let lastFiredKey;
|
|
2828
|
+
let firedTimezoneDay;
|
|
2829
|
+
const firedTimezoneMinutes = /* @__PURE__ */ new Set();
|
|
2559
2830
|
let intervalId;
|
|
2560
2831
|
const cleanup = () => {
|
|
2561
2832
|
done = true;
|
|
@@ -2576,9 +2847,18 @@ function fromCron(expr, opts = {}) {
|
|
|
2576
2847
|
const check = () => {
|
|
2577
2848
|
if (done) return;
|
|
2578
2849
|
const now = /* @__PURE__ */ new Date();
|
|
2579
|
-
const key = cronMinuteKey(now);
|
|
2580
|
-
|
|
2850
|
+
const key = cronMinuteKey(now, timezone);
|
|
2851
|
+
const alreadyFired = timezone === void 0 ? key === lastFiredKey : firedTimezoneMinutes.has(key);
|
|
2852
|
+
if (!alreadyFired && matchesCron(schedule, now, { timezone })) {
|
|
2581
2853
|
lastFiredKey = key;
|
|
2854
|
+
if (timezone !== void 0) {
|
|
2855
|
+
const dayKey = cronDayKey(now, timezone);
|
|
2856
|
+
if (dayKey !== firedTimezoneDay) {
|
|
2857
|
+
firedTimezoneDay = dayKey;
|
|
2858
|
+
firedTimezoneMinutes.clear();
|
|
2859
|
+
}
|
|
2860
|
+
firedTimezoneMinutes.add(key);
|
|
2861
|
+
}
|
|
2582
2862
|
emitNow(now);
|
|
2583
2863
|
}
|
|
2584
2864
|
};
|