(first, second, internalCaching = false)
| 332 | * @returns {T & O} merged object of first and second object |
| 333 | */ |
| 334 | const _cleverMerge = (first, second, internalCaching = false) => { |
| 335 | const firstObject = internalCaching |
| 336 | ? cachedParseObject(first) |
| 337 | : parseObject(first); |
| 338 | const { static: firstInfo, dynamic: firstDynamicInfo } = firstObject; |
| 339 | |
| 340 | // If the first argument has a dynamic part we modify the dynamic part to merge the second argument |
| 341 | if (firstDynamicInfo !== undefined) { |
| 342 | let { byProperty, fn } = firstDynamicInfo; |
| 343 | const fnInfo = fn[DYNAMIC_INFO]; |
| 344 | if (fnInfo) { |
| 345 | second = |
| 346 | /** @type {O} */ |
| 347 | ( |
| 348 | internalCaching |
| 349 | ? cachedCleverMerge(fnInfo[1], second) |
| 350 | : cleverMerge(fnInfo[1], second) |
| 351 | ); |
| 352 | fn = fnInfo[0]; |
| 353 | } |
| 354 | /** @type {DynamicFunction} */ |
| 355 | const newFn = (...args) => { |
| 356 | const fnResult = fn(...args); |
| 357 | return internalCaching |
| 358 | ? cachedCleverMerge(fnResult, second) |
| 359 | : cleverMerge(fnResult, second); |
| 360 | }; |
| 361 | newFn[DYNAMIC_INFO] = [fn, second]; |
| 362 | return /** @type {T & O} */ ( |
| 363 | serializeObject(firstObject.static, { byProperty, fn: newFn }) |
| 364 | ); |
| 365 | } |
| 366 | |
| 367 | // If the first part is static only, we merge the static parts and keep the dynamic part of the second argument |
| 368 | const secondObject = internalCaching |
| 369 | ? cachedParseObject(second) |
| 370 | : parseObject(second); |
| 371 | const { static: secondInfo, dynamic: secondDynamicInfo } = secondObject; |
| 372 | const resultInfo = new Map(); |
| 373 | for (const [key, firstEntry] of firstInfo) { |
| 374 | const secondEntry = secondInfo.get( |
| 375 | /** @type {keyof (T | O)} */ |
| 376 | (key) |
| 377 | ); |
| 378 | const entry = |
| 379 | secondEntry !== undefined |
| 380 | ? mergeEntries(firstEntry, secondEntry, internalCaching) |
| 381 | : firstEntry; |
| 382 | resultInfo.set(key, entry); |
| 383 | } |
| 384 | for (const [key, secondEntry] of secondInfo) { |
| 385 | if (!firstInfo.has(/** @type {keyof (T | O)} */ (key))) { |
| 386 | resultInfo.set(key, secondEntry); |
| 387 | } |
| 388 | } |
| 389 | return /** @type {T & O} */ (serializeObject(resultInfo, secondDynamicInfo)); |
| 390 | }; |
| 391 |
no test coverage detected