@graphrefly/graphrefly 0.22.0 → 0.24.0
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/{chunk-QA3RP5NH.js → chunk-5DJTTKX3.js} +111 -17
- package/dist/chunk-5DJTTKX3.js.map +1 -0
- package/dist/{chunk-BLD3IFYF.js → chunk-5WGT55R4.js} +9 -7
- package/dist/{chunk-BLD3IFYF.js.map → chunk-5WGT55R4.js.map} +1 -1
- package/dist/{chunk-IR3KMOLX.js → chunk-AOCBDH4T.js} +3 -383
- package/dist/chunk-AOCBDH4T.js.map +1 -0
- package/dist/{chunk-TH6COGOP.js → chunk-H4RVA4VE.js} +2 -2
- package/dist/chunk-HWPIFSW2.js +36 -0
- package/dist/chunk-HWPIFSW2.js.map +1 -0
- package/dist/{chunk-MQBQOFDS.js → chunk-IPLKX3L2.js} +12 -31
- package/dist/chunk-IPLKX3L2.js.map +1 -0
- package/dist/{chunk-44HD4BTA.js → chunk-MW4VAKAO.js} +3 -3
- package/dist/chunk-PY4XCDLR.js +391 -0
- package/dist/chunk-PY4XCDLR.js.map +1 -0
- package/dist/{chunk-RHI3GHZW.js → chunk-QOWVNWOC.js} +3 -3
- package/dist/{chunk-EQUZ5NLD.js → chunk-TDEXAMGO.js} +11 -16
- package/dist/chunk-TDEXAMGO.js.map +1 -0
- package/dist/{chunk-NXC35KC5.js → chunk-XOFWRC73.js} +3 -3
- package/dist/compat/nestjs/index.cjs +110 -16
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +6 -6
- package/dist/compat/nestjs/index.d.ts +6 -6
- package/dist/compat/nestjs/index.js +9 -7
- package/dist/core/index.cjs +110 -16
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +3 -3
- package/dist/extra/index.cjs +110 -16
- package/dist/extra/index.cjs.map +1 -1
- package/dist/extra/index.d.cts +4 -4
- package/dist/extra/index.d.ts +4 -4
- package/dist/extra/index.js +9 -7
- package/dist/graph/index.cjs +110 -16
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +5 -5
- package/dist/graph/index.d.ts +5 -5
- package/dist/graph/index.js +4 -4
- package/dist/{graph-DFr0diXB.d.ts → graph-B6NFqv3z.d.ts} +3 -3
- package/dist/{graph-ab1yPwIB.d.cts → graph-D-3JIQme.d.cts} +3 -3
- package/dist/{index-BvWfZCTt.d.cts → index-1z8vRTCt.d.cts} +3 -3
- package/dist/{index-Dy04P4W3.d.cts → index-AMWewNDe.d.cts} +2 -2
- package/dist/{index-C9z6rU9P.d.cts → index-BJB7t9gg.d.cts} +19 -15
- package/dist/{index-BbYZma8G.d.ts → index-BysCTzJz.d.ts} +3 -3
- package/dist/{index-HdJx_BjO.d.ts → index-C-TXEa7C.d.ts} +19 -15
- package/dist/{index-DsGxLfwL.d.ts → index-CYkjxu3s.d.ts} +2 -2
- package/dist/{index-BHm3Ba5q.d.ts → index-D7XgsUt7.d.ts} +2 -2
- package/dist/{index-D36MAQ3f.d.ts → index-DiobMNwE.d.ts} +3 -3
- package/dist/{index-DrJq9B1T.d.cts → index-J7Kc0oIQ.d.cts} +3 -3
- package/dist/{index-DLE1Sp-L.d.cts → index-b5BYtczN.d.cts} +2 -2
- package/dist/index.cjs +129 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +36 -42
- package/dist/index.js.map +1 -1
- package/dist/{meta-n3FoVWML.d.ts → meta-CnkLA_43.d.ts} +1 -1
- package/dist/{meta--fr9sxRM.d.cts → meta-DWbkoq1s.d.cts} +1 -1
- package/dist/{node-C5UD5MGq.d.cts → node-B-f-Lu-k.d.cts} +57 -13
- package/dist/{node-C5UD5MGq.d.ts → node-B-f-Lu-k.d.ts} +57 -13
- package/dist/{observable-DWydVy5b.d.cts → observable-DBnrwcar.d.cts} +1 -1
- package/dist/{observable-CQRBtEbq.d.ts → observable-uP-wy_uK.d.ts} +1 -1
- package/dist/patterns/reactive-layout/index.cjs +224 -129
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +5 -5
- package/dist/patterns/reactive-layout/index.d.ts +5 -5
- package/dist/patterns/reactive-layout/index.js +6 -4
- package/dist/{storage-Bew05Xy6.d.cts → storage-BuTdpCI1.d.cts} +1 -1
- package/dist/{storage-C9fZfMfM.d.ts → storage-F2X1U1x0.d.ts} +1 -1
- package/package.json +3 -2
- package/dist/chunk-EQUZ5NLD.js.map +0 -1
- package/dist/chunk-IR3KMOLX.js.map +0 -1
- package/dist/chunk-MQBQOFDS.js.map +0 -1
- package/dist/chunk-QA3RP5NH.js.map +0 -1
- /package/dist/{chunk-TH6COGOP.js.map → chunk-H4RVA4VE.js.map} +0 -0
- /package/dist/{chunk-44HD4BTA.js.map → chunk-MW4VAKAO.js.map} +0 -0
- /package/dist/{chunk-RHI3GHZW.js.map → chunk-QOWVNWOC.js.map} +0 -0
- /package/dist/{chunk-NXC35KC5.js.map → chunk-XOFWRC73.js.map} +0 -0
package/dist/core/index.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { A as Actor, C as COMPLETE, c as COMPLETE_MSG, d as COMPLETE_ONLY_BATCH, D as DATA, e as DEFAULT_ACTOR, f as DIRTY, g as DIRTY_MSG, h as DIRTY_ONLY_BATCH, i as DepRecord, E as ERROR, F as FnCtx, G as GlobalInspectorEvent, j as GlobalInspectorHook, k as GraphReFlyConfig, l as GuardAction, m as GuardDenied, n as GuardDeniedDetails, H as HashFn, I as INVALIDATE, o as INVALIDATE_MSG, p as INVALIDATE_ONLY_BATCH, M as Message, q as MessageContext, r as MessageTypeRegistration, s as MessageTypeRegistrationInput, t as Messages, N as Node, b as NodeActions, u as NodeCtx, v as NodeDescribeKind, w as NodeFn, x as NodeFnCleanup, y as NodeGuard, z as NodeImpl, B as NodeInspectorHook, J as NodeInspectorHookEvent, a as NodeOptions, K as NodeSink, L as NodeStatus, O as NodeTransportOptions, P as NodeVersionInfo, Q as OnMessageHandler, R as OnSubscribeHandler, S as PAUSE, T as PolicyAllow, U as PolicyDeny, V as PolicyRuleData, W as RESOLVED, X as RESOLVED_MSG, Y as RESOLVED_ONLY_BATCH, Z as RESUME, _ as START, $ as START_MSG, a0 as SubscribeContext, a1 as TEARDOWN, a2 as TEARDOWN_MSG, a3 as TEARDOWN_ONLY_BATCH, a4 as V0, a5 as V1, a6 as VersioningLevel, a7 as VersioningOptions, a8 as accessHintForGuard, a9 as advanceVersion, aa as configure, ab as createVersioning, ac as defaultConfig, ad as defaultHash, ae as isV1, af as node, ag as normalizeActor, ah as policy, ai as policyFromRules, aj as registerBuiltins } from '../node-
|
|
2
|
-
export { A as AutoTrackOptions, D as DerivedFn, a as DynamicFn, E as EffectFn, P as PipeOperator, b as ProducerFn, T as TrackFn, c as autoTrackNode, d as batch, e as derived, f as downWithBatch, g as dynamicNode, h as effect, j as isBatching, m as monotonicNs, p as pipe, k as producer, s as state, w as wallClockNs } from '../index-
|
|
3
|
-
export { D as DescribeDetail, a as DescribeField, b as DescribeNodeOutput, r as resolveDescribeFields } from '../meta
|
|
1
|
+
export { A as Actor, C as COMPLETE, c as COMPLETE_MSG, d as COMPLETE_ONLY_BATCH, D as DATA, e as DEFAULT_ACTOR, f as DIRTY, g as DIRTY_MSG, h as DIRTY_ONLY_BATCH, i as DepRecord, E as ERROR, F as FnCtx, G as GlobalInspectorEvent, j as GlobalInspectorHook, k as GraphReFlyConfig, l as GuardAction, m as GuardDenied, n as GuardDeniedDetails, H as HashFn, I as INVALIDATE, o as INVALIDATE_MSG, p as INVALIDATE_ONLY_BATCH, M as Message, q as MessageContext, r as MessageTypeRegistration, s as MessageTypeRegistrationInput, t as Messages, N as Node, b as NodeActions, u as NodeCtx, v as NodeDescribeKind, w as NodeFn, x as NodeFnCleanup, y as NodeGuard, z as NodeImpl, B as NodeInspectorHook, J as NodeInspectorHookEvent, a as NodeOptions, K as NodeSink, L as NodeStatus, O as NodeTransportOptions, P as NodeVersionInfo, Q as OnMessageHandler, R as OnSubscribeHandler, S as PAUSE, T as PolicyAllow, U as PolicyDeny, V as PolicyRuleData, W as RESOLVED, X as RESOLVED_MSG, Y as RESOLVED_ONLY_BATCH, Z as RESUME, _ as START, $ as START_MSG, a0 as SubscribeContext, a1 as TEARDOWN, a2 as TEARDOWN_MSG, a3 as TEARDOWN_ONLY_BATCH, a4 as V0, a5 as V1, a6 as VersioningLevel, a7 as VersioningOptions, a8 as accessHintForGuard, a9 as advanceVersion, aa as configure, ab as createVersioning, ac as defaultConfig, ad as defaultHash, ae as isV1, af as node, ag as normalizeActor, ah as policy, ai as policyFromRules, aj as registerBuiltins } from '../node-B-f-Lu-k.cjs';
|
|
2
|
+
export { A as AutoTrackOptions, D as DerivedFn, a as DynamicFn, E as EffectFn, P as PipeOperator, b as ProducerFn, T as TrackFn, c as autoTrackNode, d as batch, e as derived, f as downWithBatch, g as dynamicNode, h as effect, j as isBatching, m as monotonicNs, p as pipe, k as producer, s as state, w as wallClockNs } from '../index-BJB7t9gg.cjs';
|
|
3
|
+
export { D as DescribeDetail, a as DescribeField, b as DescribeNodeOutput, r as resolveDescribeFields } from '../meta-DWbkoq1s.cjs';
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { A as Actor, C as COMPLETE, c as COMPLETE_MSG, d as COMPLETE_ONLY_BATCH, D as DATA, e as DEFAULT_ACTOR, f as DIRTY, g as DIRTY_MSG, h as DIRTY_ONLY_BATCH, i as DepRecord, E as ERROR, F as FnCtx, G as GlobalInspectorEvent, j as GlobalInspectorHook, k as GraphReFlyConfig, l as GuardAction, m as GuardDenied, n as GuardDeniedDetails, H as HashFn, I as INVALIDATE, o as INVALIDATE_MSG, p as INVALIDATE_ONLY_BATCH, M as Message, q as MessageContext, r as MessageTypeRegistration, s as MessageTypeRegistrationInput, t as Messages, N as Node, b as NodeActions, u as NodeCtx, v as NodeDescribeKind, w as NodeFn, x as NodeFnCleanup, y as NodeGuard, z as NodeImpl, B as NodeInspectorHook, J as NodeInspectorHookEvent, a as NodeOptions, K as NodeSink, L as NodeStatus, O as NodeTransportOptions, P as NodeVersionInfo, Q as OnMessageHandler, R as OnSubscribeHandler, S as PAUSE, T as PolicyAllow, U as PolicyDeny, V as PolicyRuleData, W as RESOLVED, X as RESOLVED_MSG, Y as RESOLVED_ONLY_BATCH, Z as RESUME, _ as START, $ as START_MSG, a0 as SubscribeContext, a1 as TEARDOWN, a2 as TEARDOWN_MSG, a3 as TEARDOWN_ONLY_BATCH, a4 as V0, a5 as V1, a6 as VersioningLevel, a7 as VersioningOptions, a8 as accessHintForGuard, a9 as advanceVersion, aa as configure, ab as createVersioning, ac as defaultConfig, ad as defaultHash, ae as isV1, af as node, ag as normalizeActor, ah as policy, ai as policyFromRules, aj as registerBuiltins } from '../node-
|
|
2
|
-
export { A as AutoTrackOptions, D as DerivedFn, a as DynamicFn, E as EffectFn, P as PipeOperator, b as ProducerFn, T as TrackFn, c as autoTrackNode, d as batch, e as derived, f as downWithBatch, g as dynamicNode, h as effect, j as isBatching, m as monotonicNs, p as pipe, k as producer, s as state, w as wallClockNs } from '../index-
|
|
3
|
-
export { D as DescribeDetail, a as DescribeField, b as DescribeNodeOutput, r as resolveDescribeFields } from '../meta-
|
|
1
|
+
export { A as Actor, C as COMPLETE, c as COMPLETE_MSG, d as COMPLETE_ONLY_BATCH, D as DATA, e as DEFAULT_ACTOR, f as DIRTY, g as DIRTY_MSG, h as DIRTY_ONLY_BATCH, i as DepRecord, E as ERROR, F as FnCtx, G as GlobalInspectorEvent, j as GlobalInspectorHook, k as GraphReFlyConfig, l as GuardAction, m as GuardDenied, n as GuardDeniedDetails, H as HashFn, I as INVALIDATE, o as INVALIDATE_MSG, p as INVALIDATE_ONLY_BATCH, M as Message, q as MessageContext, r as MessageTypeRegistration, s as MessageTypeRegistrationInput, t as Messages, N as Node, b as NodeActions, u as NodeCtx, v as NodeDescribeKind, w as NodeFn, x as NodeFnCleanup, y as NodeGuard, z as NodeImpl, B as NodeInspectorHook, J as NodeInspectorHookEvent, a as NodeOptions, K as NodeSink, L as NodeStatus, O as NodeTransportOptions, P as NodeVersionInfo, Q as OnMessageHandler, R as OnSubscribeHandler, S as PAUSE, T as PolicyAllow, U as PolicyDeny, V as PolicyRuleData, W as RESOLVED, X as RESOLVED_MSG, Y as RESOLVED_ONLY_BATCH, Z as RESUME, _ as START, $ as START_MSG, a0 as SubscribeContext, a1 as TEARDOWN, a2 as TEARDOWN_MSG, a3 as TEARDOWN_ONLY_BATCH, a4 as V0, a5 as V1, a6 as VersioningLevel, a7 as VersioningOptions, a8 as accessHintForGuard, a9 as advanceVersion, aa as configure, ab as createVersioning, ac as defaultConfig, ad as defaultHash, ae as isV1, af as node, ag as normalizeActor, ah as policy, ai as policyFromRules, aj as registerBuiltins } from '../node-B-f-Lu-k.js';
|
|
2
|
+
export { A as AutoTrackOptions, D as DerivedFn, a as DynamicFn, E as EffectFn, P as PipeOperator, b as ProducerFn, T as TrackFn, c as autoTrackNode, d as batch, e as derived, f as downWithBatch, g as dynamicNode, h as effect, j as isBatching, m as monotonicNs, p as pipe, k as producer, s as state, w as wallClockNs } from '../index-C-TXEa7C.js';
|
|
3
|
+
export { D as DescribeDetail, a as DescribeField, b as DescribeNodeOutput, r as resolveDescribeFields } from '../meta-CnkLA_43.js';
|
package/dist/core/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-QOWVNWOC.js";
|
|
2
2
|
import {
|
|
3
3
|
resolveDescribeFields
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-H4RVA4VE.js";
|
|
5
5
|
import {
|
|
6
6
|
COMPLETE,
|
|
7
7
|
COMPLETE_MSG,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
registerBuiltins,
|
|
53
53
|
state,
|
|
54
54
|
wallClockNs
|
|
55
|
-
} from "../chunk-
|
|
55
|
+
} from "../chunk-5DJTTKX3.js";
|
|
56
56
|
export {
|
|
57
57
|
COMPLETE,
|
|
58
58
|
COMPLETE_MSG,
|
package/dist/extra/index.cjs
CHANGED
|
@@ -210,9 +210,20 @@ var flushInProgress = false;
|
|
|
210
210
|
var drainPhase2 = [];
|
|
211
211
|
var drainPhase3 = [];
|
|
212
212
|
var drainPhase4 = [];
|
|
213
|
+
var flushHooks = [];
|
|
213
214
|
function isBatching() {
|
|
214
215
|
return batchDepth > 0 || flushInProgress;
|
|
215
216
|
}
|
|
217
|
+
function isExplicitlyBatching() {
|
|
218
|
+
return batchDepth > 0;
|
|
219
|
+
}
|
|
220
|
+
function registerBatchFlushHook(hook) {
|
|
221
|
+
if (batchDepth > 0) {
|
|
222
|
+
flushHooks.push(hook);
|
|
223
|
+
} else {
|
|
224
|
+
hook();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
216
227
|
function batch(fn) {
|
|
217
228
|
batchDepth += 1;
|
|
218
229
|
let threw = false;
|
|
@@ -226,6 +237,13 @@ function batch(fn) {
|
|
|
226
237
|
if (batchDepth === 0) {
|
|
227
238
|
if (threw) {
|
|
228
239
|
if (!flushInProgress) {
|
|
240
|
+
const hooks = flushHooks.splice(0);
|
|
241
|
+
for (const h of hooks) {
|
|
242
|
+
try {
|
|
243
|
+
h();
|
|
244
|
+
} catch {
|
|
245
|
+
}
|
|
246
|
+
}
|
|
229
247
|
drainPhase2.length = 0;
|
|
230
248
|
drainPhase3.length = 0;
|
|
231
249
|
drainPhase4.length = 0;
|
|
@@ -242,7 +260,18 @@ function drainPending() {
|
|
|
242
260
|
const errors = [];
|
|
243
261
|
let iterations = 0;
|
|
244
262
|
try {
|
|
245
|
-
while (drainPhase2.length > 0 || drainPhase3.length > 0 || drainPhase4.length > 0) {
|
|
263
|
+
while (drainPhase2.length > 0 || drainPhase3.length > 0 || drainPhase4.length > 0 || ownsFlush && flushHooks.length > 0) {
|
|
264
|
+
if (ownsFlush && flushHooks.length > 0) {
|
|
265
|
+
const hooks = flushHooks.splice(0);
|
|
266
|
+
for (const h of hooks) {
|
|
267
|
+
try {
|
|
268
|
+
h();
|
|
269
|
+
} catch (e) {
|
|
270
|
+
errors.push(e);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
246
275
|
iterations += 1;
|
|
247
276
|
if (iterations > MAX_DRAIN_ITERATIONS) {
|
|
248
277
|
drainPhase2.length = 0;
|
|
@@ -900,6 +929,22 @@ var NodeImpl = class _NodeImpl {
|
|
|
900
929
|
* treats `0` as "wave settled" — O(1) check for full dep settlement.
|
|
901
930
|
*/
|
|
902
931
|
_dirtyDepCount = 0;
|
|
932
|
+
// --- Per-batch emit accumulator (Bug 2: K+1 fan-in fix) ---
|
|
933
|
+
/**
|
|
934
|
+
* Inside an explicit `batch(() => ...)` scope, every `_emit` accumulates
|
|
935
|
+
* its already-framed messages here instead of dispatching synchronously.
|
|
936
|
+
* At batch end, `_flushBatchPending` runs (registered via
|
|
937
|
+
* `registerBatchFlushHook`) and delivers the whole accumulated batch as
|
|
938
|
+
* one `downWithBatch` call — collapsing what would otherwise be K
|
|
939
|
+
* separate sink invocations into one. This is the fix for the diamond
|
|
940
|
+
* fan-in K+1 over-fire.
|
|
941
|
+
*
|
|
942
|
+
* `null` outside batch (or after flush). Only ever appended to within
|
|
943
|
+
* a single explicit batch lifetime; reset to `null` on flush. State
|
|
944
|
+
* updates (cache, version, status) still happen per-emit via
|
|
945
|
+
* `_updateState` — only the downstream delivery is coalesced.
|
|
946
|
+
*/
|
|
947
|
+
_batchPendingMessages = null;
|
|
903
948
|
// --- PAUSE/RESUME lock tracking (C0) ---
|
|
904
949
|
/**
|
|
905
950
|
* Set of active pause locks held against this node. Every `[PAUSE, lockId]`
|
|
@@ -1277,7 +1322,10 @@ var NodeImpl = class _NodeImpl {
|
|
|
1277
1322
|
dep.unsub = noopUnsub;
|
|
1278
1323
|
dep.unsub = dep.node.subscribe((msgs) => {
|
|
1279
1324
|
if (dep.unsub === null) return;
|
|
1325
|
+
const tierOf = this._config.tierOf;
|
|
1326
|
+
let sawSettlement = false;
|
|
1280
1327
|
for (const m of msgs) {
|
|
1328
|
+
if (tierOf(m[0]) >= 3) sawSettlement = true;
|
|
1281
1329
|
this._config.onMessage(
|
|
1282
1330
|
this,
|
|
1283
1331
|
m,
|
|
@@ -1285,6 +1333,7 @@ var NodeImpl = class _NodeImpl {
|
|
|
1285
1333
|
this._actions
|
|
1286
1334
|
);
|
|
1287
1335
|
}
|
|
1336
|
+
if (sawSettlement) this._maybeRunFnOnSettlement();
|
|
1288
1337
|
});
|
|
1289
1338
|
subscribedCount++;
|
|
1290
1339
|
}
|
|
@@ -1339,7 +1388,10 @@ var NodeImpl = class _NodeImpl {
|
|
|
1339
1388
|
try {
|
|
1340
1389
|
record.unsub = depNode.subscribe((msgs) => {
|
|
1341
1390
|
if (record.unsub === null) return;
|
|
1391
|
+
const tierOf = this._config.tierOf;
|
|
1392
|
+
let sawSettlement = false;
|
|
1342
1393
|
for (const m of msgs) {
|
|
1394
|
+
if (tierOf(m[0]) >= 3) sawSettlement = true;
|
|
1343
1395
|
this._config.onMessage(
|
|
1344
1396
|
this,
|
|
1345
1397
|
m,
|
|
@@ -1347,6 +1399,7 @@ var NodeImpl = class _NodeImpl {
|
|
|
1347
1399
|
this._actions
|
|
1348
1400
|
);
|
|
1349
1401
|
}
|
|
1402
|
+
if (sawSettlement) this._maybeRunFnOnSettlement();
|
|
1350
1403
|
});
|
|
1351
1404
|
} catch (err) {
|
|
1352
1405
|
record.unsub = null;
|
|
@@ -1468,7 +1521,6 @@ var NodeImpl = class _NodeImpl {
|
|
|
1468
1521
|
}
|
|
1469
1522
|
return;
|
|
1470
1523
|
}
|
|
1471
|
-
this._maybeRunFnOnSettlement();
|
|
1472
1524
|
}
|
|
1473
1525
|
// --- Centralized dep-state transitions (A3 settlement counters) ---
|
|
1474
1526
|
//
|
|
@@ -1714,37 +1766,35 @@ var NodeImpl = class _NodeImpl {
|
|
|
1714
1766
|
// --- Emit pipeline ---
|
|
1715
1767
|
/**
|
|
1716
1768
|
* @internal The unified dispatch waist — one call = one wave.
|
|
1769
|
+
* See `GRAPHREFLY-SPEC.md` §1.3.1 for protocol context — the stages
|
|
1770
|
+
* below are the implementation order.
|
|
1717
1771
|
*
|
|
1718
1772
|
* Pipeline stages, in order:
|
|
1719
1773
|
*
|
|
1720
|
-
* 1.
|
|
1721
|
-
* 2. Terminal filter — post-COMPLETE/ERROR only TEARDOWN/INVALIDATE
|
|
1774
|
+
* 1. Terminal filter — post-COMPLETE/ERROR only TEARDOWN/INVALIDATE
|
|
1722
1775
|
* still propagate so graph teardown and cache-clear still work.
|
|
1723
|
-
*
|
|
1776
|
+
* 2. Tier sort (stable) — the batch can be in any order when it
|
|
1724
1777
|
* arrives; the walker downstream (`downWithBatch`) assumes
|
|
1725
1778
|
* ascending tier monotone, and so does `_updateState`'s tier-3
|
|
1726
1779
|
* slice walk. This is the single source of truth for ordering.
|
|
1727
|
-
*
|
|
1780
|
+
* 3. Synthetic DIRTY prefix — if a tier-3 payload is present, no
|
|
1728
1781
|
* DIRTY is already in the batch, and the node isn't already in
|
|
1729
1782
|
* `"dirty"` status, prepend `[DIRTY]` after any tier-0 START
|
|
1730
1783
|
* entries. Guarantees spec §1.3.1 (DIRTY precedes DATA within
|
|
1731
1784
|
* the same batch) uniformly across every entry point.
|
|
1732
|
-
*
|
|
1785
|
+
* 4. PAUSE/RESUME lock bookkeeping (C0) — update `_pauseLocks`,
|
|
1733
1786
|
* derive `_paused`, filter unknown-lockId RESUME, replay
|
|
1734
1787
|
* bufferAll buffer on final lock release.
|
|
1735
|
-
*
|
|
1788
|
+
* 5. Meta TEARDOWN fan-out — notify meta children before
|
|
1736
1789
|
* `_updateState`'s TEARDOWN branch calls `_deactivate`. Hoisted
|
|
1737
1790
|
* out of the walk to keep `_updateState` re-entrance-free.
|
|
1738
|
-
*
|
|
1791
|
+
* 6. `_updateState` — walk the batch in tier order, advancing
|
|
1739
1792
|
* `_cached` / `_status` / `_versioning` and running equals
|
|
1740
1793
|
* substitution on tier-3 DATA (§3.5.1). Returns
|
|
1741
1794
|
* `{finalMessages, equalsError?}`.
|
|
1742
|
-
*
|
|
1795
|
+
* 7. `downWithBatch` dispatch (or bufferAll capture if paused with
|
|
1743
1796
|
* `pausable: "resumeAll"`).
|
|
1744
|
-
*
|
|
1745
|
-
*
|
|
1746
|
-
* `node.down` / `node.emit` / `actions.down` / `actions.emit` all
|
|
1747
|
-
* converge here — the unified `_emit` waist (spec §1.3.1).
|
|
1797
|
+
* 8. Recursive ERROR emission if equals threw mid-walk.
|
|
1748
1798
|
*/
|
|
1749
1799
|
_emit(messages) {
|
|
1750
1800
|
if (messages.length === 0) return;
|
|
@@ -1840,10 +1890,10 @@ var NodeImpl = class _NodeImpl {
|
|
|
1840
1890
|
}
|
|
1841
1891
|
}
|
|
1842
1892
|
if (immediate.length > 0) {
|
|
1843
|
-
|
|
1893
|
+
this._dispatchOrAccumulate(immediate);
|
|
1844
1894
|
}
|
|
1845
1895
|
} else {
|
|
1846
|
-
|
|
1896
|
+
this._dispatchOrAccumulate(finalMessages);
|
|
1847
1897
|
}
|
|
1848
1898
|
}
|
|
1849
1899
|
if (equalsError != null) {
|
|
@@ -1966,6 +2016,50 @@ var NodeImpl = class _NodeImpl {
|
|
|
1966
2016
|
const snapshot = [...this._sinks];
|
|
1967
2017
|
for (const sink of snapshot) sink(messages);
|
|
1968
2018
|
};
|
|
2019
|
+
/**
|
|
2020
|
+
* @internal Dispatch entry point that respects the per-batch emit
|
|
2021
|
+
* accumulator (Bug 2). Inside an explicit `batch()` scope, append to
|
|
2022
|
+
* `_batchPendingMessages` and register a flush hook on first append.
|
|
2023
|
+
* Outside batch — or during a drain (where `flushInProgress` is true
|
|
2024
|
+
* but `batchDepth` is 0) — dispatch synchronously through `downWithBatch`.
|
|
2025
|
+
*
|
|
2026
|
+
* Per-emit state updates (`_frameBatch`, `_updateState`) have already
|
|
2027
|
+
* happened by the time we reach here; only the **downstream delivery**
|
|
2028
|
+
* is coalesced. Cache, version, and status are visible mid-batch on
|
|
2029
|
+
* the emitting node itself.
|
|
2030
|
+
*/
|
|
2031
|
+
_dispatchOrAccumulate(messages) {
|
|
2032
|
+
if (isExplicitlyBatching()) {
|
|
2033
|
+
if (this._batchPendingMessages === null) {
|
|
2034
|
+
this._batchPendingMessages = [];
|
|
2035
|
+
registerBatchFlushHook(() => this._flushBatchPending());
|
|
2036
|
+
}
|
|
2037
|
+
for (const m of messages) this._batchPendingMessages.push(m);
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
downWithBatch(this._deliverToSinks, messages, this._config.tierOf);
|
|
2041
|
+
}
|
|
2042
|
+
/**
|
|
2043
|
+
* @internal Flushes the accumulated batch through `downWithBatch` and
|
|
2044
|
+
* clears the pending state. Idempotent — safe to call when pending is
|
|
2045
|
+
* already null or empty (e.g. on a `batch()` throw, where the hook
|
|
2046
|
+
* fires for cleanup but the drainPhase queues are wiped after).
|
|
2047
|
+
*
|
|
2048
|
+
* Critical: the accumulated batch is interleaved per-emit framings like
|
|
2049
|
+
* `[DIRTY, DATA(1), DIRTY, DATA(2)]` — non-monotone tier order. We must
|
|
2050
|
+
* re-frame to sort by tier before handing to `downWithBatch`, which
|
|
2051
|
+
* assumes pre-sorted input. `_frameBatch` also handles the synthetic
|
|
2052
|
+
* DIRTY prepend rule (no-op here — `hasDirty` is true since each
|
|
2053
|
+
* accumulated emit already carries its own DIRTY prefix).
|
|
2054
|
+
*/
|
|
2055
|
+
_flushBatchPending() {
|
|
2056
|
+
const pending = this._batchPendingMessages;
|
|
2057
|
+
if (pending === null) return;
|
|
2058
|
+
this._batchPendingMessages = null;
|
|
2059
|
+
if (pending.length === 0) return;
|
|
2060
|
+
const framed = this._frameBatch(pending);
|
|
2061
|
+
downWithBatch(this._deliverToSinks, framed, this._config.tierOf);
|
|
2062
|
+
}
|
|
1969
2063
|
};
|
|
1970
2064
|
var isNodeArray = (value) => Array.isArray(value);
|
|
1971
2065
|
var isNodeOptionsObject = (value) => typeof value === "object" && value != null && !Array.isArray(value);
|