Projekt

Obecné

Profil

Stáhnout (59.1 KB) Statistiky
| Větev: | Revize:
1
/** @license React v16.13.1
2
 * react-dom-unstable-native-dependencies.development.js
3
 *
4
 * Copyright (c) Facebook, Inc. and its affiliates.
5
 *
6
 * This source code is licensed under the MIT license found in the
7
 * LICENSE file in the root directory of this source tree.
8
 */
9

    
10
'use strict';
11

    
12
(function (global, factory) {
13
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react-dom'), require('react')) :
14
  typeof define === 'function' && define.amd ? define(['react-dom', 'react'], factory) :
15
  (global = global || self, global.ReactDOMUnstableNativeDependencies = factory(global.ReactDOM, global.React));
16
}(this, (function (ReactDOM, React) { 'use strict';
17

    
18
  var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Prevent newer renderers from RTE when used with older react package versions.
19
  // Current owner and dispatcher used to share the same ref,
20
  // but PR #14548 split them out to better support the react-debug-tools package.
21

    
22
  if (!ReactSharedInternals.hasOwnProperty('ReactCurrentDispatcher')) {
23
    ReactSharedInternals.ReactCurrentDispatcher = {
24
      current: null
25
    };
26
  }
27

    
28
  if (!ReactSharedInternals.hasOwnProperty('ReactCurrentBatchConfig')) {
29
    ReactSharedInternals.ReactCurrentBatchConfig = {
30
      suspense: null
31
    };
32
  }
33

    
34
  // by calls to these methods by a Babel plugin.
35
  //
36
  // In PROD (or in packages without access to React internals),
37
  // they are left as they are instead.
38

    
39
  function warn(format) {
40
    {
41
      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
42
        args[_key - 1] = arguments[_key];
43
      }
44

    
45
      printWarning('warn', format, args);
46
    }
47
  }
48
  function error(format) {
49
    {
50
      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
51
        args[_key2 - 1] = arguments[_key2];
52
      }
53

    
54
      printWarning('error', format, args);
55
    }
56
  }
57

    
58
  function printWarning(level, format, args) {
59
    // When changing this logic, you might want to also
60
    // update consoleWithStackDev.www.js as well.
61
    {
62
      var hasExistingStack = args.length > 0 && typeof args[args.length - 1] === 'string' && args[args.length - 1].indexOf('\n    in') === 0;
63

    
64
      if (!hasExistingStack) {
65
        var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
66
        var stack = ReactDebugCurrentFrame.getStackAddendum();
67

    
68
        if (stack !== '') {
69
          format += '%s';
70
          args = args.concat([stack]);
71
        }
72
      }
73

    
74
      var argsWithFormat = args.map(function (item) {
75
        return '' + item;
76
      }); // Careful: RN currently depends on this prefix
77

    
78
      argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
79
      // breaks IE9: https://github.com/facebook/react/issues/13610
80
      // eslint-disable-next-line react-internal/no-production-logging
81

    
82
      Function.prototype.apply.call(console[level], console, argsWithFormat);
83

    
84
      try {
85
        // --- Welcome to debugging React ---
86
        // This error was thrown as a convenience so that you can use this stack
87
        // to find the callsite that caused this warning to fire.
88
        var argIndex = 0;
89
        var message = 'Warning: ' + format.replace(/%s/g, function () {
90
          return args[argIndex++];
91
        });
92
        throw new Error(message);
93
      } catch (x) {}
94
    }
95
  }
96

    
97
  {
98
    // In DEV mode, we swap out invokeGuardedCallback for a special version
99
    // that plays more nicely with the browser's DevTools. The idea is to preserve
100
    // "Pause on exceptions" behavior. Because React wraps all user-provided
101
    // functions in invokeGuardedCallback, and the production version of
102
    // invokeGuardedCallback uses a try-catch, all user exceptions are treated
103
    // like caught exceptions, and the DevTools won't pause unless the developer
104
    // takes the extra step of enabling pause on caught exceptions. This is
105
    // unintuitive, though, because even though React has caught the error, from
106
    // the developer's perspective, the error is uncaught.
107
    //
108
    // To preserve the expected "Pause on exceptions" behavior, we don't use a
109
    // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake
110
    // DOM node, and call the user-provided callback from inside an event handler
111
    // for that fake event. If the callback throws, the error is "captured" using
112
    // a global event handler. But because the error happens in a different
113
    // event loop context, it does not interrupt the normal program flow.
114
    // Effectively, this gives us try-catch behavior without actually using
115
    // try-catch. Neat!
116
    // Check that the browser supports the APIs we need to implement our special
117
    // DEV version of invokeGuardedCallback
118
    if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
119
      var fakeNode = document.createElement('react');
120
    }
121
  }
122

    
123
  var getFiberCurrentPropsFromNode = null;
124
  var getInstanceFromNode = null;
125
  var getNodeFromInstance = null;
126
  function setComponentTree(getFiberCurrentPropsFromNodeImpl, getInstanceFromNodeImpl, getNodeFromInstanceImpl) {
127
    getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl;
128
    getInstanceFromNode = getInstanceFromNodeImpl;
129
    getNodeFromInstance = getNodeFromInstanceImpl;
130

    
131
    {
132
      if (!getNodeFromInstance || !getInstanceFromNode) {
133
        error('EventPluginUtils.setComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.');
134
      }
135
    }
136
  }
137
  var validateEventDispatches;
138

    
139
  {
140
    validateEventDispatches = function (event) {
141
      var dispatchListeners = event._dispatchListeners;
142
      var dispatchInstances = event._dispatchInstances;
143
      var listenersIsArr = Array.isArray(dispatchListeners);
144
      var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
145
      var instancesIsArr = Array.isArray(dispatchInstances);
146
      var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
147

    
148
      if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) {
149
        error('EventPluginUtils: Invalid `event`.');
150
      }
151
    };
152
  }
153
  /**
154
   * Standard/simple iteration through an event's collected dispatches, but stops
155
   * at the first dispatch execution returning true, and returns that id.
156
   *
157
   * @return {?string} id of the first dispatch execution who's listener returns
158
   * true, or null if no listener returned true.
159
   */
160

    
161
  function executeDispatchesInOrderStopAtTrueImpl(event) {
162
    var dispatchListeners = event._dispatchListeners;
163
    var dispatchInstances = event._dispatchInstances;
164

    
165
    {
166
      validateEventDispatches(event);
167
    }
168

    
169
    if (Array.isArray(dispatchListeners)) {
170
      for (var i = 0; i < dispatchListeners.length; i++) {
171
        if (event.isPropagationStopped()) {
172
          break;
173
        } // Listeners and Instances are two parallel arrays that are always in sync.
174

    
175

    
176
        if (dispatchListeners[i](event, dispatchInstances[i])) {
177
          return dispatchInstances[i];
178
        }
179
      }
180
    } else if (dispatchListeners) {
181
      if (dispatchListeners(event, dispatchInstances)) {
182
        return dispatchInstances;
183
      }
184
    }
185

    
186
    return null;
187
  }
188
  /**
189
   * @see executeDispatchesInOrderStopAtTrueImpl
190
   */
191

    
192

    
193
  function executeDispatchesInOrderStopAtTrue(event) {
194
    var ret = executeDispatchesInOrderStopAtTrueImpl(event);
195
    event._dispatchInstances = null;
196
    event._dispatchListeners = null;
197
    return ret;
198
  }
199
  /**
200
   * Execution of a "direct" dispatch - there must be at most one dispatch
201
   * accumulated on the event or it is considered an error. It doesn't really make
202
   * sense for an event with multiple dispatches (bubbled) to keep track of the
203
   * return values at each dispatch execution, but it does tend to make sense when
204
   * dealing with "direct" dispatches.
205
   *
206
   * @return {*} The return value of executing the single dispatch.
207
   */
