1/** 2 * Common functions and function call helpers. 3 * 4 * @module function 5 */ 6 7import * as array from 'lib0/array' 8import * as object from 'lib0/object' 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 && ((array.isArray(a) && array.equalFlat(a, /** @type {Array<T>} */ (b))) || (typeof a === 'object' && object.equalFlat(a, b)))) 62 63/* c8 ignore start */ 64 65/** 66 * @param {any} a 67 * @param {any} b 68 * @return {boolean} 69 */ 70export const equalityDeep = (a, b) => { 71 if (a == null || b == null) { 72 return equalityStrict(a, b) 73 } 74 if (a.constructor !== b.constructor) { 75 return false 76 } 77 if (a === b) { 78 return true 79 } 80 switch (a.constructor) { 81 case ArrayBuffer: 82 a = new Uint8Array(a) 83 b = new Uint8Array(b) 84 // eslint-disable-next-line no-fallthrough 85 case Uint8Array: { 86 if (a.byteLength !== b.byteLength) { 87 return false 88 } 89 for (let i = 0; i < a.length; i++) { 90 if (a[i] !== b[i]) { 91 return false 92 } 93 } 94 break 95 } 96 case Set: { 97 if (a.size !== b.size) { 98 return false 99 } 100 for (const value of a) { 101 if (!b.has(value)) { 102 return false 103 } 104 } 105 break 106 } 107 case Map: { 108 if (a.size !== b.size) { 109 return false 110 } 111 for (const key of a.keys()) { 112 if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) { 113 return false 114 } 115 } 116 break 117 } 118 case Object: 119 if (object.length(a) !== object.length(b)) { 120 return false 121 } 122 for (const key in a) { 123 if (!object.hasProperty(a, key) || !equalityDeep(a[key], b[key])) { 124 return false 125 } 126 } 127 break 128 case Array: 129 if (a.length !== b.length) { 130 return false 131 } 132 for (let i = 0; i < a.length; i++) { 133 if (!equalityDeep(a[i], b[i])) { 134 return false 135 } 136 } 137 break 138 default: 139 return false 140 } 141 return true 142} 143 144/** 145 * @template V 146 * @template {V} OPTS 147 * 148 * @param {V} value 149 * @param {Array<OPTS>} options 150 */ 151// @ts-ignore 152export const isOneOf = (value, options) => options.includes(value) 153/* c8 ignore stop */ 154 155export const isArray = array.isArray 156 157/** 158 * @param {any} s 159 * @return {s is String} 160 */ 161export const isString = (s) => s && s.constructor === String 162 163/** 164 * @param {any} n 165 * @return {n is Number} 166 */ 167export const isNumber = n => n != null && n.constructor === Number 168 169/** 170 * @template {abstract new (...args: any) => any} TYPE 171 * @param {any} n 172 * @param {TYPE} T 173 * @return {n is InstanceType<TYPE>} 174 */ 175export const is = (n, T) => n && n.constructor === T 176 177/** 178 * @template {abstract new (...args: any) => any} TYPE 179 * @param {TYPE} T 180 */ 181export const isTemplate = (T) => 182 /** 183 * @param {any} n 184 * @return {n is InstanceType<TYPE>} 185 **/ 186 n => n && n.constructor === T
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.