|
|
@ -120,59 +120,42 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Here we have async deferring wrappers using microtasks.
|
|
|
|
// An asynchronous deferring mechanism.
|
|
|
|
// In 2.5 we used (macro) tasks (in combination with microtasks).
|
|
|
|
// In pre 2.4, we used to use microtasks (Promise/MutationObserver)
|
|
|
|
// However, it has subtle problems when state is changed right before repaint
|
|
|
|
// but microtasks actually has too high a priority and fires in between
|
|
|
|
// (e.g. #6813, out-in transitions).
|
|
|
|
// supposedly sequential events (e.g. #4521, #6690) or even between
|
|
|
|
// Also, using (macro) tasks in event handler would cause some weird behaviors
|
|
|
|
// bubbling of the same event (#6566). Technically setImmediate should be
|
|
|
|
// that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109).
|
|
|
|
// the ideal choice, but it's not available everywhere; and the only polyfill
|
|
|
|
// So we now use microtasks everywhere, again.
|
|
|
|
// that consistently queues the callback after all DOM events triggered in the
|
|
|
|
// A major drawback of this tradeoff is that there are some scenarios
|
|
|
|
// same loop is by using MessageChannel.
|
|
|
|
// where microtasks have too high a priority and fire in between supposedly
|
|
|
|
/* istanbul ignore if */ |
|
|
|
// sequential events (e.g. #4521, #6690, which have workarounds)
|
|
|
|
if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { |
|
|
|
// or even between bubbling of the same event (#6566).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The nextTick behavior leverages the microtask queue, which can be accessed
|
|
|
|
|
|
|
|
// via either native Promise.then or MutationObserver.
|
|
|
|
|
|
|
|
// MutationObserver has wider support, however it is seriously bugged in
|
|
|
|
|
|
|
|
// UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
|
|
|
|
|
|
|
|
// completely stops working after triggering a few times... so, if native
|
|
|
|
|
|
|
|
// Promise is available, we will use it:
|
|
|
|
|
|
|
|
/* istanbul ignore next, $flow-disable-line */ |
|
|
|
|
|
|
|
if (typeof Promise !== 'undefined' && isNative(Promise)) { |
|
|
|
|
|
|
|
var p = Promise.resolve(); |
|
|
|
|
|
|
|
timerFunc = function timerFunc() { |
|
|
|
|
|
|
|
p.then(nextTickHandler); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} else if (!isIE && typeof MutationObserver !== 'undefined' && (isNative(MutationObserver) || |
|
|
|
|
|
|
|
// PhantomJS and iOS 7.x
|
|
|
|
|
|
|
|
MutationObserver.toString() === '[object MutationObserverConstructor]')) { |
|
|
|
|
|
|
|
// Use MutationObserver where native Promise is not available,
|
|
|
|
|
|
|
|
// e.g. PhantomJS, iOS7, Android 4.4
|
|
|
|
|
|
|
|
// (#6466 MutationObserver is unreliable in IE11)
|
|
|
|
|
|
|
|
var counter = 1; |
|
|
|
|
|
|
|
var observer = new MutationObserver(nextTickHandler); |
|
|
|
|
|
|
|
var textNode = document.createTextNode(String(counter)); |
|
|
|
|
|
|
|
observer.observe(textNode, { |
|
|
|
|
|
|
|
characterData: true |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
timerFunc = function timerFunc() { |
|
|
|
|
|
|
|
counter = (counter + 1) % 2; |
|
|
|
|
|
|
|
textNode.data = String(counter); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { |
|
|
|
|
|
|
|
// Fallback to setImmediate.
|
|
|
|
|
|
|
|
// Technically it leverages the (macro) task queue,
|
|
|
|
|
|
|
|
// but it is still a better choice than setTimeout.
|
|
|
|
|
|
|
|
timerFunc = function timerFunc() { |
|
|
|
timerFunc = function timerFunc() { |
|
|
|
setImmediate(nextTickHandler); |
|
|
|
setImmediate(nextTickHandler); |
|
|
|
}; |
|
|
|
}; |
|
|
|
} else { |
|
|
|
} else if (typeof MessageChannel !== 'undefined' && (isNative(MessageChannel) || |
|
|
|
// Fallback to setTimeout.
|
|
|
|
// PhantomJS
|
|
|
|
|
|
|
|
MessageChannel.toString() === '[object MessageChannelConstructor]')) { |
|
|
|
|
|
|
|
var channel = new MessageChannel(); |
|
|
|
|
|
|
|
var port = channel.port2; |
|
|
|
|
|
|
|
channel.port1.onmessage = nextTickHandler; |
|
|
|
timerFunc = function timerFunc() { |
|
|
|
timerFunc = function timerFunc() { |
|
|
|
setTimeout(nextTickHandler, 0); |
|
|
|
port.postMessage(1); |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} else |
|
|
|
|
|
|
|
/* istanbul ignore next */ |
|
|
|
|
|
|
|
if (typeof Promise !== 'undefined' && isNative(Promise)) { |
|
|
|
|
|
|
|
// use microtask in non-DOM environments, e.g. Weex
|
|
|
|
|
|
|
|
var p = Promise.resolve(); |
|
|
|
|
|
|
|
timerFunc = function timerFunc() { |
|
|
|
|
|
|
|
p.then(nextTickHandler); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// fallback to setTimeout
|
|
|
|
|
|
|
|
timerFunc = function timerFunc() { |
|
|
|
|
|
|
|
setTimeout(nextTickHandler, 0); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return function queueNextTick(cb, ctx) { |
|
|
|
return function queueNextTick(cb, ctx) { |
|
|
|
var _resolve = void 0; |
|
|
|
var _resolve = void 0; |
|
|
|