@longlast/equals 0.5.3 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +17 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,6 +3,8 @@
3
3
  */
4
4
  import { curry } from "@longlast/curry";
5
5
  import { $boundArguments, $equals, $getBoundArguments, $unapplied, } from "@longlast/symbols";
6
+ // TODO: export an `Equatable` interface that classes with the [$equals] method
7
+ // can implement.
6
8
  /**
7
9
  * @function
8
10
  * Deeply compares two values, returning true if they're equal and false
@@ -65,6 +67,11 @@ export const equals = curry(_equals);
65
67
  function _equals(a, b) {
66
68
  // This is an optimized implementation. There is a simpler, equivalent one
67
69
  // in pkg/equals/alt/reference.ts.
70
+ // TODO: (pre-1.0.0) decide if we should pass `equals` as the second
71
+ // argument to [$equals]. This would open the "protocol" up a bit more,
72
+ // since people could then define their own implementations of `equals`
73
+ // that work consistently through custom equality comparisons.
74
+ // TODO: Compare cross-realm objects.
68
75
  if (a != null && typeof a[$equals] === "function") {
69
76
  return Boolean(a[$equals](b));
70
77
  }
@@ -78,8 +85,7 @@ function _equals(a, b) {
78
85
  return String(a) === String(b);
79
86
  }
80
87
  if (a instanceof Error && b instanceof Error) {
81
- return (a.message === b.message &&
82
- Object.getPrototypeOf(a) === Object.getPrototypeOf(b));
88
+ return a.message === b.message && protoOf(a) === protoOf(b);
83
89
  }
84
90
  if (Array.isArray(a) && Array.isArray(b)) {
85
91
  return a.length === b.length && a.every((_, i) => _equals(a[i], b[i]));
@@ -95,9 +101,14 @@ function _equals(a, b) {
95
101
  _equals(getBoundArguments(a), getBoundArguments(b)));
96
102
  }
97
103
  if (a && b && typeof a === "object" && protoOf(a) === protoOf(b)) {
98
- const bKeys = new Set(Object.keys(b));
99
- for (const key of Object.keys(a)) {
100
- if (!bKeys.has(key)) {
104
+ const aKeys = Object.keys(a);
105
+ const bKeys = Object.keys(b);
106
+ if (aKeys.length !== bKeys.length) {
107
+ return false;
108
+ }
109
+ const bKeySet = new Set(bKeys);
110
+ for (const key of aKeys) {
111
+ if (!bKeySet.has(key)) {
101
112
  return false;
102
113
  }
103
114
  if (!_equals(a[key], b[key])) {
@@ -109,6 +120,7 @@ function _equals(a, b) {
109
120
  return false;
110
121
  }
111
122
  function getBoundArguments(f) {
123
+ // TODO: (pre-1.0.0) remove `f[$boundArguments]` fallback.
112
124
  return f[$getBoundArguments]?.() ?? f[$boundArguments];
113
125
  }
114
126
  const protoOf = Object.getPrototypeOf;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longlast/equals",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Deeply compares objects",
5
5
  "homepage": "https://longlast.js.org/",
6
6
  "license": "MIT",