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