@@ -80,12 +80,6 @@ function replaceRelatedRecordsLocal(graph: Graph, op: ReplaceRelatedRecordsOpera
80
80
const relationship = graph . get ( op . record , op . field ) ;
81
81
assert ( `expected hasMany relationship` , isHasMany ( relationship ) ) ;
82
82
83
- // relationships for newly created records begin in the dirty state, so if updated
84
- // before flushed we would fail to notify. This check helps us avoid that.
85
- const isMaybeFirstUpdate =
86
- relationship . remoteState . length === 0 &&
87
- relationship . localState === null &&
88
- relationship . state . hasReceivedData === false ;
89
83
relationship . state . hasReceivedData = true ;
90
84
const { additions, removals } = relationship ;
91
85
const { inverseKey, type } = relationship . definition ;
@@ -158,13 +152,11 @@ function replaceRelatedRecordsLocal(graph: Graph, op: ReplaceRelatedRecordsOpera
158
152
relationship . additions = diff . add ;
159
153
relationship . removals = diff . del ;
160
154
relationship . localState = diff . finalState ;
161
- relationship . isDirty = wasDirty ;
162
155
163
- // we notify if this is the first update to the relationship
164
- // because ?? may need to recalculate.
165
- // otherwise we only notify if we are dirty and were not already dirty before
166
- if ( isMaybeFirstUpdate || ( becameDirty && ! wasDirty ) ) {
167
- notifyChange ( graph , op . record , op . field ) ;
156
+ // we only notify if the localState changed and were not already dirty before
157
+ // because if we were already dirty then we have already notified
158
+ if ( becameDirty && ! wasDirty ) {
159
+ notifyChange ( graph , relationship ) ;
168
160
}
169
161
}
170
162
@@ -180,8 +172,14 @@ function replaceRelatedRecordsRemote(graph: Graph, op: ReplaceRelatedRecordsOper
180
172
graph . _addToTransaction ( relationship ) ;
181
173
}
182
174
183
- // see note before flushCanonical
184
- // const wasDirty = relationship.isDirty;
175
+ const wasDirty = relationship . isDirty ;
176
+ // if this is our first time receiving data
177
+ // we need to mark the relationship as dirty
178
+ // so that non-materializing APIs like `hasManyReference.value()`
179
+ // will get notified and updated.
180
+ if ( ! relationship . state . hasReceivedData ) {
181
+ relationship . isDirty = true ;
182
+ }
185
183
relationship . state . hasReceivedData = true ;
186
184
187
185
// cache existing state
@@ -310,10 +308,7 @@ function replaceRelatedRecordsRemote(graph: Graph, op: ReplaceRelatedRecordsOper
310
308
}
311
309
}
312
310
313
- // we ought to only flush if we became dirty and were not before
314
- // but this causes a fw test failures around unloadRecord and reference autotracking
315
- // we should investigate this further
316
- if ( relationship . isDirty /*&& !wasDirty*/ ) {
311
+ if ( relationship . isDirty && ! wasDirty ) {
317
312
flushCanonical ( graph , relationship ) ;
318
313
}
319
314
}
@@ -352,7 +347,8 @@ export function addToInverse(
352
347
removeFromInverse ( graph , relationship . localState , relationship . definition . inverseKey , identifier , isRemote ) ;
353
348
}
354
349
relationship . localState = value ;
355
- notifyChange ( graph , identifier , key ) ;
350
+
351
+ notifyChange ( graph , relationship ) ;
356
352
}
357
353
} else if ( isHasMany ( relationship ) ) {
358
354
if ( isRemote ) {
@@ -374,8 +370,15 @@ export function addToInverse(
374
370
}
375
371
}
376
372
} else {
373
+ // if we are not dirty but have a null localState then we
374
+ // are mutating a relationship that has never been fetched
375
+ // so we initialize localState to an empty array
376
+ if ( ! relationship . isDirty && ! relationship . localState ) {
377
+ relationship . localState = [ ] ;
378
+ }
379
+
377
380
if ( _addLocal ( graph , identifier , relationship , value , null ) ) {
378
- notifyChange ( graph , identifier , key ) ;
381
+ notifyChange ( graph , relationship ) ;
379
382
}
380
383
}
381
384
} else {
@@ -401,7 +404,7 @@ export function notifyInverseOfPotentialMaterialization(
401
404
) {
402
405
const relationship = graph . get ( identifier , key ) ;
403
406
if ( isHasMany ( relationship ) && isRemote && relationship . remoteMembers . has ( value ) ) {
404
- notifyChange ( graph , identifier , key ) ;
407
+ notifyChange ( graph , relationship ) ;
405
408
}
406
409
}
407
410
@@ -423,17 +426,17 @@ export function removeFromInverse(
423
426
if ( relationship . localState === value ) {
424
427
relationship . localState = null ;
425
428
426
- notifyChange ( graph , identifier , key ) ;
429
+ notifyChange ( graph , relationship ) ;
427
430
}
428
431
} else if ( isHasMany ( relationship ) ) {
429
432
if ( isRemote ) {
430
433
graph . _addToTransaction ( relationship ) ;
431
434
if ( _removeRemote ( relationship , value ) ) {
432
- notifyChange ( graph , identifier , key ) ;
435
+ notifyChange ( graph , relationship ) ;
433
436
}
434
437
} else {
435
438
if ( _removeLocal ( relationship , value ) ) {
436
- notifyChange ( graph , identifier , key ) ;
439
+ notifyChange ( graph , relationship ) ;
437
440
}
438
441
}
439
442
} else {
@@ -449,5 +452,7 @@ export function removeFromInverse(
449
452
}
450
453
451
454
function flushCanonical ( graph : Graph , rel : CollectionEdge ) {
452
- graph . _scheduleLocalSync ( rel ) ;
455
+ if ( rel . accessed ) {
456
+ graph . _scheduleLocalSync ( rel ) ;
457
+ }
453
458
}
0 commit comments