@bian-womp/spark-graph 0.1.28 → 0.1.29
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/lib/cjs/index.cjs +76 -18
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/runtime/GraphRuntime.d.ts +1 -0
- package/lib/cjs/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/lib/esm/index.js +76 -18
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/runtime/GraphRuntime.d.ts +1 -0
- package/lib/esm/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/cjs/index.cjs
CHANGED
|
@@ -409,6 +409,22 @@ class GraphRuntime {
|
|
|
409
409
|
this.environment = {};
|
|
410
410
|
this.paused = false;
|
|
411
411
|
}
|
|
412
|
+
// Shallow/deep-ish equality to avoid unnecessary runs on identical values
|
|
413
|
+
valuesEqual(a, b) {
|
|
414
|
+
if (a === b)
|
|
415
|
+
return true;
|
|
416
|
+
if (typeof a !== typeof b)
|
|
417
|
+
return false;
|
|
418
|
+
if (a && b && typeof a === "object") {
|
|
419
|
+
try {
|
|
420
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
412
428
|
static create(def, registry, opts) {
|
|
413
429
|
const gr = new GraphRuntime();
|
|
414
430
|
gr.environment = opts?.environment ?? {};
|
|
@@ -545,17 +561,23 @@ class GraphRuntime {
|
|
|
545
561
|
const node = this.nodes.get(nodeId);
|
|
546
562
|
if (!node)
|
|
547
563
|
throw new Error(`Node not found: ${nodeId}`);
|
|
564
|
+
let anyChanged = false;
|
|
548
565
|
for (const [handle, value] of Object.entries(inputs)) {
|
|
549
566
|
const hasInbound = this.edges.some((e) => e.target.nodeId === nodeId && e.target.handle === handle);
|
|
550
567
|
if (hasInbound)
|
|
551
568
|
continue;
|
|
552
|
-
node.inputs[handle]
|
|
553
|
-
|
|
554
|
-
|
|
569
|
+
const prev = node.inputs[handle];
|
|
570
|
+
const same = this.valuesEqual(prev, value);
|
|
571
|
+
if (!same) {
|
|
572
|
+
node.inputs[handle] = value;
|
|
573
|
+
// Emit value event for input updates
|
|
574
|
+
this.emit("value", { nodeId, handle, value, io: "input" });
|
|
575
|
+
anyChanged = true;
|
|
576
|
+
}
|
|
555
577
|
}
|
|
556
578
|
if (!this.paused) {
|
|
557
579
|
// Only schedule if all inbound inputs are present (or there are none)
|
|
558
|
-
if (this.allInboundHaveValue(nodeId))
|
|
580
|
+
if (anyChanged && this.allInboundHaveValue(nodeId))
|
|
559
581
|
this.scheduleInputsChanged(nodeId);
|
|
560
582
|
}
|
|
561
583
|
}
|
|
@@ -812,17 +834,21 @@ class GraphRuntime {
|
|
|
812
834
|
const dstNode = this.nodes.get(e.target.nodeId);
|
|
813
835
|
if (!dstNode)
|
|
814
836
|
return;
|
|
815
|
-
dstNode.inputs[e.target.handle]
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
value
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
837
|
+
const prev = dstNode.inputs[e.target.handle];
|
|
838
|
+
const same = this.valuesEqual(prev, v);
|
|
839
|
+
if (!same) {
|
|
840
|
+
dstNode.inputs[e.target.handle] = v;
|
|
841
|
+
// Emit value event for input updates
|
|
842
|
+
this.emit("value", {
|
|
843
|
+
nodeId: e.target.nodeId,
|
|
844
|
+
handle: e.target.handle,
|
|
845
|
+
value: v,
|
|
846
|
+
io: "input",
|
|
847
|
+
runtimeTypeId: getTypedOutputTypeId(v),
|
|
848
|
+
});
|
|
849
|
+
if (!this.paused && this.allInboundHaveValue(e.target.nodeId))
|
|
850
|
+
this.scheduleInputsChanged(e.target.nodeId);
|
|
851
|
+
}
|
|
826
852
|
};
|
|
827
853
|
if (e.convertAsync) {
|
|
828
854
|
// emit edge-start before launching async conversion
|
|
@@ -1102,6 +1128,13 @@ class GraphRuntime {
|
|
|
1102
1128
|
set.add(e.target.handle);
|
|
1103
1129
|
prevInbound.set(e.target.nodeId, set);
|
|
1104
1130
|
}
|
|
1131
|
+
// Capture previous outgoing map before rebuilding edges
|
|
1132
|
+
const prevOutgoing = new Map();
|
|
1133
|
+
for (const e of this.edges) {
|
|
1134
|
+
const set = prevOutgoing.get(e.source.nodeId) ?? new Set();
|
|
1135
|
+
set.add(e.source.handle);
|
|
1136
|
+
prevOutgoing.set(e.source.nodeId, set);
|
|
1137
|
+
}
|
|
1105
1138
|
// Rebuild edges mapping with coercions
|
|
1106
1139
|
this.edges = def.edges.map((e) => {
|
|
1107
1140
|
const srcNode = def.nodes.find((nn) => nn.nodeId === e.source.nodeId);
|
|
@@ -1191,9 +1224,34 @@ class GraphRuntime {
|
|
|
1191
1224
|
this.scheduleInputsChanged(nodeId);
|
|
1192
1225
|
}
|
|
1193
1226
|
}
|
|
1194
|
-
// Re-emit
|
|
1195
|
-
|
|
1196
|
-
|
|
1227
|
+
// Re-emit outputs only for sources whose outgoing edge set changed
|
|
1228
|
+
const nextOutgoing = new Map();
|
|
1229
|
+
for (const e of this.edges) {
|
|
1230
|
+
const set = nextOutgoing.get(e.source.nodeId) ?? new Set();
|
|
1231
|
+
set.add(e.source.handle);
|
|
1232
|
+
nextOutgoing.set(e.source.nodeId, set);
|
|
1233
|
+
}
|
|
1234
|
+
const setsEqual = (a, b) => {
|
|
1235
|
+
if (!a && !b)
|
|
1236
|
+
return true;
|
|
1237
|
+
if (!a || !b)
|
|
1238
|
+
return false;
|
|
1239
|
+
if (a.size !== b.size)
|
|
1240
|
+
return false;
|
|
1241
|
+
for (const v of a)
|
|
1242
|
+
if (!b.has(v))
|
|
1243
|
+
return false;
|
|
1244
|
+
return true;
|
|
1245
|
+
};
|
|
1246
|
+
const reemitCandidates = new Set([
|
|
1247
|
+
...Array.from(prevOutgoing.keys()),
|
|
1248
|
+
...Array.from(nextOutgoing.keys()),
|
|
1249
|
+
]);
|
|
1250
|
+
for (const nodeId of reemitCandidates) {
|
|
1251
|
+
const prev = prevOutgoing.get(nodeId);
|
|
1252
|
+
const next = nextOutgoing.get(nodeId);
|
|
1253
|
+
if (!setsEqual(prev, next))
|
|
1254
|
+
this.reemitNodeOutputs(nodeId);
|
|
1197
1255
|
}
|
|
1198
1256
|
}
|
|
1199
1257
|
}
|