GeezerVison is showing github.com — assert,util: improve array comparison · nodejs/node@5f9cc5e
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: benchmark/assert/deepequal-simple-array-and-set.js +20-6Lines changed: 20 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -11,6 +11,8 @@ const bench = common.createBenchmark(main, { | 11 | 11 | method: [ | 12 | 12 | 'deepEqual_Array', | 13 | 13 | 'notDeepEqual_Array', | | 14 | + 'deepEqual_sparseArray', | | 15 | + 'notDeepEqual_sparseArray', | 14 | 16 | 'deepEqual_Set', | 15 | 17 | 'notDeepEqual_Set', | 16 | 18 | ], | @@ -25,18 +27,30 @@ function run(fn, n, actual, expected) { | 25 | 27 | } | 26 | 28 |
| 27 | 29 | function main({ n, len, method, strict }) { | 28 | | - const actual = []; | 29 | | - const expected = []; | | 30 | + let actual = Array.from({ length: len }, (_, i) => i); | | 31 | + // Contain one undefined value to trigger a specific code path | | 32 | + actual[0] = undefined; | | 33 | + let expected = actual.slice(0); | 30 | 34 |
| 31 | | - for (let i = 0; i < len; i++) { | 32 | | - actual.push(i); | 33 | | - expected.push(i); | 34 | | - } | 35 | 35 | if (method.includes('not')) { | 36 | 36 | expected[len - 1] += 1; | 37 | 37 | } | 38 | 38 |
| 39 | 39 | switch (method) { | | 40 | + case 'deepEqual_sparseArray': | | 41 | + case 'notDeepEqual_sparseArray': | | 42 | + actual = new Array(len); | | 43 | + for (let i = 0; i < len; i += 2) { | | 44 | + actual[i] = i; | | 45 | + } | | 46 | + expected = actual.slice(0); | | 47 | + if (method.includes('not')) { | | 48 | + expected[len - 2] += 1; | | 49 | + run(strict ? notDeepStrictEqual : notDeepEqual, n, actual, expected); | | 50 | + } else { | | 51 | + run(strict ? deepStrictEqual : deepEqual, n, actual, expected); | | 52 | + } | | 53 | + break; | 40 | 54 | case 'deepEqual_Array': | 41 | 55 | run(strict ? deepStrictEqual : deepEqual, n, actual, expected); | 42 | 56 | break; | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/assert/myers_diff.js +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -29,6 +29,7 @@ function myersDiff(actual, expected, checkCommaDisparity = false) { | 29 | 29 | const actualLength = actual.length; | 30 | 30 | const expectedLength = expected.length; | 31 | 31 | const max = actualLength + expectedLength; | | 32 | + // TODO(BridgeAR): Cap the input in case the values go beyond the limit of 2^31 - 1. | 32 | 33 | const v = new Int32Array(2 * max + 1); | 33 | 34 | const trace = []; | 34 | 35 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/util/comparisons.js +13-20Lines changed: 13 additions & 20 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -196,11 +196,9 @@ function innerDeepEqual(val1, val2, mode, memos) { | 196 | 196 | } | 197 | 197 | } else { | 198 | 198 | if (val1 === null || typeof val1 !== 'object') { | 199 | | - if (val2 === null || typeof val2 !== 'object') { | 200 | | - // eslint-disable-next-line eqeqeq | 201 | | - return val1 == val2 || (NumberIsNaN(val1) && NumberIsNaN(val2)); | 202 | | - } | 203 | | - return false; | | 199 | + return (val2 === null || typeof val2 !== 'object') && | | 200 | + // eslint-disable-next-line eqeqeq | | 201 | + (val1 == val2 || (NumberIsNaN(val1) && NumberIsNaN(val2))); | 204 | 202 | } | 205 | 203 | if (val2 === null || typeof val2 !== 'object') { | 206 | 204 | return false; | @@ -384,9 +382,7 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) { | 384 | 382 | } | 385 | 383 | } else if (keys2.length !== ObjectKeys(val1).length) { | 386 | 384 | return false; | 387 | | - } | 388 | | - | 389 | | - if (mode === kStrict) { | | 385 | + } else if (mode === kStrict) { | 390 | 386 | const symbolKeysA = getOwnSymbols(val1); | 391 | 387 | if (symbolKeysA.length !== 0) { | 392 | 388 | let count = 0; | @@ -761,9 +757,9 @@ function sparseArrayEquiv(a, b, mode, memos, i) { | 761 | 757 | if (keysA.length !== keysB.length) { | 762 | 758 | return false; | 763 | 759 | } | 764 | | - for (; i < keysA.length; i++) { | 765 | | - const key = keysA[i]; | 766 | | - if (!hasOwn(b, key) || !innerDeepEqual(a[key], b[key], mode, memos)) { | | 760 | + for (; i < keysB.length; i++) { | | 761 | + const key = keysB[i]; | | 762 | + if ((a[key] === undefined && !hasOwn(a, key)) || !innerDeepEqual(a[key], b[key], mode, memos)) { | 767 | 763 | return false; | 768 | 764 | } | 769 | 765 | } | @@ -785,17 +781,14 @@ function objEquiv(a, b, mode, keys2, memos, iterationType) { | 785 | 781 | return partialArrayEquiv(a, b, mode, memos); | 786 | 782 | } | 787 | 783 | for (let i = 0; i < a.length; i++) { | 788 | | - if (!innerDeepEqual(a[i], b[i], mode, memos)) { | 789 | | - return false; | 790 | | - } | 791 | | - const isSparseA = a[i] === undefined && !hasOwn(a, i); | 792 | | - const isSparseB = b[i] === undefined && !hasOwn(b, i); | 793 | | - if (isSparseA !== isSparseB) { | | 784 | + if (b[i] === undefined) { | | 785 | + if (!hasOwn(b, i)) | | 786 | + return sparseArrayEquiv(a, b, mode, memos, i); | | 787 | + if (a[i] !== undefined || !hasOwn(a, i)) | | 788 | + return false; | | 789 | + } else if (a[i] === undefined || !innerDeepEqual(a[i], b[i], mode, memos)) { | 794 | 790 | return false; | 795 | 791 | } | 796 | | - if (isSparseA) { | 797 | | - return sparseArrayEquiv(a, b, mode, memos, i); | 798 | | - } | 799 | 792 | } | 800 | 793 | } else if (iterationType === kIsSet) { | 801 | 794 | if (!setEquiv(a, b, mode, memos)) { | |
|