208

    
209
  function executeDirectDispatch(event) {
210
    {
211
      validateEventDispatches(event);
212
    }
213

    
214
    var dispatchListener = event._dispatchListeners;
215
    var dispatchInstance = event._dispatchInstances;
216

    
217
    if (!!Array.isArray(dispatchListener)) {
218
      {
219
        throw Error( "executeDirectDispatch(...): Invalid `event`." );
220
      }
221
    }
222

    
223
    event.currentTarget = dispatchListener ? getNodeFromInstance(dispatchInstance) : null;
224
    var res = dispatchListener ? dispatchListener(event) : null;
225
    event.currentTarget = null;
226
    event._dispatchListeners = null;
227
    event._dispatchInstances = null;
228
    return res;
229
  }
230
  /**
231
   * @param {SyntheticEvent} event
232
   * @return {boolean} True iff number of dispatches accumulated is greater than 0.
233
   */
234

    
235
  function hasDispatches(event) {
236
    return !!event._dispatchListeners;
237
  }
238

    
239
  var HostComponent = 5;
240

    
241
  function getParent(inst) {
242
    do {
243
      inst = inst.return; // TODO: If this is a HostRoot we might want to bail out.
244
      // That is depending on if we want nested subtrees (layers) to bubble
245
      // events to their parent. We could also go through parentNode on the
246
      // host node but that wouldn't work for React Native and doesn't let us
247
      // do the portal feature.
248
    } while (inst && inst.tag !== HostComponent);
249

    
250
    if (inst) {
251
      return inst;
252
    }
253

    
254
    return null;
255
  }
256
  /**
257
   * Return the lowest common ancestor of A and B, or null if they are in
258
   * different trees.
259
   */
260

    
261

    
262
  function getLowestCommonAncestor(instA, instB) {
263
    var depthA = 0;
264

    
265
    for (var tempA = instA; tempA; tempA = getParent(tempA)) {
266
      depthA++;
267
    }
268

    
269
    var depthB = 0;
270

    
271
    for (var tempB = instB; tempB; tempB = getParent(tempB)) {
272
      depthB++;
273
    } // If A is deeper, crawl up.
274

    
275

    
276
    while (depthA - depthB > 0) {
277
      instA = getParent(instA);
278
      depthA--;
279
    } // If B is deeper, crawl up.
280

    
281

    
282
    while (depthB - depthA > 0) {
283
      instB = getParent(instB);
284
      depthB--;
285
    } // Walk in lockstep until we find a match.
286

    
287

    
288
    var depth = depthA;
289

    
290
    while (depth--) {
291
      if (instA === instB || instA === instB.alternate) {
292
        return instA;
293
      }
294

    
295
      instA = getParent(instA);
296
      instB = getParent(instB);
297
    }
298

    
299
    return null;
300
  }
301
  /**
302
   * Return if A is an ancestor of B.
303
   */
304

    
305
  function isAncestor(instA, instB) {
306
    while (instB) {
307
      if (instA === instB || instA === instB.alternate) {
308
        return true;
309
      }
310

    
311
      instB = getParent(instB);
312
    }
313

    
314
    return false;
315
  }
316
  /**
317
   * Return the parent instance of the passed-in instance.
318
   */
319

    
320
  function getParentInstance(inst) {
321
    return getParent(inst);
322
  }
323
  /**
324
   * Simulates the traversal of a two-phase, capture/bubble event dispatch.
325
   */
326

    
327
  function traverseTwoPhase(inst, fn, arg) {
328
    var path = [];
329

    
330
    while (inst) {
331
      path.push(inst);
332
      inst = getParent(inst);
333
    }
334

    
335
    var i;
336

    
337
    for (i = path.length; i-- > 0;) {
338
      fn(path[i], 'captured', arg);
339
    }
340

    
341
    for (i = 0; i < path.length; i++) {
342
      fn(path[i], 'bubbled', arg);
343
    }
344
  }
345

    
346
  function isInteractive(tag) {
347
    return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
348
  }
349

    
350
  function shouldPreventMouseEvent(name, type, props) {
351
    switch (name) {
352
      case 'onClick':
353
      case 'onClickCapture':
354
      case 'onDoubleClick':
355
      case 'onDoubleClickCapture':
356
      case 'onMouseDown':
357
      case 'onMouseDownCapture':
358
      case 'onMouseMove':
359
      case 'onMouseMoveCapture':
360
      case 'onMouseUp':
361
      case 'onMouseUpCapture':
362
      case 'onMouseEnter':
363
        return !!(props.disabled && isInteractive(type));
364

    
365
      default:
366
        return false;
367
    }
368
  }
369
  /**
370
   * @param {object} inst The instance, which is the source of events.
371
   * @param {string} registrationName Name of listener (e.g. `onClick`).
372
   * @return {?function} The stored callback.
373
   */
374

    
375

    
376
  function getListener(inst, registrationName) {
377
    var listener; // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
378
    // live here; needs to be moved to a better place soon
379

    
380
    var stateNode = inst.stateNode;
381

    
382
    if (!stateNode) {
383
      // Work in progress (ex: onload events in incremental mode).
384
      return null;
385
    }
386

    
387
    var props = getFiberCurrentPropsFromNode(stateNode);
388

    
389
    if (!props) {
390
      // Work in progress.
391
      return null;
392
    }
393

    
394
    listener = props[registrationName];
395

    
396
    if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
397
      return null;
398
    }
399

    
400
    if (!(!listener || typeof listener === 'function')) {
401
      {
402
        throw Error( "Expected `" + registrationName + "` listener to be a function, instead got a value of `" + typeof listener + "` type." );
403
      }
404
    }
405

    
406
    return listener;
407
  }
408

    
409
  /**
410
   * Accumulates items that must not be null or undefined into the first one. This
411
   * is used to conserve memory by avoiding array allocations, and thus sacrifices
412
   * API cleanness. Since `current` can be null before being passed in and not
413
   * null after this function, make sure to assign it back to `current`:
414
   *
415
   * `a = accumulateInto(a, b);`
416
   *
417
   * This API should be sparingly used. Try `accumulate` for something cleaner.
418
   *
419
   * @return {*|array<*>} An accumulation of items.
420
   */
421

    
422
  function accumulateInto(current, next) {
423
    if (!(next != null)) {
424
      {
425
        throw Error( "accumulateInto(...): Accumulated items must not be null or undefined." );
426
      }
427
    }
428

    
429
    if (current == null) {
430
      return next;
431
    } // Both are not empty. Warning: Never call x.concat(y) when you are not
432
    // certain that x is an Array (x could be a string with concat method).
433

    
434

    
435
    if (Array.isArray(current)) {
436
      if (Array.isArray(next)) {
437
        current.push.apply(current, next);
438
        return current;
439
      }
440

    
441
      current.push(next);
442
      return current;
443
    }
444

    
445
    if (Array.isArray(next)) {
446
      // A bit too dangerous to mutate `next`.
447
      return [current].concat(next);
448
    }
449

    
450
    return [current, next];
451
  }
452

    
453
  /**
454
   * @param {array} arr an "accumulation" of items which is either an Array or
455
   * a single item. Useful when paired with the `accumulate` module. This is a
456
   * simple utility that allows us to reason about a collection of items, but
457
   * handling the case when there is exactly one item (and we do not need to
458
   * allocate an array).
459
   * @param {function} cb Callback invoked with each element or a collection.
460
   * @param {?} [scope] Scope used as `this` in a callback.
461
   */
