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' ;
2
3
import { arrayContentDidChange , arrayContentWillChange } from './array_events' ;
3
4
import { addListener , removeListener } from './events' ;
4
5
5
6
const EMPTY_ARRAY = Object . freeze ( [ ] ) ;
6
7
7
- interface ObservedObject < T > extends EmberArray < T > {
8
+ type ObservedArray < T > = ( T [ ] | EmberArray < T > ) & ObservedObject ;
9
+
10
+ interface ObservedObject {
8
11
_revalidate ?: ( ) => void ;
9
12
}
10
13
@@ -16,16 +19,23 @@ export function objectAt<T>(array: T[] | EmberArray<T>, index: number): T | unde
16
19
}
17
20
}
18
21
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
+
19
28
export function replace < T > (
20
- array : NativeArray < T > | MutableArray < T > ,
29
+ array : T [ ] | MutableArray < T > ,
21
30
start : number ,
22
31
deleteCount : number ,
23
- items : T [ ] = EMPTY_ARRAY as [ ]
32
+ items : readonly T [ ] = EMPTY_ARRAY as [ ]
24
33
) : void {
25
- if ( Array . isArray ( array ) ) {
26
- replaceInNativeArray ( array , start , deleteCount , items ) ;
27
- } else {
34
+ if ( isMutableArray ( array ) ) {
28
35
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 ) ;
29
39
}
30
40
}
31
41
@@ -34,7 +44,7 @@ const CHUNK_SIZE = 60000;
34
44
// To avoid overflowing the stack, we splice up to CHUNK_SIZE items at a time.
35
45
// See https://code.google.com/p/chromium/issues/detail?id=56588 for more details.
36
46
export function replaceInNativeArray < T > (
37
- array : T [ ] | NativeArray < T > ,
47
+ array : T [ ] ,
38
48
start : number ,
39
49
deleteCount : number ,
40
50
items : ReadonlyArray < T >
@@ -61,18 +71,18 @@ interface ArrayObserverOptions {
61
71
}
62
72
63
73
type Operation < T > = (
64
- obj : ObservedObject < T > ,
74
+ obj : ObservedArray < T > ,
65
75
eventName : string ,
66
76
target : object | Function | null ,
67
77
callbackName : string
68
78
) => void ;
69
79
70
80
function arrayObserversHelper < T > (
71
- obj : ObservedObject < T > ,
81
+ obj : ObservedArray < T > ,
72
82
target : object | Function | null ,
73
83
opts : ArrayObserverOptions ,
74
84
operation : Operation < T >
75
- ) : ObservedObject < T > {
85
+ ) : ObservedArray < T > {
76
86
let { willChange, didChange } = opts ;
77
87
78
88
operation ( obj , '@array:before' , target , willChange ) ;
@@ -91,14 +101,14 @@ export function addArrayObserver<T>(
91
101
array : EmberArray < T > ,
92
102
target : object | Function | null ,
93
103
opts : ArrayObserverOptions
94
- ) : ObservedObject < T > {
104
+ ) : ObservedArray < T > {
95
105
return arrayObserversHelper ( array , target , opts , addListener ) ;
96
106
}
97
107
98
108
export function removeArrayObserver < T > (
99
- array : EmberArray < T > ,
109
+ array : T [ ] | EmberArray < T > ,
100
110
target : object | Function | null ,
101
111
opts : ArrayObserverOptions
102
- ) : ObservedObject < T > {
112
+ ) : ObservedArray < T > {
103
113
return arrayObserversHelper ( array , target , opts , removeListener ) ;
104
114
}
0 commit comments