Skip to content

Commit 4cde1da

Browse files
authored
Merge pull request #2131 from immutable-js/extract-collection-impl-helpers
2 parents 5f04bd0 + d613de2 commit 4cde1da

File tree

3 files changed

+114
-85
lines changed

3 files changed

+114
-85
lines changed

src/CollectionHelperMethods.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { Collection } from '../type-definitions/immutable';
2+
import assertNotInfinite from './utils/assertNotInfinite';
3+
4+
export function reduce(
5+
collection: Collection<unknown, unknown>,
6+
reducer: (...args: unknown[]) => unknown,
7+
reduction: unknown,
8+
context: unknown,
9+
useFirst: boolean,
10+
reverse: boolean
11+
) {
12+
// @ts-expect-error Migrate to CollectionImpl in v6
13+
assertNotInfinite(collection.size);
14+
// @ts-expect-error Migrate to CollectionImpl in v6
15+
collection.__iterate((v, k, c) => {
16+
if (useFirst) {
17+
useFirst = false;
18+
reduction = v;
19+
} else {
20+
reduction = reducer.call(context, reduction, v, k, c);
21+
}
22+
}, reverse);
23+
return reduction;
24+
}
25+
26+
export function keyMapper<K, V>(v: V, k: K): K {
27+
return k;
28+
}
29+
30+
export function entryMapper<K, V>(v: V, k: K): [K, V] {
31+
return [k, v];
32+
}
33+
34+
export function not(predicate: (...args: unknown[]) => boolean) {
35+
return function (this: unknown, ...args: unknown[]): boolean {
36+
return !predicate.apply(this, args);
37+
};
38+
}
39+
40+
export function neg(predicate: (...args: unknown[]) => number) {
41+
return function (this: unknown, ...args: unknown[]): number {
42+
return -predicate.apply(this, args);
43+
};
44+
}
45+
46+
export function defaultNegComparator(
47+
a: number | string,
48+
b: number | string
49+
): number {
50+
return a < b ? 1 : a > b ? -1 : 0;
51+
}

src/CollectionImpl.js

