{"version":3,"file":"webpack-adapter.cjs","names":[],"sources":["../../../../src/core/hmr/webpack-adapter.ts"],"sourcesContent":["import * as template from '@babel/template'\nimport { getHandleRouteUpdateCode } from './handle-route-update'\nimport type { Config } from '../config'\nimport type * as t from '@babel/types'\n\n/**\n * Emits HMR accept code for bundlers with webpack-compatible `module.hot`\n * semantics (classic webpack via `import.meta.webpackHot`, and Rspack).\n *\n * Unlike Vite's `hot.accept((newModule) => {...})` — where the callback receives\n * the freshly re-imported module — webpack re-executes the module factory on\n * accept, so our HMR logic must live at module top level and read the previous\n * `routeId` out of `hot.data`. `hot.dispose` stashes it for the next run, and\n * `hot.accept()` (no callback) enrolls us as a self-accepting boundary.\n *\n * Returns an array of statements so that for React we can prepend an\n * `import { performReactRefresh } from 'react-refresh/runtime'` hoisted to the\n * top of the module.\n */\nexport function createWebpackHmrStatement(\n  stableRouteOptionKeys: Array<string>,\n  opts: {\n    targetFramework: Config['target']\n    routeId?: string\n  },\n): Array<t.Statement> {\n  const handleRouteUpdateCode = getHandleRouteUpdateCode(stableRouteOptionKeys)\n  const staticRouteIdLiteral =\n    typeof opts.routeId === 'string'\n      ? JSON.stringify(opts.routeId)\n      : 'undefined'\n\n  const statements: Array<t.Statement> = []\n\n  // React-only: route modules aren't React Refresh \"boundaries\" (they export\n  // a non-component `Route`), so the bundler's react-refresh runtime won't\n  // call `performReactRefresh` for us. We kick it manually after swapping\n  // route options so newly-registered component bodies get patched into live\n  // fibers.\n  //\n  // We import `performReactRefresh` directly from `react-refresh/runtime` —\n  // the canonical public API — rather than relying on the ProvidePlugin-\n  // injected `__react_refresh_utils__` global, whose name is an internal\n  // detail of `@rspack/plugin-react-refresh`. The rspack plugin aliases\n  // `react-refresh` → its bundled runtime (getRefreshRuntimeDirPath), so this\n  // resolves to the same singleton the plugin itself uses and shares the\n  // registry React was patched against.\n  //\n  // Use the same delayed refresh style as Rspack's React Refresh runtime.\n  // Route modules and their split component chunks can arrive in separate HMR\n  // steps under CI load; a microtask can run before the split chunk registers\n  // its new component family, causing the refresh to no-op or remount.\n  //\n  // For non-React frameworks we skip this entirely.\n  const reactRefreshCall =\n    opts.targetFramework === 'react'\n      ? `\n    const tsrRefreshState = globalThis.__TSR_HMR__ ??= {}\n    try {\n      if (!tsrRefreshState.refreshScheduled) {\n        tsrRefreshState.refreshScheduled = true\n        setTimeout(() => {\n          tsrRefreshState.refreshScheduled = false\n          try { __tsr_performReactRefresh() } catch (_e) { /* noop */ }\n        }, 30)\n      }\n    } catch (_err) { /* noop */ }`\n      : ''\n\n  if (opts.targetFramework === 'react') {\n    statements.push(\n      template.statement(\n        `import { performReactRefresh as __tsr_performReactRefresh } from 'react-refresh/runtime'`,\n      )(),\n    )\n  }\n\n  statements.push(\n    template.statement(\n      `\nif (import.meta.webpackHot) {\n  const hot = import.meta.webpackHot\n  const hotData = hot.data ??= {}\n  const routeId = hotData['tsr-route-id'] ?? Route.id ?? (Route.isRoot ? '__root__' : ${staticRouteIdLiteral})\n  if (routeId) {\n    hotData['tsr-route-id'] = routeId\n  }\n  const existingRoute =\n    typeof window !== 'undefined' && routeId\n      ? window.__TSR_ROUTER__?.routesById?.[routeId]\n      : undefined\n  if (routeId && existingRoute && existingRoute !== Route) {\n    (${handleRouteUpdateCode})(routeId, Route)${reactRefreshCall}\n  }\n  hot.dispose((data) => {\n    if (routeId) {\n      data['tsr-route-id'] = routeId\n    }\n  })\n  hot.accept()\n}\n`,\n      {\n        syntacticPlaceholders: true,\n      },\n    )(),\n  )\n\n  return statements\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,0BACd,uBACA,MAIoB;CACpB,MAAM,wBAAwB,4BAAA,yBAAyB,sBAAsB;CAC7E,MAAM,uBACJ,OAAO,KAAK,YAAY,WACpB,KAAK,UAAU,KAAK,QAAQ,GAC5B;CAEN,MAAM,aAAiC,EAAE;CAsBzC,MAAM,mBACJ,KAAK,oBAAoB,UACrB;;;;;;;;;;qCAWA;AAEN,KAAI,KAAK,oBAAoB,QAC3B,YAAW,KACT,gBAAS,UACP,2FACD,EAAE,CACJ;AAGH,YAAW,KACT,gBAAS,UACP;;;;wFAIkF,qBAAqB;;;;;;;;;OAStG,sBAAsB,mBAAmB,iBAAiB;;;;;;;;;GAU3D,EACE,uBAAuB,MACxB,CACF,EAAE,CACJ;AAED,QAAO"}