react-refresh-babel.development.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /**
  2. * @license React
  3. * react-refresh-babel.development.js
  4. *
  5. * Copyright (c) Meta Platforms, Inc. and 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. "production" !== process.env.NODE_ENV &&
  12. (module.exports = function (babel) {
  13. function createRegistration(programPath, persistentID) {
  14. var handle = programPath.scope.generateUidIdentifier("c");
  15. registrationsByProgramPath.has(programPath) ||
  16. registrationsByProgramPath.set(programPath, []);
  17. registrationsByProgramPath
  18. .get(programPath)
  19. .push({ handle: handle, persistentID: persistentID });
  20. return handle;
  21. }
  22. function isComponentishName(name) {
  23. return "string" === typeof name && "A" <= name[0] && "Z" >= name[0];
  24. }
  25. function findInnerComponents(inferredName, path, callback) {
  26. var node = path.node;
  27. switch (node.type) {
  28. case "Identifier":
  29. if (!isComponentishName(node.name)) break;
  30. callback(inferredName, node, null);
  31. return !0;
  32. case "FunctionDeclaration":
  33. return callback(inferredName, node.id, null), !0;
  34. case "ArrowFunctionExpression":
  35. if ("ArrowFunctionExpression" === node.body.type) break;
  36. callback(inferredName, node, path);
  37. return !0;
  38. case "FunctionExpression":
  39. return callback(inferredName, node, path), !0;
  40. case "CallExpression":
  41. var argsPath = path.get("arguments");
  42. if (void 0 === argsPath || 0 === argsPath.length) break;
  43. var calleePath = path.get("callee");
  44. switch (calleePath.node.type) {
  45. case "MemberExpression":
  46. case "Identifier":
  47. calleePath = calleePath.getSource();
  48. if (
  49. !findInnerComponents(
  50. inferredName + "$" + calleePath,
  51. argsPath[0],
  52. callback
  53. )
  54. )
  55. return !1;
  56. callback(inferredName, node, path);
  57. return !0;
  58. default:
  59. return !1;
  60. }
  61. case "VariableDeclarator":
  62. if (
  63. ((argsPath = node.init),
  64. null !== argsPath &&
  65. ((calleePath = node.id.name), isComponentishName(calleePath)))
  66. ) {
  67. switch (argsPath.type) {
  68. case "ArrowFunctionExpression":
  69. case "FunctionExpression":
  70. break;
  71. case "CallExpression":
  72. node = argsPath.callee;
  73. var calleeType = node.type;
  74. if (
  75. "Import" === calleeType ||
  76. ("Identifier" === calleeType &&
  77. (0 === node.name.indexOf("require") ||
  78. 0 === node.name.indexOf("import")))
  79. )
  80. return !1;
  81. break;
  82. case "TaggedTemplateExpression":
  83. break;
  84. default:
  85. return !1;
  86. }
  87. node = path.get("init");
  88. if (findInnerComponents(inferredName, node, callback)) return !0;
  89. calleePath = path.scope.getBinding(calleePath);
  90. if (void 0 === calleePath) return;
  91. path = !1;
  92. calleePath = calleePath.referencePaths;
  93. for (calleeType = 0; calleeType < calleePath.length; calleeType++) {
  94. var ref = calleePath[calleeType];
  95. if (
  96. !ref.node ||
  97. "JSXIdentifier" === ref.node.type ||
  98. "Identifier" === ref.node.type
  99. ) {
  100. ref = ref.parent;
  101. if ("JSXOpeningElement" === ref.type) path = !0;
  102. else if ("CallExpression" === ref.type) {
  103. ref = ref.callee;
  104. var fnName = void 0;
  105. switch (ref.type) {
  106. case "Identifier":
  107. fnName = ref.name;
  108. break;
  109. case "MemberExpression":
  110. fnName = ref.property.name;
  111. }
  112. switch (fnName) {
  113. case "createElement":
  114. case "jsx":
  115. case "jsxDEV":
  116. case "jsxs":
  117. path = !0;
  118. }
  119. }
  120. if (path) return callback(inferredName, argsPath, node), !0;
  121. }
  122. }
  123. }
  124. }
  125. return !1;
  126. }
  127. function getHookCallsSignature(functionNode) {
  128. functionNode = hookCalls.get(functionNode);
  129. return void 0 === functionNode
  130. ? null
  131. : {
  132. key: functionNode
  133. .map(function (call) {
  134. return call.name + "{" + call.key + "}";
  135. })
  136. .join("\n"),
  137. customHooks: functionNode
  138. .filter(function (call) {
  139. a: switch (call.name) {
  140. case "useState":
  141. case "React.useState":
  142. case "useReducer":
  143. case "React.useReducer":
  144. case "useEffect":
  145. case "React.useEffect":
  146. case "useLayoutEffect":
  147. case "React.useLayoutEffect":
  148. case "useMemo":
  149. case "React.useMemo":
  150. case "useCallback":
  151. case "React.useCallback":
  152. case "useRef":
  153. case "React.useRef":
  154. case "useContext":
  155. case "React.useContext":
  156. case "useImperativeHandle":
  157. case "React.useImperativeHandle":
  158. case "useDebugValue":
  159. case "React.useDebugValue":
  160. case "useId":
  161. case "React.useId":
  162. case "useDeferredValue":
  163. case "React.useDeferredValue":
  164. case "useTransition":
  165. case "React.useTransition":
  166. case "useInsertionEffect":
  167. case "React.useInsertionEffect":
  168. case "useSyncExternalStore":
  169. case "React.useSyncExternalStore":
  170. case "useFormStatus":
  171. case "React.useFormStatus":
  172. case "useFormState":
  173. case "React.useFormState":
  174. case "useActionState":
  175. case "React.useActionState":
  176. case "useOptimistic":
  177. case "React.useOptimistic":
  178. call = !0;
  179. break a;
  180. default:
  181. call = !1;
  182. }
  183. return !call;
  184. })
  185. .map(function (call) {
  186. return t.cloneDeep(call.callee);
  187. })
  188. };
  189. }
  190. function hasForceResetComment(path) {
  191. path = path.hub.file;
  192. var hasForceReset = hasForceResetCommentByFile.get(path);
  193. if (void 0 !== hasForceReset) return hasForceReset;
  194. hasForceReset = !1;
  195. for (var comments = path.ast.comments, i = 0; i < comments.length; i++)
  196. if (-1 !== comments[i].value.indexOf("@refresh reset")) {
  197. hasForceReset = !0;
  198. break;
  199. }
  200. hasForceResetCommentByFile.set(path, hasForceReset);
  201. return hasForceReset;
  202. }
  203. function createArgumentsForSignature(node, signature, scope) {
  204. var key = signature.key;
  205. signature = signature.customHooks;
  206. var forceReset = hasForceResetComment(scope.path),
  207. customHooksInScope = [];
  208. signature.forEach(function (callee) {
  209. switch (callee.type) {
  210. case "MemberExpression":
  211. if ("Identifier" === callee.object.type)
  212. var bindingName = callee.object.name;
  213. break;
  214. case "Identifier":
  215. bindingName = callee.name;
  216. }
  217. scope.hasBinding(bindingName)
  218. ? customHooksInScope.push(callee)
  219. : (forceReset = !0);
  220. });
  221. signature = key;
  222. "function" !== typeof require ||
  223. opts.emitFullSignatures ||
  224. (signature = require("crypto")
  225. .createHash("sha1")
  226. .update(key)
  227. .digest("base64"));
  228. node = [node, t.stringLiteral(signature)];
  229. (forceReset || 0 < customHooksInScope.length) &&
  230. node.push(t.booleanLiteral(forceReset));
  231. 0 < customHooksInScope.length &&
  232. node.push(
  233. t.functionExpression(
  234. null,
  235. [],
  236. t.blockStatement([
  237. t.returnStatement(t.arrayExpression(customHooksInScope))
  238. ])
  239. )
  240. );
  241. return node;
  242. }
  243. function findHOCCallPathsAbove(path) {
  244. for (var calls = []; ; ) {
  245. if (!path) return calls;
  246. var parentPath = path.parentPath;
  247. if (!parentPath) return calls;
  248. if (
  249. "AssignmentExpression" === parentPath.node.type &&
  250. path.node === parentPath.node.right
  251. )
  252. path = parentPath;
  253. else if (
  254. "CallExpression" === parentPath.node.type &&
  255. path.node !== parentPath.node.callee
  256. )
  257. calls.push(parentPath), (path = parentPath);
  258. else return calls;
  259. }
  260. }
  261. var opts =
  262. 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {};
  263. if ("function" === typeof babel.env) {
  264. var env = babel.env();
  265. if ("development" !== env && !opts.skipEnvCheck)
  266. throw Error(
  267. 'React Refresh Babel transform should only be enabled in development environment. Instead, the environment is: "' +
  268. env +
  269. '". If you want to override this check, pass {skipEnvCheck: true} as plugin options.'
  270. );
  271. }
  272. var t = babel.types,
  273. refreshReg = t.identifier(opts.refreshReg || "$RefreshReg$"),
  274. refreshSig = t.identifier(opts.refreshSig || "$RefreshSig$"),
  275. registrationsByProgramPath = new Map(),
  276. hasForceResetCommentByFile = new WeakMap(),
  277. seenForRegistration = new WeakSet(),
  278. seenForSignature = new WeakSet(),
  279. seenForOutro = new WeakSet(),
  280. hookCalls = new WeakMap(),
  281. HookCallsVisitor = {
  282. CallExpression: function (path) {
  283. var callee = path.node.callee,
  284. name = null;
  285. switch (callee.type) {
  286. case "Identifier":
  287. name = callee.name;
  288. break;
  289. case "MemberExpression":
  290. name = callee.property.name;
  291. }
  292. if (
  293. null !== name &&
  294. /^use[A-Z]/.test(name) &&
  295. ((callee = path.scope.getFunctionParent()), null !== callee)
  296. ) {
  297. callee = callee.block;
  298. hookCalls.has(callee) || hookCalls.set(callee, []);
  299. callee = hookCalls.get(callee);
  300. var key = "";
  301. "VariableDeclarator" === path.parent.type &&
  302. (key = path.parentPath.get("id").getSource());
  303. var args = path.get("arguments");
  304. "useState" === name && 0 < args.length
  305. ? (key += "(" + args[0].getSource() + ")")
  306. : "useReducer" === name &&
  307. 1 < args.length &&
  308. (key += "(" + args[1].getSource() + ")");
  309. callee.push({ callee: path.node.callee, name: name, key: key });
  310. }
  311. }
  312. };
  313. return {
  314. visitor: {
  315. ExportDefaultDeclaration: function (path) {
  316. var node = path.node,
  317. decl = node.declaration,
  318. declPath = path.get("declaration");
  319. if (
  320. "CallExpression" === decl.type &&
  321. !seenForRegistration.has(node)
  322. ) {
  323. seenForRegistration.add(node);
  324. var programPath = path.parentPath;
  325. findInnerComponents(
  326. "%default%",
  327. declPath,
  328. function (persistentID, targetExpr, targetPath) {
  329. null !== targetPath &&
  330. ((persistentID = createRegistration(
  331. programPath,
  332. persistentID
  333. )),
  334. targetPath.replaceWith(
  335. t.assignmentExpression("=", persistentID, targetExpr)
  336. ));
  337. }
  338. );
  339. }
  340. },
  341. FunctionDeclaration: {
  342. enter: function (path) {
  343. var node = path.node,
  344. modulePrefix = "";
  345. switch (path.parent.type) {
  346. case "Program":
  347. var insertAfterPath = path;
  348. var programPath = path.parentPath;
  349. break;
  350. case "TSModuleBlock":
  351. insertAfterPath = path;
  352. programPath = insertAfterPath.parentPath.parentPath;
  353. break;
  354. case "ExportNamedDeclaration":
  355. insertAfterPath = path.parentPath;
  356. programPath = insertAfterPath.parentPath;
  357. break;
  358. case "ExportDefaultDeclaration":
  359. insertAfterPath = path.parentPath;
  360. programPath = insertAfterPath.parentPath;
  361. break;
  362. default:
  363. return;
  364. }
  365. if (
  366. "TSModuleBlock" === path.parent.type ||
  367. "ExportNamedDeclaration" === path.parent.type
  368. )
  369. for (; "Program" !== programPath.type; ) {
  370. if ("TSModuleDeclaration" === programPath.type) {
  371. if (
  372. "Program" !== programPath.parentPath.type &&
  373. "ExportNamedDeclaration" !== programPath.parentPath.type
  374. )
  375. return;
  376. modulePrefix = programPath.node.id.name + "$" + modulePrefix;
  377. }
  378. programPath = programPath.parentPath;
  379. }
  380. var id = node.id;
  381. null !== id &&
  382. ((id = id.name),
  383. isComponentishName(id) &&
  384. !seenForRegistration.has(node) &&
  385. (seenForRegistration.add(node),
  386. findInnerComponents(
  387. modulePrefix + id,
  388. path,
  389. function (persistentID, targetExpr) {
  390. persistentID = createRegistration(
  391. programPath,
  392. persistentID
  393. );
  394. insertAfterPath.insertAfter(
  395. t.expressionStatement(
  396. t.assignmentExpression("=", persistentID, targetExpr)
  397. )
  398. );
  399. }
  400. )));
  401. },
  402. exit: function (path) {
  403. var node = path.node,
  404. id = node.id;
  405. if (null !== id) {
  406. var signature = getHookCallsSignature(node);
  407. if (null !== signature && !seenForSignature.has(node)) {
  408. seenForSignature.add(node);
  409. node = path.scope.generateUidIdentifier("_s");
  410. path.scope.parent.push({
  411. id: node,
  412. init: t.callExpression(refreshSig, [])
  413. });
  414. path
  415. .get("body")
  416. .unshiftContainer(
  417. "body",
  418. t.expressionStatement(t.callExpression(node, []))
  419. );
  420. var insertAfterPath = null;
  421. path.find(function (p) {
  422. if (p.parentPath.isBlock()) return (insertAfterPath = p), !0;
  423. });
  424. null !== insertAfterPath &&
  425. insertAfterPath.insertAfter(
  426. t.expressionStatement(
  427. t.callExpression(
  428. node,
  429. createArgumentsForSignature(
  430. id,
  431. signature,
  432. insertAfterPath.scope
  433. )
  434. )
  435. )
  436. );
  437. }
  438. }
  439. }
  440. },
  441. "ArrowFunctionExpression|FunctionExpression": {
  442. exit: function (path) {
  443. var node = path.node,
  444. signature = getHookCallsSignature(node);
  445. if (null !== signature && !seenForSignature.has(node)) {
  446. seenForSignature.add(node);
  447. var sigCallID = path.scope.generateUidIdentifier("_s");
  448. path.scope.parent.push({
  449. id: sigCallID,
  450. init: t.callExpression(refreshSig, [])
  451. });
  452. "BlockStatement" !== path.node.body.type &&
  453. (path.node.body = t.blockStatement([
  454. t.returnStatement(path.node.body)
  455. ]));
  456. path
  457. .get("body")
  458. .unshiftContainer(
  459. "body",
  460. t.expressionStatement(t.callExpression(sigCallID, []))
  461. );
  462. if ("VariableDeclarator" === path.parent.type) {
  463. var insertAfterPath = null;
  464. path.find(function (p) {
  465. if (p.parentPath.isBlock()) return (insertAfterPath = p), !0;
  466. });
  467. null !== insertAfterPath &&
  468. insertAfterPath.insertAfter(
  469. t.expressionStatement(
  470. t.callExpression(
  471. sigCallID,
  472. createArgumentsForSignature(
  473. path.parent.id,
  474. signature,
  475. insertAfterPath.scope
  476. )
  477. )
  478. )
  479. );
  480. } else
  481. [path]
  482. .concat(findHOCCallPathsAbove(path))
  483. .forEach(function (p) {
  484. p.replaceWith(
  485. t.callExpression(
  486. sigCallID,
  487. createArgumentsForSignature(p.node, signature, p.scope)
  488. )
  489. );
  490. });
  491. }
  492. }
  493. },
  494. VariableDeclaration: function (path) {
  495. var node = path.node,
  496. modulePrefix = "";
  497. switch (path.parent.type) {
  498. case "Program":
  499. var insertAfterPath = path;
  500. var programPath = path.parentPath;
  501. break;
  502. case "TSModuleBlock":
  503. insertAfterPath = path;
  504. programPath = insertAfterPath.parentPath.parentPath;
  505. break;
  506. case "ExportNamedDeclaration":
  507. insertAfterPath = path.parentPath;
  508. programPath = insertAfterPath.parentPath;
  509. break;
  510. case "ExportDefaultDeclaration":
  511. insertAfterPath = path.parentPath;
  512. programPath = insertAfterPath.parentPath;
  513. break;
  514. default:
  515. return;
  516. }
  517. if (
  518. "TSModuleBlock" === path.parent.type ||
  519. "ExportNamedDeclaration" === path.parent.type
  520. )
  521. for (; "Program" !== programPath.type; ) {
  522. if ("TSModuleDeclaration" === programPath.type) {
  523. if (
  524. "Program" !== programPath.parentPath.type &&
  525. "ExportNamedDeclaration" !== programPath.parentPath.type
  526. )
  527. return;
  528. modulePrefix = programPath.node.id.name + "$" + modulePrefix;
  529. }
  530. programPath = programPath.parentPath;
  531. }
  532. if (
  533. !seenForRegistration.has(node) &&
  534. (seenForRegistration.add(node),
  535. (path = path.get("declarations")),
  536. 1 === path.length)
  537. ) {
  538. var declPath = path[0];
  539. findInnerComponents(
  540. modulePrefix + declPath.node.id.name,
  541. declPath,
  542. function (persistentID, targetExpr, targetPath) {
  543. null !== targetPath &&
  544. ((persistentID = createRegistration(
  545. programPath,
  546. persistentID
  547. )),
  548. "VariableDeclarator" === targetPath.parent.type
  549. ? insertAfterPath.insertAfter(
  550. t.expressionStatement(
  551. t.assignmentExpression(
  552. "=",
  553. persistentID,
  554. declPath.node.id
  555. )
  556. )
  557. )
  558. : targetPath.replaceWith(
  559. t.assignmentExpression("=", persistentID, targetExpr)
  560. ));
  561. }
  562. );
  563. }
  564. },
  565. Program: {
  566. enter: function (path) {
  567. path.traverse(HookCallsVisitor);
  568. },
  569. exit: function (path) {
  570. var registrations = registrationsByProgramPath.get(path);
  571. if (void 0 !== registrations) {
  572. var node = path.node;
  573. if (!seenForOutro.has(node)) {
  574. seenForOutro.add(node);
  575. registrationsByProgramPath.delete(path);
  576. var declarators = [];
  577. path.pushContainer(
  578. "body",
  579. t.variableDeclaration("var", declarators)
  580. );
  581. registrations.forEach(function (_ref) {
  582. var handle = _ref.handle;
  583. path.pushContainer(
  584. "body",
  585. t.expressionStatement(
  586. t.callExpression(refreshReg, [
  587. handle,
  588. t.stringLiteral(_ref.persistentID)
  589. ])
  590. )
  591. );
  592. declarators.push(t.variableDeclarator(handle));
  593. });
  594. }
  595. }
  596. }
  597. }
  598. }
  599. };
  600. });