99
1010import invariant from 'shared/invariant' ;
1111
12- let invokeGuardedCallbackImpl = function < A , B , C , D , E , F , Context > (
12+ function invokeGuardedCallbackProd < A , B , C , D , E , F , Context > (
1313 name : string | null ,
1414 func : ( a : A , b : B , c : C , d : D , e : E , f : F ) = > mixed ,
1515 context : Context ,
@@ -26,7 +26,9 @@ let invokeGuardedCallbackImpl = function<A, B, C, D, E, F, Context>(
2626 } catch ( error ) {
2727 this . onError ( error ) ;
2828 }
29- } ;
29+ }
30+
31+ let invokeGuardedCallbackImpl = invokeGuardedCallbackProd ;
3032
3133if ( __DEV__ ) {
3234 // In DEV mode, we swap out invokeGuardedCallback for a special version
@@ -58,7 +60,15 @@ if (__DEV__) {
5860 ) {
5961 const fakeNode = document . createElement ( 'react' ) ;
6062
61- const invokeGuardedCallbackDev = function < A , B , C , D , E , F , Context > (
63+ invokeGuardedCallbackImpl = function invokeGuardedCallbackDev <
64+ A ,
65+ B ,
66+ C ,
67+ D ,
68+ E ,
69+ F ,
70+ Context ,
71+ > (
6272 name : string | null ,
6373 func : ( a : A , b : B , c : C , d : D , e : E , f : F ) = > mixed ,
6474 context : Context ,
@@ -85,6 +95,7 @@ if (__DEV__) {
8595 ) ;
8696 const evt = document . createEvent ( 'Event' ) ;
8797
98+ let didCall = false ;
8899 // Keeps track of whether the user-provided callback threw an error. We
89100 // set this to true at the beginning, then set it to false right after
90101 // calling the function. If the function errors, `didError` will never be
@@ -105,11 +116,7 @@ if (__DEV__) {
105116 'event' ,
106117 ) ;
107118
108- // Create an event handler for our fake event. We will synchronously
109- // dispatch our fake event using `dispatchEvent`. Inside the handler, we
110- // call the user-provided callback.
111- const funcArgs = Array . prototype . slice . call ( arguments , 3 ) ;
112- function callCallback ( ) {
119+ function restoreAfterDispatch ( ) {
113120 // We immediately remove the callback from event listeners so that
114121 // nested `invokeGuardedCallback` calls do not clash. Otherwise, a
115122 // nested call would trigger the fake event handlers of any call higher
@@ -126,7 +133,15 @@ if (__DEV__) {
126133 ) {
127134 window . event = windowEvent ;
128135 }
136+ }
129137
138+ // Create an event handler for our fake event. We will synchronously
139+ // dispatch our fake event using `dispatchEvent`. Inside the handler, we
140+ // call the user-provided callback.
141+ const funcArgs = Array . prototype . slice . call ( arguments , 3 ) ;
142+ function callCallback ( ) {
143+ didCall = true ;
144+ restoreAfterDispatch ( ) ;
130145 func . apply ( context , funcArgs ) ;
131146 didError = false ;
132147 }
@@ -183,7 +198,7 @@ if (__DEV__) {
183198 Object . defineProperty ( window , 'event' , windowEventDescriptor ) ;
184199 }
185200
186- if ( didError ) {
201+ if ( didCall && didError ) {
187202 if ( ! didSetError ) {
188203 // The callback errored, but the error event never fired.
189204 error = new Error (
@@ -208,9 +223,16 @@ if (__DEV__) {
208223
209224 // Remove our event listeners
210225 window . removeEventListener ( 'error' , handleWindowError ) ;
211- } ;
212226
213- invokeGuardedCallbackImpl = invokeGuardedCallbackDev ;
227+ if ( ! didCall ) {
228+ // Something went really wrong, and our event was not dispatched.
229+ // https://github.com/facebook/react/issues/16734
230+ // https://github.com/facebook/react/issues/16585
231+ // Fall back to the production implementation.
232+ restoreAfterDispatch ( ) ;
233+ return invokeGuardedCallbackProd . apply ( this , arguments ) ;
234+ }
235+ } ;
214236 }
215237}
216238
0 commit comments