From b5ffd1fc57ed7872c966b4c769e267317f6f32e1 Mon Sep 17 00:00:00 2001 From: Richard Viney Date: Thu, 14 Nov 2024 08:07:07 +1300 Subject: [PATCH] Optimise dict equality check on JavaScript --- CHANGELOG.md | 2 ++ src/dict.mjs | 31 ++++++++++++++++++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99b8c83df..234df688d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ `trim_right` functions, which have been deprecated. - The `result.nil_error` function has been deprecated in favour of `result.replace_error`. +- Comparing two `Dict`s for equality has been optimised on the JavaScript + target. ## v0.41.0 - 2024-10-31 diff --git a/src/dict.mjs b/src/dict.mjs index a8309e0cd..ea0287052 100644 --- a/src/dict.mjs +++ b/src/dict.mjs @@ -792,12 +792,12 @@ function withoutCollision(root, key) { /** * @template K,V * @param {undefined | Node} root - * @param {(value:V,key:K)=>void} fn - * @returns {void} + * @param {(value:V,key:K)=>boolean|void} fn + * @returns {boolean} */ function forEach(root, fn) { if (root === undefined) { - return; + return true; } const items = root.array; const size = items.length; @@ -807,11 +807,16 @@ function forEach(root, fn) { continue; } if (item.type === ENTRY) { - fn(item.v, item.k); + if (fn(item.v, item.k) === false) { + return false; + } continue; } - forEach(item, fn); + if (forEach(item, fn) === false) { + return false; + } } + return true; } /** * Extra wrapper to keep track of Dict size and clean up the API @@ -923,15 +928,18 @@ export default class Dict { } /** @type [K,V][] */ const result = []; - this.forEach((v, k) => result.push([k, v])); + this.forEach((v, k) => { + result.push([k, v]); + }); return result; } /** * - * @param {(val:V,key:K)=>void} fn + * @param {(val:V,key:K)=>boolean|void} fn + * @returns {boolean} */ forEach(fn) { - forEach(this.root, fn); + return forEach(this.root, fn); } hashCode() { let h = 0; @@ -948,10 +956,7 @@ export default class Dict { if (!(o instanceof Dict) || this.size !== o.size) { return false; } - let equal = true; - this.forEach((v, k) => { - equal = equal && isEqual(o.get(k, !v), v); - }); - return equal; + + return this.forEach((v, k) => isEqual(o.get(k, !v), v)); } }