462
  function forEachAccumulated(arr, cb, scope) {
463
    if (Array.isArray(arr)) {
464
      arr.forEach(cb, scope);
465
    } else if (arr) {
466
      cb.call(scope, arr);
467
    }
468
  }
469

    
470
  /**
471
   * Some event types have a notion of different registration names for different
472
   * "phases" of propagation. This finds listeners by a given phase.
473
   */
474
  function listenerAtPhase(inst, event, propagationPhase) {
475
    var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
476
    return getListener(inst, registrationName);
477
  }
478
  /**
479
   * A small set of propagation patterns, each of which will accept a small amount
480
   * of information, and generate a set of "dispatch ready event objects" - which
481
   * are sets of events that have already been annotated with a set of dispatched
482
   * listener functions/ids. The API is designed this way to discourage these
483
   * propagation strategies from actually executing the dispatches, since we
484
   * always want to collect the entire set of dispatches before executing even a
485
   * single one.
486
   */
487

    
488
  /**
489
   * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
490
   * here, allows us to not have to bind or create functions for each event.
491
   * Mutating the event's members allows us to not have to create a wrapping
492
   * "dispatch" object that pairs the event with the listener.
493
   */
494

    
495

    
496
  function accumulateDirectionalDispatches(inst, phase, event) {
497
    {
498
      if (!inst) {
499
        error('Dispatching inst must not be null');
500
      }
501
    }
502

    
503
    var listener = listenerAtPhase(inst, event, phase);
504

    
505
    if (listener) {
506
      event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
507
      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
508
    }
509
  }
510
  /**
511
   * Collect dispatches (must be entirely collected before dispatching - see unit
512
   * tests). Lazily allocate the array to conserve memory.  We must loop through
513
   * each event and perform the traversal for each one. We cannot perform a
514
   * single traversal for the entire collection of events because each event may
515
   * have a different target.
516
   */
517

    
518

    
519
  function accumulateTwoPhaseDispatchesSingle(event) {
520
    if (event && event.dispatchConfig.phasedRegistrationNames) {
521
      traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
522
    }
523
  }
524
  /**
525
   * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
526
   */
527

    
528

    
529
  function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
530
    if (event && event.dispatchConfig.phasedRegistrationNames) {
531
      var targetInst = event._targetInst;
532
      var parentInst = targetInst ? getParentInstance(targetInst) : null;
533
      traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
534
    }
535
  }
536
  /**
537
   * Accumulates without regard to direction, does not look for phased
538
   * registration names. Same as `accumulateDirectDispatchesSingle` but without
539
   * requiring that the `dispatchMarker` be the same as the dispatched ID.
540
   */
541

    
542

    
543
  function accumulateDispatches(inst, ignoredDirection, event) {
544
    if (inst && event && event.dispatchConfig.registrationName) {
545
      var registrationName = event.dispatchConfig.registrationName;
546
      var listener = getListener(inst, registrationName);
547

    
548
      if (listener) {
549
        event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
550
        event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
551
      }
552
    }
553
  }
554
  /**
555
   * Accumulates dispatches on an `SyntheticEvent`, but only for the
556
   * `dispatchMarker`.
557
   * @param {SyntheticEvent} event
558
   */
559

    
560

    
561
  function accumulateDirectDispatchesSingle(event) {
562
    if (event && event.dispatchConfig.registrationName) {
563
      accumulateDispatches(event._targetInst, null, event);
564
    }
565
  }
566

    
567
  function accumulateTwoPhaseDispatches(events) {
568
    forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
569
  }
570
  function accumulateTwoPhaseDispatchesSkipTarget(events) {
571
    forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
572
  }
573
  function accumulateDirectDispatches(events) {
574
    forEachAccumulated(events, accumulateDirectDispatchesSingle);
575
  }
576

    
577
  var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
578
  var _assign = ReactInternals.assign;
579

    
580
  var EVENT_POOL_SIZE = 10;
581
  /**
582
   * @interface Event
583
   * @see http://www.w3.org/TR/DOM-Level-3-Events/
584
   */
585

    
586
  var EventInterface = {
587
    type: null,
588
    target: null,
589
    // currentTarget is set when dispatching; no use in copying it here
590
    currentTarget: function () {
591
      return null;
592
    },
593
    eventPhase: null,
594
    bubbles: null,
595
    cancelable: null,
596
    timeStamp: function (event) {
597
      return event.timeStamp || Date.now();
598
    },
599
    defaultPrevented: null,
600
    isTrusted: null
601
  };
602

    
603
  function functionThatReturnsTrue() {
604
    return true;
605
  }
606

    
607
  function functionThatReturnsFalse() {
608
    return false;
609
  }
610
  /**
611
   * Synthetic events are dispatched by event plugins, typically in response to a
612
   * top-level event delegation handler.
613
   *
614
   * These systems should generally use pooling to reduce the frequency of garbage
615
   * collection. The system should check `isPersistent` to determine whether the
616
   * event should be released into the pool after being dispatched. Users that
617
   * need a persisted event should invoke `persist`.
618
   *
619
   * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
620
   * normalizing browser quirks. Subclasses do not necessarily have to implement a
621
   * DOM interface; custom application-specific events can also subclass this.
622
   *
623
   * @param {object} dispatchConfig Configuration used to dispatch this event.
624
   * @param {*} targetInst Marker identifying the event target.
625
   * @param {object} nativeEvent Native browser event.
626
   * @param {DOMEventTarget} nativeEventTarget Target node.
627
   */
628

    
629

    
630
  function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
631
    {
632
      // these have a getter/setter for warnings
633
      delete this.nativeEvent;
634
      delete this.preventDefault;
635
      delete this.stopPropagation;
636
      delete this.isDefaultPrevented;
637
      delete this.isPropagationStopped;
638
    }
639

    
640
    this.dispatchConfig = dispatchConfig;
641
    this._targetInst = targetInst;
642
    this.nativeEvent = nativeEvent;
643
    var Interface = this.constructor.Interface;
644

    
645
    for (var propName in Interface) {
646
      if (!Interface.hasOwnProperty(propName)) {
647
        continue;
648
      }
649

    
650
      {
651
        delete this[propName]; // this has a getter/setter for warnings
652
      }
653

    
654
      var normalize = Interface[propName];
655

    
656
      if (normalize) {
657
        this[propName] = normalize(nativeEvent);
658
      } else {
659
        if (propName === 'target') {
660
          this.target = nativeEventTarget;
661
        } else {
662
          this[propName] = nativeEvent[propName];
663
        }
664
      }
665
    }
666

    
667
    var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
668

    
669
    if (defaultPrevented) {
670
      this.isDefaultPrevented = functionThatReturnsTrue;
671
    } else {
672
      this.isDefaultPrevented = functionThatReturnsFalse;
673
    }
674

    
675
    this.isPropagationStopped = functionThatReturnsFalse;
676
    return this;
677
  }
