use-sync-external-store-shim.development.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /**
  2. * @license React
  3. * use-sync-external-store-shim.development.js
  4. *
  5. * Copyright (c) Facebook, Inc. and its affiliates.
  6. *
  7. * This source code is licensed under the MIT license found in the
  8. * LICENSE file in the root directory of this source tree.
  9. */
  10. 'use strict';
  11. if (process.env.NODE_ENV !== "production") {
  12. (function() {
  13. 'use strict';
  14. /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
  15. if (
  16. typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
  17. typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===
  18. 'function'
  19. ) {
  20. __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
  21. }
  22. var React = require('react');
  23. var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
  24. function error(format) {
  25. {
  26. {
  27. for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  28. args[_key2 - 1] = arguments[_key2];
  29. }
  30. printWarning('error', format, args);
  31. }
  32. }
  33. }
  34. function printWarning(level, format, args) {
  35. // When changing this logic, you might want to also
  36. // update consoleWithStackDev.www.js as well.
  37. {
  38. var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
  39. var stack = ReactDebugCurrentFrame.getStackAddendum();
  40. if (stack !== '') {
  41. format += '%s';
  42. args = args.concat([stack]);
  43. } // eslint-disable-next-line react-internal/safe-string-coercion
  44. var argsWithFormat = args.map(function (item) {
  45. return String(item);
  46. }); // Careful: RN currently depends on this prefix
  47. argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
  48. // breaks IE9: https://github.com/facebook/react/issues/13610
  49. // eslint-disable-next-line react-internal/no-production-logging
  50. Function.prototype.apply.call(console[level], console, argsWithFormat);
  51. }
  52. }
  53. /**
  54. * inlined Object.is polyfill to avoid requiring consumers ship their own
  55. * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
  56. */
  57. function is(x, y) {
  58. return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
  59. ;
  60. }
  61. var objectIs = typeof Object.is === 'function' ? Object.is : is;
  62. // dispatch for CommonJS interop named imports.
  63. var useState = React.useState,
  64. useEffect = React.useEffect,
  65. useLayoutEffect = React.useLayoutEffect,
  66. useDebugValue = React.useDebugValue;
  67. var didWarnOld18Alpha = false;
  68. var didWarnUncachedGetSnapshot = false; // Disclaimer: This shim breaks many of the rules of React, and only works
  69. // because of a very particular set of implementation details and assumptions
  70. // -- change any one of them and it will break. The most important assumption
  71. // is that updates are always synchronous, because concurrent rendering is
  72. // only available in versions of React that also have a built-in
  73. // useSyncExternalStore API. And we only use this shim when the built-in API
  74. // does not exist.
  75. //
  76. // Do not assume that the clever hacks used by this hook also work in general.
  77. // The point of this shim is to replace the need for hacks by other libraries.
  78. function useSyncExternalStore(subscribe, getSnapshot, // Note: The shim does not use getServerSnapshot, because pre-18 versions of
  79. // React do not expose a way to check if we're hydrating. So users of the shim
  80. // will need to track that themselves and return the correct value
  81. // from `getSnapshot`.
  82. getServerSnapshot) {
  83. {
  84. if (!didWarnOld18Alpha) {
  85. if (React.startTransition !== undefined) {
  86. didWarnOld18Alpha = true;
  87. error('You are using an outdated, pre-release alpha of React 18 that ' + 'does not support useSyncExternalStore. The ' + 'use-sync-external-store shim will not work correctly. Upgrade ' + 'to a newer pre-release.');
  88. }
  89. }
  90. } // Read the current snapshot from the store on every render. Again, this
  91. // breaks the rules of React, and only works here because of specific
  92. // implementation details, most importantly that updates are
  93. // always synchronous.
  94. var value = getSnapshot();
  95. {
  96. if (!didWarnUncachedGetSnapshot) {
  97. var cachedValue = getSnapshot();
  98. if (!objectIs(value, cachedValue)) {
  99. error('The result of getSnapshot should be cached to avoid an infinite loop');
  100. didWarnUncachedGetSnapshot = true;
  101. }
  102. }
  103. } // Because updates are synchronous, we don't queue them. Instead we force a
  104. // re-render whenever the subscribed state changes by updating an some
  105. // arbitrary useState hook. Then, during render, we call getSnapshot to read
  106. // the current value.
  107. //
  108. // Because we don't actually use the state returned by the useState hook, we
  109. // can save a bit of memory by storing other stuff in that slot.
  110. //
  111. // To implement the early bailout, we need to track some things on a mutable
  112. // object. Usually, we would put that in a useRef hook, but we can stash it in
  113. // our useState hook instead.
  114. //
  115. // To force a re-render, we call forceUpdate({inst}). That works because the
  116. // new object always fails an equality check.
  117. var _useState = useState({
  118. inst: {
  119. value: value,
  120. getSnapshot: getSnapshot
  121. }
  122. }),
  123. inst = _useState[0].inst,
  124. forceUpdate = _useState[1]; // Track the latest getSnapshot function with a ref. This needs to be updated
  125. // in the layout phase so we can access it during the tearing check that
  126. // happens on subscribe.
  127. useLayoutEffect(function () {
  128. inst.value = value;
  129. inst.getSnapshot = getSnapshot; // Whenever getSnapshot or subscribe changes, we need to check in the
  130. // commit phase if there was an interleaved mutation. In concurrent mode
  131. // this can happen all the time, but even in synchronous mode, an earlier
  132. // effect may have mutated the store.
  133. if (checkIfSnapshotChanged(inst)) {
  134. // Force a re-render.
  135. forceUpdate({
  136. inst: inst
  137. });
  138. }
  139. }, [subscribe, value, getSnapshot]);
  140. useEffect(function () {
  141. // Check for changes right before subscribing. Subsequent changes will be
  142. // detected in the subscription handler.
  143. if (checkIfSnapshotChanged(inst)) {
  144. // Force a re-render.
  145. forceUpdate({
  146. inst: inst
  147. });
  148. }
  149. var handleStoreChange = function () {
  150. // TODO: Because there is no cross-renderer API for batching updates, it's
  151. // up to the consumer of this library to wrap their subscription event
  152. // with unstable_batchedUpdates. Should we try to detect when this isn't
  153. // the case and print a warning in development?
  154. // The store changed. Check if the snapshot changed since the last time we
  155. // read from the store.
  156. if (checkIfSnapshotChanged(inst)) {
  157. // Force a re-render.
  158. forceUpdate({
  159. inst: inst
  160. });
  161. }
  162. }; // Subscribe to the store and return a clean-up function.
  163. return subscribe(handleStoreChange);
  164. }, [subscribe]);
  165. useDebugValue(value);
  166. return value;
  167. }
  168. function checkIfSnapshotChanged(inst) {
  169. var latestGetSnapshot = inst.getSnapshot;
  170. var prevValue = inst.value;
  171. try {
  172. var nextValue = latestGetSnapshot();
  173. return !objectIs(prevValue, nextValue);
  174. } catch (error) {
  175. return true;
  176. }
  177. }
  178. function useSyncExternalStore$1(subscribe, getSnapshot, getServerSnapshot) {
  179. // Note: The shim does not use getServerSnapshot, because pre-18 versions of
  180. // React do not expose a way to check if we're hydrating. So users of the shim
  181. // will need to track that themselves and return the correct value
  182. // from `getSnapshot`.
  183. return getSnapshot();
  184. }
  185. var canUseDOM = !!(typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined');
  186. var isServerEnvironment = !canUseDOM;
  187. var shim = isServerEnvironment ? useSyncExternalStore$1 : useSyncExternalStore;
  188. var useSyncExternalStore$2 = React.useSyncExternalStore !== undefined ? React.useSyncExternalStore : shim;
  189. exports.useSyncExternalStore = useSyncExternalStore$2;
  190. /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
  191. if (
  192. typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
  193. typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop ===
  194. 'function'
  195. ) {
  196. __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error());
  197. }
  198. })();
  199. }