f4192b6f0c76c54861e24f739c272b.blob 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /** @license React v0.6.0
  2. * react-refresh-runtime.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 ("development" !== "production") {
  11. (function () {
  12. 'use strict'; // The Symbol used to tag the ReactElement-like types. If there is no native Symbol
  13. // nor polyfill, then a plain number is used for performance.
  14. var hasSymbol = typeof Symbol === 'function' && Symbol.for; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
  15. // (unstable) APIs that have been removed. Can we remove the symbols?
  16. var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
  17. var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
  18. var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; // We never remove these associations.
  19. // It's OK to reference families, but use WeakMap/Set for types.
  20. var allFamiliesByID = new Map();
  21. var allFamiliesByType = new PossiblyWeakMap();
  22. var allSignaturesByType = new PossiblyWeakMap(); // This WeakMap is read by React, so we only put families
  23. // that have actually been edited here. This keeps checks fast.
  24. // $FlowIssue
  25. var updatedFamiliesByType = new PossiblyWeakMap(); // This is cleared on every performReactRefresh() call.
  26. // It is an array of [Family, NextType] tuples.
  27. var pendingUpdates = []; // This is injected by the renderer via DevTools global hook.
  28. var helpersByRendererID = new Map();
  29. var helpersByRoot = new Map(); // We keep track of mounted roots so we can schedule updates.
  30. var mountedRoots = new Set(); // If a root captures an error, we add its element to this Map so we can retry on edit.
  31. var failedRoots = new Map();
  32. var didSomeRootFailOnMount = false;
  33. function computeFullKey(signature) {
  34. if (signature.fullKey !== null) {
  35. return signature.fullKey;
  36. }
  37. var fullKey = signature.ownKey;
  38. var hooks;
  39. try {
  40. hooks = signature.getCustomHooks();
  41. } catch (err) {
  42. // This can happen in an edge case, e.g. if expression like Foo.useSomething
  43. // depends on Foo which is lazily initialized during rendering.
  44. // In that case just assume we'll have to remount.
  45. signature.forceReset = true;
  46. signature.fullKey = fullKey;
  47. return fullKey;
  48. }
  49. for (var i = 0; i < hooks.length; i++) {
  50. var hook = hooks[i];
  51. if (typeof hook !== 'function') {
  52. // Something's wrong. Assume we need to remount.
  53. signature.forceReset = true;
  54. signature.fullKey = fullKey;
  55. return fullKey;
  56. }
  57. var nestedHookSignature = allSignaturesByType.get(hook);
  58. if (nestedHookSignature === undefined) {
  59. // No signature means Hook wasn't in the source code, e.g. in a library.
  60. // We'll skip it because we can assume it won't change during this session.
  61. continue;
  62. }
  63. var nestedHookKey = computeFullKey(nestedHookSignature);
  64. if (nestedHookSignature.forceReset) {
  65. signature.forceReset = true;
  66. }
  67. fullKey += '\n---\n' + nestedHookKey;
  68. }
  69. signature.fullKey = fullKey;
  70. return fullKey;
  71. }
  72. function haveEqualSignatures(prevType, nextType) {
  73. var prevSignature = allSignaturesByType.get(prevType);
  74. var nextSignature = allSignaturesByType.get(nextType);
  75. if (prevSignature === undefined && nextSignature === undefined) {
  76. return true;
  77. }
  78. if (prevSignature === undefined || nextSignature === undefined) {
  79. return false;
  80. }
  81. if (computeFullKey(prevSignature) !== computeFullKey(nextSignature)) {
  82. return false;
  83. }
  84. if (nextSignature.forceReset) {
  85. return false;
  86. }
  87. return true;
  88. }
  89. function isReactClass(type) {
  90. return type.prototype && type.prototype.isReactComponent;
  91. }
  92. function canPreserveStateBetween(prevType, nextType) {
  93. if (isReactClass(prevType) || isReactClass(nextType)) {
  94. return false;
  95. }
  96. if (haveEqualSignatures(prevType, nextType)) {
  97. return true;
  98. }
  99. return false;
  100. }
  101. function resolveFamily(type) {
  102. // Only check updated types to keep lookups fast.
  103. return updatedFamiliesByType.get(type);
  104. }
  105. function performReactRefresh() {
  106. {
  107. if (pendingUpdates.length === 0) {
  108. return null;
  109. }
  110. var staleFamilies = new Set();
  111. var updatedFamilies = new Set();
  112. var updates = pendingUpdates;
  113. pendingUpdates = [];
  114. updates.forEach(function (_ref) {
  115. var family = _ref[0],
  116. nextType = _ref[1]; // Now that we got a real edit, we can create associations
  117. // that will be read by the React reconciler.
  118. var prevType = family.current;
  119. updatedFamiliesByType.set(prevType, family);
  120. updatedFamiliesByType.set(nextType, family);
  121. family.current = nextType; // Determine whether this should be a re-render or a re-mount.
  122. if (canPreserveStateBetween(prevType, nextType)) {
  123. updatedFamilies.add(family);
  124. } else {
  125. staleFamilies.add(family);
  126. }
  127. }); // TODO: rename these fields to something more meaningful.
  128. var update = {
  129. updatedFamilies: updatedFamilies,
  130. // Families that will re-render preserving state
  131. staleFamilies: staleFamilies // Families that will be remounted
  132. };
  133. helpersByRendererID.forEach(function (helpers) {
  134. // Even if there are no roots, set the handler on first update.
  135. // This ensures that if *new* roots are mounted, they'll use the resolve handler.
  136. helpers.setRefreshHandler(resolveFamily);
  137. });
  138. var didError = false;
  139. var firstError = null;
  140. failedRoots.forEach(function (element, root) {
  141. var helpers = helpersByRoot.get(root);
  142. if (helpers === undefined) {
  143. throw new Error('Could not find helpers for a root. This is a bug in React Refresh.');
  144. }
  145. try {
  146. helpers.scheduleRoot(root, element);
  147. } catch (err) {
  148. if (!didError) {
  149. didError = true;
  150. firstError = err;
  151. } // Keep trying other roots.
  152. }
  153. });
  154. mountedRoots.forEach(function (root) {
  155. var helpers = helpersByRoot.get(root);
  156. if (helpers === undefined) {
  157. throw new Error('Could not find helpers for a root. This is a bug in React Refresh.');
  158. }
  159. try {
  160. helpers.scheduleRefresh(root, update);
  161. } catch (err) {
  162. if (!didError) {
  163. didError = true;
  164. firstError = err;
  165. } // Keep trying other roots.
  166. }
  167. });
  168. if (didError) {
  169. throw firstError;
  170. }
  171. return update;
  172. }
  173. }
  174. function register(type, id) {
  175. {
  176. if (type === null) {
  177. return;
  178. }
  179. if (typeof type !== 'function' && typeof type !== 'object') {
  180. return;
  181. } // This can happen in an edge case, e.g. if we register
  182. // return value of a HOC but it returns a cached component.
  183. // Ignore anything but the first registration for each type.
  184. if (allFamiliesByType.has(type)) {
  185. return;
  186. } // Create family or remember to update it.
  187. // None of this bookkeeping affects reconciliation
  188. // until the first performReactRefresh() call above.
  189. var family = allFamiliesByID.get(id);
  190. if (family === undefined) {
  191. family = {
  192. current: type
  193. };
  194. allFamiliesByID.set(id, family);
  195. } else {
  196. pendingUpdates.push([family, type]);
  197. }
  198. allFamiliesByType.set(type, family); // Visit inner types because we might not have registered them.
  199. if (typeof type === 'object' && type !== null) {
  200. switch (type.$$typeof) {
  201. case REACT_FORWARD_REF_TYPE:
  202. register(type.render, id + '$render');
  203. break;
  204. case REACT_MEMO_TYPE:
  205. register(type.type, id + '$type');
  206. break;
  207. }
  208. }
  209. }
  210. }
  211. function setSignature(type, key) {
  212. var forceReset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  213. var getCustomHooks = arguments.length > 3 ? arguments[3] : undefined;
  214. {
  215. allSignaturesByType.set(type, {
  216. forceReset: forceReset,
  217. ownKey: key,
  218. fullKey: null,
  219. getCustomHooks: getCustomHooks || function () {
  220. return [];
  221. }
  222. });
  223. }
  224. } // This is lazily called during first render for a type.
  225. // It captures Hook list at that time so inline requires don't break comparisons.
  226. function collectCustomHooksForSignature(type) {
  227. {
  228. var signature = allSignaturesByType.get(type);
  229. if (signature !== undefined) {
  230. computeFullKey(signature);
  231. }
  232. }
  233. }
  234. function getFamilyByID(id) {
  235. {
  236. return allFamiliesByID.get(id);
  237. }
  238. }
  239. function getFamilyByType(type) {
  240. {
  241. return allFamiliesByType.get(type);
  242. }
  243. }
  244. function findAffectedHostInstances(families) {
  245. {
  246. var affectedInstances = new Set();
  247. mountedRoots.forEach(function (root) {
  248. var helpers = helpersByRoot.get(root);
  249. if (helpers === undefined) {
  250. throw new Error('Could not find helpers for a root. This is a bug in React Refresh.');
  251. }
  252. var instancesForRoot = helpers.findHostInstancesForRefresh(root, families);
  253. instancesForRoot.forEach(function (inst) {
  254. affectedInstances.add(inst);
  255. });
  256. });
  257. return affectedInstances;
  258. }
  259. }
  260. function injectIntoGlobalHook(globalObject) {
  261. {
  262. // For React Native, the global hook will be set up by require('react-devtools-core').
  263. // That code will run before us. So we need to monkeypatch functions on existing hook.
  264. // For React Web, the global hook will be set up by the extension.
  265. // This will also run before us.
  266. var hook = globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__;
  267. if (hook === undefined) {
  268. // However, if there is no DevTools extension, we'll need to set up the global hook ourselves.
  269. // Note that in this case it's important that renderer code runs *after* this method call.
  270. // Otherwise, the renderer will think that there is no global hook, and won't do the injection.
  271. var nextID = 0;
  272. globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook = {
  273. supportsFiber: true,
  274. inject: function (injected) {
  275. return nextID++;
  276. },
  277. onCommitFiberRoot: function (id, root, maybePriorityLevel, didError) {},
  278. onCommitFiberUnmount: function () {}
  279. };
  280. } // Here, we just want to get a reference to scheduleRefresh.
  281. var oldInject = hook.inject;
  282. hook.inject = function (injected) {
  283. var id = oldInject.apply(this, arguments);
  284. if (typeof injected.scheduleRefresh === 'function' && typeof injected.setRefreshHandler === 'function') {
  285. // This version supports React Refresh.
  286. helpersByRendererID.set(id, injected);
  287. }
  288. return id;
  289. }; // We also want to track currently mounted roots.
  290. var oldOnCommitFiberRoot = hook.onCommitFiberRoot;
  291. hook.onCommitFiberRoot = function (id, root, maybePriorityLevel, didError) {
  292. var helpers = helpersByRendererID.get(id);
  293. if (helpers === undefined) {
  294. return;
  295. }
  296. helpersByRoot.set(root, helpers);
  297. var current = root.current;
  298. var alternate = current.alternate; // We need to determine whether this root has just (un)mounted.
  299. // This logic is copy-pasted from similar logic in the DevTools backend.
  300. // If this breaks with some refactoring, you'll want to update DevTools too.
  301. if (alternate !== null) {
  302. var wasMounted = alternate.memoizedState != null && alternate.memoizedState.element != null;
  303. var isMounted = current.memoizedState != null && current.memoizedState.element != null;
  304. if (!wasMounted && isMounted) {
  305. // Mount a new root.
  306. mountedRoots.add(root);
  307. failedRoots.delete(root);
  308. } else if (wasMounted && isMounted) {// Update an existing root.
  309. // This doesn't affect our mounted root Set.
  310. } else if (wasMounted && !isMounted) {
  311. // Unmount an existing root.
  312. mountedRoots.delete(root);
  313. if (didError) {
  314. // We'll remount it on future edits.
  315. // Remember what was rendered so we can restore it.
  316. failedRoots.set(root, alternate.memoizedState.element);
  317. } else {
  318. helpersByRoot.delete(root);
  319. }
  320. } else if (!wasMounted && !isMounted) {
  321. if (didError && !failedRoots.has(root)) {
  322. // The root had an error during the initial mount.
  323. // We can't read its last element from the memoized state
  324. // because there was no previously committed alternate.
  325. // Ideally, it would be nice if we had a way to extract
  326. // the last attempted rendered element, but accessing the update queue
  327. // would tie this package too closely to the reconciler version.
  328. // So instead, we just set a flag.
  329. // TODO: Maybe we could fix this as the same time as when we fix
  330. // DevTools to not depend on `alternate.memoizedState.element`.
  331. didSomeRootFailOnMount = true;
  332. }
  333. }
  334. } else {
  335. // Mount a new root.
  336. mountedRoots.add(root);
  337. }
  338. return oldOnCommitFiberRoot.apply(this, arguments);
  339. };
  340. }
  341. }
  342. function hasUnrecoverableErrors() {
  343. return didSomeRootFailOnMount;
  344. } // Exposed for testing.
  345. function _getMountedRootCount() {
  346. {
  347. return mountedRoots.size;
  348. }
  349. } // This is a wrapper over more primitive functions for setting signature.
  350. // Signatures let us decide whether the Hook order has changed on refresh.
  351. //
  352. // This function is intended to be used as a transform target, e.g.:
  353. // var _s = createSignatureFunctionForTransform()
  354. //
  355. // function Hello() {
  356. // const [foo, setFoo] = useState(0);
  357. // const value = useCustomHook();
  358. // _s(); /* Second call triggers collecting the custom Hook list.
  359. // * This doesn't happen during the module evaluation because we
  360. // * don't want to change the module order with inline requires.
  361. // * Next calls are noops. */
  362. // return <h1>Hi</h1>;
  363. // }
  364. //
  365. // /* First call specifies the signature: */
  366. // _s(
  367. // Hello,
  368. // 'useState{[foo, setFoo]}(0)',
  369. // () => [useCustomHook], /* Lazy to avoid triggering inline requires */
  370. // );
  371. function createSignatureFunctionForTransform() {
  372. {
  373. var call = 0;
  374. var savedType;
  375. var hasCustomHooks;
  376. return function (type, key, forceReset, getCustomHooks) {
  377. switch (call++) {
  378. case 0:
  379. savedType = type;
  380. hasCustomHooks = typeof getCustomHooks === 'function';
  381. setSignature(type, key, forceReset, getCustomHooks);
  382. break;
  383. case 1:
  384. if (hasCustomHooks) {
  385. collectCustomHooksForSignature(savedType);
  386. }
  387. break;
  388. }
  389. return type;
  390. };
  391. }
  392. }
  393. function isLikelyComponentType(type) {
  394. {
  395. switch (typeof type) {
  396. case 'function':
  397. {
  398. // First, deal with classes.
  399. if (type.prototype != null) {
  400. if (type.prototype.isReactComponent) {
  401. // React class.
  402. return true;
  403. }
  404. var ownNames = Object.getOwnPropertyNames(type.prototype);
  405. if (ownNames.length > 1 || ownNames[0] !== 'constructor') {
  406. // This looks like a class.
  407. return false;
  408. } // eslint-disable-next-line no-proto
  409. if (type.prototype.__proto__ !== Object.prototype) {
  410. // It has a superclass.
  411. return false;
  412. } // Pass through.
  413. // This looks like a regular function with empty prototype.
  414. } // For plain functions and arrows, use name as a heuristic.
  415. var name = type.name || type.displayName;
  416. return typeof name === 'string' && /^[A-Z]/.test(name);
  417. }
  418. case 'object':
  419. {
  420. if (type != null) {
  421. switch (type.$$typeof) {
  422. case REACT_FORWARD_REF_TYPE:
  423. case REACT_MEMO_TYPE:
  424. // Definitely React components.
  425. return true;
  426. default:
  427. return false;
  428. }
  429. }
  430. return false;
  431. }
  432. default:
  433. {
  434. return false;
  435. }
  436. }
  437. }
  438. }
  439. var ReactFreshRuntime = Object.freeze({
  440. performReactRefresh: performReactRefresh,
  441. register: register,
  442. setSignature: setSignature,
  443. collectCustomHooksForSignature: collectCustomHooksForSignature,
  444. getFamilyByID: getFamilyByID,
  445. getFamilyByType: getFamilyByType,
  446. findAffectedHostInstances: findAffectedHostInstances,
  447. injectIntoGlobalHook: injectIntoGlobalHook,
  448. hasUnrecoverableErrors: hasUnrecoverableErrors,
  449. _getMountedRootCount: _getMountedRootCount,
  450. createSignatureFunctionForTransform: createSignatureFunctionForTransform,
  451. isLikelyComponentType: isLikelyComponentType
  452. }); // This is hacky but makes it work with both Rollup and Jest.
  453. var runtime = ReactFreshRuntime.default || ReactFreshRuntime;
  454. module.exports = runtime;
  455. })();
  456. }