UNPKG

2.8 kBJavaScriptView Raw
1/**
2 * Common functions and function call helpers.
3 *
4 * @module function
5 */
6
7import * as array from './array.js'
8import * as object from './object.js'
9
10/**
11 * Calls all functions in `fs` with args. Only throws after all functions were called.
12 *
13 * @param {Array<function>} fs
14 * @param {Array<any>} args
15 */
16export const callAll = (fs, args, i = 0) => {
17 try {
18 for (; i < fs.length; i++) {
19 fs[i](...args)
20 }
21 } finally {
22 if (i < fs.length) {
23 callAll(fs, args, i + 1)
24 }
25 }
26}
27
28export const nop = () => {}
29
30/**
31 * @template T
32 * @param {function():T} f
33 * @return {T}
34 */
35export const apply = f => f()
36
37/**
38 * @template A
39 *
40 * @param {A} a
41 * @return {A}
42 */
43export const id = a => a
44
45/**
46 * @template T
47 *
48 * @param {T} a
49 * @param {T} b
50 * @return {boolean}
51 */
52export const equalityStrict = (a, b) => a === b
53
54/**
55 * @template T
56 *
57 * @param {Array<T>|object} a
58 * @param {Array<T>|object} b
59 * @return {boolean}
60 */
61export const equalityFlat = (a, b) => a === b || (a != null && b != null && a.constructor === b.constructor && ((a instanceof Array && array.equalFlat(a, /** @type {Array<T>} */ (b))) || (typeof a === 'object' && object.equalFlat(a, b))))
62
63/**
64 * @param {any} a
65 * @param {any} b
66 * @return {boolean}
67 */
68export const equalityDeep = (a, b) => {
69 if (a == null || b == null) {
70 return equalityStrict(a, b)
71 }
72 if (a.constructor !== b.constructor) {
73 return false
74 }
75 if (a === b) {
76 return true
77 }
78 switch (a.constructor) {
79 case ArrayBuffer:
80 a = new Uint8Array(a)
81 b = new Uint8Array(b)
82 // eslint-disable-next-line no-fallthrough
83 case Uint8Array: {
84 if (a.byteLength !== b.byteLength) {
85 return false
86 }
87 for (let i = 0; i < a.length; i++) {
88 if (a[i] !== b[i]) {
89 return false
90 }
91 }
92 break
93 }
94 case Set: {
95 if (a.size !== b.size) {
96 return false
97 }
98 for (const value of a) {
99 if (!b.has(value)) {
100 return false
101 }
102 }
103 break
104 }
105 case Map: {
106 if (a.size !== b.size) {
107 return false
108 }
109 for (const key of a.keys()) {
110 if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
111 return false
112 }
113 }
114 break
115 }
116 case Object:
117 if (object.length(a) !== object.length(b)) {
118 return false
119 }
120 for (const key in a) {
121 if (!object.hasProperty(a, key) || !equalityDeep(a[key], b[key])) {
122 return false
123 }
124 }
125 break
126 case Array:
127 if (a.length !== b.length) {
128 return false
129 }
130 for (let i = 0; i < a.length; i++) {
131 if (!equalityDeep(a[i], b[i])) {
132 return false
133 }
134 }
135 break
136 default:
137 return false
138 }
139 return true
140}