678

    
679
  _assign(SyntheticEvent.prototype, {
680
    preventDefault: function () {
681
      this.defaultPrevented = true;
682
      var event = this.nativeEvent;
683

    
684
      if (!event) {
685
        return;
686
      }
687

    
688
      if (event.preventDefault) {
689
        event.preventDefault();
690
      } else if (typeof event.returnValue !== 'unknown') {
691
        event.returnValue = false;
692
      }
693

    
694
      this.isDefaultPrevented = functionThatReturnsTrue;
695
    },
696
    stopPropagation: function () {
697
      var event = this.nativeEvent;
698

    
699
      if (!event) {
700
        return;
701
      }
702

    
703
      if (event.stopPropagation) {
704
        event.stopPropagation();
705
      } else if (typeof event.cancelBubble !== 'unknown') {
706
        // The ChangeEventPlugin registers a "propertychange" event for
707
        // IE. This event does not support bubbling or cancelling, and
708
        // any references to cancelBubble throw "Member not found".  A
709
        // typeof check of "unknown" circumvents this issue (and is also
710
        // IE specific).
711
        event.cancelBubble = true;
712
      }
713

    
714
      this.isPropagationStopped = functionThatReturnsTrue;
715
    },
716

    
717
    /**
718
     * We release all dispatched `SyntheticEvent`s after each event loop, adding
719
     * them back into the pool. This allows a way to hold onto a reference that
720
     * won't be added back into the pool.
721
     */
722
    persist: function () {
723
      this.isPersistent = functionThatReturnsTrue;
724
    },
725

    
726
    /**
727
     * Checks if this event should be released back into the pool.
728
     *
729
     * @return {boolean} True if this should not be released, false otherwise.
730
     */
731
    isPersistent: functionThatReturnsFalse,
732

    
733
    /**
734
     * `PooledClass` looks for `destructor` on each instance it releases.
735
     */
736
    destructor: function () {
737
      var Interface = this.constructor.Interface;
738

    
739
      for (var propName in Interface) {
740
        {
741
          Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));
742
        }
743
      }
744

    
745
      this.dispatchConfig = null;
746
      this._targetInst = null;
747
      this.nativeEvent = null;
748
      this.isDefaultPrevented = functionThatReturnsFalse;
749
      this.isPropagationStopped = functionThatReturnsFalse;
750
      this._dispatchListeners = null;
751
      this._dispatchInstances = null;
752

    
753
      {
754
        Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));
755
        Object.defineProperty(this, 'isDefaultPrevented', getPooledWarningPropertyDefinition('isDefaultPrevented', functionThatReturnsFalse));
756
        Object.defineProperty(this, 'isPropagationStopped', getPooledWarningPropertyDefinition('isPropagationStopped', functionThatReturnsFalse));
757
        Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', function () {}));
758
        Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', function () {}));
759
      }
760
    }
761
  });
762

    
763
  SyntheticEvent.Interface = EventInterface;
764
  /**
765
   * Helper to reduce boilerplate when creating subclasses.
766
   */
767

    
768
  SyntheticEvent.extend = function (Interface) {
769
    var Super = this;
770

    
771
    var E = function () {};
772

    
773
    E.prototype = Super.prototype;
774
    var prototype = new E();
775

    
776
    function Class() {
777
      return Super.apply(this, arguments);
778
    }
779

    
780
    _assign(prototype, Class.prototype);
781

    
782
    Class.prototype = prototype;
783
    Class.prototype.constructor = Class;
784
    Class.Interface = _assign({}, Super.Interface, Interface);
785
    Class.extend = Super.extend;
786
    addEventPoolingTo(Class);
787
    return Class;
788
  };
789

    
790
  addEventPoolingTo(SyntheticEvent);
791
  /**
792
   * Helper to nullify syntheticEvent instance properties when destructing
793
   *
794
   * @param {String} propName
795
   * @param {?object} getVal
796
   * @return {object} defineProperty object
797
   */
798

    
799
  function getPooledWarningPropertyDefinition(propName, getVal) {
800
    var isFunction = typeof getVal === 'function';
801
    return {
802
      configurable: true,
803
      set: set,
804
      get: get
805
    };
806

    
807
    function set(val) {
808
      var action = isFunction ? 'setting the method' : 'setting the property';
809
      warn(action, 'This is effectively a no-op');
810
      return val;
811
    }
812

    
813
    function get() {
814
      var action = isFunction ? 'accessing the method' : 'accessing the property';
815
      var result = isFunction ? 'This is a no-op function' : 'This is set to null';
816
      warn(action, result);
817
      return getVal;
818
    }
819

    
820
    function warn(action, result) {
821
      {
822
        error("This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result);
823
      }
824
    }
825
  }
826

    
827
  function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {
828
    var EventConstructor = this;
829

    
830
    if (EventConstructor.eventPool.length) {
831
      var instance = EventConstructor.eventPool.pop();
832
      EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst);
833
      return instance;
834
    }
835

    
836
    return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst);
837
  }
838

    
839
  function releasePooledEvent(event) {
840
    var EventConstructor = this;
841

    
842
    if (!(event instanceof EventConstructor)) {
843
      {
844
        throw Error( "Trying to release an event instance into a pool of a different type." );
845
      }
846
    }
847

    
848
    event.destructor();
849

    
850
    if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
851
      EventConstructor.eventPool.push(event);
852
    }
853
  }
854

    
855
  function addEventPoolingTo(EventConstructor) {
856
    EventConstructor.eventPool = [];
857
    EventConstructor.getPooled = getPooledEvent;
858
    EventConstructor.release = releasePooledEvent;
859
  }
860

    
861
  /**
862
   * `touchHistory` isn't actually on the native event, but putting it in the
863
   * interface will ensure that it is cleaned up when pooled/destroyed. The
864
   * `ResponderEventPlugin` will populate it appropriately.
865
   */
866

    
867
  var ResponderSyntheticEvent = SyntheticEvent.extend({
868
    touchHistory: function (nativeEvent) {
869
      return null; // Actually doesn't even look at the native event.
870
    }
871
  });
872

    
873
  // Note: ideally these would be imported from DOMTopLevelEventTypes,
874
  // but our build system currently doesn't let us do that from a fork.
875
  var TOP_TOUCH_START = 'touchstart';
876
  var TOP_TOUCH_MOVE = 'touchmove';
877
  var TOP_TOUCH_END = 'touchend';
878
  var TOP_TOUCH_CANCEL = 'touchcancel';
879
  var TOP_SCROLL = 'scroll';
880
  var TOP_SELECTION_CHANGE = 'selectionchange';
881
  var TOP_MOUSE_DOWN = 'mousedown';
882
  var TOP_MOUSE_MOVE = 'mousemove';
883
  var TOP_MOUSE_UP = 'mouseup';
884
  function isStartish(topLevelType) {
885
    return topLevelType === TOP_TOUCH_START || topLevelType === TOP_MOUSE_DOWN;
886
  }
887
  function isMoveish(topLevelType) {
888
    return topLevelType === TOP_TOUCH_MOVE || topLevelType === TOP_MOUSE_MOVE;
889
  }
890
  function isEndish(topLevelType) {
891
    return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL || topLevelType === TOP_MOUSE_UP;
892
  }
893
  var startDependencies = [TOP_TOUCH_START, TOP_MOUSE_DOWN];
894
  var moveDependencies = [TOP_TOUCH_MOVE, TOP_MOUSE_MOVE];
895
  var endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END, TOP_MOUSE_UP];
896

    
897
  /**
898
   * Tracks the position and time of each active touch by `touch.identifier`. We
899
   * should typically only see IDs in the range of 1-20 because IDs get recycled
900
   * when touches end and start again.
901
   */
902

    
903
  var MAX_TOUCH_BANK = 20;
904
  var touchBank = [];
905
  var touchHistory = {
906
    touchBank: touchBank,
907
    numberActiveTouches: 0,
908
    // If there is only one active touch, we remember its location. This prevents
909
    // us having to loop through all of the touches all the time in the most
910
    // common case.
911
    indexOfSingleActiveTouch: -1,
912
    mostRecentTimeStamp: 0
913
  };
914

    
915
  function timestampForTouch(touch) {
916
    // The legacy internal implementation provides "timeStamp", which has been
917
    // renamed to "timestamp". Let both work for now while we iron it out
918
    // TODO (evv): rename timeStamp to timestamp in internal code
919
    return touch.timeStamp || touch.timestamp;
920
  }
