Skip to content

Commit 8c6a159

Browse files
committedMay 12, 2022
Improve types for array internals
1 parent 1b557e9 commit 8c6a159

File tree

6 files changed

+294
-231
lines changed

6 files changed

+294
-231
lines changed
 

‎packages/@ember/-internals/metal/lib/array.ts

+24-14
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
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';
23
import { arrayContentDidChange, arrayContentWillChange } from './array_events';
34
import { addListener, removeListener } from './events';
45

56
const 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+
1928
export 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.
3646
export 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

6373
type Operation<T> = (
64-
obj: ObservedObject<T>,
74+
obj: ObservedArray<T>,
6575
eventName: string,
6676
target: object | Function | null,
6777
callbackName: string
6878
) => void;
6979

7080
function 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

98108
export 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
}

‎packages/@ember/-internals/metal/lib/mixin.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,9 @@ export default class Mixin {
672672

673673
/** @internal */
674674
keys() {
675-
return _keys(this);
675+
let keys = _keys(this);
676+
assert('[BUG] Missing keys for mixin!', keys);
677+
return keys;
676678
}
677679

678680
/** @internal */
@@ -739,16 +741,16 @@ function _detect(curMixin: Mixin, targetMixin: Mixin, seen = new Set()): boolean
739741
return false;
740742
}
741743

742-
function _keys(mixin: Mixin, ret = new Set(), seen = new Set()) {
744+
function _keys(mixin: Mixin, ret = new Set<string>(), seen = new Set()) {
743745
if (seen.has(mixin)) {
744746
return;
745747
}
746748
seen.add(mixin);
747749

748750
if (mixin.properties) {
749751
let props = Object.keys(mixin.properties);
750-
for (let i = 0; i < props.length; i++) {
751-
ret.add(props[i]);
752+
for (let prop of props) {
753+
ret.add(prop);
752754
}
753755
} else if (mixin.mixins) {
754756
mixin.mixins.forEach((x: any) => _keys(x, ret, seen));

‎packages/@ember/-internals/runtime/lib/mixins/array.d.ts

-110
This file was deleted.

0 commit comments

Comments
 (0)
Failed to load comments.