@creact-labs/creact 0.2.6 → 0.2.8

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.
@@ -4,6 +4,26 @@
4
4
  import { createSignal } from '../reactive/signal';
5
5
  import { batch } from '../reactive/tracking';
6
6
  import { getCurrentFiber, getCurrentResourcePath, pushResourcePath } from '../runtime/render';
7
+ /**
8
+ * Shallow equality check for output deduplication
9
+ */
10
+ function shallowEqual(a, b) {
11
+ if (a === b)
12
+ return true;
13
+ if (a == null || b == null)
14
+ return false;
15
+ if (typeof a !== 'object' || typeof b !== 'object')
16
+ return false;
17
+ const keysA = Object.keys(a);
18
+ const keysB = Object.keys(b);
19
+ if (keysA.length !== keysB.length)
20
+ return false;
21
+ for (const key of keysA) {
22
+ if (a[key] !== b[key])
23
+ return false;
24
+ }
25
+ return true;
26
+ }
7
27
  // Registry of all instance nodes by ID
8
28
  const nodeRegistry = new Map();
9
29
  // Track which fiber owns each nodeId (to detect duplicate siblings)
@@ -101,9 +121,23 @@ export function useInstance(construct, props) {
101
121
  outputSignals: new Map(),
102
122
  children: [],
103
123
  setOutputs(outputs) {
104
- // Clear ownership before batch triggers re-renders
105
- // When signals update, components re-execute and create new fibers
106
- // that need to claim the same nodeIds
124
+ // First check if any values actually changed
125
+ let hasChanges = false;
126
+ for (const [key, value] of Object.entries(outputs)) {
127
+ if (!this.outputSignals.has(key)) {
128
+ hasChanges = true;
129
+ break;
130
+ }
131
+ const [read] = this.outputSignals.get(key);
132
+ if (!shallowEqual(read(), value)) {
133
+ hasChanges = true;
134
+ break;
135
+ }
136
+ }
137
+ // Early exit if nothing changed - no re-render needed
138
+ if (!hasChanges)
139
+ return;
140
+ // Only clear ownership and batch if there are actual changes
107
141
  nodeOwnership.clear();
108
142
  batch(() => {
109
143
  for (const [key, value] of Object.entries(outputs)) {
@@ -112,8 +146,7 @@ export function useInstance(construct, props) {
112
146
  }
113
147
  else {
114
148
  const [read, write] = this.outputSignals.get(key);
115
- // Only update if value actually changed
116
- if (read() !== value) {
149
+ if (!shallowEqual(read(), value)) {
117
150
  write(value);
118
151
  }
119
152
  }
@@ -139,7 +172,7 @@ export function useInstance(construct, props) {
139
172
  else {
140
173
  const [read, write] = node.outputSignals.get(key);
141
174
  // Only update if value actually changed
142
- if (read() !== value) {
175
+ if (!shallowEqual(read(), value)) {
143
176
  write(value);
144
177
  }
145
178
  }
@@ -194,16 +227,29 @@ export function fillInstanceOutputs(nodeId, outputs) {
194
227
  const node = nodeRegistry.get(nodeId);
195
228
  if (!node)
196
229
  return;
197
- // Clear ownership before batch triggers re-renders
198
- // When signals update, components re-execute and create new fibers
199
- // that need to claim the same nodeIds
230
+ // First check if any values actually changed
231
+ let hasChanges = false;
232
+ for (const [key, value] of Object.entries(outputs)) {
233
+ if (!node.outputSignals.has(key)) {
234
+ hasChanges = true;
235
+ break;
236
+ }
237
+ const [read] = node.outputSignals.get(key);
238
+ if (!shallowEqual(read(), value)) {
239
+ hasChanges = true;
240
+ break;
241
+ }
242
+ }
243
+ // Early exit if nothing changed - no re-render needed
244
+ if (!hasChanges)
245
+ return;
246
+ // Only clear ownership and batch if there are actual changes
200
247
  nodeOwnership.clear();
201
248
  batch(() => {
202
249
  for (const [key, value] of Object.entries(outputs)) {
203
250
  if (node.outputSignals.has(key)) {
204
251
  const [read, write] = node.outputSignals.get(key);
205
- // Only update if value actually changed
206
- if (read() !== value) {
252
+ if (!shallowEqual(read(), value)) {
207
253
  write(value);
208
254
  }
209
255
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@creact-labs/creact",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "type": "module",
5
5
  "description": "Declarative universal reactive runtime",
6
6
  "main": "dist/index.js",