import isNative from './isNative';
const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
let timeoutDuration = 0;
for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) {
Iif (navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
timeoutDuration = 1;
break;
}
}
export function microtaskDebounce(fn) {
let scheduled = false;
let i = 0;
const elem = document.createElement('span');
// MutationObserver provides a mechanism for scheduling microtasks, which
// are scheduled *before* the next task. This gives us a way to debounce
// a function but ensure it's called *before* the next paint.
const observer = new MutationObserver(() => {
fn();
scheduled = false;
});
observer.observe(elem, { attributes: true });
return () => {
if (!scheduled) {
scheduled = true;
elem.setAttribute('x-index', i);
i = i + 1; // don't use compund (+=) because it doesn't get optimized in V8
}
};
}
export function taskDebounce(fn) {
let scheduled = false;
return () => {
if (!scheduled) {
scheduled = true;
setTimeout(() => {
scheduled = false;
fn();
}, timeoutDuration);
}
};
}
// It's common for MutationObserver polyfills to be seen in the wild, however
// these rely on Mutation Events which only occur when an element is connected
// to the DOM. The algorithm used in this module does not use a connected element,
// and so we must ensure that a *native* MutationObserver is available.
const supportsNativeMutationObserver = isNative(window.MutationObserver);
/**
* Create a debounced version of a method, that's asynchronously deferred
* but called in the minimum time possible.
*
* @method
* @memberof Popper.Utils
* @argument {Function} fn
* @returns {Function}
*/
export default supportsNativeMutationObserver ? microtaskDebounce : taskDebounce;
|