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