react-refresh-runtime.development.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. /** @license React vundefined
  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 (process.env.NODE_ENV !== "production") {
  11. (function() {
  12. 'use strict';
  13. // ATTENTION
  14. // When adding new symbols to this file,
  15. // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
  16. // The Symbol used to tag the ReactElement-like types. If there is no native Symbol
  17. // nor polyfill, then a plain number is used for performance.
  18. var REACT_ELEMENT_TYPE = 0xeac7;
  19. var REACT_PORTAL_TYPE = 0xeaca;
  20. var REACT_FRAGMENT_TYPE = 0xeacb;
  21. var REACT_STRICT_MODE_TYPE = 0xeacc;
  22. var REACT_PROFILER_TYPE = 0xead2;
  23. var REACT_PROVIDER_TYPE = 0xeacd;
  24. var REACT_CONTEXT_TYPE = 0xeace;
  25. var REACT_FORWARD_REF_TYPE = 0xead0;
  26. var REACT_SUSPENSE_TYPE = 0xead1;
  27. var REACT_SUSPENSE_LIST_TYPE = 0xead8;
  28. var REACT_MEMO_TYPE = 0xead3;
  29. var REACT_LAZY_TYPE = 0xead4;
  30. var REACT_BLOCK_TYPE = 0xead9;
  31. var REACT_SERVER_BLOCK_TYPE = 0xeada;
  32. var REACT_FUNDAMENTAL_TYPE = 0xead5;
  33. var REACT_RESPONDER_TYPE = 0xead6;
  34. var REACT_SCOPE_TYPE = 0xead7;
  35. var REACT_OPAQUE_ID_TYPE = 0xeae0;
  36. var REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;
  37. var REACT_OFFSCREEN_TYPE = 0xeae2;
  38. var REACT_LEGACY_HIDDEN_TYPE = 0xeae3;
  39. if (typeof Symbol === 'function' && Symbol.for) {
  40. var symbolFor = Symbol.for;
  41. REACT_ELEMENT_TYPE = symbolFor('react.element');
  42. REACT_PORTAL_TYPE = symbolFor('react.portal');
  43. REACT_FRAGMENT_TYPE = symbolFor('react.fragment');
  44. REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');
  45. REACT_PROFILER_TYPE = symbolFor('react.profiler');
  46. REACT_PROVIDER_TYPE = symbolFor('react.provider');
  47. REACT_CONTEXT_TYPE = symbolFor('react.context');
  48. REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');
  49. REACT_SUSPENSE_TYPE = symbolFor('react.suspense');
  50. REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');
  51. REACT_MEMO_TYPE = symbolFor('react.memo');
  52. REACT_LAZY_TYPE = symbolFor('react.lazy');
  53. REACT_BLOCK_TYPE = symbolFor('react.block');
  54. REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');
  55. REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');
  56. REACT_RESPONDER_TYPE = symbolFor('react.responder');
  57. REACT_SCOPE_TYPE = symbolFor('react.scope');
  58. REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');
  59. REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');
  60. REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');
  61. REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');
  62. }
  63. var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; // We never remove these associations.
  64. // It's OK to reference families, but use WeakMap/Set for types.
  65. var allFamiliesByID = new Map();
  66. var allFamiliesByType = new PossiblyWeakMap();
  67. var allSignaturesByType = new PossiblyWeakMap(); // This WeakMap is read by React, so we only put families
  68. // that have actually been edited here. This keeps checks fast.
  69. // $FlowIssue
  70. var updatedFamiliesByType = new PossiblyWeakMap(); // This is cleared on every performReactRefresh() call.
  71. // It is an array of [Family, NextType] tuples.
  72. var pendingUpdates = []; // This is injected by the renderer via DevTools global hook.
  73. var helpersByRendererID = new Map();
  74. var helpersByRoot = new Map(); // We keep track of mounted roots so we can schedule updates.
  75. var mountedRoots = new Set(); // If a root captures an error, we remember it so we can retry on edit.
  76. var failedRoots = new Set(); // In environments that support WeakMap, we also remember the last element for every root.
  77. // It needs to be weak because we do this even for roots that failed to mount.
  78. // If there is no WeakMap, we won't attempt to do retrying.
  79. // $FlowIssue
  80. var rootElements = // $FlowIssue
  81. typeof WeakMap === 'function' ? new WeakMap() : null;
  82. var isPerformingRefresh = false;
  83. function computeFullKey(signature) {
  84. if (signature.fullKey !== null) {
  85. return signature.fullKey;
  86. }
  87. var fullKey = signature.ownKey;
  88. var hooks;
  89. try {
  90. hooks = signature.getCustomHooks();
  91. } catch (err) {
  92. // This can happen in an edge case, e.g. if expression like Foo.useSomething
  93. // depends on Foo which is lazily initialized during rendering.
  94. // In that case just assume we'll have to remount.
  95. signature.forceReset = true;
  96. signature.fullKey = fullKey;
  97. return fullKey;
  98. }
  99. for (var i = 0; i < hooks.length; i++) {
  100. var hook = hooks[i];
  101. if (typeof hook !== 'function') {
  102. // Something's wrong. Assume we need to remount.
  103. signature.forceReset = true;
  104. signature.fullKey = fullKey;
  105. return fullKey;
  106. }
  107. var nestedHookSignature = allSignaturesByType.get(hook);
  108. if (nestedHookSignature === undefined) {
  109. // No signature means Hook wasn't in the source code, e.g. in a library.
  110. // We'll skip it because we can assume it won't change during this session.
  111. continue;
  112. }
  113. var nestedHookKey = computeFullKey(nestedHookSignature);
  114. if (nestedHookSignature.forceReset) {
  115. signature.forceReset = true;
  116. }
  117. fullKey += '\n---\n' + nestedHookKey;
  118. }
  119. signature.fullKey = fullKey;
  120. return fullKey;
  121. }
  122. function haveEqualSignatures(prevType, nextType) {
  123. var prevSignature = allSignaturesByType.get(prevType);
  124. var nextSignature = allSignaturesByType.get(nextType);
  125. if (prevSignature === undefined && nextSignature === undefined) {
  126. return true;
  127. }
  128. if (prevSignature === undefined || nextSignature === undefined) {
  129. return false;
  130. }
  131. if (computeFullKey(prevSignature) !== computeFullKey(nextSignature)) {
  132. return false;
  133. }
  134. if (nextSignature.forceReset) {
  135. return false;
  136. }
  137. return true;
  138. }
  139. function isReactClass(type) {
  140. return type.prototype && type.prototype.isReactComponent;
  141. }
  142. function canPreserveStateBetween(prevType, nextType) {
  143. if (isReactClass(prevType) || isReactClass(nextType)) {
  144. return false;
  145. }
  146. if (haveEqualSignatures(prevType, nextType)) {
  147. return true;
  148. }
  149. return false;
  150. }
  151. function resolveFamily(type) {
  152. // Only check updated types to keep lookups fast.
  153. return updatedFamiliesByType.get(type);
  154. } // If we didn't care about IE11, we could use new Map/Set(iterable).
  155. function cloneMap(map) {
  156. var clone = new Map();
  157. map.forEach(function (value, key) {
  158. clone.set(key, value);
  159. });
  160. return clone;
  161. }
  162. function cloneSet(set) {
  163. var clone = new Set();
  164. set.forEach(function (value) {
  165. clone.add(value);
  166. });
  167. return clone;
  168. }
  169. function performReactRefresh() {
  170. if (pendingUpdates.length === 0) {
  171. return null;
  172. }
  173. if (isPerformingRefresh) {
  174. return null;
  175. }
  176. isPerformingRefresh = true;
  177. try {
  178. var staleFamilies = new Set();
  179. var updatedFamilies = new Set();
  180. var updates = pendingUpdates;
  181. pendingUpdates = [];
  182. updates.forEach(function (_ref) {
  183. var family = _ref[0],
  184. nextType = _ref[1];
  185. // Now that we got a real edit, we can create associations
  186. // that will be read by the React reconciler.
  187. var prevType = family.current;
  188. updatedFamiliesByType.set(prevType, family);
  189. updatedFamiliesByType.set(nextType, family);
  190. family.current = nextType; // Determine whether this should be a re-render or a re-mount.
  191. if (canPreserveStateBetween(prevType, nextType)) {
  192. updatedFamilies.add(family);
  193. } else {
  194. staleFamilies.add(family);
  195. }
  196. }); // TODO: rename these fields to something more meaningful.
  197. var update = {
  198. updatedFamilies: updatedFamilies,
  199. // Families that will re-render preserving state
  200. staleFamilies: staleFamilies // Families that will be remounted
  201. };
  202. helpersByRendererID.forEach(function (helpers) {
  203. // Even if there are no roots, set the handler on first update.
  204. // This ensures that if *new* roots are mounted, they'll use the resolve handler.
  205. helpers.setRefreshHandler(resolveFamily);
  206. });
  207. var didError = false;
  208. var firstError = null; // We snapshot maps and sets that are mutated during commits.
  209. // If we don't do this, there is a risk they will be mutated while
  210. // we iterate over them. For example, trying to recover a failed root
  211. // may cause another root to be added to the failed list -- an infinite loop.
  212. var failedRootsSnapshot = cloneSet(failedRoots);
  213. var mountedRootsSnapshot = cloneSet(mountedRoots);
  214. var helpersByRootSnapshot = cloneMap(helpersByRoot);
  215. failedRootsSnapshot.forEach(function (root) {
  216. var helpers = helpersByRootSnapshot.get(root);
  217. if (helpers === undefined) {
  218. throw new Error('Could not find helpers for a root. This is a bug in React Refresh.');
  219. }
  220. if (!failedRoots.has(root)) {// No longer failed.
  221. }
  222. if (rootElements === null) {
  223. return;
  224. }
  225. if (!rootElements.has(root)) {
  226. return;
  227. }
  228. var element = rootElements.get(root);
  229. try {
  230. helpers.scheduleRoot(root, element);
  231. } catch (err) {
  232. if (!didError) {
  233. didError = true;
  234. firstError = err;
  235. } // Keep trying other roots.
  236. }
  237. });
  238. mountedRootsSnapshot.forEach(function (root) {
  239. var helpers = helpersByRootSnapshot.get(root);
  240. if (helpers === undefined) {
  241. throw new Error('Could not find helpers for a root. This is a bug in React Refresh.');
  242. }
  243. if (!mountedRoots.has(root)) {// No longer mounted.
  244. }
  245. try {
  246. helpers.scheduleRefresh(root, update);
  247. } catch (err) {
  248. if (!didError) {
  249. didError = true;
  250. firstError = err;
  251. } // Keep trying other roots.
  252. }
  253. });
  254. if (didError) {
  255. throw firstError;
  256. }
  257. return update;
  258. } finally {
  259. isPerformingRefresh = false;
  260. }
  261. }
  262. function register(type, id) {
  263. {
  264. if (type === null) {
  265. return;
  266. }
  267. if (typeof type !== 'function' && typeof type !== 'object') {
  268. return;
  269. } // This can happen in an edge case, e.g. if we register
  270. // return value of a HOC but it returns a cached component.
  271. // Ignore anything but the first registration for each type.
  272. if (allFamiliesByType.has(type)) {
  273. return;
  274. } // Create family or remember to update it.
  275. // None of this bookkeeping affects reconciliation
  276. // until the first performReactRefresh() call above.
  277. var family = allFamiliesByID.get(id);
  278. if (family === undefined) {
  279. family = {
  280. current: type
  281. };
  282. allFamiliesByID.set(id, family);
  283. } else {
  284. pendingUpdates.push([family, type]);
  285. }
  286. allFamiliesByType.set(type, family); // Visit inner types because we might not have registered them.
  287. if (typeof type === 'object' && type !== null) {
  288. switch (type.$$typeof) {
  289. case REACT_FORWARD_REF_TYPE:
  290. register(type.render, id + '$render');
  291. break;
  292. case REACT_MEMO_TYPE:
  293. register(type.type, id + '$type');
  294. break;
  295. }
  296. }
  297. }
  298. }
  299. function setSignature(type, key) {
  300. var forceReset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  301. var getCustomHooks = arguments.length > 3 ? arguments[3] : undefined;
  302. {
  303. allSignaturesByType.set(type, {
  304. forceReset: forceReset,
  305. ownKey: key,
  306. fullKey: null,
  307. getCustomHooks: getCustomHooks || function () {
  308. return [];
  309. }
  310. });
  311. }
  312. } // This is lazily called during first render for a type.
  313. // It captures Hook list at that time so inline requires don't break comparisons.
  314. function collectCustomHooksForSignature(type) {
  315. {
  316. var signature = allSignaturesByType.get(type);
  317. if (signature !== undefined) {
  318. computeFullKey(signature);
  319. }
  320. }
  321. }
  322. function getFamilyByID(id) {
  323. {
  324. return allFamiliesByID.get(id);
  325. }
  326. }
  327. function getFamilyByType(type) {
  328. {
  329. return allFamiliesByType.get(type);
  330. }
  331. }
  332. function findAffectedHostInstances(families) {
  333. {
  334. var affectedInstances = new Set();
  335. mountedRoots.forEach(function (root) {
  336. var helpers = helpersByRoot.get(root);
  337. if (helpers === undefined) {
  338. throw new Error('Could not find helpers for a root. This is a bug in React Refresh.');
  339. }
  340. var instancesForRoot = helpers.findHostInstancesForRefresh(root, families);
  341. instancesForRoot.forEach(function (inst) {
  342. affectedInstances.add(inst);
  343. });
  344. });
  345. return affectedInstances;
  346. }
  347. }
  348. function injectIntoGlobalHook(globalObject) {
  349. {
  350. // For React Native, the global hook will be set up by require('react-devtools-core').
  351. // That code will run before us. So we need to monkeypatch functions on existing hook.
  352. // For React Web, the global hook will be set up by the extension.
  353. // This will also run before us.
  354. var hook = globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__;
  355. if (hook === undefined) {
  356. // However, if there is no DevTools extension, we'll need to set up the global hook ourselves.
  357. // Note that in this case it's important that renderer code runs *after* this method call.
  358. // Otherwise, the renderer will think that there is no global hook, and won't do the injection.
  359. var nextID = 0;
  360. globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook = {
  361. renderers: new Map(),
  362. supportsFiber: true,
  363. inject: function (injected) {
  364. return nextID++;
  365. },
  366. onScheduleFiberRoot: function (id, root, children) {},
  367. onCommitFiberRoot: function (id, root, maybePriorityLevel, didError) {},
  368. onCommitFiberUnmount: function () {}
  369. };
  370. } // Here, we just want to get a reference to scheduleRefresh.
  371. var oldInject = hook.inject;
  372. hook.inject = function (injected) {
  373. var id = oldInject.apply(this, arguments);
  374. if (typeof injected.scheduleRefresh === 'function' && typeof injected.setRefreshHandler === 'function') {
  375. // This version supports React Refresh.
  376. helpersByRendererID.set(id, injected);
  377. }
  378. return id;
  379. }; // Do the same for any already injected roots.
  380. // This is useful if ReactDOM has already been initialized.
  381. // https://github.com/facebook/react/issues/17626
  382. hook.renderers.forEach(function (injected, id) {
  383. if (typeof injected.scheduleRefresh === 'function' && typeof injected.setRefreshHandler === 'function') {
  384. // This version supports React Refresh.
  385. helpersByRendererID.set(id, injected);
  386. }
  387. }); // We also want to track currently mounted roots.
  388. var oldOnCommitFiberRoot = hook.onCommitFiberRoot;
  389. var oldOnScheduleFiberRoot = hook.onScheduleFiberRoot || function () {};
  390. hook.onScheduleFiberRoot = function (id, root, children) {
  391. if (!isPerformingRefresh) {
  392. // If it was intentionally scheduled, don't attempt to restore.
  393. // This includes intentionally scheduled unmounts.
  394. failedRoots.delete(root);
  395. if (rootElements !== null) {
  396. rootElements.set(root, children);
  397. }
  398. }
  399. return oldOnScheduleFiberRoot.apply(this, arguments);
  400. };
  401. hook.onCommitFiberRoot = function (id, root, maybePriorityLevel, didError) {
  402. var helpers = helpersByRendererID.get(id);
  403. if (helpers === undefined) {
  404. return;
  405. }
  406. helpersByRoot.set(root, helpers);
  407. var current = root.current;
  408. var alternate = current.alternate; // We need to determine whether this root has just (un)mounted.
  409. // This logic is copy-pasted from similar logic in the DevTools backend.
  410. // If this breaks with some refactoring, you'll want to update DevTools too.
  411. if (alternate !== null) {
  412. var wasMounted = alternate.memoizedState != null && alternate.memoizedState.element != null;
  413. var isMounted = current.memoizedState != null && current.memoizedState.element != null;
  414. if (!wasMounted && isMounted) {
  415. // Mount a new root.
  416. mountedRoots.add(root);
  417. failedRoots.delete(root);
  418. } else if (wasMounted && isMounted) ; else if (wasMounted && !isMounted) {
  419. // Unmount an existing root.
  420. mountedRoots.delete(root);
  421. if (didError) {
  422. // We'll remount it on future edits.
  423. failedRoots.add(root);
  424. } else {
  425. helpersByRoot.delete(root);
  426. }
  427. } else if (!wasMounted && !isMounted) {
  428. if (didError) {
  429. // We'll remount it on future edits.
  430. failedRoots.add(root);
  431. }
  432. }
  433. } else {
  434. // Mount a new root.
  435. mountedRoots.add(root);
  436. }
  437. return oldOnCommitFiberRoot.apply(this, arguments);
  438. };
  439. }
  440. }
  441. function hasUnrecoverableErrors() {
  442. // TODO: delete this after removing dependency in RN.
  443. return false;
  444. } // Exposed for testing.
  445. function _getMountedRootCount() {
  446. {
  447. return mountedRoots.size;
  448. }
  449. } // This is a wrapper over more primitive functions for setting signature.
  450. // Signatures let us decide whether the Hook order has changed on refresh.
  451. //
  452. // This function is intended to be used as a transform target, e.g.:
  453. // var _s = createSignatureFunctionForTransform()
  454. //
  455. // function Hello() {
  456. // const [foo, setFoo] = useState(0);
  457. // const value = useCustomHook();
  458. // _s(); /* Second call triggers collecting the custom Hook list.
  459. // * This doesn't happen during the module evaluation because we
  460. // * don't want to change the module order with inline requires.
  461. // * Next calls are noops. */
  462. // return <h1>Hi</h1>;
  463. // }
  464. //
  465. // /* First call specifies the signature: */
  466. // _s(
  467. // Hello,
  468. // 'useState{[foo, setFoo]}(0)',
  469. // () => [useCustomHook], /* Lazy to avoid triggering inline requires */
  470. // );
  471. function createSignatureFunctionForTransform() {
  472. {
  473. // We'll fill in the signature in two steps.
  474. // First, we'll know the signature itself. This happens outside the component.
  475. // Then, we'll know the references to custom Hooks. This happens inside the component.
  476. // After that, the returned function will be a fast path no-op.
  477. var status = 'needsSignature';
  478. var savedType;
  479. var hasCustomHooks;
  480. return function (type, key, forceReset, getCustomHooks) {
  481. switch (status) {
  482. case 'needsSignature':
  483. if (type !== undefined) {
  484. // If we received an argument, this is the initial registration call.
  485. savedType = type;
  486. hasCustomHooks = typeof getCustomHooks === 'function';
  487. setSignature(type, key, forceReset, getCustomHooks); // The next call we expect is from inside a function, to fill in the custom Hooks.
  488. status = 'needsCustomHooks';
  489. }
  490. break;
  491. case 'needsCustomHooks':
  492. if (hasCustomHooks) {
  493. collectCustomHooksForSignature(savedType);
  494. }
  495. status = 'resolved';
  496. break;
  497. }
  498. return type;
  499. };
  500. }
  501. }
  502. function isLikelyComponentType(type) {
  503. {
  504. switch (typeof type) {
  505. case 'function':
  506. {
  507. // First, deal with classes.
  508. if (type.prototype != null) {
  509. if (type.prototype.isReactComponent) {
  510. // React class.
  511. return true;
  512. }
  513. var ownNames = Object.getOwnPropertyNames(type.prototype);
  514. if (ownNames.length > 1 || ownNames[0] !== 'constructor') {
  515. // This looks like a class.
  516. return false;
  517. } // eslint-disable-next-line no-proto
  518. if (type.prototype.__proto__ !== Object.prototype) {
  519. // It has a superclass.
  520. return false;
  521. } // Pass through.
  522. // This looks like a regular function with empty prototype.
  523. } // For plain functions and arrows, use name as a heuristic.
  524. var name = type.name || type.displayName;
  525. return typeof name === 'string' && /^[A-Z]/.test(name);
  526. }
  527. case 'object':
  528. {
  529. if (type != null) {
  530. switch (type.$$typeof) {
  531. case REACT_FORWARD_REF_TYPE:
  532. case REACT_MEMO_TYPE:
  533. // Definitely React components.
  534. return true;
  535. default:
  536. return false;
  537. }
  538. }
  539. return false;
  540. }
  541. default:
  542. {
  543. return false;
  544. }
  545. }
  546. }
  547. }
  548. exports._getMountedRootCount = _getMountedRootCount;
  549. exports.collectCustomHooksForSignature = collectCustomHooksForSignature;
  550. exports.createSignatureFunctionForTransform = createSignatureFunctionForTransform;
  551. exports.findAffectedHostInstances = findAffectedHostInstances;
  552. exports.getFamilyByID = getFamilyByID;
  553. exports.getFamilyByType = getFamilyByType;
  554. exports.hasUnrecoverableErrors = hasUnrecoverableErrors;
  555. exports.injectIntoGlobalHook = injectIntoGlobalHook;
  556. exports.isLikelyComponentType = isLikelyComponentType;
  557. exports.performReactRefresh = performReactRefresh;
  558. exports.register = register;
  559. exports.setSignature = setSignature;
  560. })();
  561. }