@bian-womp/spark-graph 0.2.43 → 0.2.45
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
CHANGED
|
@@ -846,10 +846,7 @@ class GraphRuntime {
|
|
|
846
846
|
if (dynamicHandles.has(handle))
|
|
847
847
|
continue; // Skip defaults for dynamic handles
|
|
848
848
|
// Clone to avoid shared references
|
|
849
|
-
effective[handle] =
|
|
850
|
-
typeof structuredClone === "function"
|
|
851
|
-
? structuredClone(defaultValue)
|
|
852
|
-
: JSON.parse(JSON.stringify(defaultValue));
|
|
849
|
+
effective[handle] = structuredClone(defaultValue);
|
|
853
850
|
}
|
|
854
851
|
return effective;
|
|
855
852
|
}
|
|
@@ -1266,10 +1263,7 @@ class GraphRuntime {
|
|
|
1266
1263
|
const hasInbound = this.edges.some((e) => e.target.nodeId === n.nodeId && e.target.handle === handle);
|
|
1267
1264
|
if (!hasInbound && value !== undefined) {
|
|
1268
1265
|
// Clone to avoid shared references
|
|
1269
|
-
initialInputs[handle] =
|
|
1270
|
-
typeof structuredClone === "function"
|
|
1271
|
-
? structuredClone(value)
|
|
1272
|
-
: JSON.parse(JSON.stringify(value));
|
|
1266
|
+
initialInputs[handle] = structuredClone(value);
|
|
1273
1267
|
}
|
|
1274
1268
|
}
|
|
1275
1269
|
return {
|
|
@@ -1328,30 +1322,12 @@ class GraphRuntime {
|
|
|
1328
1322
|
this.paused = true;
|
|
1329
1323
|
try {
|
|
1330
1324
|
const ins = payload?.inputs || {};
|
|
1331
|
-
const outsPayload = payload?.outputs || {};
|
|
1332
1325
|
for (const [nodeId, map] of Object.entries(ins)) {
|
|
1333
1326
|
const node = this.nodes.get(nodeId);
|
|
1334
1327
|
if (!node)
|
|
1335
1328
|
continue;
|
|
1336
1329
|
for (const [h, v] of Object.entries(map || {})) {
|
|
1337
|
-
|
|
1338
|
-
// Fallback: if not all upstream output values are present in the snapshot, hydrate the saved input
|
|
1339
|
-
// so the initial view matches last saved state (important for array inputs with multiple edges).
|
|
1340
|
-
const inboundEdges = this.edges.filter((e) => e.target.nodeId === nodeId && e.target.handle === h);
|
|
1341
|
-
if (inboundEdges.length > 0) {
|
|
1342
|
-
// Check if ALL upstream outputs exist in snapshot (required for correct array input restoration)
|
|
1343
|
-
const allUpstreamOutputsExist = inboundEdges.every((e) => {
|
|
1344
|
-
const srcMap = outsPayload[e.source.nodeId] || {};
|
|
1345
|
-
return Object.prototype.hasOwnProperty.call(srcMap, e.source.handle);
|
|
1346
|
-
});
|
|
1347
|
-
// Only skip input hydration if all upstream outputs are present (re-emit will populate correctly)
|
|
1348
|
-
if (allUpstreamOutputsExist)
|
|
1349
|
-
continue;
|
|
1350
|
-
}
|
|
1351
|
-
node.inputs[h] =
|
|
1352
|
-
typeof structuredClone === "function"
|
|
1353
|
-
? structuredClone(v)
|
|
1354
|
-
: JSON.parse(JSON.stringify(v));
|
|
1330
|
+
node.inputs[h] = structuredClone(v);
|
|
1355
1331
|
// emit input value event
|
|
1356
1332
|
this.emit("value", {
|
|
1357
1333
|
nodeId,
|
|
@@ -1368,10 +1344,7 @@ class GraphRuntime {
|
|
|
1368
1344
|
if (!node)
|
|
1369
1345
|
continue;
|
|
1370
1346
|
for (const [h, v] of Object.entries(map || {})) {
|
|
1371
|
-
node.outputs[h] =
|
|
1372
|
-
typeof structuredClone === "function"
|
|
1373
|
-
? structuredClone(v)
|
|
1374
|
-
: JSON.parse(JSON.stringify(v));
|
|
1347
|
+
node.outputs[h] = structuredClone(v);
|
|
1375
1348
|
// emit output value event
|
|
1376
1349
|
this.emit("value", {
|
|
1377
1350
|
nodeId,
|
|
@@ -1506,6 +1479,15 @@ class GraphRuntime {
|
|
|
1506
1479
|
}
|
|
1507
1480
|
// Precompute per-node resolved handles for updated graph (include dynamic)
|
|
1508
1481
|
const resolved = GraphRuntime.computeResolvedHandleMap(def, registry, this.environment);
|
|
1482
|
+
// Check which handles changed and emit events for those
|
|
1483
|
+
const changedHandles = {};
|
|
1484
|
+
for (const [nodeId, newHandles] of resolved.map) {
|
|
1485
|
+
const oldHandles = this.resolvedByNode.get(nodeId);
|
|
1486
|
+
if (!oldHandles ||
|
|
1487
|
+
JSON.stringify(oldHandles) !== JSON.stringify(newHandles)) {
|
|
1488
|
+
changedHandles[nodeId] = newHandles;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1509
1491
|
this.resolvedByNode = resolved.map;
|
|
1510
1492
|
// Rebuild edges mapping with coercions
|
|
1511
1493
|
this.edges = GraphRuntime.buildEdges(def, registry, this.resolvedByNode);
|
|
@@ -1613,8 +1595,16 @@ class GraphRuntime {
|
|
|
1613
1595
|
this.arrayInputBuckets.delete(nodeId);
|
|
1614
1596
|
}
|
|
1615
1597
|
// Schedule async recompute for nodes that indicated Promise-based resolveHandles in this update
|
|
1616
|
-
for
|
|
1598
|
+
// Emit event for changed handles (if any)
|
|
1599
|
+
if (Object.keys(changedHandles).length > 0) {
|
|
1600
|
+
this.emit("invalidate", {
|
|
1601
|
+
reason: "graph-updated",
|
|
1602
|
+
resolvedHandles: changedHandles,
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
for (const nodeId of resolved.pending) {
|
|
1617
1606
|
this.scheduleRecomputeHandles(nodeId);
|
|
1607
|
+
}
|
|
1618
1608
|
}
|
|
1619
1609
|
// Schedule a recomputation of dynamic handles for a node (async to avoid mutating during propagation)
|
|
1620
1610
|
scheduleRecomputeHandles(nodeId) {
|
|
@@ -1667,8 +1657,11 @@ class GraphRuntime {
|
|
|
1667
1657
|
return;
|
|
1668
1658
|
this.resolvedByNode.set(nodeId, next);
|
|
1669
1659
|
this.updateNodeHandles(nodeId, next, registry);
|
|
1670
|
-
// Notify graph updated
|
|
1671
|
-
this.emit("invalidate", {
|
|
1660
|
+
// Notify graph updated with the changed handles
|
|
1661
|
+
this.emit("invalidate", {
|
|
1662
|
+
reason: "graph-updated",
|
|
1663
|
+
resolvedHandles: { [nodeId]: next },
|
|
1664
|
+
});
|
|
1672
1665
|
}
|
|
1673
1666
|
}
|
|
1674
1667
|
|