Skip to content

Commit d7a41f7

Browse files
committed
Migrate some function from the mixin to the main class
1 parent 4b62a15 commit d7a41f7

File tree

13 files changed

+153
-118
lines changed

13 files changed

+153
-118
lines changed

src/Collection.ts

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
import { IndexedSeq, KeyedSeq, KeyedSeqImpl, Seq, SetSeq } from './Seq';
1+
import { ITERATE_ENTRIES, type IteratorType } from './Iterator';
2+
import { IndexedSeq, KeyedSeq, Seq, SetSeq } from './Seq';
23
import type ValueObject from './ValueObject';
34
import { isAssociative } from './predicates/isAssociative';
45
import { isCollection } from './predicates/isCollection';
56
import { isIndexed } from './predicates/isIndexed';
67
import { isKeyed } from './predicates/isKeyed';
8+
import assertNotInfinite from './utils/assertNotInfinite';
9+
import deepEqual from './utils/deepEqual';
10+
import { hashCollection } from './utils/hashCollection';
711

812
export function Collection<I extends CollectionImpl<unknown, unknown>>(
913
collection: I
@@ -21,11 +25,65 @@ export function Collection(value: unknown): CollectionImpl<unknown, unknown> {
2125
return isCollection(value) ? value : Seq(value);
2226
}
2327

24-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2528
export class CollectionImpl<K, V> implements ValueObject {
26-
declare equals: (other: unknown) => boolean;
29+
private __hash: number | undefined;
2730

28-
declare hashCode: () => number;
31+
size: number = 0;
32+
33+
equals(other: unknown): boolean {
34+
return deepEqual(this, other);
35+
}
36+
37+
hashCode() {
38+
return this.__hash || (this.__hash = hashCollection(this));
39+
}
40+
41+
every(
42+
predicate: (value: V, key: K, iter: this) => boolean,
43+
context?: CollectionImpl<K, V>
44+
): boolean {
45+
assertNotInfinite(this.size);
46+
let returnValue = true;
47+
this.__iterate((v, k, c) => {
48+
if (!predicate.call(context, v, k, c)) {
49+
returnValue = false;
50+
return false;
51+
}
52+
});
53+
return returnValue;
54+
}
55+
56+
entries() {
57+
return this.__iterator(ITERATE_ENTRIES);
58+
}
59+
60+
__iterate(
61+
fn: (value: V, index: K, iter: this) => boolean,
62+
reverse?: boolean
63+
): number;
64+
__iterate(
65+
fn: (value: V, index: K, iter: this) => void,
66+
reverse?: boolean
67+
): void;
68+
__iterate(
69+
fn: (value: V, index: K, iter: this) => boolean | void,
70+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
71+
reverse: boolean = false
72+
): number | void {
73+
throw new Error(
74+
'CollectionImpl does not implement __iterate. Use a subclass instead.'
75+
);
76+
}
77+
78+
__iterator(
79+
type: IteratorType,
80+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
81+
reverse: boolean = false
82+
): Iterator<K | V | [K, V]> {
83+
throw new Error(
84+
'CollectionImpl does not implement __iterator. Use a subclass instead.'
85+
);
86+
}
2987
}
3088

3189
/**
@@ -35,19 +93,23 @@ export class CollectionImpl<K, V> implements ValueObject {
3593
* Note: `Seq.Keyed` is a conversion function and not a class, and does not
3694
* use the `new` keyword during construction.
3795
*/
38-
export function Keyed<K, V>(
96+
export function KeyedCollection<K, V>(
3997
collection?: Iterable<[K, V]>
4098
): KeyedCollectionImpl<K, V>;
41-
export function Keyed<V>(obj: {
99+
export function KeyedCollection<V>(obj: {
42100
[key: string]: V;
43101
}): KeyedCollectionImpl<string, V>;
44-
export function Keyed(value: unknown): KeyedCollectionImpl<unknown, unknown> {
102+
export function KeyedCollection(
103+
value: unknown
104+
): KeyedCollectionImpl<unknown, unknown> {
45105
return isKeyed(value) ? value : KeyedSeq(value);
46106
}
47107

48108
export class KeyedCollectionImpl<K, V> extends CollectionImpl<K, V> {}
49109

50-
export function IndexedCollection(value) {
110+
export function IndexedCollection<T>(
111+
value: Iterable<T> | ArrayLike<T>
112+
): IndexedCollectionImpl<T> {
51113
return isIndexed(value) ? value : IndexedSeq(value);
52114
}
53115

@@ -74,12 +136,14 @@ export class IndexedCollectionImpl<T>
74136
declare [Symbol.iterator]: () => IterableIterator<T>;
75137
}
76138

77-
export function SetCollection(value) {
139+
export function SetCollection<T>(
140+
value: Iterable<T> | ArrayLike<T>
141+
): SetCollectionImpl<T> {
78142
return isCollection(value) && !isAssociative(value) ? value : SetSeq(value);
79143
}
80144

81145
export class SetCollectionImpl<T> extends CollectionImpl<T, T> {}
82146

83-
Collection.Keyed = Keyed;
147+
Collection.Keyed = KeyedCollection;
84148
Collection.Indexed = IndexedCollection;
85149
Collection.Set = SetCollection;

src/CollectionImpl.js

Lines changed: 8 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,9 @@ import {
55
KeyedCollectionImpl,
66
SetCollectionImpl,
77
} from './Collection';
8-
import { hash } from './Hash';
9-
import {
10-
ITERATE_ENTRIES,
11-
ITERATE_KEYS,
12-
ITERATE_VALUES,
13-
Iterator,
14-
} from './Iterator';
8+
import { ITERATE_KEYS, ITERATE_VALUES, Iterator } from './Iterator';
159
import { List } from './List';
1610
import { Map } from './Map';
17-
import { imul, smi } from './Math';
1811
import {
1912
concatFactory,
2013
countByFactory,
@@ -65,10 +58,9 @@ import { toObject } from './methods/toObject';
6558
import { IS_COLLECTION_SYMBOL } from './predicates/isCollection';
6659
import { IS_INDEXED_SYMBOL, isIndexed } from './predicates/isIndexed';
6760
import { IS_KEYED_SYMBOL, isKeyed } from './predicates/isKeyed';
68-
import { IS_ORDERED_SYMBOL, isOrdered } from './predicates/isOrdered';
61+
import { IS_ORDERED_SYMBOL } from './predicates/isOrdered';
6962
import { toJS } from './toJS';
7063
import assertNotInfinite from './utils/assertNotInfinite';
71-
import deepEqual from './utils/deepEqual';
7264
import mixin from './utils/mixin';
7365
import quoteString from './utils/quoteString';
7466

@@ -176,22 +168,6 @@ mixin(CollectionImpl, {
176168
return this.some((value) => is(value, searchValue));
177169
},
178170

179-
entries() {
180-
return this.__iterator(ITERATE_ENTRIES);
181-
},
182-
183-
every(predicate, context) {
184-
assertNotInfinite(this.size);
185-
let returnValue = true;
186-
this.__iterate((v, k, c) => {
187-
if (!predicate.call(context, v, k, c)) {
188-
returnValue = false;
189-
return false;
190-
}
191-
});
192-
return returnValue;
193-
},
194-
195171
filter(predicate, context) {
196172
return reify(this, filterFactory(this, predicate, context, true));
197173
},
@@ -301,9 +277,9 @@ mixin(CollectionImpl, {
301277
return countByFactory(this, grouper, context);
302278
},
303279

304-
equals(other) {
305-
return deepEqual(this, other);
306-
},
280+
// equals(other) {
281+
// return deepEqual(this, other);
282+
// },
307283

308284
entrySeq() {
309285
// eslint-disable-next-line @typescript-eslint/no-this-alias
@@ -482,9 +458,9 @@ mixin(CollectionImpl, {
482458

483459
// ### Hashable Object
484460

485-
hashCode() {
486-
return this.__hash || (this.__hash = hashCollection(this));
487-
},
461+
// hashCode() {
462+
// return this.__hash || (this.__hash = hashCollection(this));
463+
// },
488464

489465
// ### Internal
490466

@@ -755,47 +731,3 @@ function defaultZipper(...values) {
755731
function defaultNegComparator(a, b) {
756732
return a < b ? 1 : a > b ? -1 : 0;
757733
}
758-
759-
function hashCollection(collection) {
760-
if (collection.size === Infinity) {
761-
return 0;
762-
}
763-
const ordered = isOrdered(collection);
764-
const keyed = isKeyed(collection);
765-
let h = ordered ? 1 : 0;
766-
767-
collection.__iterate(
768-
keyed
769-
? ordered
770-
? (v, k) => {
771-
h = (31 * h + hashMerge(hash(v), hash(k))) | 0;
772-
}
773-
: (v, k) => {
774-
h = (h + hashMerge(hash(v), hash(k))) | 0;
775-
}
776-
: ordered
777-
? (v) => {
778-
h = (31 * h + hash(v)) | 0;
779-
}
780-
: (v) => {
781-
h = (h + hash(v)) | 0;
782-
}
783-
);
784-
785-
return murmurHashOfSize(collection.size, h);
786-
}
787-
788-
function murmurHashOfSize(size, h) {
789-
h = imul(h, 0xcc9e2d51);
790-
h = imul((h << 15) | (h >>> -15), 0x1b873593);
791-
h = imul((h << 13) | (h >>> -13), 5);
792-
h = ((h + 0xe6546b64) | 0) ^ size;
793-
h = imul(h ^ (h >>> 16), 0x85ebca6b);
794-
h = imul(h ^ (h >>> 13), 0xc2b2ae35);
795-
h = smi(h ^ (h >>> 16));
796-
return h;
797-
}
798-
799-
function hashMerge(a, b) {
800-
return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; // int
801-
}

src/Iterator.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ export function iteratorValue<K, V>(
6868
const value = getValueFromType(type, k, v);
6969
// type === ITERATE_KEYS ? k : type === ITERATE_VALUES ? v : [k, v];
7070

71-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
72-
7371
if (iteratorResult) {
7472
iteratorResult.value = value;
7573

src/Range.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export class RangeImpl extends IndexedSeqImpl implements Seq.Indexed<number> {
115115
}
116116

117117
override __iterate(
118-
fn: (value: number, index: number, iter: this) => boolean,
118+
fn: (value: number, index: number, iter: this) => boolean | void,
119119
reverse: boolean = false
120120
): number {
121121
const size = this.size;
@@ -149,7 +149,7 @@ export class RangeImpl extends IndexedSeqImpl implements Seq.Indexed<number> {
149149
});
150150
}
151151

152-
equals(other: unknown): boolean {
152+
override equals(other: unknown): boolean {
153153
return other instanceof RangeImpl
154154
? this._start === other._start &&
155155
this._end === other._end &&

src/TrieUtils.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,10 @@ export function SetRef(ref: Ref): void {
3131
export function OwnerID() {}
3232

3333
export function ensureSize(iter: CollectionImpl<unknown, unknown>): number {
34-
// @ts-expect-error size should exists on Collection
3534
if (iter.size === undefined) {
36-
// @ts-expect-error size should exists on Collection, __iterate does exist on Collection
3735
iter.size = iter.__iterate(returnTrue);
3836
}
39-
// @ts-expect-error size should exists on Collection
37+
4038
return iter.size;
4139
}
4240

src/predicates/isAssociative.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Collection } from '../../type-definitions/immutable';
1+
import type { IndexedCollectionImpl, KeyedCollectionImpl } from '../Collection';
22
import { isIndexed } from './isIndexed';
33
import { isKeyed } from './isKeyed';
44

@@ -19,7 +19,7 @@ import { isKeyed } from './isKeyed';
1919
export function isAssociative(
2020
maybeAssociative: unknown
2121
): maybeAssociative is
22-
| Collection.Keyed<unknown, unknown>
23-
| Collection.Indexed<unknown> {
22+
| KeyedCollectionImpl<unknown, unknown>
23+
| IndexedCollectionImpl<unknown> {
2424
return isKeyed(maybeAssociative) || isIndexed(maybeAssociative);
2525
}

src/predicates/isCollection.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Collection } from '../../type-definitions/immutable';
1+
import type { CollectionImpl } from '../Collection';
22

33
// Note: value is unchanged to not break immutable-devtools.
44
export const IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@';
@@ -18,7 +18,7 @@ export const IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@';
1818
*/
1919
export function isCollection(
2020
maybeCollection: unknown
21-
): maybeCollection is Collection<unknown, unknown> {
21+
): maybeCollection is CollectionImpl<unknown, unknown> {
2222
return Boolean(
2323
maybeCollection &&
2424
// @ts-expect-error: maybeCollection is typed as `{}`, need to change in 6.0 to `maybeCollection && typeof maybeCollection === 'object' && IS_COLLECTION_SYMBOL in maybeCollection`

src/predicates/isIndexed.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Collection } from '../../type-definitions/immutable';
1+
import type { IndexedCollectionImpl } from '../Collection';
22

33
export const IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@';
44

@@ -18,7 +18,7 @@ export const IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@';
1818
*/
1919
export function isIndexed(
2020
maybeIndexed: unknown
21-
): maybeIndexed is Collection.Indexed<unknown> {
21+
): maybeIndexed is IndexedCollectionImpl<unknown> {
2222
return Boolean(
2323
maybeIndexed &&
2424
// @ts-expect-error: maybeIndexed is typed as `{}`, need to change in 6.0 to `maybeIndexed && typeof maybeIndexed === 'object' && IS_INDEXED_SYMBOL in maybeIndexed`

src/predicates/isKeyed.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Collection } from '../../type-definitions/immutable';
1+
import type { KeyedCollectionImpl } from '../Collection';
22

33
export const IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@';
44

@@ -17,7 +17,7 @@ export const IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@';
1717
*/
1818
export function isKeyed(
1919
maybeKeyed: unknown
20-
): maybeKeyed is Collection.Keyed<unknown, unknown> {
20+
): maybeKeyed is KeyedCollectionImpl<unknown, unknown> {
2121
return Boolean(
2222
maybeKeyed &&
2323
// @ts-expect-error: maybeKeyed is typed as `{}`, need to change in 6.0 to `maybeKeyed && typeof maybeKeyed === 'object' && IS_KEYED_SYMBOL in maybeKeyed`

src/predicates/isOrdered.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ export const IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@';
2020
export function isOrdered<I>(
2121
maybeOrdered: Iterable<I>
2222
): maybeOrdered is OrderedCollection<I>;
23+
export function isOrdered(
24+
maybeOrdered: unknown
25+
): maybeOrdered is OrderedCollection<unknown>;
2326
export function isOrdered(
2427
maybeOrdered: unknown
2528
): maybeOrdered is OrderedCollection<unknown> {

0 commit comments

Comments
 (0)