(root: Document | ShadowRoot, callbacks: OptimizedTreeObserverCallbacks)
| 333 | |
| 334 | // TODO: Use a single function to observe all shadow roots. |
| 335 | export function createOptimizedTreeObserver(root: Document | ShadowRoot, callbacks: OptimizedTreeObserverCallbacks): {disconnect: () => void} { |
| 336 | let observer: MutationObserver; |
| 337 | let observerCallbacks: Set<OptimizedTreeObserverCallbacks>; |
| 338 | let domReadyListener: () => void; |
| 339 | |
| 340 | if (optimizedTreeObservers.has(root)) { |
| 341 | observer = optimizedTreeObservers.get(root)!; |
| 342 | observerCallbacks = optimizedTreeCallbacks.get(observer)!; |
| 343 | } else { |
| 344 | let hadHugeMutationsBefore = false; |
| 345 | let subscribedForReadyState = false; |
| 346 | |
| 347 | observer = new MutationObserver((mutations: MutationRecord[]) => { |
| 348 | if (isHugeMutation(mutations)) { |
| 349 | if (!hadHugeMutationsBefore || isDOMReady()) { |
| 350 | observerCallbacks.forEach(({onHugeMutations}) => onHugeMutations(root)); |
| 351 | } else if (!subscribedForReadyState) { |
| 352 | domReadyListener = () => observerCallbacks.forEach(({onHugeMutations}) => onHugeMutations(root)); |
| 353 | addDOMReadyListener(domReadyListener); |
| 354 | subscribedForReadyState = true; |
| 355 | } |
| 356 | hadHugeMutationsBefore = true; |
| 357 | } else { |
| 358 | const elementsOperations = getElementsTreeOperations(mutations); |
| 359 | observerCallbacks.forEach(({onMinorMutations}) => onMinorMutations(root, elementsOperations)); |
| 360 | } |
| 361 | }); |
| 362 | observer.observe(root, {childList: true, subtree: true}); |
| 363 | optimizedTreeObservers.set(root, observer); |
| 364 | observerCallbacks = new Set(); |
| 365 | optimizedTreeCallbacks.set(observer, observerCallbacks); |
| 366 | } |
| 367 | |
| 368 | observerCallbacks.add(callbacks); |
| 369 | |
| 370 | return { |
| 371 | disconnect() { |
| 372 | observerCallbacks.delete(callbacks); |
| 373 | if (domReadyListener) { |
| 374 | removeDOMReadyListener(domReadyListener); |
| 375 | } |
| 376 | if (observerCallbacks.size === 0) { |
| 377 | observer.disconnect(); |
| 378 | optimizedTreeCallbacks.delete(observer); |
| 379 | optimizedTreeObservers.delete(root); |
| 380 | } |
| 381 | }, |
| 382 | }; |
| 383 | } |
no test coverage detected