react-dom-unstable-native-dependencies.development.js 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628
  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. 'use strict';
  10. (function (global, factory) {
  11. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react-dom'), require('react')) :
  12. typeof define === 'function' && define.amd ? define(['react-dom', 'react'], factory) :
  13. (global = global || self, global.ReactDOMUnstableNativeDependencies = factory(global.ReactDOM, global.React));
  14. }(this, (function (ReactDOM, React) { 'use strict';
  15. 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.
  16. // Current owner and dispatcher used to share the same ref,
  17. // but PR #14548 split them out to better support the react-debug-tools package.
  18. if (!ReactSharedInternals.hasOwnProperty('ReactCurrentDispatcher')) {
  19. ReactSharedInternals.ReactCurrentDispatcher = {
  20. current: null
  21. };
  22. }
  23. if (!ReactSharedInternals.hasOwnProperty('ReactCurrentBatchConfig')) {
  24. ReactSharedInternals.ReactCurrentBatchConfig = {
  25. suspense: null
  26. };
  27. }
  28. // by calls to these methods by a Babel plugin.
  29. //
  30. // In PROD (or in packages without access to React internals),
  31. // they are left as they are instead.
  32. function warn(format) {
  33. {
  34. for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  35. args[_key - 1] = arguments[_key];
  36. }
  37. printWarning('warn', format, args);
  38. }
  39. }
  40. function error(format) {
  41. {
  42. for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  43. args[_key2 - 1] = arguments[_key2];
  44. }
  45. printWarning('error', format, args);
  46. }
  47. }
  48. function printWarning(level, format, args) {
  49. // When changing this logic, you might want to also
  50. // update consoleWithStackDev.www.js as well.
  51. {
  52. var hasExistingStack = args.length > 0 && typeof args[args.length - 1] === 'string' && args[args.length - 1].indexOf('\n in') === 0;
  53. if (!hasExistingStack) {
  54. var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
  55. var stack = ReactDebugCurrentFrame.getStackAddendum();
  56. if (stack !== '') {
  57. format += '%s';
  58. args = args.concat([stack]);
  59. }
  60. }
  61. var argsWithFormat = args.map(function (item) {
  62. return '' + item;
  63. }); // Careful: RN currently depends on this prefix
  64. argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
  65. // breaks IE9: https://github.com/facebook/react/issues/13610
  66. // eslint-disable-next-line react-internal/no-production-logging
  67. Function.prototype.apply.call(console[level], console, argsWithFormat);
  68. try {
  69. // --- Welcome to debugging React ---
  70. // This error was thrown as a convenience so that you can use this stack
  71. // to find the callsite that caused this warning to fire.
  72. var argIndex = 0;
  73. var message = 'Warning: ' + format.replace(/%s/g, function () {
  74. return args[argIndex++];
  75. });
  76. throw new Error(message);
  77. } catch (x) {}
  78. }
  79. }
  80. {
  81. // In DEV mode, we swap out invokeGuardedCallback for a special version
  82. // that plays more nicely with the browser's DevTools. The idea is to preserve
  83. // "Pause on exceptions" behavior. Because React wraps all user-provided
  84. // functions in invokeGuardedCallback, and the production version of
  85. // invokeGuardedCallback uses a try-catch, all user exceptions are treated
  86. // like caught exceptions, and the DevTools won't pause unless the developer
  87. // takes the extra step of enabling pause on caught exceptions. This is
  88. // unintuitive, though, because even though React has caught the error, from
  89. // the developer's perspective, the error is uncaught.
  90. //
  91. // To preserve the expected "Pause on exceptions" behavior, we don't use a
  92. // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake
  93. // DOM node, and call the user-provided callback from inside an event handler
  94. // for that fake event. If the callback throws, the error is "captured" using
  95. // a global event handler. But because the error happens in a different
  96. // event loop context, it does not interrupt the normal program flow.
  97. // Effectively, this gives us try-catch behavior without actually using
  98. // try-catch. Neat!
  99. // Check that the browser supports the APIs we need to implement our special
  100. // DEV version of invokeGuardedCallback
  101. if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
  102. var fakeNode = document.createElement('react');
  103. }
  104. }
  105. var getFiberCurrentPropsFromNode = null;
  106. var getInstanceFromNode = null;
  107. var getNodeFromInstance = null;
  108. function setComponentTree(getFiberCurrentPropsFromNodeImpl, getInstanceFromNodeImpl, getNodeFromInstanceImpl) {
  109. getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl;
  110. getInstanceFromNode = getInstanceFromNodeImpl;
  111. getNodeFromInstance = getNodeFromInstanceImpl;
  112. {
  113. if (!getNodeFromInstance || !getInstanceFromNode) {
  114. error('EventPluginUtils.setComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.');
  115. }
  116. }
  117. }
  118. var validateEventDispatches;
  119. {
  120. validateEventDispatches = function (event) {
  121. var dispatchListeners = event._dispatchListeners;
  122. var dispatchInstances = event._dispatchInstances;
  123. var listenersIsArr = Array.isArray(dispatchListeners);
  124. var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
  125. var instancesIsArr = Array.isArray(dispatchInstances);
  126. var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
  127. if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) {
  128. error('EventPluginUtils: Invalid `event`.');
  129. }
  130. };
  131. }
  132. /**
  133. * Standard/simple iteration through an event's collected dispatches, but stops
  134. * at the first dispatch execution returning true, and returns that id.
  135. *
  136. * @return {?string} id of the first dispatch execution who's listener returns
  137. * true, or null if no listener returned true.
  138. */
  139. function executeDispatchesInOrderStopAtTrueImpl(event) {
  140. var dispatchListeners = event._dispatchListeners;
  141. var dispatchInstances = event._dispatchInstances;
  142. {
  143. validateEventDispatches(event);
  144. }
  145. if (Array.isArray(dispatchListeners)) {
  146. for (var i = 0; i < dispatchListeners.length; i++) {
  147. if (event.isPropagationStopped()) {
  148. break;
  149. } // Listeners and Instances are two parallel arrays that are always in sync.
  150. if (dispatchListeners[i](event, dispatchInstances[i])) {
  151. return dispatchInstances[i];
  152. }
  153. }
  154. } else if (dispatchListeners) {
  155. if (dispatchListeners(event, dispatchInstances)) {
  156. return dispatchInstances;
  157. }
  158. }
  159. return null;
  160. }
  161. /**
  162. * @see executeDispatchesInOrderStopAtTrueImpl
  163. */
  164. function executeDispatchesInOrderStopAtTrue(event) {
  165. var ret = executeDispatchesInOrderStopAtTrueImpl(event);
  166. event._dispatchInstances = null;
  167. event._dispatchListeners = null;
  168. return ret;
  169. }
  170. /**
  171. * Execution of a "direct" dispatch - there must be at most one dispatch
  172. * accumulated on the event or it is considered an error. It doesn't really make
  173. * sense for an event with multiple dispatches (bubbled) to keep track of the
  174. * return values at each dispatch execution, but it does tend to make sense when
  175. * dealing with "direct" dispatches.
  176. *
  177. * @return {*} The return value of executing the single dispatch.
  178. */
  179. function executeDirectDispatch(event) {
  180. {
  181. validateEventDispatches(event);
  182. }
  183. var dispatchListener = event._dispatchListeners;
  184. var dispatchInstance = event._dispatchInstances;
  185. if (!!Array.isArray(dispatchListener)) {
  186. {
  187. throw Error( "executeDirectDispatch(...): Invalid `event`." );
  188. }
  189. }
  190. event.currentTarget = dispatchListener ? getNodeFromInstance(dispatchInstance) : null;
  191. var res = dispatchListener ? dispatchListener(event) : null;
  192. event.currentTarget = null;
  193. event._dispatchListeners = null;
  194. event._dispatchInstances = null;
  195. return res;
  196. }
  197. /**
  198. * @param {SyntheticEvent} event
  199. * @return {boolean} True iff number of dispatches accumulated is greater than 0.
  200. */
  201. function hasDispatches(event) {
  202. return !!event._dispatchListeners;
  203. }
  204. var HostComponent = 5;
  205. function getParent(inst) {
  206. do {
  207. inst = inst.return; // TODO: If this is a HostRoot we might want to bail out.
  208. // That is depending on if we want nested subtrees (layers) to bubble
  209. // events to their parent. We could also go through parentNode on the
  210. // host node but that wouldn't work for React Native and doesn't let us
  211. // do the portal feature.
  212. } while (inst && inst.tag !== HostComponent);
  213. if (inst) {
  214. return inst;
  215. }
  216. return null;
  217. }
  218. /**
  219. * Return the lowest common ancestor of A and B, or null if they are in
  220. * different trees.
  221. */
  222. function getLowestCommonAncestor(instA, instB) {
  223. var depthA = 0;
  224. for (var tempA = instA; tempA; tempA = getParent(tempA)) {
  225. depthA++;
  226. }
  227. var depthB = 0;
  228. for (var tempB = instB; tempB; tempB = getParent(tempB)) {
  229. depthB++;
  230. } // If A is deeper, crawl up.
  231. while (depthA - depthB > 0) {
  232. instA = getParent(instA);
  233. depthA--;
  234. } // If B is deeper, crawl up.
  235. while (depthB - depthA > 0) {
  236. instB = getParent(instB);
  237. depthB--;
  238. } // Walk in lockstep until we find a match.
  239. var depth = depthA;
  240. while (depth--) {
  241. if (instA === instB || instA === instB.alternate) {
  242. return instA;
  243. }
  244. instA = getParent(instA);
  245. instB = getParent(instB);
  246. }
  247. return null;
  248. }
  249. /**
  250. * Return if A is an ancestor of B.
  251. */
  252. function isAncestor(instA, instB) {
  253. while (instB) {
  254. if (instA === instB || instA === instB.alternate) {
  255. return true;
  256. }
  257. instB = getParent(instB);
  258. }
  259. return false;
  260. }
  261. /**
  262. * Return the parent instance of the passed-in instance.
  263. */
  264. function getParentInstance(inst) {
  265. return getParent(inst);
  266. }
  267. /**
  268. * Simulates the traversal of a two-phase, capture/bubble event dispatch.
  269. */
  270. function traverseTwoPhase(inst, fn, arg) {
  271. var path = [];
  272. while (inst) {
  273. path.push(inst);
  274. inst = getParent(inst);
  275. }
  276. var i;
  277. for (i = path.length; i-- > 0;) {
  278. fn(path[i], 'captured', arg);
  279. }
  280. for (i = 0; i < path.length; i++) {
  281. fn(path[i], 'bubbled', arg);
  282. }
  283. }
  284. function isInteractive(tag) {
  285. return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
  286. }
  287. function shouldPreventMouseEvent(name, type, props) {
  288. switch (name) {
  289. case 'onClick':
  290. case 'onClickCapture':
  291. case 'onDoubleClick':
  292. case 'onDoubleClickCapture':
  293. case 'onMouseDown':
  294. case 'onMouseDownCapture':
  295. case 'onMouseMove':
  296. case 'onMouseMoveCapture':
  297. case 'onMouseUp':
  298. case 'onMouseUpCapture':
  299. case 'onMouseEnter':
  300. return !!(props.disabled && isInteractive(type));
  301. default:
  302. return false;
  303. }
  304. }
  305. /**
  306. * @param {object} inst The instance, which is the source of events.
  307. * @param {string} registrationName Name of listener (e.g. `onClick`).
  308. * @return {?function} The stored callback.
  309. */
  310. function getListener(inst, registrationName) {
  311. var listener; // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
  312. // live here; needs to be moved to a better place soon
  313. var stateNode = inst.stateNode;
  314. if (!stateNode) {
  315. // Work in progress (ex: onload events in incremental mode).
  316. return null;
  317. }
  318. var props = getFiberCurrentPropsFromNode(stateNode);
  319. if (!props) {
  320. // Work in progress.
  321. return null;
  322. }
  323. listener = props[registrationName];
  324. if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
  325. return null;
  326. }
  327. if (!(!listener || typeof listener === 'function')) {
  328. {
  329. throw Error( "Expected `" + registrationName + "` listener to be a function, instead got a value of `" + typeof listener + "` type." );
  330. }
  331. }
  332. return listener;
  333. }
  334. /**
  335. * Accumulates items that must not be null or undefined into the first one. This
  336. * is used to conserve memory by avoiding array allocations, and thus sacrifices
  337. * API cleanness. Since `current` can be null before being passed in and not
  338. * null after this function, make sure to assign it back to `current`:
  339. *
  340. * `a = accumulateInto(a, b);`
  341. *
  342. * This API should be sparingly used. Try `accumulate` for something cleaner.
  343. *
  344. * @return {*|array<*>} An accumulation of items.
  345. */
  346. function accumulateInto(current, next) {
  347. if (!(next != null)) {
  348. {
  349. throw Error( "accumulateInto(...): Accumulated items must not be null or undefined." );
  350. }
  351. }
  352. if (current == null) {
  353. return next;
  354. } // Both are not empty. Warning: Never call x.concat(y) when you are not
  355. // certain that x is an Array (x could be a string with concat method).
  356. if (Array.isArray(current)) {
  357. if (Array.isArray(next)) {
  358. current.push.apply(current, next);
  359. return current;
  360. }
  361. current.push(next);
  362. return current;
  363. }
  364. if (Array.isArray(next)) {
  365. // A bit too dangerous to mutate `next`.
  366. return [current].concat(next);
  367. }
  368. return [current, next];
  369. }
  370. /**
  371. * @param {array} arr an "accumulation" of items which is either an Array or
  372. * a single item. Useful when paired with the `accumulate` module. This is a
  373. * simple utility that allows us to reason about a collection of items, but
  374. * handling the case when there is exactly one item (and we do not need to
  375. * allocate an array).
  376. * @param {function} cb Callback invoked with each element or a collection.
  377. * @param {?} [scope] Scope used as `this` in a callback.
  378. */
  379. function forEachAccumulated(arr, cb, scope) {
  380. if (Array.isArray(arr)) {
  381. arr.forEach(cb, scope);
  382. } else if (arr) {
  383. cb.call(scope, arr);
  384. }
  385. }
  386. /**
  387. * Some event types have a notion of different registration names for different
  388. * "phases" of propagation. This finds listeners by a given phase.
  389. */
  390. function listenerAtPhase(inst, event, propagationPhase) {
  391. var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
  392. return getListener(inst, registrationName);
  393. }
  394. /**
  395. * A small set of propagation patterns, each of which will accept a small amount
  396. * of information, and generate a set of "dispatch ready event objects" - which
  397. * are sets of events that have already been annotated with a set of dispatched
  398. * listener functions/ids. The API is designed this way to discourage these
  399. * propagation strategies from actually executing the dispatches, since we
  400. * always want to collect the entire set of dispatches before executing even a
  401. * single one.
  402. */
  403. /**
  404. * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
  405. * here, allows us to not have to bind or create functions for each event.
  406. * Mutating the event's members allows us to not have to create a wrapping
  407. * "dispatch" object that pairs the event with the listener.
  408. */
  409. function accumulateDirectionalDispatches(inst, phase, event) {
  410. {
  411. if (!inst) {
  412. error('Dispatching inst must not be null');
  413. }
  414. }
  415. var listener = listenerAtPhase(inst, event, phase);
  416. if (listener) {
  417. event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
  418. event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
  419. }
  420. }
  421. /**
  422. * Collect dispatches (must be entirely collected before dispatching - see unit
  423. * tests). Lazily allocate the array to conserve memory. We must loop through
  424. * each event and perform the traversal for each one. We cannot perform a
  425. * single traversal for the entire collection of events because each event may
  426. * have a different target.
  427. */
  428. function accumulateTwoPhaseDispatchesSingle(event) {
  429. if (event && event.dispatchConfig.phasedRegistrationNames) {
  430. traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
  431. }
  432. }
  433. /**
  434. * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
  435. */
  436. function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
  437. if (event && event.dispatchConfig.phasedRegistrationNames) {
  438. var targetInst = event._targetInst;
  439. var parentInst = targetInst ? getParentInstance(targetInst) : null;
  440. traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
  441. }
  442. }
  443. /**
  444. * Accumulates without regard to direction, does not look for phased
  445. * registration names. Same as `accumulateDirectDispatchesSingle` but without
  446. * requiring that the `dispatchMarker` be the same as the dispatched ID.
  447. */
  448. function accumulateDispatches(inst, ignoredDirection, event) {
  449. if (inst && event && event.dispatchConfig.registrationName) {
  450. var registrationName = event.dispatchConfig.registrationName;
  451. var listener = getListener(inst, registrationName);
  452. if (listener) {
  453. event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
  454. event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
  455. }
  456. }
  457. }
  458. /**
  459. * Accumulates dispatches on an `SyntheticEvent`, but only for the
  460. * `dispatchMarker`.
  461. * @param {SyntheticEvent} event
  462. */
  463. function accumulateDirectDispatchesSingle(event) {
  464. if (event && event.dispatchConfig.registrationName) {
  465. accumulateDispatches(event._targetInst, null, event);
  466. }
  467. }
  468. function accumulateTwoPhaseDispatches(events) {
  469. forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
  470. }
  471. function accumulateTwoPhaseDispatchesSkipTarget(events) {
  472. forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
  473. }
  474. function accumulateDirectDispatches(events) {
  475. forEachAccumulated(events, accumulateDirectDispatchesSingle);
  476. }
  477. var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
  478. var _assign = ReactInternals.assign;
  479. var EVENT_POOL_SIZE = 10;
  480. /**
  481. * @interface Event
  482. * @see http://www.w3.org/TR/DOM-Level-3-Events/
  483. */
  484. var EventInterface = {
  485. type: null,
  486. target: null,
  487. // currentTarget is set when dispatching; no use in copying it here
  488. currentTarget: function () {
  489. return null;
  490. },
  491. eventPhase: null,
  492. bubbles: null,
  493. cancelable: null,
  494. timeStamp: function (event) {
  495. return event.timeStamp || Date.now();
  496. },
  497. defaultPrevented: null,
  498. isTrusted: null
  499. };
  500. function functionThatReturnsTrue() {
  501. return true;
  502. }
  503. function functionThatReturnsFalse() {
  504. return false;
  505. }
  506. /**
  507. * Synthetic events are dispatched by event plugins, typically in response to a
  508. * top-level event delegation handler.
  509. *
  510. * These systems should generally use pooling to reduce the frequency of garbage
  511. * collection. The system should check `isPersistent` to determine whether the
  512. * event should be released into the pool after being dispatched. Users that
  513. * need a persisted event should invoke `persist`.
  514. *
  515. * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
  516. * normalizing browser quirks. Subclasses do not necessarily have to implement a
  517. * DOM interface; custom application-specific events can also subclass this.
  518. *
  519. * @param {object} dispatchConfig Configuration used to dispatch this event.
  520. * @param {*} targetInst Marker identifying the event target.
  521. * @param {object} nativeEvent Native browser event.
  522. * @param {DOMEventTarget} nativeEventTarget Target node.
  523. */
  524. function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
  525. {
  526. // these have a getter/setter for warnings
  527. delete this.nativeEvent;
  528. delete this.preventDefault;
  529. delete this.stopPropagation;
  530. delete this.isDefaultPrevented;
  531. delete this.isPropagationStopped;
  532. }
  533. this.dispatchConfig = dispatchConfig;
  534. this._targetInst = targetInst;
  535. this.nativeEvent = nativeEvent;
  536. var Interface = this.constructor.Interface;
  537. for (var propName in Interface) {
  538. if (!Interface.hasOwnProperty(propName)) {
  539. continue;
  540. }
  541. {
  542. delete this[propName]; // this has a getter/setter for warnings
  543. }
  544. var normalize = Interface[propName];
  545. if (normalize) {
  546. this[propName] = normalize(nativeEvent);
  547. } else {
  548. if (propName === 'target') {
  549. this.target = nativeEventTarget;
  550. } else {
  551. this[propName] = nativeEvent[propName];
  552. }
  553. }
  554. }
  555. var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
  556. if (defaultPrevented) {
  557. this.isDefaultPrevented = functionThatReturnsTrue;
  558. } else {
  559. this.isDefaultPrevented = functionThatReturnsFalse;
  560. }
  561. this.isPropagationStopped = functionThatReturnsFalse;
  562. return this;
  563. }
  564. _assign(SyntheticEvent.prototype, {
  565. preventDefault: function () {
  566. this.defaultPrevented = true;
  567. var event = this.nativeEvent;
  568. if (!event) {
  569. return;
  570. }
  571. if (event.preventDefault) {
  572. event.preventDefault();
  573. } else if (typeof event.returnValue !== 'unknown') {
  574. event.returnValue = false;
  575. }
  576. this.isDefaultPrevented = functionThatReturnsTrue;
  577. },
  578. stopPropagation: function () {
  579. var event = this.nativeEvent;
  580. if (!event) {
  581. return;
  582. }
  583. if (event.stopPropagation) {
  584. event.stopPropagation();
  585. } else if (typeof event.cancelBubble !== 'unknown') {
  586. // The ChangeEventPlugin registers a "propertychange" event for
  587. // IE. This event does not support bubbling or cancelling, and
  588. // any references to cancelBubble throw "Member not found". A
  589. // typeof check of "unknown" circumvents this issue (and is also
  590. // IE specific).
  591. event.cancelBubble = true;
  592. }
  593. this.isPropagationStopped = functionThatReturnsTrue;
  594. },
  595. /**
  596. * We release all dispatched `SyntheticEvent`s after each event loop, adding
  597. * them back into the pool. This allows a way to hold onto a reference that
  598. * won't be added back into the pool.
  599. */
  600. persist: function () {
  601. this.isPersistent = functionThatReturnsTrue;
  602. },
  603. /**
  604. * Checks if this event should be released back into the pool.
  605. *
  606. * @return {boolean} True if this should not be released, false otherwise.
  607. */
  608. isPersistent: functionThatReturnsFalse,
  609. /**
  610. * `PooledClass` looks for `destructor` on each instance it releases.
  611. */
  612. destructor: function () {
  613. var Interface = this.constructor.Interface;
  614. for (var propName in Interface) {
  615. {
  616. Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));
  617. }
  618. }
  619. this.dispatchConfig = null;
  620. this._targetInst = null;
  621. this.nativeEvent = null;
  622. this.isDefaultPrevented = functionThatReturnsFalse;
  623. this.isPropagationStopped = functionThatReturnsFalse;
  624. this._dispatchListeners = null;
  625. this._dispatchInstances = null;
  626. {
  627. Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));
  628. Object.defineProperty(this, 'isDefaultPrevented', getPooledWarningPropertyDefinition('isDefaultPrevented', functionThatReturnsFalse));
  629. Object.defineProperty(this, 'isPropagationStopped', getPooledWarningPropertyDefinition('isPropagationStopped', functionThatReturnsFalse));
  630. Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', function () {}));
  631. Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', function () {}));
  632. }
  633. }
  634. });
  635. SyntheticEvent.Interface = EventInterface;
  636. /**
  637. * Helper to reduce boilerplate when creating subclasses.
  638. */
  639. SyntheticEvent.extend = function (Interface) {
  640. var Super = this;
  641. var E = function () {};
  642. E.prototype = Super.prototype;
  643. var prototype = new E();
  644. function Class() {
  645. return Super.apply(this, arguments);
  646. }
  647. _assign(prototype, Class.prototype);
  648. Class.prototype = prototype;
  649. Class.prototype.constructor = Class;
  650. Class.Interface = _assign({}, Super.Interface, Interface);
  651. Class.extend = Super.extend;
  652. addEventPoolingTo(Class);
  653. return Class;
  654. };
  655. addEventPoolingTo(SyntheticEvent);
  656. /**
  657. * Helper to nullify syntheticEvent instance properties when destructing
  658. *
  659. * @param {String} propName
  660. * @param {?object} getVal
  661. * @return {object} defineProperty object
  662. */
  663. function getPooledWarningPropertyDefinition(propName, getVal) {
  664. var isFunction = typeof getVal === 'function';
  665. return {
  666. configurable: true,
  667. set: set,
  668. get: get
  669. };
  670. function set(val) {
  671. var action = isFunction ? 'setting the method' : 'setting the property';
  672. warn(action, 'This is effectively a no-op');
  673. return val;
  674. }
  675. function get() {
  676. var action = isFunction ? 'accessing the method' : 'accessing the property';
  677. var result = isFunction ? 'This is a no-op function' : 'This is set to null';
  678. warn(action, result);
  679. return getVal;
  680. }
  681. function warn(action, result) {
  682. {
  683. 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);
  684. }
  685. }
  686. }
  687. function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {
  688. var EventConstructor = this;
  689. if (EventConstructor.eventPool.length) {
  690. var instance = EventConstructor.eventPool.pop();
  691. EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst);
  692. return instance;
  693. }
  694. return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst);
  695. }
  696. function releasePooledEvent(event) {
  697. var EventConstructor = this;
  698. if (!(event instanceof EventConstructor)) {
  699. {
  700. throw Error( "Trying to release an event instance into a pool of a different type." );
  701. }
  702. }
  703. event.destructor();
  704. if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
  705. EventConstructor.eventPool.push(event);
  706. }
  707. }
  708. function addEventPoolingTo(EventConstructor) {
  709. EventConstructor.eventPool = [];
  710. EventConstructor.getPooled = getPooledEvent;
  711. EventConstructor.release = releasePooledEvent;
  712. }
  713. /**
  714. * `touchHistory` isn't actually on the native event, but putting it in the
  715. * interface will ensure that it is cleaned up when pooled/destroyed. The
  716. * `ResponderEventPlugin` will populate it appropriately.
  717. */
  718. var ResponderSyntheticEvent = SyntheticEvent.extend({
  719. touchHistory: function (nativeEvent) {
  720. return null; // Actually doesn't even look at the native event.
  721. }
  722. });
  723. // Note: ideally these would be imported from DOMTopLevelEventTypes,
  724. // but our build system currently doesn't let us do that from a fork.
  725. var TOP_TOUCH_START = 'touchstart';
  726. var TOP_TOUCH_MOVE = 'touchmove';
  727. var TOP_TOUCH_END = 'touchend';
  728. var TOP_TOUCH_CANCEL = 'touchcancel';
  729. var TOP_SCROLL = 'scroll';
  730. var TOP_SELECTION_CHANGE = 'selectionchange';
  731. var TOP_MOUSE_DOWN = 'mousedown';
  732. var TOP_MOUSE_MOVE = 'mousemove';
  733. var TOP_MOUSE_UP = 'mouseup';
  734. function isStartish(topLevelType) {
  735. return topLevelType === TOP_TOUCH_START || topLevelType === TOP_MOUSE_DOWN;
  736. }
  737. function isMoveish(topLevelType) {
  738. return topLevelType === TOP_TOUCH_MOVE || topLevelType === TOP_MOUSE_MOVE;
  739. }
  740. function isEndish(topLevelType) {
  741. return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL || topLevelType === TOP_MOUSE_UP;
  742. }
  743. var startDependencies = [TOP_TOUCH_START, TOP_MOUSE_DOWN];
  744. var moveDependencies = [TOP_TOUCH_MOVE, TOP_MOUSE_MOVE];
  745. var endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END, TOP_MOUSE_UP];
  746. /**
  747. * Tracks the position and time of each active touch by `touch.identifier`. We
  748. * should typically only see IDs in the range of 1-20 because IDs get recycled
  749. * when touches end and start again.
  750. */
  751. var MAX_TOUCH_BANK = 20;
  752. var touchBank = [];
  753. var touchHistory = {
  754. touchBank: touchBank,
  755. numberActiveTouches: 0,
  756. // If there is only one active touch, we remember its location. This prevents
  757. // us having to loop through all of the touches all the time in the most
  758. // common case.
  759. indexOfSingleActiveTouch: -1,
  760. mostRecentTimeStamp: 0
  761. };
  762. function timestampForTouch(touch) {
  763. // The legacy internal implementation provides "timeStamp", which has been
  764. // renamed to "timestamp". Let both work for now while we iron it out
  765. // TODO (evv): rename timeStamp to timestamp in internal code
  766. return touch.timeStamp || touch.timestamp;
  767. }
  768. /**
  769. * TODO: Instead of making gestures recompute filtered velocity, we could
  770. * include a built in velocity computation that can be reused globally.
  771. */
  772. function createTouchRecord(touch) {
  773. return {
  774. touchActive: true,
  775. startPageX: touch.pageX,
  776. startPageY: touch.pageY,
  777. startTimeStamp: timestampForTouch(touch),
  778. currentPageX: touch.pageX,
  779. currentPageY: touch.pageY,
  780. currentTimeStamp: timestampForTouch(touch),
  781. previousPageX: touch.pageX,
  782. previousPageY: touch.pageY,
  783. previousTimeStamp: timestampForTouch(touch)
  784. };
  785. }
  786. function resetTouchRecord(touchRecord, touch) {
  787. touchRecord.touchActive = true;
  788. touchRecord.startPageX = touch.pageX;
  789. touchRecord.startPageY = touch.pageY;
  790. touchRecord.startTimeStamp = timestampForTouch(touch);
  791. touchRecord.currentPageX = touch.pageX;
  792. touchRecord.currentPageY = touch.pageY;
  793. touchRecord.currentTimeStamp = timestampForTouch(touch);
  794. touchRecord.previousPageX = touch.pageX;
  795. touchRecord.previousPageY = touch.pageY;
  796. touchRecord.previousTimeStamp = timestampForTouch(touch);
  797. }
  798. function getTouchIdentifier(_ref) {
  799. var identifier = _ref.identifier;
  800. if (!(identifier != null)) {
  801. {
  802. throw Error( "Touch object is missing identifier." );
  803. }
  804. }
  805. {
  806. if (identifier > MAX_TOUCH_BANK) {
  807. 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);
  808. }
  809. }
  810. return identifier;
  811. }
  812. function recordTouchStart(touch) {
  813. var identifier = getTouchIdentifier(touch);
  814. var touchRecord = touchBank[identifier];
  815. if (touchRecord) {
  816. resetTouchRecord(touchRecord, touch);
  817. } else {
  818. touchBank[identifier] = createTouchRecord(touch);
  819. }
  820. touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
  821. }
  822. function recordTouchMove(touch) {
  823. var touchRecord = touchBank[getTouchIdentifier(touch)];
  824. if (touchRecord) {
  825. touchRecord.touchActive = true;
  826. touchRecord.previousPageX = touchRecord.currentPageX;
  827. touchRecord.previousPageY = touchRecord.currentPageY;
  828. touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
  829. touchRecord.currentPageX = touch.pageX;
  830. touchRecord.currentPageY = touch.pageY;
  831. touchRecord.currentTimeStamp = timestampForTouch(touch);
  832. touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
  833. } else {
  834. {
  835. warn('Cannot record touch move without a touch start.\n' + 'Touch Move: %s\n' + 'Touch Bank: %s', printTouch(touch), printTouchBank());
  836. }
  837. }
  838. }
  839. function recordTouchEnd(touch) {
  840. var touchRecord = touchBank[getTouchIdentifier(touch)];
  841. if (touchRecord) {
  842. touchRecord.touchActive = false;
  843. touchRecord.previousPageX = touchRecord.currentPageX;
  844. touchRecord.previousPageY = touchRecord.currentPageY;
  845. touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
  846. touchRecord.currentPageX = touch.pageX;
  847. touchRecord.currentPageY = touch.pageY;
  848. touchRecord.currentTimeStamp = timestampForTouch(touch);
  849. touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
  850. } else {
  851. {
  852. warn('Cannot record touch end without a touch start.\n' + 'Touch End: %s\n' + 'Touch Bank: %s', printTouch(touch), printTouchBank());
  853. }
  854. }
  855. }
  856. function printTouch(touch) {
  857. return JSON.stringify({
  858. identifier: touch.identifier,
  859. pageX: touch.pageX,
  860. pageY: touch.pageY,
  861. timestamp: timestampForTouch(touch)
  862. });
  863. }
  864. function printTouchBank() {
  865. var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK));
  866. if (touchBank.length > MAX_TOUCH_BANK) {
  867. printed += ' (original size: ' + touchBank.length + ')';
  868. }
  869. return printed;
  870. }
  871. var ResponderTouchHistoryStore = {
  872. recordTouchTrack: function (topLevelType, nativeEvent) {
  873. if (isMoveish(topLevelType)) {
  874. nativeEvent.changedTouches.forEach(recordTouchMove);
  875. } else if (isStartish(topLevelType)) {
  876. nativeEvent.changedTouches.forEach(recordTouchStart);
  877. touchHistory.numberActiveTouches = nativeEvent.touches.length;
  878. if (touchHistory.numberActiveTouches === 1) {
  879. touchHistory.indexOfSingleActiveTouch = nativeEvent.touches[0].identifier;
  880. }
  881. } else if (isEndish(topLevelType)) {
  882. nativeEvent.changedTouches.forEach(recordTouchEnd);
  883. touchHistory.numberActiveTouches = nativeEvent.touches.length;
  884. if (touchHistory.numberActiveTouches === 1) {
  885. for (var i = 0; i < touchBank.length; i++) {
  886. var touchTrackToCheck = touchBank[i];
  887. if (touchTrackToCheck != null && touchTrackToCheck.touchActive) {
  888. touchHistory.indexOfSingleActiveTouch = i;
  889. break;
  890. }
  891. }
  892. {
  893. var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch];
  894. if (activeRecord == null || !activeRecord.touchActive) {
  895. error('Cannot find single active touch.');
  896. }
  897. }
  898. }
  899. }
  900. },
  901. touchHistory: touchHistory
  902. };
  903. /**
  904. * Accumulates items that must not be null or undefined.
  905. *
  906. * This is used to conserve memory by avoiding array allocations.
  907. *
  908. * @return {*|array<*>} An accumulation of items.
  909. */
  910. function accumulate(current, next) {
  911. if (!(next != null)) {
  912. {
  913. throw Error( "accumulate(...): Accumulated items must not be null or undefined." );
  914. }
  915. }
  916. if (current == null) {
  917. return next;
  918. } // Both are not empty. Warning: Never call x.concat(y) when you are not
  919. // certain that x is an Array (x could be a string with concat method).
  920. if (Array.isArray(current)) {
  921. return current.concat(next);
  922. }
  923. if (Array.isArray(next)) {
  924. return [current].concat(next);
  925. }
  926. return [current, next];
  927. }
  928. /**
  929. * Instance of element that should respond to touch/move types of interactions,
  930. * as indicated explicitly by relevant callbacks.
  931. */
  932. var responderInst = null;
  933. /**
  934. * Count of current touches. A textInput should become responder iff the
  935. * selection changes while there is a touch on the screen.
  936. */
  937. var trackedTouchCount = 0;
  938. var changeResponder = function (nextResponderInst, blockHostResponder) {
  939. var oldResponderInst = responderInst;
  940. responderInst = nextResponderInst;
  941. if (ResponderEventPlugin.GlobalResponderHandler !== null) {
  942. ResponderEventPlugin.GlobalResponderHandler.onChange(oldResponderInst, nextResponderInst, blockHostResponder);
  943. }
  944. };
  945. var eventTypes = {
  946. /**
  947. * On a `touchStart`/`mouseDown`, is it desired that this element become the
  948. * responder?
  949. */
  950. startShouldSetResponder: {
  951. phasedRegistrationNames: {
  952. bubbled: 'onStartShouldSetResponder',
  953. captured: 'onStartShouldSetResponderCapture'
  954. },
  955. dependencies: startDependencies
  956. },
  957. /**
  958. * On a `scroll`, is it desired that this element become the responder? This
  959. * is usually not needed, but should be used to retroactively infer that a
  960. * `touchStart` had occurred during momentum scroll. During a momentum scroll,
  961. * a touch start will be immediately followed by a scroll event if the view is
  962. * currently scrolling.
  963. *
  964. * TODO: This shouldn't bubble.
  965. */
  966. scrollShouldSetResponder: {
  967. phasedRegistrationNames: {
  968. bubbled: 'onScrollShouldSetResponder',
  969. captured: 'onScrollShouldSetResponderCapture'
  970. },
  971. dependencies: [TOP_SCROLL]
  972. },
  973. /**
  974. * On text selection change, should this element become the responder? This
  975. * is needed for text inputs or other views with native selection, so the
  976. * JS view can claim the responder.
  977. *
  978. * TODO: This shouldn't bubble.
  979. */
  980. selectionChangeShouldSetResponder: {
  981. phasedRegistrationNames: {
  982. bubbled: 'onSelectionChangeShouldSetResponder',
  983. captured: 'onSelectionChangeShouldSetResponderCapture'
  984. },
  985. dependencies: [TOP_SELECTION_CHANGE]
  986. },
  987. /**
  988. * On a `touchMove`/`mouseMove`, is it desired that this element become the
  989. * responder?
  990. */
  991. moveShouldSetResponder: {
  992. phasedRegistrationNames: {
  993. bubbled: 'onMoveShouldSetResponder',
  994. captured: 'onMoveShouldSetResponderCapture'
  995. },
  996. dependencies: moveDependencies
  997. },
  998. /**
  999. * Direct responder events dispatched directly to responder. Do not bubble.
  1000. */
  1001. responderStart: {
  1002. registrationName: 'onResponderStart',
  1003. dependencies: startDependencies
  1004. },
  1005. responderMove: {
  1006. registrationName: 'onResponderMove',
  1007. dependencies: moveDependencies
  1008. },
  1009. responderEnd: {
  1010. registrationName: 'onResponderEnd',
  1011. dependencies: endDependencies
  1012. },
  1013. responderRelease: {
  1014. registrationName: 'onResponderRelease',
  1015. dependencies: endDependencies
  1016. },
  1017. responderTerminationRequest: {
  1018. registrationName: 'onResponderTerminationRequest',
  1019. dependencies: []
  1020. },
  1021. responderGrant: {
  1022. registrationName: 'onResponderGrant',
  1023. dependencies: []
  1024. },
  1025. responderReject: {
  1026. registrationName: 'onResponderReject',
  1027. dependencies: []
  1028. },
  1029. responderTerminate: {
  1030. registrationName: 'onResponderTerminate',
  1031. dependencies: []
  1032. }
  1033. };
  1034. /**
  1035. *
  1036. * Responder System:
  1037. * ----------------
  1038. *
  1039. * - A global, solitary "interaction lock" on a view.
  1040. * - If a node becomes the responder, it should convey visual feedback
  1041. * immediately to indicate so, either by highlighting or moving accordingly.
  1042. * - To be the responder means, that touches are exclusively important to that
  1043. * responder view, and no other view.
  1044. * - While touches are still occurring, the responder lock can be transferred to
  1045. * a new view, but only to increasingly "higher" views (meaning ancestors of
  1046. * the current responder).
  1047. *
  1048. * Responder being granted:
  1049. * ------------------------
  1050. *
  1051. * - Touch starts, moves, and scrolls can cause an ID to become the responder.
  1052. * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to
  1053. * the "appropriate place".
  1054. * - If nothing is currently the responder, the "appropriate place" is the
  1055. * initiating event's `targetID`.
  1056. * - If something *is* already the responder, the "appropriate place" is the
  1057. * first common ancestor of the event target and the current `responderInst`.
  1058. * - Some negotiation happens: See the timing diagram below.
  1059. * - Scrolled views automatically become responder. The reasoning is that a
  1060. * platform scroll view that isn't built on top of the responder system has
  1061. * began scrolling, and the active responder must now be notified that the
  1062. * interaction is no longer locked to it - the system has taken over.
  1063. *
  1064. * - Responder being released:
  1065. * As soon as no more touches that *started* inside of descendants of the
  1066. * *current* responderInst, an `onResponderRelease` event is dispatched to the
  1067. * current responder, and the responder lock is released.
  1068. *
  1069. * TODO:
  1070. * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that
  1071. * determines if the responder lock should remain.
  1072. * - If a view shouldn't "remain" the responder, any active touches should by
  1073. * default be considered "dead" and do not influence future negotiations or
  1074. * bubble paths. It should be as if those touches do not exist.
  1075. * -- For multitouch: Usually a translate-z will choose to "remain" responder
  1076. * after one out of many touches ended. For translate-y, usually the view
  1077. * doesn't wish to "remain" responder after one of many touches end.
  1078. * - Consider building this on top of a `stopPropagation` model similar to
  1079. * `W3C` events.
  1080. * - Ensure that `onResponderTerminate` is called on touch cancels, whether or
  1081. * not `onResponderTerminationRequest` returns `true` or `false`.
  1082. *
  1083. */
  1084. /* Negotiation Performed
  1085. +-----------------------+
  1086. / \
  1087. Process low level events to + Current Responder + wantsResponderID
  1088. determine who to perform negot-| (if any exists at all) |
  1089. iation/transition | Otherwise just pass through|
  1090. -------------------------------+----------------------------+------------------+
  1091. Bubble to find first ID | |
  1092. to return true:wantsResponderID| |
  1093. | |
  1094. +-------------+ | |
  1095. | onTouchStart| | |
  1096. +------+------+ none | |
  1097. | return| |
  1098. +-----------v-------------+true| +------------------------+ |
  1099. |onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+
  1100. +-----------+-------------+ | +------------------------+ | |
  1101. | | | +--------+-------+
  1102. | returned true for| false:REJECT +-------->|onResponderReject
  1103. | wantsResponderID | | | +----------------+
  1104. | (now attempt | +------------------+-----+ |
  1105. | handoff) | | onResponder | |
  1106. +------------------->| TerminationRequest| |
  1107. | +------------------+-----+ |
  1108. | | | +----------------+
  1109. | true:GRANT +-------->|onResponderGrant|
  1110. | | +--------+-------+
  1111. | +------------------------+ | |
  1112. | | onResponderTerminate |<-----------+
  1113. | +------------------+-----+ |
  1114. | | | +----------------+
  1115. | +-------->|onResponderStart|
  1116. | | +----------------+
  1117. Bubble to find first ID | |
  1118. to return true:wantsResponderID| |
  1119. | |
  1120. +-------------+ | |
  1121. | onTouchMove | | |
  1122. +------+------+ none | |
  1123. | return| |
  1124. +-----------v-------------+true| +------------------------+ |
  1125. |onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+
  1126. +-----------+-------------+ | +------------------------+ | |
  1127. | | | +--------+-------+
  1128. | returned true for| false:REJECT +-------->|onResponderRejec|
  1129. | wantsResponderID | | | +----------------+
  1130. | (now attempt | +------------------+-----+ |
  1131. | handoff) | | onResponder | |
  1132. +------------------->| TerminationRequest| |
  1133. | +------------------+-----+ |
  1134. | | | +----------------+
  1135. | true:GRANT +-------->|onResponderGrant|
  1136. | | +--------+-------+
  1137. | +------------------------+ | |
  1138. | | onResponderTerminate |<-----------+
  1139. | +------------------+-----+ |
  1140. | | | +----------------+
  1141. | +-------->|onResponderMove |
  1142. | | +----------------+
  1143. | |
  1144. | |
  1145. Some active touch started| |
  1146. inside current responder | +------------------------+ |
  1147. +------------------------->| onResponderEnd | |
  1148. | | +------------------------+ |
  1149. +---+---------+ | |
  1150. | onTouchEnd | | |
  1151. +---+---------+ | |
  1152. | | +------------------------+ |
  1153. +------------------------->| onResponderEnd | |
  1154. No active touches started| +-----------+------------+ |
  1155. inside current responder | | |
  1156. | v |
  1157. | +------------------------+ |
  1158. | | onResponderRelease | |
  1159. | +------------------------+ |
  1160. | |
  1161. + + */
  1162. /**
  1163. * A note about event ordering in the `EventPluginRegistry`.
  1164. *
  1165. * Suppose plugins are injected in the following order:
  1166. *
  1167. * `[R, S, C]`
  1168. *
  1169. * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for
  1170. * `onClick` etc) and `R` is `ResponderEventPlugin`.
  1171. *
  1172. * "Deferred-Dispatched Events":
  1173. *
  1174. * - The current event plugin system will traverse the list of injected plugins,
  1175. * in order, and extract events by collecting the plugin's return value of
  1176. * `extractEvents()`.
  1177. * - These events that are returned from `extractEvents` are "deferred
  1178. * dispatched events".
  1179. * - When returned from `extractEvents`, deferred-dispatched events contain an
  1180. * "accumulation" of deferred dispatches.
  1181. * - These deferred dispatches are accumulated/collected before they are
  1182. * returned, but processed at a later time by the `EventPluginRegistry` (hence the
  1183. * name deferred).
  1184. *
  1185. * In the process of returning their deferred-dispatched events, event plugins
  1186. * themselves can dispatch events on-demand without returning them from
  1187. * `extractEvents`. Plugins might want to do this, so that they can use event
  1188. * dispatching as a tool that helps them decide which events should be extracted
  1189. * in the first place.
  1190. *
  1191. * "On-Demand-Dispatched Events":
  1192. *
  1193. * - On-demand-dispatched events are not returned from `extractEvents`.
  1194. * - On-demand-dispatched events are dispatched during the process of returning
  1195. * the deferred-dispatched events.
  1196. * - They should not have side effects.
  1197. * - They should be avoided, and/or eventually be replaced with another
  1198. * abstraction that allows event plugins to perform multiple "rounds" of event
  1199. * extraction.
  1200. *
  1201. * Therefore, the sequence of event dispatches becomes:
  1202. *
  1203. * - `R`s on-demand events (if any) (dispatched by `R` on-demand)
  1204. * - `S`s on-demand events (if any) (dispatched by `S` on-demand)
  1205. * - `C`s on-demand events (if any) (dispatched by `C` on-demand)
  1206. * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`)
  1207. * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`)
  1208. * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`)
  1209. *
  1210. * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`
  1211. * on-demand dispatch returns `true` (and some other details are satisfied) the
  1212. * `onResponderGrant` deferred dispatched event is returned from
  1213. * `extractEvents`. The sequence of dispatch executions in this case
  1214. * will appear as follows:
  1215. *
  1216. * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)
  1217. * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual)
  1218. * - `touchStart` (`EventPluginRegistry` dispatches as usual)
  1219. * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual)
  1220. */
  1221. function setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
  1222. 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.
  1223. var bubbleShouldSetFrom = !responderInst ? targetInst : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target
  1224. // (deepest ID) if it happens to be the current responder. The reasoning:
  1225. // It's strange to get an `onMoveShouldSetResponder` when you're *already*
  1226. // the responder.
  1227. var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst;
  1228. var shouldSetEvent = ResponderSyntheticEvent.getPooled(shouldSetEventType, bubbleShouldSetFrom, nativeEvent, nativeEventTarget);
  1229. shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
  1230. if (skipOverBubbleShouldSetFrom) {
  1231. accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);
  1232. } else {
  1233. accumulateTwoPhaseDispatches(shouldSetEvent);
  1234. }
  1235. var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent);
  1236. if (!shouldSetEvent.isPersistent()) {
  1237. shouldSetEvent.constructor.release(shouldSetEvent);
  1238. }
  1239. if (!wantsResponderInst || wantsResponderInst === responderInst) {
  1240. return null;
  1241. }
  1242. var extracted;
  1243. var grantEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderGrant, wantsResponderInst, nativeEvent, nativeEventTarget);
  1244. grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
  1245. accumulateDirectDispatches(grantEvent);
  1246. var blockHostResponder = executeDirectDispatch(grantEvent) === true;
  1247. if (responderInst) {
  1248. var terminationRequestEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderTerminationRequest, responderInst, nativeEvent, nativeEventTarget);
  1249. terminationRequestEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
  1250. accumulateDirectDispatches(terminationRequestEvent);
  1251. var shouldSwitch = !hasDispatches(terminationRequestEvent) || executeDirectDispatch(terminationRequestEvent);
  1252. if (!terminationRequestEvent.isPersistent()) {
  1253. terminationRequestEvent.constructor.release(terminationRequestEvent);
  1254. }
  1255. if (shouldSwitch) {
  1256. var terminateEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderTerminate, responderInst, nativeEvent, nativeEventTarget);
  1257. terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
  1258. accumulateDirectDispatches(terminateEvent);
  1259. extracted = accumulate(extracted, [grantEvent, terminateEvent]);
  1260. changeResponder(wantsResponderInst, blockHostResponder);
  1261. } else {
  1262. var rejectEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderReject, wantsResponderInst, nativeEvent, nativeEventTarget);
  1263. rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
  1264. accumulateDirectDispatches(rejectEvent);
  1265. extracted = accumulate(extracted, rejectEvent);
  1266. }
  1267. } else {
  1268. extracted = accumulate(extracted, grantEvent);
  1269. changeResponder(wantsResponderInst, blockHostResponder);
  1270. }
  1271. return extracted;
  1272. }
  1273. /**
  1274. * A transfer is a negotiation between a currently set responder and the next
  1275. * element to claim responder status. Any start event could trigger a transfer
  1276. * of responderInst. Any move event could trigger a transfer.
  1277. *
  1278. * @param {string} topLevelType Record from `BrowserEventConstants`.
  1279. * @return {boolean} True if a transfer of responder could possibly occur.
  1280. */
  1281. function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) {
  1282. return topLevelInst && ( // responderIgnoreScroll: We are trying to migrate away from specifically
  1283. // tracking native scroll events here and responderIgnoreScroll indicates we
  1284. // will send topTouchCancel to handle canceling touch events instead
  1285. topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll || trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE || isStartish(topLevelType) || isMoveish(topLevelType));
  1286. }
  1287. /**
  1288. * Returns whether or not this touch end event makes it such that there are no
  1289. * longer any touches that started inside of the current `responderInst`.
  1290. *
  1291. * @param {NativeEvent} nativeEvent Native touch end event.
  1292. * @return {boolean} Whether or not this touch end event ends the responder.
  1293. */
  1294. function noResponderTouches(nativeEvent) {
  1295. var touches = nativeEvent.touches;
  1296. if (!touches || touches.length === 0) {
  1297. return true;
  1298. }
  1299. for (var i = 0; i < touches.length; i++) {
  1300. var activeTouch = touches[i];
  1301. var target = activeTouch.target;
  1302. if (target !== null && target !== undefined && target !== 0) {
  1303. // Is the original touch location inside of the current responder?
  1304. var targetInst = getInstanceFromNode(target);
  1305. if (isAncestor(responderInst, targetInst)) {
  1306. return false;
  1307. }
  1308. }
  1309. }
  1310. return true;
  1311. }
  1312. var ResponderEventPlugin = {
  1313. /* For unit testing only */
  1314. _getResponder: function () {
  1315. return responderInst;
  1316. },
  1317. eventTypes: eventTypes,
  1318. /**
  1319. * We must be resilient to `targetInst` being `null` on `touchMove` or
  1320. * `touchEnd`. On certain platforms, this means that a native scroll has
  1321. * assumed control and the original touch targets are destroyed.
  1322. */
  1323. extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags) {
  1324. if (isStartish(topLevelType)) {
  1325. trackedTouchCount += 1;
  1326. } else if (isEndish(topLevelType)) {
  1327. if (trackedTouchCount >= 0) {
  1328. trackedTouchCount -= 1;
  1329. } else {
  1330. {
  1331. warn('Ended a touch event which was not counted in `trackedTouchCount`.');
  1332. }
  1333. return null;
  1334. }
  1335. }
  1336. ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent);
  1337. 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.
  1338. // Regardless, whoever is the responder after any potential transfer, we
  1339. // direct all touch start/move/ends to them in the form of
  1340. // `onResponderMove/Start/End`. These will be called for *every* additional
  1341. // finger that move/start/end, dispatched directly to whoever is the
  1342. // current responder at that moment, until the responder is "released".
  1343. //
  1344. // These multiple individual change touch events are are always bookended
  1345. // by `onResponderGrant`, and one of
  1346. // (`onResponderRelease/onResponderTerminate`).
  1347. var isResponderTouchStart = responderInst && isStartish(topLevelType);
  1348. var isResponderTouchMove = responderInst && isMoveish(topLevelType);
  1349. var isResponderTouchEnd = responderInst && isEndish(topLevelType);
  1350. var incrementalTouch = isResponderTouchStart ? eventTypes.responderStart : isResponderTouchMove ? eventTypes.responderMove : isResponderTouchEnd ? eventTypes.responderEnd : null;
  1351. if (incrementalTouch) {
  1352. var gesture = ResponderSyntheticEvent.getPooled(incrementalTouch, responderInst, nativeEvent, nativeEventTarget);
  1353. gesture.touchHistory = ResponderTouchHistoryStore.touchHistory;
  1354. accumulateDirectDispatches(gesture);
  1355. extracted = accumulate(extracted, gesture);
  1356. }
  1357. var isResponderTerminate = responderInst && topLevelType === TOP_TOUCH_CANCEL;
  1358. var isResponderRelease = responderInst && !isResponderTerminate && isEndish(topLevelType) && noResponderTouches(nativeEvent);
  1359. var finalTouch = isResponderTerminate ? eventTypes.responderTerminate : isResponderRelease ? eventTypes.responderRelease : null;
  1360. if (finalTouch) {
  1361. var finalEvent = ResponderSyntheticEvent.getPooled(finalTouch, responderInst, nativeEvent, nativeEventTarget);
  1362. finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
  1363. accumulateDirectDispatches(finalEvent);
  1364. extracted = accumulate(extracted, finalEvent);
  1365. changeResponder(null);
  1366. }
  1367. return extracted;
  1368. },
  1369. GlobalResponderHandler: null,
  1370. injection: {
  1371. /**
  1372. * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler
  1373. * Object that handles any change in responder. Use this to inject
  1374. * integration with an existing touch handling system etc.
  1375. */
  1376. injectGlobalResponderHandler: function (GlobalResponderHandler) {
  1377. ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler;
  1378. }
  1379. }
  1380. };
  1381. // Keep in sync with ReactDOM.js, ReactTestUtils.js, and ReactTestUtilsAct.js:
  1382. var _ReactDOM$__SECRET_IN = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Events,
  1383. getInstanceFromNode$1 = _ReactDOM$__SECRET_IN[0],
  1384. getNodeFromInstance$1 = _ReactDOM$__SECRET_IN[1],
  1385. getFiberCurrentPropsFromNode$1 = _ReactDOM$__SECRET_IN[2],
  1386. injectEventPluginsByName = _ReactDOM$__SECRET_IN[3];
  1387. setComponentTree(getFiberCurrentPropsFromNode$1, getInstanceFromNode$1, getNodeFromInstance$1);
  1388. var ReactDOMUnstableNativeDependencies = /*#__PURE__*/Object.freeze({
  1389. __proto__: null,
  1390. ResponderEventPlugin: ResponderEventPlugin,
  1391. ResponderTouchHistoryStore: ResponderTouchHistoryStore,
  1392. injectEventPluginsByName: injectEventPluginsByName
  1393. });
  1394. var unstableNativeDependencies = ReactDOMUnstableNativeDependencies;
  1395. return unstableNativeDependencies;
  1396. })));