fast-equals 4.0.2 → 5.0.0-beta.0
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.
- package/.babelrc +34 -0
- package/.prettierrc +4 -0
- package/CHANGELOG.md +43 -0
- package/README.md +146 -40
- package/build/rollup/config.base.js +49 -0
- package/build/rollup/config.cjs.js +10 -0
- package/build/rollup/config.esm.js +10 -0
- package/build/rollup/config.min.js +13 -0
- package/build/rollup/config.umd.js +10 -0
- package/build/tsconfig/base.json +32 -0
- package/build/tsconfig/cjs.json +8 -0
- package/build/tsconfig/declarations.json +9 -0
- package/build/tsconfig/esm.json +8 -0
- package/build/tsconfig/min.json +8 -0
- package/build/tsconfig/umd.json +8 -0
- package/build/webpack.config.js +57 -0
- package/dist/cjs/index.cjs +510 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/types/comparator.d.ts +2 -0
- package/dist/cjs/types/equals.d.ts +46 -0
- package/dist/cjs/types/index.d.ts +56 -0
- package/dist/cjs/types/internalTypes.d.ts +36 -0
- package/dist/cjs/types/utils.d.ts +19 -0
- package/dist/esm/index.mjs +499 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/types/comparator.d.ts +2 -0
- package/dist/esm/types/equals.d.ts +46 -0
- package/dist/esm/types/index.d.ts +56 -0
- package/dist/esm/types/internalTypes.d.ts +36 -0
- package/dist/esm/types/utils.d.ts +19 -0
- package/dist/min/index.js +1 -0
- package/dist/min/types/comparator.d.ts +2 -0
- package/dist/min/types/equals.d.ts +46 -0
- package/dist/min/types/index.d.ts +56 -0
- package/dist/min/types/internalTypes.d.ts +36 -0
- package/dist/min/types/utils.d.ts +19 -0
- package/dist/umd/index.js +516 -0
- package/dist/umd/index.js.map +1 -0
- package/dist/umd/types/comparator.d.ts +2 -0
- package/dist/umd/types/equals.d.ts +46 -0
- package/dist/umd/types/index.d.ts +56 -0
- package/dist/umd/types/internalTypes.d.ts +36 -0
- package/dist/umd/types/utils.d.ts +19 -0
- package/package.json +62 -41
- package/recipes/explicit-property-check.md +4 -6
- package/recipes/legacy-circular-equal-support.md +28 -20
- package/recipes/legacy-regexp-support.md +15 -16
- package/recipes/non-standard-properties.md +35 -23
- package/recipes/using-meta-in-comparison.md +10 -13
- package/src/comparator.ts +50 -47
- package/src/equals.ts +263 -0
- package/src/index.ts +183 -79
- package/src/internalTypes.ts +74 -0
- package/src/utils.ts +42 -49
- package/dist/fast-equals.cjs.js +0 -434
- package/dist/fast-equals.cjs.js.map +0 -1
- package/dist/fast-equals.esm.js +0 -424
- package/dist/fast-equals.esm.js.map +0 -1
- package/dist/fast-equals.js +0 -440
- package/dist/fast-equals.js.map +0 -1
- package/dist/fast-equals.min.js +0 -1
- package/dist/fast-equals.mjs +0 -424
- package/dist/fast-equals.mjs.map +0 -1
- package/index.d.ts +0 -58
- package/recipes/strict-property-descriptor-check.md +0 -42
- package/src/arrays.ts +0 -36
- package/src/dates.ts +0 -12
- package/src/maps.ts +0 -66
- package/src/objects.ts +0 -62
- package/src/regexps.ts +0 -11
- package/src/sets.ts +0 -61
package/src/index.ts
CHANGED
|
@@ -1,121 +1,225 @@
|
|
|
1
1
|
import { createComparator } from './comparator';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
import {
|
|
3
|
+
areArraysEqual,
|
|
4
|
+
areDatesEqual,
|
|
5
|
+
areMapsEqual,
|
|
6
|
+
areObjectsEqual,
|
|
7
|
+
areObjectsEqualStrict,
|
|
8
|
+
arePrimitiveWrappersEqual,
|
|
9
|
+
areRegExpsEqual,
|
|
10
|
+
areSetsEqual,
|
|
11
|
+
} from './equals';
|
|
10
12
|
import type {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
CircularState,
|
|
14
|
+
ComparatorConfig,
|
|
15
|
+
CreateCustomComparatorConfig,
|
|
16
|
+
CreateState,
|
|
17
|
+
DefaultState,
|
|
13
18
|
EqualityComparator,
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
} from './internalTypes';
|
|
20
|
+
import {
|
|
21
|
+
combineComparators,
|
|
22
|
+
createInternalComparator,
|
|
23
|
+
createIsCircular,
|
|
24
|
+
sameValueZeroEqual,
|
|
25
|
+
} from './utils';
|
|
16
26
|
|
|
17
27
|
export { sameValueZeroEqual };
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
29
|
+
interface DefaultEqualCreatorOptions<Meta> {
|
|
30
|
+
comparator?: EqualityComparator<Meta>;
|
|
31
|
+
circular?: boolean;
|
|
32
|
+
strict?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface CustomEqualCreatorOptions<Meta>
|
|
36
|
+
extends DefaultEqualCreatorOptions<Meta> {
|
|
37
|
+
createCustomConfig?: CreateCustomComparatorConfig<Meta>;
|
|
38
|
+
createInternalComparator?: typeof createInternalComparator;
|
|
39
|
+
createState?: CreateState<Meta>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function createComparatorConfig<Meta>({
|
|
43
|
+
circular,
|
|
44
|
+
strict,
|
|
45
|
+
}: DefaultEqualCreatorOptions<Meta>) {
|
|
46
|
+
const config: ComparatorConfig<Meta> = {
|
|
21
47
|
areArraysEqual,
|
|
22
48
|
areDatesEqual,
|
|
23
49
|
areMapsEqual,
|
|
24
50
|
areObjectsEqual,
|
|
51
|
+
arePrimitiveWrappersEqual,
|
|
25
52
|
areRegExpsEqual,
|
|
26
53
|
areSetsEqual,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (strict) {
|
|
57
|
+
config.areArraysEqual = areObjectsEqual;
|
|
58
|
+
config.areMapsEqual = combineComparators(areMapsEqual, areObjectsEqual);
|
|
59
|
+
config.areObjectsEqual = areObjectsEqualStrict;
|
|
60
|
+
config.areSetsEqual = combineComparators(areSetsEqual, areObjectsEqual);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (circular) {
|
|
64
|
+
config.areArraysEqual = createIsCircular(config.areArraysEqual);
|
|
65
|
+
config.areMapsEqual = createIsCircular(config.areMapsEqual);
|
|
66
|
+
config.areObjectsEqual = createIsCircular(config.areObjectsEqual);
|
|
67
|
+
config.areSetsEqual = createIsCircular(config.areSetsEqual);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return config;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function createDefaultEqualCreator(
|
|
74
|
+
options: DefaultEqualCreatorOptions<undefined> = {},
|
|
75
|
+
) {
|
|
76
|
+
const config = createComparatorConfig(options);
|
|
77
|
+
const isEqual = createComparator(config);
|
|
78
|
+
const isEqualComparator =
|
|
79
|
+
options.comparator || createInternalComparator(isEqual);
|
|
80
|
+
const strict = !!options.strict;
|
|
81
|
+
|
|
82
|
+
if (options.circular) {
|
|
83
|
+
return function equals<A, B>(a: A, b: B): boolean {
|
|
84
|
+
return isEqual(a, b, {
|
|
85
|
+
cache: new WeakMap(),
|
|
86
|
+
equals: isEqualComparator,
|
|
87
|
+
meta: undefined,
|
|
88
|
+
strict,
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const state = Object.freeze({
|
|
94
|
+
cache: undefined,
|
|
95
|
+
equals: isEqualComparator,
|
|
96
|
+
meta: undefined,
|
|
97
|
+
strict,
|
|
39
98
|
});
|
|
40
99
|
|
|
41
|
-
|
|
100
|
+
return function equals<A, B>(a: A, b: B): boolean {
|
|
101
|
+
return isEqual(a, b, state);
|
|
102
|
+
};
|
|
103
|
+
}
|
|
42
104
|
|
|
43
105
|
/**
|
|
44
106
|
* Whether the items passed are deeply-equal in value.
|
|
45
107
|
*/
|
|
46
|
-
export
|
|
47
|
-
return isDeepEqual(a, b, undefined);
|
|
48
|
-
}
|
|
108
|
+
export const deepEqual = createDefaultEqualCreator();
|
|
49
109
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Whether the items passed are deeply-equal in value based on strict comparison.
|
|
112
|
+
*/
|
|
113
|
+
export const strictDeepEqual = createDefaultEqualCreator({ strict: true });
|
|
53
114
|
|
|
54
115
|
/**
|
|
55
|
-
* Whether the items passed are
|
|
116
|
+
* Whether the items passed are deeply-equal in value, including circular references.
|
|
56
117
|
*/
|
|
57
|
-
export
|
|
58
|
-
return isShallowEqual(a, b, undefined);
|
|
59
|
-
}
|
|
118
|
+
export const circularDeepEqual = createDefaultEqualCreator({ circular: true });
|
|
60
119
|
|
|
61
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Whether the items passed are deeply-equal in value, including circular references,
|
|
122
|
+
* based on strict comparison.
|
|
123
|
+
*/
|
|
124
|
+
export const strictCircularDeepEqual = createDefaultEqualCreator({
|
|
125
|
+
circular: true,
|
|
126
|
+
strict: true,
|
|
127
|
+
});
|
|
62
128
|
|
|
63
129
|
/**
|
|
64
|
-
* Whether the items passed are
|
|
130
|
+
* Whether the items passed are shallowly-equal in value.
|
|
65
131
|
*/
|
|
66
|
-
export
|
|
67
|
-
|
|
68
|
-
}
|
|
132
|
+
export const shallowEqual = createDefaultEqualCreator({
|
|
133
|
+
comparator: sameValueZeroEqual,
|
|
134
|
+
});
|
|
69
135
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Whether the items passed are shallowly-equal in value based on strict comparison
|
|
138
|
+
*/
|
|
139
|
+
export const strictShallowEqual = createDefaultEqualCreator({
|
|
140
|
+
comparator: sameValueZeroEqual,
|
|
141
|
+
strict: true,
|
|
142
|
+
});
|
|
75
143
|
|
|
76
144
|
/**
|
|
77
145
|
* Whether the items passed are shallowly-equal in value, including circular references.
|
|
78
146
|
*/
|
|
79
|
-
export
|
|
80
|
-
|
|
81
|
-
|
|
147
|
+
export const circularShallowEqual = createDefaultEqualCreator({
|
|
148
|
+
comparator: sameValueZeroEqual,
|
|
149
|
+
circular: true,
|
|
150
|
+
});
|
|
82
151
|
|
|
83
152
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* This can be done to create very targeted comparisons in extreme hot-path scenarios
|
|
87
|
-
* where the standard methods are not performant enough, but can also be used to provide
|
|
88
|
-
* support for legacy environments that do not support expected features like
|
|
89
|
-
* `RegExp.prototype.flags` out of the box.
|
|
153
|
+
* Whether the items passed are shallowly-equal in value, including circular references,
|
|
154
|
+
* based on strict comparison.
|
|
90
155
|
*/
|
|
91
|
-
export
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
);
|
|
97
|
-
}
|
|
156
|
+
export const strictCircularShallowEqual = createDefaultEqualCreator({
|
|
157
|
+
comparator: sameValueZeroEqual,
|
|
158
|
+
circular: true,
|
|
159
|
+
strict: true,
|
|
160
|
+
});
|
|
98
161
|
|
|
99
162
|
/**
|
|
100
|
-
* Create a custom equality comparison method
|
|
101
|
-
* similar to `createCustomEqual`, with the only difference being that `meta` expects to be
|
|
102
|
-
* populated with a `WeakMap`-like contract.
|
|
163
|
+
* Create a custom equality comparison method.
|
|
103
164
|
*
|
|
104
165
|
* This can be done to create very targeted comparisons in extreme hot-path scenarios
|
|
105
166
|
* where the standard methods are not performant enough, but can also be used to provide
|
|
106
167
|
* support for legacy environments that do not support expected features like
|
|
107
|
-
* `
|
|
168
|
+
* `RegExp.prototype.flags` out of the box.
|
|
108
169
|
*/
|
|
109
|
-
export function
|
|
110
|
-
Meta
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
170
|
+
export function createCustomEqual<Meta>(
|
|
171
|
+
options: CustomEqualCreatorOptions<Meta> = {},
|
|
172
|
+
) {
|
|
173
|
+
const {
|
|
174
|
+
comparator,
|
|
175
|
+
createInternalComparator: createCustomInternalComparator,
|
|
176
|
+
createCustomConfig,
|
|
177
|
+
createState,
|
|
178
|
+
} = options;
|
|
179
|
+
|
|
180
|
+
const baseConfig = createComparatorConfig(options);
|
|
181
|
+
const config = createCustomConfig
|
|
182
|
+
? Object.assign({}, baseConfig, createCustomConfig(baseConfig))
|
|
183
|
+
: baseConfig;
|
|
184
|
+
const isEqualCustom = comparator || createComparator(config);
|
|
185
|
+
const isEqualCustomComparator = createCustomInternalComparator
|
|
186
|
+
? createCustomInternalComparator(isEqualCustom)
|
|
187
|
+
: createInternalComparator(isEqualCustom);
|
|
188
|
+
const strict = !!options.strict;
|
|
189
|
+
|
|
190
|
+
if (createState) {
|
|
191
|
+
return function isEqual<A, B>(a: A, b: B, metaOverride?: Meta): boolean {
|
|
192
|
+
const customState = createState(isEqualCustom);
|
|
193
|
+
|
|
194
|
+
return isEqualCustom(a, b, {
|
|
195
|
+
cache: customState.cache || new WeakMap(),
|
|
196
|
+
equals: customState.equals || isEqualCustomComparator,
|
|
197
|
+
// @ts-expect-error - inferred `Meta` may be undefined, which is okay
|
|
198
|
+
meta: metaOverride !== undefined ? metaOverride : customState.meta,
|
|
199
|
+
strict: customState.strict !== undefined ? customState.strict : strict,
|
|
200
|
+
});
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (options.circular) {
|
|
205
|
+
return function equals<A, B>(a: A, b: B): boolean {
|
|
206
|
+
return isEqualCustom(a, b, {
|
|
207
|
+
cache: new WeakMap(),
|
|
208
|
+
equals: isEqualCustomComparator,
|
|
209
|
+
meta: undefined as Meta,
|
|
210
|
+
strict,
|
|
211
|
+
} as CircularState<Meta>);
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const state = Object.freeze({
|
|
216
|
+
cache: undefined,
|
|
217
|
+
equals: isEqualCustomComparator,
|
|
218
|
+
meta: undefined,
|
|
219
|
+
strict,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return function equals<A, B>(a: A, b: B): boolean {
|
|
223
|
+
return isEqualCustom(a, b, state as DefaultState<Meta>);
|
|
224
|
+
};
|
|
121
225
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export interface BaseCircular
|
|
2
|
+
extends Pick<WeakMap<any, any>, 'delete' | 'get'> {
|
|
3
|
+
set(key: object, value: any): any;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type State<Meta> = CircularState<Meta> | DefaultState<Meta>;
|
|
7
|
+
|
|
8
|
+
export interface CircularState<Meta> {
|
|
9
|
+
readonly cache: BaseCircular;
|
|
10
|
+
readonly equals: InternalEqualityComparator<Meta>;
|
|
11
|
+
meta: Meta;
|
|
12
|
+
readonly strict: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DefaultState<Meta> {
|
|
16
|
+
readonly cache: undefined;
|
|
17
|
+
readonly equals: InternalEqualityComparator<Meta>;
|
|
18
|
+
meta: Meta;
|
|
19
|
+
readonly strict: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface Dictionary<Value = any> {
|
|
23
|
+
[key: string | symbol]: Value;
|
|
24
|
+
$$typeof?: any;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ComparatorConfig<Meta> {
|
|
28
|
+
areArraysEqual: TypeEqualityComparator<any, Meta>;
|
|
29
|
+
areDatesEqual: TypeEqualityComparator<any, Meta>;
|
|
30
|
+
areMapsEqual: TypeEqualityComparator<any, Meta>;
|
|
31
|
+
areObjectsEqual: TypeEqualityComparator<any, Meta>;
|
|
32
|
+
arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
|
|
33
|
+
areRegExpsEqual: TypeEqualityComparator<any, Meta>;
|
|
34
|
+
areSetsEqual: TypeEqualityComparator<any, Meta>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type CreateCustomComparatorConfig<Meta> = (
|
|
38
|
+
config: ComparatorConfig<Meta>,
|
|
39
|
+
) => Partial<ComparatorConfig<Meta>>;
|
|
40
|
+
|
|
41
|
+
export type CreateState<Meta> = (
|
|
42
|
+
comparator: EqualityComparator<Meta>,
|
|
43
|
+
) => Partial<State<Meta>>;
|
|
44
|
+
|
|
45
|
+
export type EqualityComparator<Meta> = <A, B>(
|
|
46
|
+
a: A,
|
|
47
|
+
b: B,
|
|
48
|
+
state: State<Meta>,
|
|
49
|
+
) => boolean;
|
|
50
|
+
export type AnyEqualityComparator<Meta> = (
|
|
51
|
+
a: any,
|
|
52
|
+
b: any,
|
|
53
|
+
state: State<Meta>,
|
|
54
|
+
) => boolean;
|
|
55
|
+
|
|
56
|
+
export type EqualityComparatorCreator<Meta> = (
|
|
57
|
+
fn: EqualityComparator<Meta>,
|
|
58
|
+
) => InternalEqualityComparator<Meta>;
|
|
59
|
+
|
|
60
|
+
export type InternalEqualityComparator<Meta> = (
|
|
61
|
+
a: any,
|
|
62
|
+
b: any,
|
|
63
|
+
indexOrKeyA: any,
|
|
64
|
+
indexOrKeyB: any,
|
|
65
|
+
parentA: any,
|
|
66
|
+
parentB: any,
|
|
67
|
+
state: State<Meta>,
|
|
68
|
+
) => boolean;
|
|
69
|
+
|
|
70
|
+
export type TypeEqualityComparator<Type, Meta = undefined> = (
|
|
71
|
+
a: Type,
|
|
72
|
+
b: Type,
|
|
73
|
+
state: State<Meta>,
|
|
74
|
+
) => boolean;
|
package/src/utils.ts
CHANGED
|
@@ -1,31 +1,48 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AnyEqualityComparator,
|
|
3
|
+
BaseCircular,
|
|
4
|
+
CircularState,
|
|
5
|
+
Dictionary,
|
|
2
6
|
EqualityComparator,
|
|
3
7
|
InternalEqualityComparator,
|
|
8
|
+
State,
|
|
4
9
|
TypeEqualityComparator,
|
|
5
|
-
} from '
|
|
10
|
+
} from './internalTypes';
|
|
11
|
+
|
|
12
|
+
const { getOwnPropertyNames, getOwnPropertySymbols } = Object;
|
|
13
|
+
const { hasOwnProperty } = Object.prototype;
|
|
14
|
+
|
|
15
|
+
export function combineComparators<Meta>(
|
|
16
|
+
comparatorA: AnyEqualityComparator<Meta>,
|
|
17
|
+
comparatorB: AnyEqualityComparator<Meta>,
|
|
18
|
+
) {
|
|
19
|
+
return function isEqual<A, B>(a: A, b: B, state: State<Meta>) {
|
|
20
|
+
return comparatorA(a, b, state) && comparatorB(a, b, state);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
6
23
|
|
|
7
24
|
/**
|
|
8
25
|
* Default equality comparator pass-through, used as the standard `isEqual` creator for
|
|
9
26
|
* use inside the built comparator.
|
|
10
27
|
*/
|
|
11
|
-
export function
|
|
12
|
-
|
|
28
|
+
export function createInternalComparator<Meta>(
|
|
29
|
+
compare: EqualityComparator<Meta>,
|
|
13
30
|
): InternalEqualityComparator<Meta> {
|
|
14
|
-
return function
|
|
15
|
-
a:
|
|
16
|
-
b:
|
|
31
|
+
return function (
|
|
32
|
+
a: any,
|
|
33
|
+
b: any,
|
|
17
34
|
_indexOrKeyA: any,
|
|
18
35
|
_indexOrKeyB: any,
|
|
19
36
|
_parentA: any,
|
|
20
37
|
_parentB: any,
|
|
21
|
-
|
|
38
|
+
state: State<Meta>,
|
|
22
39
|
) {
|
|
23
|
-
return
|
|
40
|
+
return compare(a, b, state);
|
|
24
41
|
};
|
|
25
42
|
}
|
|
26
43
|
|
|
27
44
|
/**
|
|
28
|
-
* Wrap the provided `areItemsEqual` method to manage the circular
|
|
45
|
+
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
|
|
29
46
|
* for circular references to be safely included in the comparison without creating
|
|
30
47
|
* stack overflows.
|
|
31
48
|
*/
|
|
@@ -35,13 +52,14 @@ export function createIsCircular<
|
|
|
35
52
|
return function isCircular(
|
|
36
53
|
a: any,
|
|
37
54
|
b: any,
|
|
38
|
-
|
|
39
|
-
cache: WeakMap<any, any>,
|
|
55
|
+
state: CircularState<BaseCircular>,
|
|
40
56
|
) {
|
|
41
57
|
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
|
|
42
|
-
return areItemsEqual(a, b,
|
|
58
|
+
return areItemsEqual(a, b, state);
|
|
43
59
|
}
|
|
44
60
|
|
|
61
|
+
const { cache } = state;
|
|
62
|
+
|
|
45
63
|
const cachedA = cache.get(a);
|
|
46
64
|
const cachedB = cache.get(b);
|
|
47
65
|
|
|
@@ -52,7 +70,7 @@ export function createIsCircular<
|
|
|
52
70
|
cache.set(a, b);
|
|
53
71
|
cache.set(b, a);
|
|
54
72
|
|
|
55
|
-
const result = areItemsEqual(a, b,
|
|
73
|
+
const result = areItemsEqual(a, b, state);
|
|
56
74
|
|
|
57
75
|
cache.delete(a);
|
|
58
76
|
cache.delete(b);
|
|
@@ -61,47 +79,22 @@ export function createIsCircular<
|
|
|
61
79
|
} as AreItemsEqual;
|
|
62
80
|
}
|
|
63
81
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
*/
|
|
71
|
-
export function merge<A extends object, B extends object>(a: A, b: B): A & B {
|
|
72
|
-
const merged: Record<string, any> = {};
|
|
73
|
-
|
|
74
|
-
for (const key in a) {
|
|
75
|
-
merged[key] = a[key];
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
for (const key in b) {
|
|
79
|
-
merged[key] = b[key];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return merged as A & B;
|
|
82
|
+
export function getStrictProperties(
|
|
83
|
+
object: Dictionary,
|
|
84
|
+
): Array<string | symbol> {
|
|
85
|
+
return (getOwnPropertyNames(object) as Array<string | symbol>).concat(
|
|
86
|
+
getOwnPropertySymbols(object),
|
|
87
|
+
);
|
|
83
88
|
}
|
|
84
89
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
* This is a same-realm compariosn only.
|
|
90
|
-
*/
|
|
91
|
-
export function isPlainObject(value: any): boolean {
|
|
92
|
-
return value.constructor === Object || value.constructor == null;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* When the value is `Promise`-like, aka "then-able".
|
|
97
|
-
*/
|
|
98
|
-
export function isPromiseLike(value: any): boolean {
|
|
99
|
-
return typeof value.then === 'function';
|
|
100
|
-
}
|
|
90
|
+
export const hasOwn =
|
|
91
|
+
Object.hasOwn ||
|
|
92
|
+
((object: Dictionary, property: number | string | symbol) =>
|
|
93
|
+
hasOwnProperty.call(object, property));
|
|
101
94
|
|
|
102
95
|
/**
|
|
103
96
|
* Whether the values passed are strictly equal or both NaN.
|
|
104
97
|
*/
|
|
105
98
|
export function sameValueZeroEqual(a: any, b: any): boolean {
|
|
106
|
-
return a === b || (a !== a && b !== b);
|
|
99
|
+
return a || b ? a === b : a === b || (a !== a && b !== b);
|
|
107
100
|
}
|