1818
1919"use strict" ; 
2020
21+ var  CallbackQueue  =  require ( 'CallbackQueue' ) ; 
22+ var  PooledClass  =  require ( 'PooledClass' ) ; 
2123var  ReactCurrentOwner  =  require ( 'ReactCurrentOwner' ) ; 
2224var  ReactPerf  =  require ( 'ReactPerf' ) ; 
25+ var  Transaction  =  require ( 'Transaction' ) ; 
2326
2427var  invariant  =  require ( 'invariant' ) ; 
28+ var  mixInto  =  require ( 'mixInto' ) ; 
2529var  warning  =  require ( 'warning' ) ; 
2630
2731var  dirtyComponents  =  [ ] ; 
@@ -36,9 +40,77 @@ function ensureInjected() {
3640  ) ; 
3741} 
3842
39- function  batchedUpdates ( callback ,  param )  { 
43+ var  NESTED_UPDATES  =  { 
44+   initialize : function ( )  { 
45+     this . dirtyComponentsLength  =  dirtyComponents . length ; 
46+   } , 
47+   close : function ( )  { 
48+     if  ( this . dirtyComponentsLength  !==  dirtyComponents . length )  { 
49+       // Additional updates were enqueued by componentDidUpdate handlers or 
50+       // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run 
51+       // these new updates so that if A's componentDidUpdate calls setState on 
52+       // B, B will update before the callback A's updater provided when calling 
53+       // setState. 
54+       dirtyComponents . splice ( 0 ,  this . dirtyComponentsLength ) ; 
55+       flushBatchedUpdates ( ) ; 
56+     }  else  { 
57+       dirtyComponents . length  =  0 ; 
58+     } 
59+   } 
60+ } ; 
61+ 
62+ var  UPDATE_QUEUEING  =  { 
63+   initialize : function ( )  { 
64+     this . callbackQueue . reset ( ) ; 
65+   } , 
66+   close : function ( )  { 
67+     this . callbackQueue . notifyAll ( ) ; 
68+   } 
69+ } ; 
70+ 
71+ var  TRANSACTION_WRAPPERS  =  [ NESTED_UPDATES ,  UPDATE_QUEUEING ] ; 
72+ 
73+ function  ReactUpdatesFlushTransaction ( )  { 
74+   this . reinitializeTransaction ( ) ; 
75+   this . dirtyComponentsLength  =  null ; 
76+   this . callbackQueue  =  CallbackQueue . getPooled ( null ) ; 
77+   this . reconcileTransaction  = 
78+     ReactUpdates . ReactReconcileTransaction . getPooled ( ) ; 
79+ } 
80+ 
81+ mixInto ( ReactUpdatesFlushTransaction ,  Transaction . Mixin ) ; 
82+ mixInto ( ReactUpdatesFlushTransaction ,  { 
83+   getTransactionWrappers : function ( )  { 
84+     return  TRANSACTION_WRAPPERS ; 
85+   } , 
86+ 
87+   destructor : function ( )  { 
88+     this . dirtyComponentsLength  =  null ; 
89+     CallbackQueue . release ( this . callbackQueue ) ; 
90+     this . callbackQueue  =  null ; 
91+     ReactUpdates . ReactReconcileTransaction . release ( this . reconcileTransaction ) ; 
92+     this . reconcileTransaction  =  null ; 
93+   } , 
94+ 
95+   perform : function ( method ,  scope ,  a )  { 
96+     // Essentially calls `this.reconcileTransaction.perform(method, scope, a)` 
97+     // with this transaction's wrappers around it. 
98+     return  Transaction . Mixin . perform . call ( 
99+       this , 
100+       this . reconcileTransaction . perform , 
101+       this . reconcileTransaction , 
102+       method , 
103+       scope , 
104+       a 
105+     ) ; 
106+   } 
107+ } ) ; 
108+ 
109+ PooledClass . addPoolingTo ( ReactUpdatesFlushTransaction ) ; 
110+ 
111+ function  batchedUpdates ( callback ,  a ,  b )  { 
40112  ensureInjected ( ) ; 
41-   batchingStrategy . batchedUpdates ( callback ,  param ) ; 
113+   batchingStrategy . batchedUpdates ( callback ,  a ,   b ) ; 
42114} 
43115
44116/** 
@@ -53,13 +125,21 @@ function mountDepthComparator(c1, c2) {
53125} 
54126
55127function  runBatchedUpdates ( transaction )  { 
128+   var  len  =  transaction . dirtyComponentsLength ; 
129+   invariant ( 
130+     len  ===  dirtyComponents . length , 
131+     'Expected flush transaction\'s stored dirty-components length (%s) to '  + 
132+     'match dirty-components array length (%s).' , 
133+     len , 
134+     dirtyComponents . length 
135+   ) ; 
136+ 
56137  // Since reconciling a component higher in the owner hierarchy usually (not 
57138  // always -- see shouldComponentUpdate()) will reconcile children, reconcile 
58139  // them before their children by sorting the array. 
59- 
60140  dirtyComponents . sort ( mountDepthComparator ) ; 
61141
62-   for  ( var  i  =  0 ;  i  <  dirtyComponents . length ;  i ++ )  { 
142+   for  ( var  i  =  0 ;  i  <  len ;  i ++ )  { 
63143    // If a component is unmounted before pending changes apply, ignore them 
64144    // TODO: Queue unmounts in the same list to avoid this happening at all 
65145    var  component  =  dirtyComponents [ i ] ; 
@@ -69,11 +149,11 @@ function runBatchedUpdates(transaction) {
69149      // stash the callbacks first 
70150      var  callbacks  =  component . _pendingCallbacks ; 
71151      component . _pendingCallbacks  =  null ; 
72-       component . performUpdateIfNecessary ( transaction ) ; 
152+       component . performUpdateIfNecessary ( transaction . reconcileTransaction ) ; 
73153
74154      if  ( callbacks )  { 
75155        for  ( var  j  =  0 ;  j  <  callbacks . length ;  j ++ )  { 
76-           transaction . getReactMountReady ( ) . enqueue ( 
156+           transaction . callbackQueue . enqueue ( 
77157            callbacks [ j ] , 
78158            component 
79159          ) ; 
@@ -83,30 +163,18 @@ function runBatchedUpdates(transaction) {
83163  } 
84164} 
85165
86- function  clearDirtyComponents ( )  { 
87-   dirtyComponents . length  =  0 ; 
88- } 
89- 
90- function  flushBatchedUpdatesOnce ( transaction )  { 
91-   // Run these in separate functions so the JIT can optimize 
92-   try  { 
93-     runBatchedUpdates ( transaction ) ; 
94-   }  finally  { 
95-     clearDirtyComponents ( ) ; 
96-   } 
97- } 
98- 
99166var  flushBatchedUpdates  =  ReactPerf . measure ( 
100167  'ReactUpdates' , 
101168  'flushBatchedUpdates' , 
102169  function ( )  { 
103-     // flushBatchedUpdatesOnce will clear the dirtyComponents array, but 
104-     // mount-ready handlers (i.e., componentDidMount/Update) may enqueue more 
105-     // state updates which we should apply immediately 
170+     // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents 
171+     // array and perform any updates enqueued by mount-ready handlers (i.e., 
172+     // componentDidUpdate) but we need to check here too in order to catch 
173+     // updates enqueued by setState callbacks. 
106174    while  ( dirtyComponents . length )  { 
107-       var  transaction  =  ReactUpdates . ReactReconcileTransaction . getPooled ( ) ; 
108-       transaction . perform ( flushBatchedUpdatesOnce ,  null ,  transaction ) ; 
109-       ReactUpdates . ReactReconcileTransaction . release ( transaction ) ; 
175+       var  transaction  =  ReactUpdatesFlushTransaction . getPooled ( ) ; 
176+       transaction . perform ( runBatchedUpdates ,  null ,  transaction ) ; 
177+       ReactUpdatesFlushTransaction . release ( transaction ) ; 
110178    } 
111179  } 
112180) ; 
@@ -138,14 +206,7 @@ function enqueueUpdate(component, callback) {
138206  ) ; 
139207
140208  if  ( ! batchingStrategy . isBatchingUpdates )  { 
141-     var  transaction  =  ReactUpdates . ReactReconcileTransaction . getPooled ( ) ; 
142-     transaction . perform ( 
143-       component . performUpdateIfNecessary , 
144-       component , 
145-       transaction 
146-     ) ; 
147-     ReactUpdates . ReactReconcileTransaction . release ( transaction ) ; 
148-     callback  &&  callback . call ( component ) ; 
209+     batchingStrategy . batchedUpdates ( enqueueUpdate ,  component ,  callback ) ; 
149210    return ; 
150211  } 
151212
0 commit comments