1- import type { Array as EmberArray , MutableArray , NativeArray } from '@ember/-internals/runtime' ;
1+ import type { Array as EmberArray , MutableArray } from '@ember/-internals/runtime' ;
2+ import { assert } from '@ember/debug' ;
23import { arrayContentDidChange , arrayContentWillChange } from './array_events' ;
34import { addListener , removeListener } from './events' ;
45
56const EMPTY_ARRAY = Object . freeze ( [ ] ) ;
67
7- interface ObservedObject < T > extends EmberArray < T > {
8+ type ObservedArray < T > = ( T [ ] | EmberArray < T > ) & ObservedObject ;
9+
10+ interface ObservedObject {
811 _revalidate ?: ( ) => void ;
912}
1013
@@ -16,16 +19,23 @@ export function objectAt<T>(array: T[] | EmberArray<T>, index: number): T | unde
1619 }
1720}
1821
22+ // Ideally, we'd use MutableArray.detect but for unknown reasons this causes
23+ // the node tests to fail strangely.
24+ function isMutableArray < T > ( obj : unknown ) : obj is MutableArray < T > {
25+ return obj != null && typeof ( obj as MutableArray < T > ) . replace === 'function' ;
26+ }
27+
1928export function replace < T > (
20- array : NativeArray < T > | MutableArray < T > ,
29+ array : T [ ] | MutableArray < T > ,
2130 start : number ,
2231 deleteCount : number ,
23- items : T [ ] = EMPTY_ARRAY as [ ]
32+ items : readonly T [ ] = EMPTY_ARRAY as [ ]
2433) : void {
25- if ( Array . isArray ( array ) ) {
26- replaceInNativeArray ( array , start , deleteCount , items ) ;
27- } else {
34+ if ( isMutableArray ( array ) ) {
2835 array . replace ( start , deleteCount , items ) ;
36+ } else {
37+ assert ( 'Can only replace content of a native array or MutableArray' , Array . isArray ( array ) ) ;
38+ replaceInNativeArray ( array , start , deleteCount , items ) ;
2939 }
3040}
3141
@@ -34,7 +44,7 @@ const CHUNK_SIZE = 60000;
3444// To avoid overflowing the stack, we splice up to CHUNK_SIZE items at a time.
3545// See https://code.google.com/p/chromium/issues/detail?id=56588 for more details.
3646export function replaceInNativeArray < T > (
37- array : T [ ] | NativeArray < T > ,
47+ array : T [ ] ,
3848 start : number ,
3949 deleteCount : number ,
4050 items : ReadonlyArray < T >
@@ -61,18 +71,18 @@ interface ArrayObserverOptions {
6171}
6272
6373type Operation < T > = (
64- obj : ObservedObject < T > ,
74+ obj : ObservedArray < T > ,
6575 eventName : string ,
6676 target : object | Function | null ,
6777 callbackName : string
6878) => void ;
6979
7080function arrayObserversHelper < T > (
71- obj : ObservedObject < T > ,
81+ obj : ObservedArray < T > ,
7282 target : object | Function | null ,
7383 opts : ArrayObserverOptions ,
7484 operation : Operation < T >
75- ) : ObservedObject < T > {
85+ ) : ObservedArray < T > {
7686 let { willChange, didChange } = opts ;
7787
7888 operation ( obj , '@array:before' , target , willChange ) ;
@@ -91,14 +101,14 @@ export function addArrayObserver<T>(
91101 array : EmberArray < T > ,
92102 target : object | Function | null ,
93103 opts : ArrayObserverOptions
94- ) : ObservedObject < T > {
104+ ) : ObservedArray < T > {
95105 return arrayObserversHelper ( array , target , opts , addListener ) ;
96106}
97107
98108export function removeArrayObserver < T > (
99- array : EmberArray < T > ,
109+ array : T [ ] | EmberArray < T > ,
100110 target : object | Function | null ,
101111 opts : ArrayObserverOptions
102- ) : ObservedObject < T > {
112+ ) : ObservedArray < T > {
103113 return arrayObserversHelper ( array , target , opts , removeListener ) ;
104114}
0 commit comments