921
  /**
922
   * TODO: Instead of making gestures recompute filtered velocity, we could
923
   * include a built in velocity computation that can be reused globally.
924
   */
925

    
926

    
927
  function createTouchRecord(touch) {
928
    return {
929
      touchActive: true,
930
      startPageX: touch.pageX,
931
      startPageY: touch.pageY,
932
      startTimeStamp: timestampForTouch(touch),
933
      currentPageX: touch.pageX,
934
      currentPageY: touch.pageY,
935
      currentTimeStamp: timestampForTouch(touch),
936
      previousPageX: touch.pageX,
937
      previousPageY: touch.pageY,
938
      previousTimeStamp: timestampForTouch(touch)
939
    };
940
  }
941

    
942
  function resetTouchRecord(touchRecord, touch) {
943
    touchRecord.touchActive = true;
944
    touchRecord.startPageX = touch.pageX;
945
    touchRecord.startPageY = touch.pageY;
946
    touchRecord.startTimeStamp = timestampForTouch(touch);
947
    touchRecord.currentPageX = touch.pageX;
948
    touchRecord.currentPageY = touch.pageY;
949
    touchRecord.currentTimeStamp = timestampForTouch(touch);
950
    touchRecord.previousPageX = touch.pageX;
951
    touchRecord.previousPageY = touch.pageY;
952
    touchRecord.previousTimeStamp = timestampForTouch(touch);
953
  }
954

    
955
  function getTouchIdentifier(_ref) {
956
    var identifier = _ref.identifier;
957

    
958
    if (!(identifier != null)) {
959
      {
960
        throw Error( "Touch object is missing identifier." );
961
      }
962
    }
963

    
964
    {
965
      if (identifier > MAX_TOUCH_BANK) {
966
        error('Touch identifier %s is greater than maximum supported %s which causes ' + 'performance issues backfilling array locations for all of the indices.', identifier, MAX_TOUCH_BANK);
967
      }
968
    }
969

    
970
    return identifier;
971
  }
972

    
973
  function recordTouchStart(touch) {
974
    var identifier = getTouchIdentifier(touch);
975
    var touchRecord = touchBank[identifier];
976

    
977
    if (touchRecord) {
978
      resetTouchRecord(touchRecord, touch);
979
    } else {
980
      touchBank[identifier] = createTouchRecord(touch);
981
    }
982

    
983
    touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
984
  }
985

    
986
  function recordTouchMove(touch) {
987
    var touchRecord = touchBank[getTouchIdentifier(touch)];
988

    
989
    if (touchRecord) {
990
      touchRecord.touchActive = true;
991
      touchRecord.previousPageX = touchRecord.currentPageX;
992
      touchRecord.previousPageY = touchRecord.currentPageY;
993
      touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
994
      touchRecord.currentPageX = touch.pageX;
995
      touchRecord.currentPageY = touch.pageY;
996
      touchRecord.currentTimeStamp = timestampForTouch(touch);
997
      touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
998
    } else {
999
      {
1000
        warn('Cannot record touch move without a touch start.\n' + 'Touch Move: %s\n' + 'Touch Bank: %s', printTouch(touch), printTouchBank());
1001
      }
1002
    }
1003
  }
1004

    
1005
  function recordTouchEnd(touch) {
1006
    var touchRecord = touchBank[getTouchIdentifier(touch)];
1007

    
1008
    if (touchRecord) {
1009
      touchRecord.touchActive = false;
1010
      touchRecord.previousPageX = touchRecord.currentPageX;
1011
      touchRecord.previousPageY = touchRecord.currentPageY;
1012
      touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
1013
      touchRecord.currentPageX = touch.pageX;
1014
      touchRecord.currentPageY = touch.pageY;
1015
      touchRecord.currentTimeStamp = timestampForTouch(touch);
1016
      touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
1017
    } else {
1018
      {
1019
        warn('Cannot record touch end without a touch start.\n' + 'Touch End: %s\n' + 'Touch Bank: %s', printTouch(touch), printTouchBank());
1020
      }
1021
    }
1022
  }
1023

    
1024
  function printTouch(touch) {
1025
    return JSON.stringify({
1026
      identifier: touch.identifier,
1027
      pageX: touch.pageX,
1028
      pageY: touch.pageY,
1029
      timestamp: timestampForTouch(touch)
1030
    });
1031
  }
1032

    
1033
  function printTouchBank() {
1034
    var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK));
1035

    
1036
    if (touchBank.length > MAX_TOUCH_BANK) {
1037
      printed += ' (original size: ' + touchBank.length + ')';
1038
    }
1039

    
1040
    return printed;
1041
  }
1042

    
1043
  var ResponderTouchHistoryStore = {
1044
    recordTouchTrack: function (topLevelType, nativeEvent) {
1045
      if (isMoveish(topLevelType)) {
1046
        nativeEvent.changedTouches.forEach(recordTouchMove);
1047
      } else if (isStartish(topLevelType)) {
1048
        nativeEvent.changedTouches.forEach(recordTouchStart);
1049
        touchHistory.numberActiveTouches = nativeEvent.touches.length;
1050

    
1051
        if (touchHistory.numberActiveTouches === 1) {
1052
          touchHistory.indexOfSingleActiveTouch = nativeEvent.touches[0].identifier;
1053
        }
1054
      } else if (isEndish(topLevelType)) {
1055
        nativeEvent.changedTouches.forEach(recordTouchEnd);
1056
        touchHistory.numberActiveTouches = nativeEvent.touches.length;
1057

    
1058
        if (touchHistory.numberActiveTouches === 1) {
1059
          for (var i = 0; i < touchBank.length; i++) {
1060
            var touchTrackToCheck = touchBank[i];
1061

    
1062
            if (touchTrackToCheck != null && touchTrackToCheck.touchActive) {
1063
              touchHistory.indexOfSingleActiveTouch = i;
1064
              break;
1065
            }
1066
          }
1067

    
1068
          {
1069
            var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch];
1070

    
1071
            if (activeRecord == null || !activeRecord.touchActive) {
1072
              error('Cannot find single active touch.');
1073
            }
1074
          }
1075
        }
1076
      }
1077
    },
1078
    touchHistory: touchHistory
1079
  };
1080

    
1081
  /**
1082
   * Accumulates items that must not be null or undefined.
1083
   *
1084
   * This is used to conserve memory by avoiding array allocations.
1085
   *
1086
   * @return {*|array<*>} An accumulation of items.
1087
   */
1088

    
1089
  function accumulate(current, next) {
1090
    if (!(next != null)) {
1091
      {
1092
        throw Error( "accumulate(...): Accumulated items must not be null or undefined." );
1093
      }
1094
    }
1095

    
1096
    if (current == null) {
1097
      return next;
1098
    } // Both are not empty. Warning: Never call x.concat(y) when you are not
1099
    // certain that x is an Array (x could be a string with concat method).
1100

    
1101

    
1102
    if (Array.isArray(current)) {
1103
      return current.concat(next);
1104
    }
1105

    
1106
    if (Array.isArray(next)) {
1107
      return [current].concat(next);
1108
    }
1109

    
1110
    return [current, next];
1111
  }
1112

    
1113
  /**
1114
   * Instance of element that should respond to touch/move types of interactions,
1115
   * as indicated explicitly by relevant callbacks.
1116
   */
1117

    
1118
  var responderInst = null;
1119
  /**
1120
   * Count of current touches. A textInput should become responder iff the
1121
   * selection changes while there is a touch on the screen.
1122
   */
1123

    
1124
  var trackedTouchCount = 0;
