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