@domql/utils 3.2.3 → 3.2.10
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/array.js +11 -5
- package/cache.js +3 -0
- package/component.js +3 -4
- package/dist/cjs/array.js +11 -5
- package/dist/cjs/component.js +4 -6
- package/dist/cjs/element.js +5 -5
- package/dist/cjs/extends.js +43 -27
- package/dist/cjs/function.js +3 -3
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/key.js +2 -2
- package/dist/cjs/keys.js +30 -16
- package/dist/cjs/methods.js +64 -28
- package/dist/cjs/object.js +141 -125
- package/dist/cjs/props.js +41 -32
- package/dist/cjs/scope.js +1 -2
- package/dist/cjs/state.js +9 -8
- package/dist/cjs/string.js +15 -20
- package/dist/cjs/tags.js +69 -4
- package/dist/cjs/triggerEvent.js +90 -0
- package/dist/cjs/types.js +4 -12
- package/dist/esm/array.js +11 -5
- package/dist/esm/component.js +4 -6
- package/dist/esm/element.js +8 -26
- package/dist/esm/extends.js +47 -49
- package/dist/esm/function.js +3 -3
- package/dist/esm/index.js +1 -0
- package/dist/esm/key.js +2 -2
- package/dist/esm/keys.js +30 -16
- package/dist/esm/methods.js +63 -42
- package/dist/esm/object.js +145 -149
- package/dist/esm/props.js +41 -48
- package/dist/esm/scope.js +1 -2
- package/dist/esm/state.js +17 -34
- package/dist/esm/string.js +15 -20
- package/dist/esm/tags.js +69 -4
- package/dist/esm/triggerEvent.js +70 -0
- package/dist/esm/types.js +4 -12
- package/dist/iife/index.js +2779 -0
- package/element.js +2 -2
- package/extends.js +28 -17
- package/function.js +4 -6
- package/index.js +1 -0
- package/keys.js +26 -16
- package/methods.js +63 -18
- package/object.js +142 -200
- package/package.json +33 -12
- package/props.js +42 -25
- package/state.js +7 -7
- package/string.js +20 -38
- package/tags.js +43 -4
- package/triggerEvent.js +76 -0
- package/types.js +4 -23
- package/dist/cjs/package.json +0 -4
package/object.js
CHANGED
|
@@ -7,9 +7,7 @@ import {
|
|
|
7
7
|
isObject,
|
|
8
8
|
isArray,
|
|
9
9
|
isString,
|
|
10
|
-
is
|
|
11
|
-
isUndefined,
|
|
12
|
-
isNull
|
|
10
|
+
is
|
|
13
11
|
} from './types.js'
|
|
14
12
|
import { unstackArrayOfObjects } from './array.js'
|
|
15
13
|
import { stringIncludesAny } from './string.js'
|
|
@@ -18,8 +16,11 @@ import { METHODS_EXL } from './keys.js'
|
|
|
18
16
|
|
|
19
17
|
const ENV = process.env.NODE_ENV
|
|
20
18
|
|
|
19
|
+
const _startsWithDunder = e => e.charCodeAt(0) === 95 && e.charCodeAt(1) === 95
|
|
20
|
+
|
|
21
21
|
export const exec = (param, element, state, context) => {
|
|
22
22
|
if (isFunction(param)) {
|
|
23
|
+
if (!element) return
|
|
23
24
|
const result = param.call(
|
|
24
25
|
element,
|
|
25
26
|
element,
|
|
@@ -45,26 +46,24 @@ export const map = (obj, extention, element) => {
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export const merge = (element, obj, excludeFrom = []) => {
|
|
49
|
+
const useSet = excludeFrom instanceof Set
|
|
48
50
|
for (const e in obj) {
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const objProp = obj[e]
|
|
55
|
-
if (elementProp === undefined) {
|
|
56
|
-
element[e] = objProp
|
|
51
|
+
if (!Object.prototype.hasOwnProperty.call(obj, e)) continue
|
|
52
|
+
if (_startsWithDunder(e)) continue
|
|
53
|
+
if (useSet ? excludeFrom.has(e) : excludeFrom.includes(e)) continue
|
|
54
|
+
if (element[e] === undefined) {
|
|
55
|
+
element[e] = obj[e]
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
return element
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
export const deepMerge = (element, extend, excludeFrom = METHODS_EXL) => {
|
|
62
|
+
const useSet = excludeFrom instanceof Set
|
|
63
63
|
for (const e in extend) {
|
|
64
|
-
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
}
|
|
64
|
+
if (!Object.prototype.hasOwnProperty.call(extend, e)) continue
|
|
65
|
+
if (_startsWithDunder(e)) continue
|
|
66
|
+
if (useSet ? excludeFrom.has(e) : excludeFrom.includes(e)) continue
|
|
68
67
|
const elementProp = element[e]
|
|
69
68
|
const extendProp = extend[e]
|
|
70
69
|
if (isObjectLike(elementProp) && isObjectLike(extendProp)) {
|
|
@@ -77,16 +76,12 @@ export const deepMerge = (element, extend, excludeFrom = METHODS_EXL) => {
|
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
export const clone = (obj, excludeFrom = []) => {
|
|
79
|
+
const useSet = excludeFrom instanceof Set
|
|
80
80
|
const o = {}
|
|
81
81
|
for (const prop in obj) {
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
excludeFrom.includes(prop) ||
|
|
86
|
-
prop.startsWith('__')
|
|
87
|
-
) {
|
|
88
|
-
continue
|
|
89
|
-
}
|
|
82
|
+
if (!Object.prototype.hasOwnProperty.call(obj, prop)) continue
|
|
83
|
+
if (_startsWithDunder(prop)) continue
|
|
84
|
+
if (useSet ? excludeFrom.has(prop) : excludeFrom.includes(prop)) continue
|
|
90
85
|
o[prop] = obj[prop]
|
|
91
86
|
}
|
|
92
87
|
return o
|
|
@@ -127,35 +122,28 @@ export const deepClone = (obj, options = {}) => {
|
|
|
127
122
|
}
|
|
128
123
|
|
|
129
124
|
// Create appropriate container based on type and window context
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
? new contentWindow.Array()
|
|
133
|
-
: new contentWindow.Object()
|
|
134
|
-
: isArray(obj)
|
|
135
|
-
? []
|
|
136
|
-
: {}
|
|
125
|
+
const isArr = isArray(obj)
|
|
126
|
+
const clone = isArr ? [] : {}
|
|
137
127
|
|
|
138
128
|
// Store the clone to handle circular references
|
|
139
129
|
visited.set(obj, clone)
|
|
140
130
|
|
|
131
|
+
// Convert exclude to Set for O(1) lookups when list is non-trivial
|
|
132
|
+
const excludeSet = exclude instanceof Set ? exclude : (exclude.length > 3 ? new Set(exclude) : null)
|
|
133
|
+
|
|
141
134
|
// Clone properties
|
|
142
135
|
for (const key in obj) {
|
|
143
136
|
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue
|
|
144
137
|
|
|
145
138
|
// Skip excluded properties
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
}
|
|
139
|
+
if (_startsWithDunder(key) || key === '__proto__') continue
|
|
140
|
+
if (excludeSet ? excludeSet.has(key) : exclude.includes(key)) continue
|
|
149
141
|
|
|
150
142
|
const value = obj[key]
|
|
151
143
|
|
|
152
144
|
// Skip based on cleanup options
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
(cleanNull && isNull(value))
|
|
156
|
-
) {
|
|
157
|
-
continue
|
|
158
|
-
}
|
|
145
|
+
if (cleanUndefined && value === undefined) continue
|
|
146
|
+
if (cleanNull && value === null) continue
|
|
159
147
|
|
|
160
148
|
// Handle special cases
|
|
161
149
|
if (isDOMNode(value)) {
|
|
@@ -209,17 +197,18 @@ export const deepStringify = (obj, stringified = {}) => {
|
|
|
209
197
|
stringified[prop] = {}
|
|
210
198
|
deepStringify(objProp, stringified[prop])
|
|
211
199
|
} else if (isArray(objProp)) {
|
|
212
|
-
stringified[prop] = []
|
|
213
|
-
objProp.
|
|
200
|
+
const arr = stringified[prop] = []
|
|
201
|
+
for (let i = 0; i < objProp.length; i++) {
|
|
202
|
+
const v = objProp[i]
|
|
214
203
|
if (isObject(v)) {
|
|
215
|
-
|
|
216
|
-
deepStringify(v,
|
|
204
|
+
arr[i] = {}
|
|
205
|
+
deepStringify(v, arr[i])
|
|
217
206
|
} else if (isFunction(v)) {
|
|
218
|
-
|
|
207
|
+
arr[i] = v.toString()
|
|
219
208
|
} else {
|
|
220
|
-
|
|
209
|
+
arr[i] = v
|
|
221
210
|
}
|
|
222
|
-
}
|
|
211
|
+
}
|
|
223
212
|
} else {
|
|
224
213
|
stringified[prop] = objProp
|
|
225
214
|
}
|
|
@@ -227,38 +216,32 @@ export const deepStringify = (obj, stringified = {}) => {
|
|
|
227
216
|
return stringified
|
|
228
217
|
}
|
|
229
218
|
|
|
219
|
+
const OBJ_TO_STR_SPECIAL_CHARS = new Set([
|
|
220
|
+
'&', '*', '-', ':', '%', '{', '}', '>', '<', '@', '.', '/', '!', ' '
|
|
221
|
+
])
|
|
222
|
+
|
|
230
223
|
export const objectToString = (obj = {}, indent = 0) => {
|
|
231
224
|
// Handle empty object case
|
|
232
225
|
if (obj === null || typeof obj !== 'object') {
|
|
233
226
|
return String(obj)
|
|
234
227
|
}
|
|
235
228
|
|
|
236
|
-
// Handle empty object case
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
229
|
+
// Handle empty object case - avoid Object.keys allocation
|
|
230
|
+
let hasKeys = false
|
|
231
|
+
for (const _k in obj) { hasKeys = true; break } // eslint-disable-line
|
|
232
|
+
if (!hasKeys) return '{}'
|
|
240
233
|
|
|
241
234
|
const spaces = ' '.repeat(indent)
|
|
242
235
|
let str = '{\n'
|
|
243
236
|
|
|
244
|
-
for (const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
'}',
|
|
253
|
-
'>',
|
|
254
|
-
'<',
|
|
255
|
-
'@',
|
|
256
|
-
'.',
|
|
257
|
-
'/',
|
|
258
|
-
'!',
|
|
259
|
-
' '
|
|
260
|
-
])
|
|
261
|
-
const stringedKey = keyNotAllowdChars ? `'${key}'` : key
|
|
237
|
+
for (const key in obj) {
|
|
238
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue
|
|
239
|
+
const value = obj[key]
|
|
240
|
+
let keyNeedsQuotes = false
|
|
241
|
+
for (let i = 0; i < key.length; i++) {
|
|
242
|
+
if (OBJ_TO_STR_SPECIAL_CHARS.has(key[i])) { keyNeedsQuotes = true; break }
|
|
243
|
+
}
|
|
244
|
+
const stringedKey = keyNeedsQuotes ? `'${key}'` : key
|
|
262
245
|
str += `${spaces} ${stringedKey}: `
|
|
263
246
|
|
|
264
247
|
if (isArray(value)) {
|
|
@@ -290,44 +273,46 @@ export const objectToString = (obj = {}, indent = 0) => {
|
|
|
290
273
|
return str
|
|
291
274
|
}
|
|
292
275
|
|
|
276
|
+
const FN_PATTERNS = [
|
|
277
|
+
/^\(\s*\{[^}]*\}\s*\)\s*=>/,
|
|
278
|
+
/^(\([^)]*\)|[^=]*)\s*=>/,
|
|
279
|
+
/^function[\s(]/,
|
|
280
|
+
/^async\s+/,
|
|
281
|
+
/^\(\s*function/,
|
|
282
|
+
/^[a-zA-Z_$][a-zA-Z0-9_$]*\s*=>/
|
|
283
|
+
]
|
|
284
|
+
const RE_JSON_LIKE = /^["[{]/
|
|
285
|
+
|
|
293
286
|
export const hasFunction = str => {
|
|
294
287
|
if (!str) return false
|
|
295
288
|
|
|
296
289
|
const trimmed = str.trim().replace(/\n\s*/g, ' ').trim()
|
|
297
290
|
|
|
298
|
-
if (trimmed === '') return false
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const isFunction = patterns.some(pattern => pattern.test(trimmed))
|
|
312
|
-
const isObjectLiteral = trimmed.startsWith('{') && !trimmed.includes('=>')
|
|
313
|
-
const isArrayLiteral = trimmed.startsWith('[')
|
|
314
|
-
const isJSONLike = /^["[{]/.test(trimmed) && !trimmed.includes('=>')
|
|
315
|
-
|
|
316
|
-
return isFunction && !isObjectLiteral && !isArrayLiteral && !isJSONLike
|
|
291
|
+
if (trimmed === '' || trimmed === '{}' || trimmed === '[]') return false
|
|
292
|
+
|
|
293
|
+
const isFn = FN_PATTERNS.some(pattern => pattern.test(trimmed))
|
|
294
|
+
if (!isFn) return false
|
|
295
|
+
|
|
296
|
+
const firstChar = trimmed.charCodeAt(0)
|
|
297
|
+
const hasArrow = trimmed.includes('=>')
|
|
298
|
+
// '{' = 123, '[' = 91
|
|
299
|
+
if (firstChar === 123 && !hasArrow) return false // object literal
|
|
300
|
+
if (firstChar === 91) return false // array literal
|
|
301
|
+
if (RE_JSON_LIKE.test(trimmed) && !hasArrow) return false
|
|
302
|
+
|
|
303
|
+
return true
|
|
317
304
|
}
|
|
318
305
|
|
|
319
306
|
export const deepDestringify = (obj, destringified = {}) => {
|
|
320
307
|
for (const prop in obj) {
|
|
321
|
-
|
|
322
|
-
if (!hasOwnProperty) continue
|
|
308
|
+
if (!Object.prototype.hasOwnProperty.call(obj, prop)) continue
|
|
323
309
|
|
|
324
310
|
const objProp = obj[prop]
|
|
325
311
|
|
|
326
312
|
if (isString(objProp)) {
|
|
327
313
|
if (hasFunction(objProp)) {
|
|
328
314
|
try {
|
|
329
|
-
|
|
330
|
-
destringified[prop] = evalProp
|
|
315
|
+
destringified[prop] = window.eval(`(${objProp})`)
|
|
331
316
|
} catch (e) {
|
|
332
317
|
if (e) destringified[prop] = objProp
|
|
333
318
|
}
|
|
@@ -335,25 +320,25 @@ export const deepDestringify = (obj, destringified = {}) => {
|
|
|
335
320
|
destringified[prop] = objProp
|
|
336
321
|
}
|
|
337
322
|
} else if (isArray(objProp)) {
|
|
338
|
-
destringified[prop] = []
|
|
339
|
-
objProp.
|
|
323
|
+
const arr = destringified[prop] = []
|
|
324
|
+
for (let i = 0; i < objProp.length; i++) {
|
|
325
|
+
const arrProp = objProp[i]
|
|
340
326
|
if (isString(arrProp)) {
|
|
341
327
|
if (hasFunction(arrProp)) {
|
|
342
328
|
try {
|
|
343
|
-
|
|
344
|
-
destringified[prop].push(evalProp)
|
|
329
|
+
arr.push(window.eval(`(${arrProp})`))
|
|
345
330
|
} catch (e) {
|
|
346
|
-
if (e)
|
|
331
|
+
if (e) arr.push(arrProp)
|
|
347
332
|
}
|
|
348
333
|
} else {
|
|
349
|
-
|
|
334
|
+
arr.push(arrProp)
|
|
350
335
|
}
|
|
351
336
|
} else if (isObject(arrProp)) {
|
|
352
|
-
|
|
337
|
+
arr.push(deepDestringify(arrProp))
|
|
353
338
|
} else {
|
|
354
|
-
|
|
339
|
+
arr.push(arrProp)
|
|
355
340
|
}
|
|
356
|
-
}
|
|
341
|
+
}
|
|
357
342
|
} else if (isObject(objProp)) {
|
|
358
343
|
destringified[prop] = deepDestringify(objProp, destringified[prop])
|
|
359
344
|
} else {
|
|
@@ -374,7 +359,10 @@ export const stringToObject = (str, opts = { verbose: true }) => {
|
|
|
374
359
|
export const hasOwnProperty = (o, ...args) =>
|
|
375
360
|
Object.prototype.hasOwnProperty.call(o, ...args)
|
|
376
361
|
|
|
377
|
-
export const isEmpty = o =>
|
|
362
|
+
export const isEmpty = o => {
|
|
363
|
+
for (const _ in o) return false // eslint-disable-line
|
|
364
|
+
return true
|
|
365
|
+
}
|
|
378
366
|
|
|
379
367
|
export const isEmptyObject = o => isObject(o) && isEmpty(o)
|
|
380
368
|
|
|
@@ -388,12 +376,9 @@ export const overwrite = (element, params, opts = {}) => {
|
|
|
388
376
|
const allowUnderscore = opts.preventUnderscore
|
|
389
377
|
|
|
390
378
|
for (const e in params) {
|
|
391
|
-
if (excl.includes(e) || (!allowUnderscore && e
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
if (paramsProp !== undefined) {
|
|
396
|
-
element[e] = paramsProp
|
|
379
|
+
if (excl.includes(e) || (!allowUnderscore && _startsWithDunder(e))) continue
|
|
380
|
+
if (params[e] !== undefined) {
|
|
381
|
+
element[e] = params[e]
|
|
397
382
|
}
|
|
398
383
|
}
|
|
399
384
|
|
|
@@ -401,8 +386,10 @@ export const overwrite = (element, params, opts = {}) => {
|
|
|
401
386
|
}
|
|
402
387
|
|
|
403
388
|
export const overwriteShallow = (obj, params, excludeFrom = []) => {
|
|
389
|
+
const useSet = excludeFrom instanceof Set
|
|
404
390
|
for (const e in params) {
|
|
405
|
-
if (
|
|
391
|
+
if (_startsWithDunder(e)) continue
|
|
392
|
+
if (useSet ? excludeFrom.has(e) : excludeFrom.includes(e)) continue
|
|
406
393
|
obj[e] = params[e]
|
|
407
394
|
}
|
|
408
395
|
return obj
|
|
@@ -417,9 +404,6 @@ export const overwriteDeep = (
|
|
|
417
404
|
opts = {},
|
|
418
405
|
visited = new WeakMap()
|
|
419
406
|
) => {
|
|
420
|
-
const excl = opts.exclude || []
|
|
421
|
-
const forcedExclude = opts.preventForce ? [] : ['node', 'window']
|
|
422
|
-
|
|
423
407
|
if (
|
|
424
408
|
!isObjectLike(obj) ||
|
|
425
409
|
!isObjectLike(params) ||
|
|
@@ -432,9 +416,13 @@ export const overwriteDeep = (
|
|
|
432
416
|
if (visited.has(obj)) return visited.get(obj)
|
|
433
417
|
visited.set(obj, obj)
|
|
434
418
|
|
|
419
|
+
const excl = opts.exclude
|
|
420
|
+
const exclSet = excl ? (excl instanceof Set ? excl : new Set(excl)) : null
|
|
421
|
+
const forcedExclude = !opts.preventForce
|
|
422
|
+
|
|
435
423
|
for (const e in params) {
|
|
436
|
-
if (!Object.hasOwnProperty.call(params, e)) continue
|
|
437
|
-
if (
|
|
424
|
+
if (!Object.prototype.hasOwnProperty.call(params, e)) continue
|
|
425
|
+
if ((exclSet && exclSet.has(e)) || (forcedExclude && _startsWithDunder(e))) continue
|
|
438
426
|
|
|
439
427
|
const objProp = obj[e]
|
|
440
428
|
const paramsProp = params[e]
|
|
@@ -453,52 +441,19 @@ export const overwriteDeep = (
|
|
|
453
441
|
|
|
454
442
|
/**
|
|
455
443
|
* Recursively compares two values to determine if they are deeply equal.
|
|
456
|
-
*
|
|
457
|
-
* This function checks for deep equality between two values, including
|
|
458
|
-
* objects, arrays, and nested structures. It handles circular references to
|
|
459
|
-
* prevent infinite loops.
|
|
460
|
-
*
|
|
461
|
-
* @param {*} param - The first value to compare.
|
|
462
|
-
* @param {*} element - The second value to compare.
|
|
463
|
-
* @param {Set} [visited] - (Optional) A set to track visited objects during recursion
|
|
464
|
-
* to handle circular references. You can omit this parameter when calling
|
|
465
|
-
* the function; it is used internally for tracking visited objects.
|
|
466
|
-
*
|
|
467
|
-
* @returns {boolean} Returns `true` if the values are deeply equal, `false` otherwise.
|
|
468
|
-
*
|
|
469
|
-
* @example
|
|
470
|
-
* // Comparing primitive values
|
|
471
|
-
* isEqualDeep(42, 42); // true
|
|
472
|
-
* isEqualDeep('hello', 'hello'); // true
|
|
473
|
-
* isEqualDeep(true, true); // true
|
|
474
|
-
* isEqualDeep(42, '42'); // false
|
|
475
|
-
*
|
|
476
|
-
* // Comparing simple objects
|
|
477
|
-
* const obj1 = { a: 1, b: { c: 2 } };
|
|
478
|
-
* const obj2 = { a: 1, b: { c: 2 } };
|
|
479
|
-
* isEqualDeep(obj1, obj2); // true
|
|
480
|
-
*
|
|
481
|
-
* // Handling circular references
|
|
482
|
-
* const circularObj = { prop: null };
|
|
483
|
-
* circularObj.prop = circularObj;
|
|
484
|
-
* const anotherObj = { prop: null };
|
|
485
|
-
* anotherObj.prop = anotherObj;
|
|
486
|
-
* isEqualDeep(circularObj, anotherObj); // true
|
|
487
444
|
*/
|
|
488
445
|
export const isEqualDeep = (param, element, visited = new Set()) => {
|
|
489
|
-
// Check if both values are non-null objects
|
|
490
446
|
if (
|
|
491
447
|
typeof param !== 'object' ||
|
|
492
448
|
typeof element !== 'object' ||
|
|
493
449
|
param === null ||
|
|
494
450
|
element === null
|
|
495
451
|
) {
|
|
496
|
-
return param === element
|
|
452
|
+
return param === element
|
|
497
453
|
}
|
|
498
454
|
|
|
499
|
-
// Check for circular references
|
|
500
455
|
if (visited.has(param) || visited.has(element)) {
|
|
501
|
-
return true
|
|
456
|
+
return true
|
|
502
457
|
}
|
|
503
458
|
|
|
504
459
|
visited.add(param)
|
|
@@ -507,22 +462,16 @@ export const isEqualDeep = (param, element, visited = new Set()) => {
|
|
|
507
462
|
const keysParam = Object.keys(param)
|
|
508
463
|
const keysElement = Object.keys(element)
|
|
509
464
|
|
|
510
|
-
// Check if both objects have the same number of properties
|
|
511
465
|
if (keysParam.length !== keysElement.length) {
|
|
512
466
|
return false
|
|
513
467
|
}
|
|
514
468
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if (!
|
|
469
|
+
for (let i = 0; i < keysParam.length; i++) {
|
|
470
|
+
const key = keysParam[i]
|
|
471
|
+
if (!Object.prototype.hasOwnProperty.call(element, key)) {
|
|
518
472
|
return false
|
|
519
473
|
}
|
|
520
|
-
|
|
521
|
-
const paramProp = param[key]
|
|
522
|
-
const elementProp = element[key]
|
|
523
|
-
|
|
524
|
-
// Recursively check property values
|
|
525
|
-
if (!isEqualDeep(paramProp, elementProp, visited)) {
|
|
474
|
+
if (!isEqualDeep(param[key], element[key], visited)) {
|
|
526
475
|
return false
|
|
527
476
|
}
|
|
528
477
|
}
|
|
@@ -530,23 +479,23 @@ export const isEqualDeep = (param, element, visited = new Set()) => {
|
|
|
530
479
|
return true
|
|
531
480
|
}
|
|
532
481
|
|
|
533
|
-
|
|
482
|
+
const DEEP_CONTAINS_IGNORED = new Set(['node', '__ref'])
|
|
483
|
+
|
|
484
|
+
export const deepContains = (obj1, obj2, ignoredKeys = DEEP_CONTAINS_IGNORED) => {
|
|
534
485
|
if (obj1 === obj2) return true
|
|
535
486
|
if (!isObjectLike(obj1) || !isObjectLike(obj2)) return obj1 === obj2
|
|
536
487
|
if (isDOMNode(obj1) || isDOMNode(obj2)) return obj1 === obj2
|
|
537
488
|
|
|
489
|
+
const ignored = ignoredKeys instanceof Set ? ignoredKeys : new Set(ignoredKeys)
|
|
538
490
|
const visited = new WeakSet()
|
|
539
491
|
|
|
540
492
|
function checkContains (target, source) {
|
|
541
493
|
if (visited.has(source)) return true
|
|
542
494
|
visited.add(source)
|
|
543
495
|
|
|
544
|
-
// Check each property in source
|
|
545
496
|
for (const key in source) {
|
|
546
497
|
if (!Object.prototype.hasOwnProperty.call(source, key)) continue
|
|
547
|
-
if (
|
|
548
|
-
|
|
549
|
-
// If key doesn't exist in target, return false
|
|
498
|
+
if (ignored.has(key)) continue
|
|
550
499
|
if (!Object.prototype.hasOwnProperty.call(target, key)) return false
|
|
551
500
|
|
|
552
501
|
const sourceValue = source[key]
|
|
@@ -572,7 +521,7 @@ export const removeFromObject = (obj, props) => {
|
|
|
572
521
|
if (is(props)('string', 'number')) {
|
|
573
522
|
delete obj[props]
|
|
574
523
|
} else if (isArray(props)) {
|
|
575
|
-
props.
|
|
524
|
+
for (let i = 0; i < props.length; i++) delete obj[props[i]]
|
|
576
525
|
} else {
|
|
577
526
|
throw new Error(
|
|
578
527
|
'Invalid input: props must be a string or an array of strings'
|
|
@@ -583,14 +532,14 @@ export const removeFromObject = (obj, props) => {
|
|
|
583
532
|
|
|
584
533
|
export const createObjectWithoutPrototype = obj => {
|
|
585
534
|
if (obj === null || typeof obj !== 'object') {
|
|
586
|
-
return obj
|
|
535
|
+
return obj
|
|
587
536
|
}
|
|
588
537
|
|
|
589
|
-
const newObj = Object.create(null)
|
|
538
|
+
const newObj = Object.create(null)
|
|
590
539
|
|
|
591
540
|
for (const key in obj) {
|
|
592
541
|
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
593
|
-
newObj[key] = createObjectWithoutPrototype(obj[key])
|
|
542
|
+
newObj[key] = createObjectWithoutPrototype(obj[key])
|
|
594
543
|
}
|
|
595
544
|
}
|
|
596
545
|
|
|
@@ -598,21 +547,19 @@ export const createObjectWithoutPrototype = obj => {
|
|
|
598
547
|
}
|
|
599
548
|
|
|
600
549
|
export const createNestedObject = (arr, lastValue) => {
|
|
601
|
-
|
|
550
|
+
if (arr.length === 0) return lastValue
|
|
602
551
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
}
|
|
552
|
+
const nestedObject = {}
|
|
553
|
+
let current = nestedObject
|
|
606
554
|
|
|
607
|
-
arr.
|
|
608
|
-
if (
|
|
609
|
-
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
|
|
555
|
+
for (let i = 0; i < arr.length; i++) {
|
|
556
|
+
if (i === arr.length - 1 && lastValue) {
|
|
557
|
+
current[arr[i]] = lastValue
|
|
558
|
+
} else {
|
|
559
|
+
current[arr[i]] = {}
|
|
560
|
+
current = current[arr[i]]
|
|
613
561
|
}
|
|
614
|
-
|
|
615
|
-
}, nestedObject)
|
|
562
|
+
}
|
|
616
563
|
|
|
617
564
|
return nestedObject
|
|
618
565
|
}
|
|
@@ -625,14 +572,12 @@ export const removeNestedKeyByPath = (obj, path) => {
|
|
|
625
572
|
let current = obj
|
|
626
573
|
|
|
627
574
|
for (let i = 0; i < path.length - 1; i++) {
|
|
628
|
-
if (current[path[i]] === undefined)
|
|
629
|
-
return // Path does not exist, so nothing to remove.
|
|
630
|
-
}
|
|
575
|
+
if (current[path[i]] === undefined) return
|
|
631
576
|
current = current[path[i]]
|
|
632
577
|
}
|
|
633
578
|
|
|
634
579
|
const lastKey = path[path.length - 1]
|
|
635
|
-
if (current && Object.hasOwnProperty.call(current, lastKey)) {
|
|
580
|
+
if (current && Object.prototype.hasOwnProperty.call(current, lastKey)) {
|
|
636
581
|
delete current[lastKey]
|
|
637
582
|
}
|
|
638
583
|
}
|
|
@@ -645,15 +590,13 @@ export const setInObjectByPath = (obj, path, value) => {
|
|
|
645
590
|
let current = obj
|
|
646
591
|
|
|
647
592
|
for (let i = 0; i < path.length - 1; i++) {
|
|
648
|
-
// If the current path segment doesn't exist or isn't an object, create it
|
|
649
593
|
if (!current[path[i]] || typeof current[path[i]] !== 'object') {
|
|
650
594
|
current[path[i]] = {}
|
|
651
595
|
}
|
|
652
596
|
current = current[path[i]]
|
|
653
597
|
}
|
|
654
598
|
|
|
655
|
-
|
|
656
|
-
current[lastKey] = value
|
|
599
|
+
current[path[path.length - 1]] = value
|
|
657
600
|
|
|
658
601
|
return obj
|
|
659
602
|
}
|
|
@@ -676,25 +619,21 @@ export const getInObjectByPath = (obj, path) => {
|
|
|
676
619
|
}
|
|
677
620
|
|
|
678
621
|
export const detectInfiniteLoop = arr => {
|
|
679
|
-
const maxRepeats = 10
|
|
622
|
+
const maxRepeats = 10
|
|
680
623
|
let pattern = []
|
|
681
624
|
let repeatCount = 0
|
|
682
625
|
|
|
683
626
|
for (let i = 0; i < arr.length; i++) {
|
|
684
627
|
if (pattern.length < 2) {
|
|
685
|
-
// Build the initial pattern with two consecutive elements
|
|
686
628
|
pattern.push(arr[i])
|
|
687
629
|
} else {
|
|
688
|
-
// Check if the current element follows the repeating pattern
|
|
689
630
|
if (arr[i] === pattern[i % 2]) {
|
|
690
631
|
repeatCount++
|
|
691
632
|
} else {
|
|
692
|
-
// If there's a mismatch, reset the pattern and repeat counter
|
|
693
633
|
pattern = [arr[i - 1], arr[i]]
|
|
694
|
-
repeatCount = 1
|
|
634
|
+
repeatCount = 1
|
|
695
635
|
}
|
|
696
636
|
|
|
697
|
-
// If the pattern repeats more than `maxRepeats`, throw a warning
|
|
698
637
|
if (repeatCount >= maxRepeats * 2) {
|
|
699
638
|
if (ENV === 'test' || ENV === 'development') {
|
|
700
639
|
console.warn(
|
|
@@ -709,16 +648,14 @@ export const detectInfiniteLoop = arr => {
|
|
|
709
648
|
}
|
|
710
649
|
|
|
711
650
|
export const isCyclic = obj => {
|
|
712
|
-
const
|
|
651
|
+
const seen = new WeakSet()
|
|
713
652
|
|
|
714
653
|
function detect (obj) {
|
|
715
654
|
if (obj && typeof obj === 'object') {
|
|
716
|
-
if (
|
|
717
|
-
|
|
718
|
-
}
|
|
719
|
-
seenObjects.push(obj)
|
|
655
|
+
if (seen.has(obj)) return true
|
|
656
|
+
seen.add(obj)
|
|
720
657
|
for (const key in obj) {
|
|
721
|
-
if (Object.hasOwnProperty.call(obj, key) && detect(obj[key])) {
|
|
658
|
+
if (Object.prototype.hasOwnProperty.call(obj, key) && detect(obj[key])) {
|
|
722
659
|
console.log(obj, 'cycle at ' + key)
|
|
723
660
|
return true
|
|
724
661
|
}
|
|
@@ -731,7 +668,12 @@ export const isCyclic = obj => {
|
|
|
731
668
|
}
|
|
732
669
|
|
|
733
670
|
export const excludeKeysFromObject = (obj, excludedKeys) => {
|
|
734
|
-
const
|
|
735
|
-
|
|
671
|
+
const excluded = excludedKeys instanceof Set ? excludedKeys : new Set(excludedKeys)
|
|
672
|
+
const result = {}
|
|
673
|
+
for (const key in obj) {
|
|
674
|
+
if (Object.prototype.hasOwnProperty.call(obj, key) && !excluded.has(key)) {
|
|
675
|
+
result[key] = obj[key]
|
|
676
|
+
}
|
|
677
|
+
}
|
|
736
678
|
return result
|
|
737
679
|
}
|