Lines changed: 11 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,23 @@ import {
44
KeyedCollection,
55
SetCollection,
66
} from './Collection';
7-
import { hash } from './Hash';
7+
import {
8+
defaultNegComparator,
9+
entryMapper,
10+
keyMapper,
11+
neg,
12+
not,
13+
reduce,
14+
} from './CollectionHelperMethods';
815
import {
916
ITERATE_ENTRIES,
1017
ITERATE_KEYS,
1118
ITERATE_VALUES,
12-
ITERATOR_SYMBOL,
1319
Iterator,
20+
ITERATOR_SYMBOL,
1421
} from './Iterator';
1522
import { List } from './List';
1623
import { Map } from './Map';
17-
import { imul, smi } from './Math';
1824
import {
1925
FromEntriesSequence,
2026
ToIndexedSequence,
@@ -59,11 +65,12 @@ import { toObject } from './methods/toObject';
5965
import { IS_COLLECTION_SYMBOL } from './predicates/isCollection';
6066
import { isIndexed, IS_INDEXED_SYMBOL } from './predicates/isIndexed';
6167
import { isKeyed, IS_KEYED_SYMBOL } from './predicates/isKeyed';
62-
import { isOrdered, IS_ORDERED_SYMBOL } from './predicates/isOrdered';
68+
import { IS_ORDERED_SYMBOL } from './predicates/isOrdered';
6369
import { toJS } from './toJS';
6470
import arrCopy from './utils/arrCopy';
6571
import assertNotInfinite from './utils/assertNotInfinite';
6672
import deepEqual from './utils/deepEqual';
73+
import { hashCollection } from './utils/hasCollection';
6774
import mixin from './utils/mixin';
6875
import quoteString from './utils/quoteString';
6976

@@ -701,87 +708,6 @@ mixin(SetSeq, SetCollectionPrototype);
701708

702709
// #pragma Helper functions
703710

704-
function reduce(collection, reducer, reduction, context, useFirst, reverse) {
705-
assertNotInfinite(collection.size);
706-
collection.__iterate((v, k, c) => {
707-
if (useFirst) {
708-
useFirst = false;
709-
reduction = v;
710-
} else {
711-
reduction = reducer.call(context, reduction, v, k, c);
712-
}
713-
}, reverse);
714-
return reduction;
715-
}
716-
717-
function keyMapper(v, k) {
718-
return k;
719-
}
720-
721-
function entryMapper(v, k) {
722-
return [k, v];
723-
}
724-
725-
function not(predicate) {
726-
return function () {
727-
return !predicate.apply(this, arguments);
728-
};
729-
}
730-
731-
function neg(predicate) {
732-
return function () {
733-
return -predicate.apply(this, arguments);
734-
};
735-
}
736-
737711
function defaultZipper() {
738712
return arrCopy(arguments);
739713
}
740-
741-
function defaultNegComparator(a, b) {
742-
return a < b ? 1 : a > b ? -1 : 0;
743-
}
744-
745-
function hashCollection(collection) {
746-
if (collection.size === Infinity) {
747-
return 0;
748-
}
749-
const ordered = isOrdered(collection);
750-
const keyed = isKeyed(collection);
751-
let h = ordered ? 1 : 0;
752-
753-
collection.__iterate(
754-
keyed
755-
? ordered
756-
? (v, k) => {
757-
h = (31 * h + hashMerge(hash(v), hash(k))) | 0;
758-
}
759-
: (v, k) => {
760-
h = (h + hashMerge(hash(v), hash(k))) | 0;
761-
}
762-
: ordered
763-
? (v) => {
764-
h = (31 * h + hash(v)) | 0;
765-
}
766-
: (v) => {
767-
h = (h + hash(v)) | 0;
768-
}
769-
);
770-
771-
return murmurHashOfSize(collection.size, h);
772-
}
773-
774-
function murmurHashOfSize(size, h) {
775-
h = imul(h, 0xcc9e2d51);
776-
h = imul((h << 15) | (h >>> -15), 0x1b873593);
777-
h = imul((h << 13) | (h >>> -13), 5);
778-
h = ((h + 0xe6546b64) | 0) ^ size;
779-
h = imul(h ^ (h >>> 16), 0x85ebca6b);
780-
h = imul(h ^ (h >>> 13), 0xc2b2ae35);
781-
h = smi(h ^ (h >>> 16));
782-
return h;
783-
}
784-
785-
function hashMerge(a, b) {
786-
return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; // int
787-
}

src/utils/hasCollection.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import type { Collection } from '../../type-definitions/immutable';
2+
import { hash } from '../Hash';
3+
import { imul, smi } from '../Math';
4+
import { isKeyed } from '../predicates/isKeyed';
5+
import { isOrdered } from '../predicates/isOrdered';
6+
7+
export function hashCollection<K, V>(collection: Collection<K, V>): number {
8+
// @ts-expect-error Migrate to CollectionImpl in v6
9+
if (collection.size === Infinity) {
10+
return 0;
11+
}
12+
const ordered = isOrdered(collection);
13+
const keyed = isKeyed(collection);
14+
let h: number = ordered ? 1 : 0;
15+
16+
// @ts-expect-error Migrate to CollectionImpl in v6
17+
collection.__iterate(
18+
keyed
19+
? ordered
20+
? (v: V, k: K): void => {
21+
h = (31 * h + hashMerge(hash(v), hash(k))) | 0;
22+
}
23+
: (v: V, k: K): void => {
24+
h = (h + hashMerge(hash(v), hash(k))) | 0;
25+
}
26+
: ordered
27+
? (v: V): void => {
28+
h = (31 * h + hash(v)) | 0;
29+
}
30+
: (v: V): void => {
31+
h = (h + hash(v)) | 0;
32+
}
33+
);
34+
35+
// @ts-expect-error Migrate to CollectionImpl in v6
36+
return murmurHashOfSize(collection.size, h);
37+
}
38+
39+
function murmurHashOfSize(size: number, h: number): number {
40+
h = imul(h, 0xcc9e2d51);
41+
h = imul((h << 15) | (h >>> -15), 0x1b873593);
42+
h = imul((h << 13) | (h >>> -13), 5);
43+
h = ((h + 0xe6546b64) | 0) ^ size;
44+
h = imul(h ^ (h >>> 16), 0x85ebca6b);
45+
h = imul(h ^ (h >>> 13), 0xc2b2ae35);
46+
h = smi(h ^ (h >>> 16));
47+
return h;
48+
}
49+
50+
function hashMerge(a: number, b: number): number {
51+
return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; // int
52+
}

0 commit comments

Comments
 (0)