3
3
4
4
import { noop } from 'shared/util'
5
5
import { handleError } from './error'
6
- import { isIOS , isNative } from './env'
6
+ import { isIOS , isNative , inWeex } from './env'
7
7
8
8
const callbacks = [ ]
9
9
let pending = false
@@ -29,49 +29,60 @@ let microTimerFunc
29
29
let macroTimerFunc
30
30
let useMacroTask = false
31
31
32
- // Determine (macro) task defer implementation.
33
- // Technically setImmediate should be the ideal choice, but it's only available
34
- // in IE. The only polyfill that consistently queues the callback after all DOM
35
- // events triggered in the same loop is by using MessageChannel.
36
- /* istanbul ignore if */
37
- if ( typeof setImmediate !== 'undefined' && isNative ( setImmediate ) ) {
38
- macroTimerFunc = ( ) => {
39
- setImmediate ( flushCallbacks )
40
- }
41
- } else if ( typeof MessageChannel !== 'undefined' && (
42
- isNative ( MessageChannel ) ||
43
- // PhantomJS
44
- MessageChannel . toString ( ) === '[object MessageChannelConstructor]'
45
- ) ) {
46
- const channel = new MessageChannel ( )
47
- const port = channel . port2
48
- channel . port1 . onmessage = flushCallbacks
49
- macroTimerFunc = ( ) => {
50
- port . postMessage ( 1 )
32
+ export function initTimerFunc ( ) {
33
+ // Determine (macro) task defer implementation.
34
+ // Technically setImmediate should be the ideal choice, but it's only available
35
+ // in IE. The only polyfill that consistently queues the callback after all DOM
36
+ // events triggered in the same loop is by using MessageChannel.
37
+ /* istanbul ignore if */
38
+ if ( typeof setImmediate !== 'undefined' && isNative ( setImmediate ) ) {
39
+ macroTimerFunc = ( ) => {
40
+ setImmediate ( flushCallbacks )
41
+ }
42
+ } else if ( typeof MessageChannel !== 'undefined' && (
43
+ isNative ( MessageChannel ) ||
44
+ // PhantomJS
45
+ MessageChannel . toString ( ) === '[object MessageChannelConstructor]'
46
+ ) ) {
47
+ const channel = new MessageChannel ( )
48
+ const port = channel . port2
49
+ channel . port1 . onmessage = flushCallbacks
50
+ macroTimerFunc = ( ) => {
51
+ port . postMessage ( 1 )
52
+ }
53
+ } else {
54
+ /* istanbul ignore next */
55
+ macroTimerFunc = ( ) => {
56
+ setTimeout ( flushCallbacks , 0 )
57
+ }
51
58
}
52
- } else {
53
- /* istanbul ignore next */
54
- macroTimerFunc = ( ) => {
55
- setTimeout ( flushCallbacks , 0 )
59
+
60
+ // Determine microtask defer implementation.
61
+ /* istanbul ignore next, $flow-disable-line */
62
+ if ( typeof Promise !== 'undefined' && isNative ( Promise ) ) {
63
+ const p = Promise . resolve ( )
64
+ microTimerFunc = ( ) => {
65
+ p . then ( flushCallbacks )
66
+ // in problematic UIWebViews, Promise.then doesn't completely break, but
67
+ // it can get stuck in a weird state where callbacks are pushed into the
68
+ // microtask queue but the queue isn't being flushed, until the browser
69
+ // needs to do some other work, e.g. handle a timer. Therefore we can
70
+ // "force" the microtask queue to be flushed by adding an empty timer.
71
+ if ( ! inWeex && isIOS ) setTimeout ( noop )
72
+ }
73
+ } else {
74
+ // fallback to macro
75
+ microTimerFunc = macroTimerFunc
56
76
}
57
77
}
78
+ initTimerFunc ( )
58
79
59
- // Determine microtask defer implementation.
60
- /* istanbul ignore next, $flow-disable-line */
61
- if ( typeof Promise !== 'undefined' && isNative ( Promise ) ) {
62
- const p = Promise . resolve ( )
63
- microTimerFunc = ( ) => {
64
- p . then ( flushCallbacks )
65
- // in problematic UIWebViews, Promise.then doesn't completely break, but
66
- // it can get stuck in a weird state where callbacks are pushed into the
67
- // microtask queue but the queue isn't being flushed, until the browser
68
- // needs to do some other work, e.g. handle a timer. Therefore we can
69
- // "force" the microtask queue to be flushed by adding an empty timer.
70
- if ( isIOS ) setTimeout ( noop )
71
- }
72
- } else {
73
- // fallback to macro
74
- microTimerFunc = macroTimerFunc
80
+ export function resetTimerFunc ( ) {
81
+ callbacks . length = 0
82
+ pending = false
83
+ microTimerFunc = null
84
+ macroTimerFunc = null
85
+ useMacroTask = false
75
86
}
76
87
77
88
/**
@@ -102,10 +113,12 @@ export function nextTick (cb?: Function, ctx?: Object) {
102
113
} )
103
114
if ( ! pending ) {
104
115
pending = true
105
- if ( useMacroTask ) {
116
+ if ( useMacroTask && typeof macroTimerFunc === 'function' ) {
106
117
macroTimerFunc ( )
107
- } else {
118
+ } else if ( typeof microTimerFunc === 'function' ) {
108
119
microTimerFunc ( )
120
+ } else {
121
+ setTimeout ( flushCallbacks , 0 )
109
122
}
110
123
}
111
124
// $flow-disable-line
0 commit comments