1125

    
1126
  var changeResponder = function (nextResponderInst, blockHostResponder) {
1127
    var oldResponderInst = responderInst;
1128
    responderInst = nextResponderInst;
1129

    
1130
    if (ResponderEventPlugin.GlobalResponderHandler !== null) {
1131
      ResponderEventPlugin.GlobalResponderHandler.onChange(oldResponderInst, nextResponderInst, blockHostResponder);
1132
    }
1133
  };
1134

    
1135
  var eventTypes = {
1136
    /**
1137
     * On a `touchStart`/`mouseDown`, is it desired that this element become the
1138
     * responder?
1139
     */
1140
    startShouldSetResponder: {
1141
      phasedRegistrationNames: {
1142
        bubbled: 'onStartShouldSetResponder',
1143
        captured: 'onStartShouldSetResponderCapture'
1144
      },
1145
      dependencies: startDependencies
1146
    },
1147

    
1148
    /**
1149
     * On a `scroll`, is it desired that this element become the responder? This
1150
     * is usually not needed, but should be used to retroactively infer that a
1151
     * `touchStart` had occurred during momentum scroll. During a momentum scroll,
1152
     * a touch start will be immediately followed by a scroll event if the view is
1153
     * currently scrolling.
1154
     *
1155
     * TODO: This shouldn't bubble.
1156
     */
1157
    scrollShouldSetResponder: {
1158
      phasedRegistrationNames: {
1159
        bubbled: 'onScrollShouldSetResponder',
1160
        captured: 'onScrollShouldSetResponderCapture'
1161
      },
1162
      dependencies: [TOP_SCROLL]
1163
    },
1164

    
1165
    /**
1166
     * On text selection change, should this element become the responder? This
1167
     * is needed for text inputs or other views with native selection, so the
1168
     * JS view can claim the responder.
1169
     *
1170
     * TODO: This shouldn't bubble.
1171
     */
1172
    selectionChangeShouldSetResponder: {
1173
      phasedRegistrationNames: {
1174
        bubbled: 'onSelectionChangeShouldSetResponder',
1175
        captured: 'onSelectionChangeShouldSetResponderCapture'
1176
      },
1177
      dependencies: [TOP_SELECTION_CHANGE]
1178
    },
1179

    
1180
    /**
1181
     * On a `touchMove`/`mouseMove`, is it desired that this element become the
1182
     * responder?
1183
     */
1184
    moveShouldSetResponder: {
1185
      phasedRegistrationNames: {
1186
        bubbled: 'onMoveShouldSetResponder',
1187
        captured: 'onMoveShouldSetResponderCapture'
1188
      },
1189
      dependencies: moveDependencies
1190
    },
1191

    
1192
    /**
1193
     * Direct responder events dispatched directly to responder. Do not bubble.
1194
     */
1195
    responderStart: {
1196
      registrationName: 'onResponderStart',
1197
      dependencies: startDependencies
1198
    },
1199
    responderMove: {
1200
      registrationName: 'onResponderMove',
1201
      dependencies: moveDependencies
1202
    },
1203
    responderEnd: {
1204
      registrationName: 'onResponderEnd',
1205
      dependencies: endDependencies
1206
    },
1207
    responderRelease: {
1208
      registrationName: 'onResponderRelease',
1209
      dependencies: endDependencies
1210
    },
1211
    responderTerminationRequest: {
1212
      registrationName: 'onResponderTerminationRequest',
1213
      dependencies: []
1214
    },
1215
    responderGrant: {
1216
      registrationName: 'onResponderGrant',
1217
      dependencies: []
1218
    },
1219
    responderReject: {
1220
      registrationName: 'onResponderReject',
1221
      dependencies: []
1222
    },
1223
    responderTerminate: {
1224
      registrationName: 'onResponderTerminate',
1225
      dependencies: []
1226
    }
1227
  };
1228
  /**
1229
   *
1230
   * Responder System:
1231
   * ----------------
1232
   *
1233
   * - A global, solitary "interaction lock" on a view.
1234
   * - If a node becomes the responder, it should convey visual feedback
1235
   *   immediately to indicate so, either by highlighting or moving accordingly.
1236
   * - To be the responder means, that touches are exclusively important to that
1237
   *   responder view, and no other view.
1238
   * - While touches are still occurring, the responder lock can be transferred to
1239
   *   a new view, but only to increasingly "higher" views (meaning ancestors of
1240
   *   the current responder).
1241
   *
1242
   * Responder being granted:
1243
   * ------------------------
1244
   *
1245
   * - Touch starts, moves, and scrolls can cause an ID to become the responder.
1246
   * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to
1247
   *   the "appropriate place".
1248
   * - If nothing is currently the responder, the "appropriate place" is the
1249
   *   initiating event's `targetID`.
1250
   * - If something *is* already the responder, the "appropriate place" is the
1251
   *   first common ancestor of the event target and the current `responderInst`.
1252
   * - Some negotiation happens: See the timing diagram below.
1253
   * - Scrolled views automatically become responder. The reasoning is that a
1254
   *   platform scroll view that isn't built on top of the responder system has
1255
   *   began scrolling, and the active responder must now be notified that the
1256
   *   interaction is no longer locked to it - the system has taken over.
1257
   *
1258
   * - Responder being released:
1259
   *   As soon as no more touches that *started* inside of descendants of the
1260
   *   *current* responderInst, an `onResponderRelease` event is dispatched to the
1261
   *   current responder, and the responder lock is released.
1262
   *
1263
   * TODO:
1264
   * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that
1265
   *   determines if the responder lock should remain.
1266
   * - If a view shouldn't "remain" the responder, any active touches should by
1267
   *   default be considered "dead" and do not influence future negotiations or
1268
   *   bubble paths. It should be as if those touches do not exist.
1269
   * -- For multitouch: Usually a translate-z will choose to "remain" responder
1270
   *  after one out of many touches ended. For translate-y, usually the view
1271
   *  doesn't wish to "remain" responder after one of many touches end.
1272
   * - Consider building this on top of a `stopPropagation` model similar to
1273
   *   `W3C` events.
1274
   * - Ensure that `onResponderTerminate` is called on touch cancels, whether or
1275
   *   not `onResponderTerminationRequest` returns `true` or `false`.
1276
   *
1277
   */
