Skip to content

Commit 616cdef

Browse files
alxhubthePunderWoman
authored andcommitted
fix(core): don't coerce all producers to consumers on liveness change (#56140)
When a consumer switches its liveness state, it gets added to / removed from the consumer list of all of its producers. This operation is transitive, so if its producer is *also* a consumer and *its* liveness state is switched, then the change is applied recursively. Note that this only matters *if* the producer is also a consumer. However, the logic in `producerAddLiveConsumer` / `producerRemoveLiveConsumerAtIndex` coerced the producer node into a producer & consumer node, which allocated extra arrays into the node structure that are never used. This didn't affect correctness, but increased the memory usage of plain signal nodes (which are just producers, never consumers). This fix changes the logic in those operations to simply check if a producer is also a consumer instead of coercing it into one. PR Close #56140
1 parent 7659dff commit 616cdef

File tree

1 file changed

+6
-4
lines changed
  • packages/core/primitives/signals/src

1 file changed

+6
-4
lines changed

packages/core/primitives/signals/src/graph.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,7 @@ function producerAddLiveConsumer(
439439
indexOfThis: number,
440440
): number {
441441
assertProducerNode(node);
442-
assertConsumerNode(node);
443-
if (node.liveConsumerNode.length === 0) {
442+
if (node.liveConsumerNode.length === 0 && isConsumerNode(node)) {
444443
// When going from 0 to 1 live consumers, we become a live consumer to our producers.
445444
for (let i = 0; i < node.producerNode.length; i++) {
446445
node.producerIndexOfThis[i] = producerAddLiveConsumer(node.producerNode[i], node, i);
@@ -455,15 +454,14 @@ function producerAddLiveConsumer(
455454
*/
456455
function producerRemoveLiveConsumerAtIndex(node: ReactiveNode, idx: number): void {
457456
assertProducerNode(node);
458-
assertConsumerNode(node);
459457

460458
if (typeof ngDevMode !== 'undefined' && ngDevMode && idx >= node.liveConsumerNode.length) {
461459
throw new Error(
462460
`Assertion error: active consumer index ${idx} is out of bounds of ${node.liveConsumerNode.length} consumers)`,
463461
);
464462
}
465463

466-
if (node.liveConsumerNode.length === 1) {
464+
if (node.liveConsumerNode.length === 1 && isConsumerNode(node)) {
467465
// When removing the last live consumer, we will no longer be live. We need to remove
468466
// ourselves from our producers' tracking (which may cause consumer-producers to lose
469467
// liveness as well).
@@ -506,3 +504,7 @@ function assertProducerNode(node: ReactiveNode): asserts node is ProducerNode {
506504
node.liveConsumerNode ??= [];
507505
node.liveConsumerIndexOfThis ??= [];
508506
}
507+
508+
function isConsumerNode(node: ReactiveNode): node is ConsumerNode {
509+
return node.producerNode !== undefined;
510+
}

0 commit comments

Comments
 (0)