diff options
author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2023-12-18 23:41:23 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-19 04:41:23 +0000 |
commit | 6b07b1e6e158f718fd30c44878a72c3b6ad83fa0 (patch) | |
tree | 0b95307e82416ff154c412b42c8eeaa033dac24f /ext/js/core.js | |
parent | 1d268edcc3efce723954bcaa7dd376f0352c1a32 (diff) |
IIFE updates (#384)
* Remove most IIFEs
* Move IIFEs into functions
* Don't await background-main
Diffstat (limited to 'ext/js/core.js')
-rw-r--r-- | ext/js/core.js | 298 |
1 files changed, 139 insertions, 159 deletions
diff --git a/ext/js/core.js b/ext/js/core.js index 5c0c964b..c95eae01 100644 --- a/ext/js/core.js +++ b/ext/js/core.js @@ -53,101 +53,91 @@ export function stringReverse(string) { * @returns {T} A new clone of the value. * @throws An error if the value is circular and cannot be cloned. */ -export const clone = (() => { - /** - * @template T - * @param {T} value - * @returns {T} - */ - // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow - function clone(value) { - if (value === null) { return /** @type {T} */ (null); } - switch (typeof value) { - case 'boolean': - case 'number': - case 'string': - case 'bigint': - case 'symbol': - case 'undefined': - return value; - default: - return cloneInternal(value, new Set()); - } +export function clone(value) { + if (value === null) { return /** @type {T} */ (null); } + switch (typeof value) { + case 'boolean': + case 'number': + case 'string': + case 'bigint': + case 'symbol': + case 'undefined': + return value; + default: + return cloneInternal(value, new Set()); } +} - /** - * @template [T=unknown] - * @param {T} value - * @param {Set<unknown>} visited - * @returns {T} - * @throws {Error} - */ - function cloneInternal(value, visited) { - if (value === null) { return /** @type {T} */ (null); } - switch (typeof value) { - case 'boolean': - case 'number': - case 'string': - case 'bigint': - case 'symbol': - case 'undefined': - return value; - case 'object': - return /** @type {T} */ ( +/** + * @template [T=unknown] + * @param {T} value + * @param {Set<unknown>} visited + * @returns {T} + * @throws {Error} + */ +function cloneInternal(value, visited) { + if (value === null) { return /** @type {T} */ (null); } + switch (typeof value) { + case 'boolean': + case 'number': + case 'string': + case 'bigint': + case 'symbol': + case 'undefined': + return value; + case 'object': + return /** @type {T} */ ( Array.isArray(value) ? cloneArray(value, visited) : cloneObject(/** @type {import('core').SerializableObject} */ (value), visited) - ); - default: - throw new Error(`Cannot clone object of type ${typeof value}`); - } + ); + default: + throw new Error(`Cannot clone object of type ${typeof value}`); } +} - /** - * @param {unknown[]} value - * @param {Set<unknown>} visited - * @returns {unknown[]} - * @throws {Error} - */ - function cloneArray(value, visited) { - if (visited.has(value)) { throw new Error('Circular'); } - try { - visited.add(value); - const result = []; - for (const item of value) { - result.push(cloneInternal(item, visited)); - } - return result; - } finally { - visited.delete(value); +/** + * @param {unknown[]} value + * @param {Set<unknown>} visited + * @returns {unknown[]} + * @throws {Error} + */ +function cloneArray(value, visited) { + if (visited.has(value)) { throw new Error('Circular'); } + try { + visited.add(value); + const result = []; + for (const item of value) { + result.push(cloneInternal(item, visited)); } + return result; + } finally { + visited.delete(value); } +} - /** - * @param {import('core').SerializableObject} value - * @param {Set<unknown>} visited - * @returns {import('core').SerializableObject} - * @throws {Error} - */ - function cloneObject(value, visited) { - if (visited.has(value)) { throw new Error('Circular'); } - try { - visited.add(value); - /** @type {import('core').SerializableObject} */ - const result = {}; - for (const key in value) { - if (Object.prototype.hasOwnProperty.call(value, key)) { - result[key] = cloneInternal(value[key], visited); - } +/** + * @param {import('core').SerializableObject} value + * @param {Set<unknown>} visited + * @returns {import('core').SerializableObject} + * @throws {Error} + */ +function cloneObject(value, visited) { + if (visited.has(value)) { throw new Error('Circular'); } + try { + visited.add(value); + /** @type {import('core').SerializableObject} */ + const result = {}; + for (const key in value) { + if (Object.prototype.hasOwnProperty.call(value, key)) { + result[key] = cloneInternal(value[key], visited); } - return result; - } finally { - visited.delete(value); } + return result; + } finally { + visited.delete(value); } - - return clone; -})(); +} /** * Checks if an object or value is deeply equal to another object or value. @@ -155,98 +145,88 @@ export const clone = (() => { * @param {unknown} value2 The second value to check. * @returns {boolean} `true` if the values are the same object, or deeply equal without cycles. `false` otherwise. */ -export const deepEqual = (() => { - /** - * @param {unknown} value1 - * @param {unknown} value2 - * @returns {boolean} - */ - // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow - function deepEqual(value1, value2) { - if (value1 === value2) { return true; } - - const type = typeof value1; - if (typeof value2 !== type) { return false; } - - switch (type) { - case 'object': - case 'function': - return deepEqualInternal(value1, value2, new Set()); - default: - return false; - } +export function deepEqual(value1, value2) { + if (value1 === value2) { return true; } + + const type = typeof value1; + if (typeof value2 !== type) { return false; } + + switch (type) { + case 'object': + case 'function': + return deepEqualInternal(value1, value2, new Set()); + default: + return false; } +} - /** - * @param {unknown} value1 - * @param {unknown} value2 - * @param {Set<unknown>} visited1 - * @returns {boolean} - */ - function deepEqualInternal(value1, value2, visited1) { - if (value1 === value2) { return true; } - - const type = typeof value1; - if (typeof value2 !== type) { return false; } - - switch (type) { - case 'object': - case 'function': - { - if (value1 === null || value2 === null) { return false; } - const array = Array.isArray(value1); - if (array !== Array.isArray(value2)) { return false; } - if (visited1.has(value1)) { return false; } - visited1.add(value1); - return ( +/** + * @param {unknown} value1 + * @param {unknown} value2 + * @param {Set<unknown>} visited1 + * @returns {boolean} + */ +function deepEqualInternal(value1, value2, visited1) { + if (value1 === value2) { return true; } + + const type = typeof value1; + if (typeof value2 !== type) { return false; } + + switch (type) { + case 'object': + case 'function': + { + if (value1 === null || value2 === null) { return false; } + const array = Array.isArray(value1); + if (array !== Array.isArray(value2)) { return false; } + if (visited1.has(value1)) { return false; } + visited1.add(value1); + return ( array ? areArraysEqual(/** @type {unknown[]} */ (value1), /** @type {unknown[]} */ (value2), visited1) : areObjectsEqual(/** @type {import('core').UnknownObject} */ (value1), /** @type {import('core').UnknownObject} */ (value2), visited1) - ); - } - default: - return false; + ); } + default: + return false; } +} - /** - * @param {import('core').UnknownObject} value1 - * @param {import('core').UnknownObject} value2 - * @param {Set<unknown>} visited1 - * @returns {boolean} - */ - function areObjectsEqual(value1, value2, visited1) { - const keys1 = Object.keys(value1); - const keys2 = Object.keys(value2); - if (keys1.length !== keys2.length) { return false; } - - const keys1Set = new Set(keys1); - for (const key of keys2) { - if (!keys1Set.has(key) || !deepEqualInternal(value1[key], value2[key], visited1)) { return false; } - } +/** + * @param {import('core').UnknownObject} value1 + * @param {import('core').UnknownObject} value2 + * @param {Set<unknown>} visited1 + * @returns {boolean} + */ +function areObjectsEqual(value1, value2, visited1) { + const keys1 = Object.keys(value1); + const keys2 = Object.keys(value2); + if (keys1.length !== keys2.length) { return false; } - return true; + const keys1Set = new Set(keys1); + for (const key of keys2) { + if (!keys1Set.has(key) || !deepEqualInternal(value1[key], value2[key], visited1)) { return false; } } - /** - * @param {unknown[]} value1 - * @param {unknown[]} value2 - * @param {Set<unknown>} visited1 - * @returns {boolean} - */ - function areArraysEqual(value1, value2, visited1) { - const length = value1.length; - if (length !== value2.length) { return false; } + return true; +} - for (let i = 0; i < length; ++i) { - if (!deepEqualInternal(value1[i], value2[i], visited1)) { return false; } - } +/** + * @param {unknown[]} value1 + * @param {unknown[]} value2 + * @param {Set<unknown>} visited1 + * @returns {boolean} + */ +function areArraysEqual(value1, value2, visited1) { + const length = value1.length; + if (length !== value2.length) { return false; } - return true; + for (let i = 0; i < length; ++i) { + if (!deepEqualInternal(value1[i], value2[i], visited1)) { return false; } } - return deepEqual; -})(); + return true; +} /** * Creates a new base-16 (lower case) string of a sequence of random bytes of the given length. |