1278

    
1279
  /*                                             Negotiation Performed
1280
                                               +-----------------------+
1281
                                              /                         \
1282
  Process low level events to    +     Current Responder      +   wantsResponderID
1283
  determine who to perform negot-|   (if any exists at all)   |
1284
  iation/transition              | Otherwise just pass through|
1285
  -------------------------------+----------------------------+------------------+
1286
  Bubble to find first ID        |                            |
1287
  to return true:wantsResponderID|                            |
1288
                                 |                            |
1289
       +-------------+           |                            |
1290
       | onTouchStart|           |                            |
1291
       +------+------+     none  |                            |
1292
              |            return|                            |
1293
  +-----------v-------------+true| +------------------------+ |
1294
  |onStartShouldSetResponder|----->|onResponderStart (cur)  |<-----------+
1295
  +-----------+-------------+    | +------------------------+ |          |
1296
              |                  |                            | +--------+-------+
1297
              | returned true for|       false:REJECT +-------->|onResponderReject
1298
              | wantsResponderID |                    |       | +----------------+
1299
              | (now attempt     | +------------------+-----+ |
1300
              |  handoff)        | |   onResponder          | |
1301
              +------------------->|      TerminationRequest| |
1302
                                 | +------------------+-----+ |
1303
                                 |                    |       | +----------------+
1304
                                 |         true:GRANT +-------->|onResponderGrant|
1305
                                 |                            | +--------+-------+
1306
                                 | +------------------------+ |          |
1307
                                 | |   onResponderTerminate |<-----------+
1308
                                 | +------------------+-----+ |
1309
                                 |                    |       | +----------------+
1310
                                 |                    +-------->|onResponderStart|
1311
                                 |                            | +----------------+
1312
  Bubble to find first ID        |                            |
1313
  to return true:wantsResponderID|                            |
1314
                                 |                            |
1315
       +-------------+           |                            |
1316
       | onTouchMove |           |                            |
1317
       +------+------+     none  |                            |
1318
              |            return|                            |
1319
  +-----------v-------------+true| +------------------------+ |
1320
  |onMoveShouldSetResponder |----->|onResponderMove (cur)   |<-----------+
1321
  +-----------+-------------+    | +------------------------+ |          |
1322
              |                  |                            | +--------+-------+
1323
              | returned true for|       false:REJECT +-------->|onResponderRejec|
1324
              | wantsResponderID |                    |       | +----------------+
1325
              | (now attempt     | +------------------+-----+ |
1326
              |  handoff)        | |   onResponder          | |
1327
              +------------------->|      TerminationRequest| |
1328
                                 | +------------------+-----+ |
1329
                                 |                    |       | +----------------+
1330
                                 |         true:GRANT +-------->|onResponderGrant|
1331
                                 |                            | +--------+-------+
1332
                                 | +------------------------+ |          |
1333
                                 | |   onResponderTerminate |<-----------+
1334
                                 | +------------------+-----+ |
1335
                                 |                    |       | +----------------+
1336
                                 |                    +-------->|onResponderMove |
1337
                                 |                            | +----------------+
1338
                                 |                            |
1339
                                 |                            |
1340
        Some active touch started|                            |
1341
        inside current responder | +------------------------+ |
1342
        +------------------------->|      onResponderEnd    | |
1343
        |                        | +------------------------+ |
1344
    +---+---------+              |                            |
1345
    | onTouchEnd  |              |                            |
1346
    +---+---------+              |                            |
1347
        |                        | +------------------------+ |
1348
        +------------------------->|     onResponderEnd     | |
1349
        No active touches started| +-----------+------------+ |
1350
        inside current responder |             |              |
1351
                                 |             v              |
1352
                                 | +------------------------+ |
1353
                                 | |    onResponderRelease  | |
1354
                                 | +------------------------+ |
1355
                                 |                            |
1356
                                 +                            + */
1357

    
1358
  /**
1359
   * A note about event ordering in the `EventPluginRegistry`.
1360
   *
1361
   * Suppose plugins are injected in the following order:
1362
   *
1363
   * `[R, S, C]`
1364
   *
1365
   * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for
1366
   * `onClick` etc) and `R` is `ResponderEventPlugin`.
1367
   *
1368
   * "Deferred-Dispatched Events":
1369
   *
1370
   * - The current event plugin system will traverse the list of injected plugins,
1371
   *   in order, and extract events by collecting the plugin's return value of
1372
   *   `extractEvents()`.
1373
   * - These events that are returned from `extractEvents` are "deferred
1374
   *   dispatched events".
1375
   * - When returned from `extractEvents`, deferred-dispatched events contain an
1376
   *   "accumulation" of deferred dispatches.
1377
   * - These deferred dispatches are accumulated/collected before they are
1378
   *   returned, but processed at a later time by the `EventPluginRegistry` (hence the
1379
   *   name deferred).
1380
   *
1381
   * In the process of returning their deferred-dispatched events, event plugins
1382
   * themselves can dispatch events on-demand without returning them from
1383
   * `extractEvents`. Plugins might want to do this, so that they can use event
1384
   * dispatching as a tool that helps them decide which events should be extracted
1385
   * in the first place.
1386
   *
1387
   * "On-Demand-Dispatched Events":
1388
   *
1389
   * - On-demand-dispatched events are not returned from `extractEvents`.
1390
   * - On-demand-dispatched events are dispatched during the process of returning
1391
   *   the deferred-dispatched events.
1392
   * - They should not have side effects.
1393
   * - They should be avoided, and/or eventually be replaced with another
1394
   *   abstraction that allows event plugins to perform multiple "rounds" of event
1395
   *   extraction.
1396
   *
1397
   * Therefore, the sequence of event dispatches becomes:
1398
   *
1399
   * - `R`s on-demand events (if any)   (dispatched by `R` on-demand)
1400
   * - `S`s on-demand events (if any)   (dispatched by `S` on-demand)
1401
   * - `C`s on-demand events (if any)   (dispatched by `C` on-demand)
1402
   * - `R`s extracted events (if any)   (dispatched by `EventPluginRegistry`)
1403
   * - `S`s extracted events (if any)   (dispatched by `EventPluginRegistry`)
1404
   * - `C`s extracted events (if any)   (dispatched by `EventPluginRegistry`)
1405
   *
1406
   * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`
1407
   * on-demand dispatch returns `true` (and some other details are satisfied) the
1408
   * `onResponderGrant` deferred dispatched event is returned from
1409
   * `extractEvents`. The sequence of dispatch executions in this case
1410
   * will appear as follows:
1411
   *
1412
   * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)
1413
   * - `touchStartCapture`       (`EventPluginRegistry` dispatches as usual)
1414
   * - `touchStart`              (`EventPluginRegistry` dispatches as usual)
1415
   * - `responderGrant/Reject`   (`EventPluginRegistry` dispatches as usual)
1416
   */
1417

    
1418
  function setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
1419
    var shouldSetEventType = isStartish(topLevelType) ? eventTypes.startShouldSetResponder : isMoveish(topLevelType) ? eventTypes.moveShouldSetResponder : topLevelType === TOP_SELECTION_CHANGE ? eventTypes.selectionChangeShouldSetResponder : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder.
1420

    
1421
    var bubbleShouldSetFrom = !responderInst ? targetInst : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target
1422
    // (deepest ID) if it happens to be the current responder. The reasoning:
1423
    // It's strange to get an `onMoveShouldSetResponder` when you're *already*
1424
    // the responder.
1425

    
1426
    var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst;
1427
    var shouldSetEvent = ResponderSyntheticEvent.getPooled(shouldSetEventType, bubbleShouldSetFrom, nativeEvent, nativeEventTarget);
1428
    shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
1429

    
1430
    if (skipOverBubbleShouldSetFrom) {
1431
      accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);
1432
    } else {
1433
      accumulateTwoPhaseDispatches(shouldSetEvent);
1434
    }
1435

    
1436
    var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent);
1437

    
1438
    if (!shouldSetEvent.isPersistent()) {
1439
      shouldSetEvent.constructor.release(shouldSetEvent);
1440
    }
1441

    
1442
    if (!wantsResponderInst || wantsResponderInst === responderInst) {
1443
      return null;
1444
    }
1445

    
1446
    var extracted;
1447
    var grantEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderGrant, wantsResponderInst, nativeEvent, nativeEventTarget);
1448
    grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
1449
    accumulateDirectDispatches(grantEvent);
1450
    var blockHostResponder = executeDirectDispatch(grantEvent) === true;
1451

    
1452
    if (responderInst) {
1453
      var terminationRequestEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderTerminationRequest, responderInst, nativeEvent, nativeEventTarget);
1454
      terminationRequestEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
1455
      accumulateDirectDispatches(terminationRequestEvent);
1456
      var shouldSwitch = !hasDispatches(terminationRequestEvent) || executeDirectDispatch(terminationRequestEvent);
1457

    
1458
      if (!terminationRequestEvent.isPersistent()) {
1459
        terminationRequestEvent.constructor.release(terminationRequestEvent);
1460
      }
