Dashboard sipadu mbip
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

scheduler.development.js 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. /** @license React v0.18.0
  2. * scheduler.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. if (process.env.NODE_ENV !== "production") {
  11. (function() {
  12. 'use strict';
  13. Object.defineProperty(exports, '__esModule', { value: true });
  14. var enableSchedulerDebugging = false;
  15. var enableIsInputPending = false;
  16. var enableProfiling = true;
  17. var requestHostCallback;
  18. var requestHostTimeout;
  19. var cancelHostTimeout;
  20. var shouldYieldToHost;
  21. var requestPaint;
  22. if ( // If Scheduler runs in a non-DOM environment, it falls back to a naive
  23. // implementation using setTimeout.
  24. typeof window === 'undefined' || // Check if MessageChannel is supported, too.
  25. typeof MessageChannel !== 'function') {
  26. // If this accidentally gets imported in a non-browser environment, e.g. JavaScriptCore,
  27. // fallback to a naive implementation.
  28. var _callback = null;
  29. var _timeoutID = null;
  30. var _flushCallback = function () {
  31. if (_callback !== null) {
  32. try {
  33. var currentTime = exports.unstable_now();
  34. var hasRemainingTime = true;
  35. _callback(hasRemainingTime, currentTime);
  36. _callback = null;
  37. } catch (e) {
  38. setTimeout(_flushCallback, 0);
  39. throw e;
  40. }
  41. }
  42. };
  43. var initialTime = Date.now();
  44. exports.unstable_now = function () {
  45. return Date.now() - initialTime;
  46. };
  47. requestHostCallback = function (cb) {
  48. if (_callback !== null) {
  49. // Protect against re-entrancy.
  50. setTimeout(requestHostCallback, 0, cb);
  51. } else {
  52. _callback = cb;
  53. setTimeout(_flushCallback, 0);
  54. }
  55. };
  56. requestHostTimeout = function (cb, ms) {
  57. _timeoutID = setTimeout(cb, ms);
  58. };
  59. cancelHostTimeout = function () {
  60. clearTimeout(_timeoutID);
  61. };
  62. shouldYieldToHost = function () {
  63. return false;
  64. };
  65. requestPaint = exports.unstable_forceFrameRate = function () {};
  66. } else {
  67. // Capture local references to native APIs, in case a polyfill overrides them.
  68. var performance = window.performance;
  69. var _Date = window.Date;
  70. var _setTimeout = window.setTimeout;
  71. var _clearTimeout = window.clearTimeout;
  72. if (typeof console !== 'undefined') {
  73. // TODO: Scheduler no longer requires these methods to be polyfilled. But
  74. // maybe we want to continue warning if they don't exist, to preserve the
  75. // option to rely on it in the future?
  76. var requestAnimationFrame = window.requestAnimationFrame;
  77. var cancelAnimationFrame = window.cancelAnimationFrame; // TODO: Remove fb.me link
  78. if (typeof requestAnimationFrame !== 'function') {
  79. console.error("This browser doesn't support requestAnimationFrame. " + 'Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills');
  80. }
  81. if (typeof cancelAnimationFrame !== 'function') {
  82. console.error("This browser doesn't support cancelAnimationFrame. " + 'Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills');
  83. }
  84. }
  85. if (typeof performance === 'object' && typeof performance.now === 'function') {
  86. exports.unstable_now = function () {
  87. return performance.now();
  88. };
  89. } else {
  90. var _initialTime = _Date.now();
  91. exports.unstable_now = function () {
  92. return _Date.now() - _initialTime;
  93. };
  94. }
  95. var isMessageLoopRunning = false;
  96. var scheduledHostCallback = null;
  97. var taskTimeoutID = -1; // Scheduler periodically yields in case there is other work on the main
  98. // thread, like user events. By default, it yields multiple times per frame.
  99. // It does not attempt to align with frame boundaries, since most tasks don't
  100. // need to be frame aligned; for those that do, use requestAnimationFrame.
  101. var yieldInterval = 5;
  102. var deadline = 0; // TODO: Make this configurable
  103. // TODO: Adjust this based on priority?
  104. var maxYieldInterval = 300;
  105. var needsPaint = false;
  106. if (enableIsInputPending && navigator !== undefined && navigator.scheduling !== undefined && navigator.scheduling.isInputPending !== undefined) {
  107. var scheduling = navigator.scheduling;
  108. shouldYieldToHost = function () {
  109. var currentTime = exports.unstable_now();
  110. if (currentTime >= deadline) {
  111. // There's no time left. We may want to yield control of the main
  112. // thread, so the browser can perform high priority tasks. The main ones
  113. // are painting and user input. If there's a pending paint or a pending
  114. // input, then we should yield. But if there's neither, then we can
  115. // yield less often while remaining responsive. We'll eventually yield
  116. // regardless, since there could be a pending paint that wasn't
  117. // accompanied by a call to `requestPaint`, or other main thread tasks
  118. // like network events.
  119. if (needsPaint || scheduling.isInputPending()) {
  120. // There is either a pending paint or a pending input.
  121. return true;
  122. } // There's no pending input. Only yield if we've reached the max
  123. // yield interval.
  124. return currentTime >= maxYieldInterval;
  125. } else {
  126. // There's still time left in the frame.
  127. return false;
  128. }
  129. };
  130. requestPaint = function () {
  131. needsPaint = true;
  132. };
  133. } else {
  134. // `isInputPending` is not available. Since we have no way of knowing if
  135. // there's pending input, always yield at the end of the frame.
  136. shouldYieldToHost = function () {
  137. return exports.unstable_now() >= deadline;
  138. }; // Since we yield every frame regardless, `requestPaint` has no effect.
  139. requestPaint = function () {};
  140. }
  141. exports.unstable_forceFrameRate = function (fps) {
  142. if (fps < 0 || fps > 125) {
  143. console.error('forceFrameRate takes a positive int between 0 and 125, ' + 'forcing framerates higher than 125 fps is not unsupported');
  144. return;
  145. }
  146. if (fps > 0) {
  147. yieldInterval = Math.floor(1000 / fps);
  148. } else {
  149. // reset the framerate
  150. yieldInterval = 5;
  151. }
  152. };
  153. var performWorkUntilDeadline = function () {
  154. if (scheduledHostCallback !== null) {
  155. var currentTime = exports.unstable_now(); // Yield after `yieldInterval` ms, regardless of where we are in the vsync
  156. // cycle. This means there's always time remaining at the beginning of
  157. // the message event.
  158. deadline = currentTime + yieldInterval;
  159. var hasTimeRemaining = true;
  160. try {
  161. var hasMoreWork = scheduledHostCallback(hasTimeRemaining, currentTime);
  162. if (!hasMoreWork) {
  163. isMessageLoopRunning = false;
  164. scheduledHostCallback = null;
  165. } else {
  166. // If there's more work, schedule the next message event at the end
  167. // of the preceding one.
  168. port.postMessage(null);
  169. }
  170. } catch (error) {
  171. // If a scheduler task throws, exit the current browser task so the
  172. // error can be observed.
  173. port.postMessage(null);
  174. throw error;
  175. }
  176. } else {
  177. isMessageLoopRunning = false;
  178. } // Yielding to the browser will give it a chance to paint, so we can
  179. // reset this.
  180. needsPaint = false;
  181. };
  182. var channel = new MessageChannel();
  183. var port = channel.port2;
  184. channel.port1.onmessage = performWorkUntilDeadline;
  185. requestHostCallback = function (callback) {
  186. scheduledHostCallback = callback;
  187. if (!isMessageLoopRunning) {
  188. isMessageLoopRunning = true;
  189. port.postMessage(null);
  190. }
  191. };
  192. requestHostTimeout = function (callback, ms) {
  193. taskTimeoutID = _setTimeout(function () {
  194. callback(exports.unstable_now());
  195. }, ms);
  196. };
  197. cancelHostTimeout = function () {
  198. _clearTimeout(taskTimeoutID);
  199. taskTimeoutID = -1;
  200. };
  201. }
  202. function push(heap, node) {
  203. var index = heap.length;
  204. heap.push(node);
  205. siftUp(heap, node, index);
  206. }
  207. function peek(heap) {
  208. var first = heap[0];
  209. return first === undefined ? null : first;
  210. }
  211. function pop(heap) {
  212. var first = heap[0];
  213. if (first !== undefined) {
  214. var last = heap.pop();
  215. if (last !== first) {
  216. heap[0] = last;
  217. siftDown(heap, last, 0);
  218. }
  219. return first;
  220. } else {
  221. return null;
  222. }
  223. }
  224. function siftUp(heap, node, i) {
  225. var index = i;
  226. while (true) {
  227. var parentIndex = Math.floor((index - 1) / 2);
  228. var parent = heap[parentIndex];
  229. if (parent !== undefined && compare(parent, node) > 0) {
  230. // The parent is larger. Swap positions.
  231. heap[parentIndex] = node;
  232. heap[index] = parent;
  233. index = parentIndex;
  234. } else {
  235. // The parent is smaller. Exit.
  236. return;
  237. }
  238. }
  239. }
  240. function siftDown(heap, node, i) {
  241. var index = i;
  242. var length = heap.length;
  243. while (index < length) {
  244. var leftIndex = (index + 1) * 2 - 1;
  245. var left = heap[leftIndex];
  246. var rightIndex = leftIndex + 1;
  247. var right = heap[rightIndex]; // If the left or right node is smaller, swap with the smaller of those.
  248. if (left !== undefined && compare(left, node) < 0) {
  249. if (right !== undefined && compare(right, left) < 0) {
  250. heap[index] = right;
  251. heap[rightIndex] = node;
  252. index = rightIndex;
  253. } else {
  254. heap[index] = left;
  255. heap[leftIndex] = node;
  256. index = leftIndex;
  257. }
  258. } else if (right !== undefined && compare(right, node) < 0) {
  259. heap[index] = right;
  260. heap[rightIndex] = node;
  261. index = rightIndex;
  262. } else {
  263. // Neither child is smaller. Exit.
  264. return;
  265. }
  266. }
  267. }
  268. function compare(a, b) {
  269. // Compare sort index first, then task id.
  270. var diff = a.sortIndex - b.sortIndex;
  271. return diff !== 0 ? diff : a.id - b.id;
  272. }
  273. // TODO: Use symbols?
  274. var NoPriority = 0;
  275. var ImmediatePriority = 1;
  276. var UserBlockingPriority = 2;
  277. var NormalPriority = 3;
  278. var LowPriority = 4;
  279. var IdlePriority = 5;
  280. var runIdCounter = 0;
  281. var mainThreadIdCounter = 0;
  282. var profilingStateSize = 4;
  283. var sharedProfilingBuffer = enableProfiling ? // $FlowFixMe Flow doesn't know about SharedArrayBuffer
  284. typeof SharedArrayBuffer === 'function' ? new SharedArrayBuffer(profilingStateSize * Int32Array.BYTES_PER_ELEMENT) : // $FlowFixMe Flow doesn't know about ArrayBuffer
  285. typeof ArrayBuffer === 'function' ? new ArrayBuffer(profilingStateSize * Int32Array.BYTES_PER_ELEMENT) : null // Don't crash the init path on IE9
  286. : null;
  287. var profilingState = enableProfiling && sharedProfilingBuffer !== null ? new Int32Array(sharedProfilingBuffer) : []; // We can't read this but it helps save bytes for null checks
  288. var PRIORITY = 0;
  289. var CURRENT_TASK_ID = 1;
  290. var CURRENT_RUN_ID = 2;
  291. var QUEUE_SIZE = 3;
  292. if (enableProfiling) {
  293. profilingState[PRIORITY] = NoPriority; // This is maintained with a counter, because the size of the priority queue
  294. // array might include canceled tasks.
  295. profilingState[QUEUE_SIZE] = 0;
  296. profilingState[CURRENT_TASK_ID] = 0;
  297. } // Bytes per element is 4
  298. var INITIAL_EVENT_LOG_SIZE = 131072;
  299. var MAX_EVENT_LOG_SIZE = 524288; // Equivalent to 2 megabytes
  300. var eventLogSize = 0;
  301. var eventLogBuffer = null;
  302. var eventLog = null;
  303. var eventLogIndex = 0;
  304. var TaskStartEvent = 1;
  305. var TaskCompleteEvent = 2;
  306. var TaskErrorEvent = 3;
  307. var TaskCancelEvent = 4;
  308. var TaskRunEvent = 5;
  309. var TaskYieldEvent = 6;
  310. var SchedulerSuspendEvent = 7;
  311. var SchedulerResumeEvent = 8;
  312. function logEvent(entries) {
  313. if (eventLog !== null) {
  314. var offset = eventLogIndex;
  315. eventLogIndex += entries.length;
  316. if (eventLogIndex + 1 > eventLogSize) {
  317. eventLogSize *= 2;
  318. if (eventLogSize > MAX_EVENT_LOG_SIZE) {
  319. console.error("Scheduler Profiling: Event log exceeded maximum size. Don't " + 'forget to call `stopLoggingProfilingEvents()`.');
  320. stopLoggingProfilingEvents();
  321. return;
  322. }
  323. var newEventLog = new Int32Array(eventLogSize * 4);
  324. newEventLog.set(eventLog);
  325. eventLogBuffer = newEventLog.buffer;
  326. eventLog = newEventLog;
  327. }
  328. eventLog.set(entries, offset);
  329. }
  330. }
  331. function startLoggingProfilingEvents() {
  332. eventLogSize = INITIAL_EVENT_LOG_SIZE;
  333. eventLogBuffer = new ArrayBuffer(eventLogSize * 4);
  334. eventLog = new Int32Array(eventLogBuffer);
  335. eventLogIndex = 0;
  336. }
  337. function stopLoggingProfilingEvents() {
  338. var buffer = eventLogBuffer;
  339. eventLogSize = 0;
  340. eventLogBuffer = null;
  341. eventLog = null;
  342. eventLogIndex = 0;
  343. return buffer;
  344. }
  345. function markTaskStart(task, ms) {
  346. if (enableProfiling) {
  347. profilingState[QUEUE_SIZE]++;
  348. if (eventLog !== null) {
  349. // performance.now returns a float, representing milliseconds. When the
  350. // event is logged, it's coerced to an int. Convert to microseconds to
  351. // maintain extra degrees of precision.
  352. logEvent([TaskStartEvent, ms * 1000, task.id, task.priorityLevel]);
  353. }
  354. }
  355. }
  356. function markTaskCompleted(task, ms) {
  357. if (enableProfiling) {
  358. profilingState[PRIORITY] = NoPriority;
  359. profilingState[CURRENT_TASK_ID] = 0;
  360. profilingState[QUEUE_SIZE]--;
  361. if (eventLog !== null) {
  362. logEvent([TaskCompleteEvent, ms * 1000, task.id]);
  363. }
  364. }
  365. }
  366. function markTaskCanceled(task, ms) {
  367. if (enableProfiling) {
  368. profilingState[QUEUE_SIZE]--;
  369. if (eventLog !== null) {
  370. logEvent([TaskCancelEvent, ms * 1000, task.id]);
  371. }
  372. }
  373. }
  374. function markTaskErrored(task, ms) {
  375. if (enableProfiling) {
  376. profilingState[PRIORITY] = NoPriority;
  377. profilingState[CURRENT_TASK_ID] = 0;
  378. profilingState[QUEUE_SIZE]--;
  379. if (eventLog !== null) {
  380. logEvent([TaskErrorEvent, ms * 1000, task.id]);
  381. }
  382. }
  383. }
  384. function markTaskRun(task, ms) {
  385. if (enableProfiling) {
  386. runIdCounter++;
  387. profilingState[PRIORITY] = task.priorityLevel;
  388. profilingState[CURRENT_TASK_ID] = task.id;
  389. profilingState[CURRENT_RUN_ID] = runIdCounter;
  390. if (eventLog !== null) {
  391. logEvent([TaskRunEvent, ms * 1000, task.id, runIdCounter]);
  392. }
  393. }
  394. }
  395. function markTaskYield(task, ms) {
  396. if (enableProfiling) {
  397. profilingState[PRIORITY] = NoPriority;
  398. profilingState[CURRENT_TASK_ID] = 0;
  399. profilingState[CURRENT_RUN_ID] = 0;
  400. if (eventLog !== null) {
  401. logEvent([TaskYieldEvent, ms * 1000, task.id, runIdCounter]);
  402. }
  403. }
  404. }
  405. function markSchedulerSuspended(ms) {
  406. if (enableProfiling) {
  407. mainThreadIdCounter++;
  408. if (eventLog !== null) {
  409. logEvent([SchedulerSuspendEvent, ms * 1000, mainThreadIdCounter]);
  410. }
  411. }
  412. }
  413. function markSchedulerUnsuspended(ms) {
  414. if (enableProfiling) {
  415. if (eventLog !== null) {
  416. logEvent([SchedulerResumeEvent, ms * 1000, mainThreadIdCounter]);
  417. }
  418. }
  419. }
  420. /* eslint-disable no-var */
  421. // Math.pow(2, 30) - 1
  422. // 0b111111111111111111111111111111
  423. var maxSigned31BitInt = 1073741823; // Times out immediately
  424. var IMMEDIATE_PRIORITY_TIMEOUT = -1; // Eventually times out
  425. var USER_BLOCKING_PRIORITY = 250;
  426. var NORMAL_PRIORITY_TIMEOUT = 5000;
  427. var LOW_PRIORITY_TIMEOUT = 10000; // Never times out
  428. var IDLE_PRIORITY = maxSigned31BitInt; // Tasks are stored on a min heap
  429. var taskQueue = [];
  430. var timerQueue = []; // Incrementing id counter. Used to maintain insertion order.
  431. var taskIdCounter = 1; // Pausing the scheduler is useful for debugging.
  432. var isSchedulerPaused = false;
  433. var currentTask = null;
  434. var currentPriorityLevel = NormalPriority; // This is set while performing work, to prevent re-entrancy.
  435. var isPerformingWork = false;
  436. var isHostCallbackScheduled = false;
  437. var isHostTimeoutScheduled = false;
  438. function advanceTimers(currentTime) {
  439. // Check for tasks that are no longer delayed and add them to the queue.
  440. var timer = peek(timerQueue);
  441. while (timer !== null) {
  442. if (timer.callback === null) {
  443. // Timer was cancelled.
  444. pop(timerQueue);
  445. } else if (timer.startTime <= currentTime) {
  446. // Timer fired. Transfer to the task queue.
  447. pop(timerQueue);
  448. timer.sortIndex = timer.expirationTime;
  449. push(taskQueue, timer);
  450. if (enableProfiling) {
  451. markTaskStart(timer, currentTime);
  452. timer.isQueued = true;
  453. }
  454. } else {
  455. // Remaining timers are pending.
  456. return;
  457. }
  458. timer = peek(timerQueue);
  459. }
  460. }
  461. function handleTimeout(currentTime) {
  462. isHostTimeoutScheduled = false;
  463. advanceTimers(currentTime);
  464. if (!isHostCallbackScheduled) {
  465. if (peek(taskQueue) !== null) {
  466. isHostCallbackScheduled = true;
  467. requestHostCallback(flushWork);
  468. } else {
  469. var firstTimer = peek(timerQueue);
  470. if (firstTimer !== null) {
  471. requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);
  472. }
  473. }
  474. }
  475. }
  476. function flushWork(hasTimeRemaining, initialTime) {
  477. if (enableProfiling) {
  478. markSchedulerUnsuspended(initialTime);
  479. } // We'll need a host callback the next time work is scheduled.
  480. isHostCallbackScheduled = false;
  481. if (isHostTimeoutScheduled) {
  482. // We scheduled a timeout but it's no longer needed. Cancel it.
  483. isHostTimeoutScheduled = false;
  484. cancelHostTimeout();
  485. }
  486. isPerformingWork = true;
  487. var previousPriorityLevel = currentPriorityLevel;
  488. try {
  489. if (enableProfiling) {
  490. try {
  491. return workLoop(hasTimeRemaining, initialTime);
  492. } catch (error) {
  493. if (currentTask !== null) {
  494. var currentTime = exports.unstable_now();
  495. markTaskErrored(currentTask, currentTime);
  496. currentTask.isQueued = false;
  497. }
  498. throw error;
  499. }
  500. } else {
  501. // No catch in prod codepath.
  502. return workLoop(hasTimeRemaining, initialTime);
  503. }
  504. } finally {
  505. currentTask = null;
  506. currentPriorityLevel = previousPriorityLevel;
  507. isPerformingWork = false;
  508. if (enableProfiling) {
  509. var _currentTime = exports.unstable_now();
  510. markSchedulerSuspended(_currentTime);
  511. }
  512. }
  513. }
  514. function workLoop(hasTimeRemaining, initialTime) {
  515. var currentTime = initialTime;
  516. advanceTimers(currentTime);
  517. currentTask = peek(taskQueue);
  518. while (currentTask !== null && !(enableSchedulerDebugging && isSchedulerPaused)) {
  519. if (currentTask.expirationTime > currentTime && (!hasTimeRemaining || shouldYieldToHost())) {
  520. // This currentTask hasn't expired, and we've reached the deadline.
  521. break;
  522. }
  523. var callback = currentTask.callback;
  524. if (callback !== null) {
  525. currentTask.callback = null;
  526. currentPriorityLevel = currentTask.priorityLevel;
  527. var didUserCallbackTimeout = currentTask.expirationTime <= currentTime;
  528. markTaskRun(currentTask, currentTime);
  529. var continuationCallback = callback(didUserCallbackTimeout);
  530. currentTime = exports.unstable_now();
  531. if (typeof continuationCallback === 'function') {
  532. currentTask.callback = continuationCallback;
  533. markTaskYield(currentTask, currentTime);
  534. } else {
  535. if (enableProfiling) {
  536. markTaskCompleted(currentTask, currentTime);
  537. currentTask.isQueued = false;
  538. }
  539. if (currentTask === peek(taskQueue)) {
  540. pop(taskQueue);
  541. }
  542. }
  543. advanceTimers(currentTime);
  544. } else {
  545. pop(taskQueue);
  546. }
  547. currentTask = peek(taskQueue);
  548. } // Return whether there's additional work
  549. if (currentTask !== null) {
  550. return true;
  551. } else {
  552. var firstTimer = peek(timerQueue);
  553. if (firstTimer !== null) {
  554. requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);
  555. }
  556. return false;
  557. }
  558. }
  559. function unstable_runWithPriority(priorityLevel, eventHandler) {
  560. switch (priorityLevel) {
  561. case ImmediatePriority:
  562. case UserBlockingPriority:
  563. case NormalPriority:
  564. case LowPriority:
  565. case IdlePriority:
  566. break;
  567. default:
  568. priorityLevel = NormalPriority;
  569. }
  570. var previousPriorityLevel = currentPriorityLevel;
  571. currentPriorityLevel = priorityLevel;
  572. try {
  573. return eventHandler();
  574. } finally {
  575. currentPriorityLevel = previousPriorityLevel;
  576. }
  577. }
  578. function unstable_next(eventHandler) {
  579. var priorityLevel;
  580. switch (currentPriorityLevel) {
  581. case ImmediatePriority:
  582. case UserBlockingPriority:
  583. case NormalPriority:
  584. // Shift down to normal priority
  585. priorityLevel = NormalPriority;
  586. break;
  587. default:
  588. // Anything lower than normal priority should remain at the current level.
  589. priorityLevel = currentPriorityLevel;
  590. break;
  591. }
  592. var previousPriorityLevel = currentPriorityLevel;
  593. currentPriorityLevel = priorityLevel;
  594. try {
  595. return eventHandler();
  596. } finally {
  597. currentPriorityLevel = previousPriorityLevel;
  598. }
  599. }
  600. function unstable_wrapCallback(callback) {
  601. var parentPriorityLevel = currentPriorityLevel;
  602. return function () {
  603. // This is a fork of runWithPriority, inlined for performance.
  604. var previousPriorityLevel = currentPriorityLevel;
  605. currentPriorityLevel = parentPriorityLevel;
  606. try {
  607. return callback.apply(this, arguments);
  608. } finally {
  609. currentPriorityLevel = previousPriorityLevel;
  610. }
  611. };
  612. }
  613. function timeoutForPriorityLevel(priorityLevel) {
  614. switch (priorityLevel) {
  615. case ImmediatePriority:
  616. return IMMEDIATE_PRIORITY_TIMEOUT;
  617. case UserBlockingPriority:
  618. return USER_BLOCKING_PRIORITY;
  619. case IdlePriority:
  620. return IDLE_PRIORITY;
  621. case LowPriority:
  622. return LOW_PRIORITY_TIMEOUT;
  623. case NormalPriority:
  624. default:
  625. return NORMAL_PRIORITY_TIMEOUT;
  626. }
  627. }
  628. function unstable_scheduleCallback(priorityLevel, callback, options) {
  629. var currentTime = exports.unstable_now();
  630. var startTime;
  631. var timeout;
  632. if (typeof options === 'object' && options !== null) {
  633. var delay = options.delay;
  634. if (typeof delay === 'number' && delay > 0) {
  635. startTime = currentTime + delay;
  636. } else {
  637. startTime = currentTime;
  638. }
  639. timeout = typeof options.timeout === 'number' ? options.timeout : timeoutForPriorityLevel(priorityLevel);
  640. } else {
  641. timeout = timeoutForPriorityLevel(priorityLevel);
  642. startTime = currentTime;
  643. }
  644. var expirationTime = startTime + timeout;
  645. var newTask = {
  646. id: taskIdCounter++,
  647. callback: callback,
  648. priorityLevel: priorityLevel,
  649. startTime: startTime,
  650. expirationTime: expirationTime,
  651. sortIndex: -1
  652. };
  653. if (enableProfiling) {
  654. newTask.isQueued = false;
  655. }
  656. if (startTime > currentTime) {
  657. // This is a delayed task.
  658. newTask.sortIndex = startTime;
  659. push(timerQueue, newTask);
  660. if (peek(taskQueue) === null && newTask === peek(timerQueue)) {
  661. // All tasks are delayed, and this is the task with the earliest delay.
  662. if (isHostTimeoutScheduled) {
  663. // Cancel an existing timeout.
  664. cancelHostTimeout();
  665. } else {
  666. isHostTimeoutScheduled = true;
  667. } // Schedule a timeout.
  668. requestHostTimeout(handleTimeout, startTime - currentTime);
  669. }
  670. } else {
  671. newTask.sortIndex = expirationTime;
  672. push(taskQueue, newTask);
  673. if (enableProfiling) {
  674. markTaskStart(newTask, currentTime);
  675. newTask.isQueued = true;
  676. } // Schedule a host callback, if needed. If we're already performing work,
  677. // wait until the next time we yield.
  678. if (!isHostCallbackScheduled && !isPerformingWork) {
  679. isHostCallbackScheduled = true;
  680. requestHostCallback(flushWork);
  681. }
  682. }
  683. return newTask;
  684. }
  685. function unstable_pauseExecution() {
  686. isSchedulerPaused = true;
  687. }
  688. function unstable_continueExecution() {
  689. isSchedulerPaused = false;
  690. if (!isHostCallbackScheduled && !isPerformingWork) {
  691. isHostCallbackScheduled = true;
  692. requestHostCallback(flushWork);
  693. }
  694. }
  695. function unstable_getFirstCallbackNode() {
  696. return peek(taskQueue);
  697. }
  698. function unstable_cancelCallback(task) {
  699. if (enableProfiling) {
  700. if (task.isQueued) {
  701. var currentTime = exports.unstable_now();
  702. markTaskCanceled(task, currentTime);
  703. task.isQueued = false;
  704. }
  705. } // Null out the callback to indicate the task has been canceled. (Can't
  706. // remove from the queue because you can't remove arbitrary nodes from an
  707. // array based heap, only the first one.)
  708. task.callback = null;
  709. }
  710. function unstable_getCurrentPriorityLevel() {
  711. return currentPriorityLevel;
  712. }
  713. function unstable_shouldYield() {
  714. var currentTime = exports.unstable_now();
  715. advanceTimers(currentTime);
  716. var firstTask = peek(taskQueue);
  717. return firstTask !== currentTask && currentTask !== null && firstTask !== null && firstTask.callback !== null && firstTask.startTime <= currentTime && firstTask.expirationTime < currentTask.expirationTime || shouldYieldToHost();
  718. }
  719. var unstable_requestPaint = requestPaint;
  720. var unstable_Profiling = enableProfiling ? {
  721. startLoggingProfilingEvents: startLoggingProfilingEvents,
  722. stopLoggingProfilingEvents: stopLoggingProfilingEvents,
  723. sharedProfilingBuffer: sharedProfilingBuffer
  724. } : null;
  725. exports.unstable_ImmediatePriority = ImmediatePriority;
  726. exports.unstable_UserBlockingPriority = UserBlockingPriority;
  727. exports.unstable_NormalPriority = NormalPriority;
  728. exports.unstable_IdlePriority = IdlePriority;
  729. exports.unstable_LowPriority = LowPriority;
  730. exports.unstable_runWithPriority = unstable_runWithPriority;
  731. exports.unstable_next = unstable_next;
  732. exports.unstable_scheduleCallback = unstable_scheduleCallback;
  733. exports.unstable_cancelCallback = unstable_cancelCallback;
  734. exports.unstable_wrapCallback = unstable_wrapCallback;
  735. exports.unstable_getCurrentPriorityLevel = unstable_getCurrentPriorityLevel;
  736. exports.unstable_shouldYield = unstable_shouldYield;
  737. exports.unstable_requestPaint = unstable_requestPaint;
  738. exports.unstable_continueExecution = unstable_continueExecution;
  739. exports.unstable_pauseExecution = unstable_pauseExecution;
  740. exports.unstable_getFirstCallbackNode = unstable_getFirstCallbackNode;
  741. exports.unstable_Profiling = unstable_Profiling;
  742. })();
  743. }