1461

    
1462
      if (shouldSwitch) {
1463
        var terminateEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderTerminate, responderInst, nativeEvent, nativeEventTarget);
1464
        terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
1465
        accumulateDirectDispatches(terminateEvent);
1466
        extracted = accumulate(extracted, [grantEvent, terminateEvent]);
1467
        changeResponder(wantsResponderInst, blockHostResponder);
1468
      } else {
1469
        var rejectEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderReject, wantsResponderInst, nativeEvent, nativeEventTarget);
1470
        rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
1471
        accumulateDirectDispatches(rejectEvent);
1472
        extracted = accumulate(extracted, rejectEvent);
1473
      }
1474
    } else {
1475
      extracted = accumulate(extracted, grantEvent);
1476
      changeResponder(wantsResponderInst, blockHostResponder);
1477
    }
1478

    
1479
    return extracted;
1480
  }
1481
  /**
1482
   * A transfer is a negotiation between a currently set responder and the next
1483
   * element to claim responder status. Any start event could trigger a transfer
1484
   * of responderInst. Any move event could trigger a transfer.
1485
   *
1486
   * @param {string} topLevelType Record from `BrowserEventConstants`.
1487
   * @return {boolean} True if a transfer of responder could possibly occur.
1488
   */
1489

    
1490

    
1491
  function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) {
1492
    return topLevelInst && ( // responderIgnoreScroll: We are trying to migrate away from specifically
1493
    // tracking native scroll events here and responderIgnoreScroll indicates we
1494
    // will send topTouchCancel to handle canceling touch events instead
1495
    topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll || trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE || isStartish(topLevelType) || isMoveish(topLevelType));
1496
  }
1497
  /**
1498
   * Returns whether or not this touch end event makes it such that there are no
1499
   * longer any touches that started inside of the current `responderInst`.
1500
   *
1501
   * @param {NativeEvent} nativeEvent Native touch end event.
1502
   * @return {boolean} Whether or not this touch end event ends the responder.
1503
   */
1504

    
1505

    
1506
  function noResponderTouches(nativeEvent) {
1507
    var touches = nativeEvent.touches;
1508

    
1509
    if (!touches || touches.length === 0) {
1510
      return true;
1511
    }
1512

    
1513
    for (var i = 0; i < touches.length; i++) {
1514
      var activeTouch = touches[i];
1515
      var target = activeTouch.target;
1516

    
1517
      if (target !== null && target !== undefined && target !== 0) {
1518
        // Is the original touch location inside of the current responder?
1519
        var targetInst = getInstanceFromNode(target);
1520

    
1521
        if (isAncestor(responderInst, targetInst)) {
1522
          return false;
1523
        }
1524
      }
1525
    }
1526

    
1527
    return true;
1528
  }
1529

    
1530
  var ResponderEventPlugin = {
1531
    /* For unit testing only */
1532
    _getResponder: function () {
1533
      return responderInst;
1534
    },
1535
    eventTypes: eventTypes,
1536

    
1537
    /**
1538
     * We must be resilient to `targetInst` being `null` on `touchMove` or
1539
     * `touchEnd`. On certain platforms, this means that a native scroll has
1540
     * assumed control and the original touch targets are destroyed.
1541
     */
1542
    extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags) {
1543
      if (isStartish(topLevelType)) {
1544
        trackedTouchCount += 1;
1545
      } else if (isEndish(topLevelType)) {
1546
        if (trackedTouchCount >= 0) {
1547
          trackedTouchCount -= 1;
1548
        } else {
1549
          {
1550
            warn('Ended a touch event which was not counted in `trackedTouchCount`.');
1551
          }
1552

    
1553
          return null;
1554
        }
1555
      }
1556

    
1557
      ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent);
1558
      var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) ? setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) : null; // Responder may or may not have transferred on a new touch start/move.
1559
      // Regardless, whoever is the responder after any potential transfer, we
1560
      // direct all touch start/move/ends to them in the form of
1561
      // `onResponderMove/Start/End`. These will be called for *every* additional
1562
      // finger that move/start/end, dispatched directly to whoever is the
1563
      // current responder at that moment, until the responder is "released".
1564
      //
1565
      // These multiple individual change touch events are are always bookended
1566
      // by `onResponderGrant`, and one of
1567
      // (`onResponderRelease/onResponderTerminate`).
1568

    
1569
      var isResponderTouchStart = responderInst && isStartish(topLevelType);
1570
      var isResponderTouchMove = responderInst && isMoveish(topLevelType);
1571
      var isResponderTouchEnd = responderInst && isEndish(topLevelType);
1572
      var incrementalTouch = isResponderTouchStart ? eventTypes.responderStart : isResponderTouchMove ? eventTypes.responderMove : isResponderTouchEnd ? eventTypes.responderEnd : null;
1573

    
1574
      if (incrementalTouch) {
1575
        var gesture = ResponderSyntheticEvent.getPooled(incrementalTouch, responderInst, nativeEvent, nativeEventTarget);
1576
        gesture.touchHistory = ResponderTouchHistoryStore.touchHistory;
1577
        accumulateDirectDispatches(gesture);
1578
        extracted = accumulate(extracted, gesture);
1579
      }
1580

    
1581
      var isResponderTerminate = responderInst && topLevelType === TOP_TOUCH_CANCEL;
1582
      var isResponderRelease = responderInst && !isResponderTerminate && isEndish(topLevelType) && noResponderTouches(nativeEvent);
1583
      var finalTouch = isResponderTerminate ? eventTypes.responderTerminate : isResponderRelease ? eventTypes.responderRelease : null;
1584

    
1585
      if (finalTouch) {
1586
        var finalEvent = ResponderSyntheticEvent.getPooled(finalTouch, responderInst, nativeEvent, nativeEventTarget);
1587
        finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
1588
        accumulateDirectDispatches(finalEvent);
1589
        extracted = accumulate(extracted, finalEvent);
1590
        changeResponder(null);
1591
      }
1592

    
1593
      return extracted;
1594
    },
1595
    GlobalResponderHandler: null,
1596
    injection: {
1597
      /**
1598
       * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler
1599
       * Object that handles any change in responder. Use this to inject
1600
       * integration with an existing touch handling system etc.
1601
       */
1602
      injectGlobalResponderHandler: function (GlobalResponderHandler) {
1603
        ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler;
1604
      }
1605
    }
1606
  };
1607

    
1608
  // Keep in sync with ReactDOM.js, ReactTestUtils.js, and ReactTestUtilsAct.js:
1609

    
1610
  var _ReactDOM$__SECRET_IN = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Events,
1611
      getInstanceFromNode$1 = _ReactDOM$__SECRET_IN[0],
1612
      getNodeFromInstance$1 = _ReactDOM$__SECRET_IN[1],
1613
      getFiberCurrentPropsFromNode$1 = _ReactDOM$__SECRET_IN[2],
1614
      injectEventPluginsByName = _ReactDOM$__SECRET_IN[3];
1615
  setComponentTree(getFiberCurrentPropsFromNode$1, getInstanceFromNode$1, getNodeFromInstance$1);
1616

    
1617
  var ReactDOMUnstableNativeDependencies = /*#__PURE__*/Object.freeze({
1618
    __proto__: null,
1619
    ResponderEventPlugin: ResponderEventPlugin,
1620
    ResponderTouchHistoryStore: ResponderTouchHistoryStore,
1621
    injectEventPluginsByName: injectEventPluginsByName
1622
  });
1623

    
1624
  var unstableNativeDependencies = ReactDOMUnstableNativeDependencies;
1625

    
1626
  return unstableNativeDependencies;
1627

    
1628
})));
(7-7/11)