{"version":3,"sources":["../../../../src/client/dev/hot-reloader/turbopack-hot-reloader-common.ts"],"sourcesContent":["import type { TurbopackMessage } from '../../../server/dev/hot-reloader-types'\nimport type { Update as TurbopackUpdate } from '../../../build/swc/types'\nimport { DeferredEmit } from '../../../shared/lib/turbopack/deferred-emit'\n\ndeclare global {\n  interface Window {\n    __NEXT_HMR_TURBOPACK_REPORT_NOISY_NOOP_EVENTS: boolean | undefined\n  }\n}\n\n// How long to wait before reporting the HMR start, used to suppress irrelevant\n// `BUILDING` events. Does not impact reported latency.\nconst TURBOPACK_HMR_START_DELAY_MS = 100\n\ninterface HmrUpdate {\n  hasUpdates: boolean\n  updatedModules: Set<string>\n  startMsSinceEpoch: number\n  endMsSinceEpoch: number\n}\n\nexport class TurbopackHmr {\n  #updatedModules: Set<string>\n  #startMsSinceEpoch: number | undefined\n  #lastUpdateMsSinceEpoch: number | undefined\n  // HACK: Turbopack tends to generate a lot of irrelevant \"BUILDING\" actions,\n  // as it reports *any* compilation, including fully no-op/cached compilations\n  // and those unrelated to HMR. Fixing this would require significant\n  // architectural changes.\n  //\n  // Work around this by deferring the `[Fast Refresh] rebuilding` message by\n  // 100ms. If we get a BUILT event within that threshold and nothing has\n  // changed, just suppress the message entirely. (The dev server applies the\n  // same defer to the BUILDING HMR message itself; see `DeferredEmit` usage in\n  // hot-reloader-turbopack.ts.)\n  #deferredReportHmrStart: DeferredEmit\n  #reportedHmrStart: boolean\n\n  constructor() {\n    this.#updatedModules = new Set()\n    this.#deferredReportHmrStart = new DeferredEmit()\n    this.#reportedHmrStart = false\n  }\n\n  onBuilding() {\n    this.#lastUpdateMsSinceEpoch = undefined\n    this.#deferredReportHmrStart.cancel()\n    this.#startMsSinceEpoch = Date.now()\n\n    // report the HMR start after a short delay\n    this.#deferredReportHmrStart.schedule(\n      // debugging feature: don't defer/suppress noisy no-op HMR update messages\n      self.__NEXT_HMR_TURBOPACK_REPORT_NOISY_NOOP_EVENTS\n        ? 0\n        : TURBOPACK_HMR_START_DELAY_MS,\n      () => {\n        console.log('[Fast Refresh] rebuilding')\n        this.#reportedHmrStart = true\n      }\n    )\n  }\n\n  /** Helper for other `onEvent` methods. */\n  #onUpdate() {\n    this.#deferredReportHmrStart.flush()\n    this.#lastUpdateMsSinceEpoch = Date.now()\n  }\n\n  onTurbopackMessage(msg: TurbopackMessage) {\n    this.#onUpdate()\n    const updatedModules = extractModulesFromTurbopackMessage(msg.data)\n    for (const module of updatedModules) {\n      this.#updatedModules.add(module)\n    }\n  }\n\n  onServerComponentChanges() {\n    this.#onUpdate()\n  }\n\n  onReloadPage() {\n    this.#onUpdate()\n  }\n\n  onPageAddRemove() {\n    this.#onUpdate()\n  }\n\n  /**\n   * @returns `null` if the caller should ignore the update entirely. Returns an\n   *   object with `hasUpdates: false` if the caller should report the end of\n   *   the HMR in the browser console, but the HMR was a no-op.\n   */\n  onBuilt(): HmrUpdate | null {\n    // Check that we got *any* `TurbopackMessage`, even if\n    // `updatedModules` is empty (not everything gets recorded there).\n    //\n    // There's also a case where `onBuilt` gets called before `onBuilding`,\n    // which can happen during initial page load. Ignore that too!\n    const hasUpdates =\n      this.#lastUpdateMsSinceEpoch != null && this.#startMsSinceEpoch != null\n    if (!hasUpdates && !this.#reportedHmrStart) {\n      // suppress the update entirely\n      this.#deferredReportHmrStart.cancel()\n      return null\n    }\n    this.#deferredReportHmrStart.flush()\n\n    const result = {\n      hasUpdates,\n      updatedModules: this.#updatedModules,\n      startMsSinceEpoch: this.#startMsSinceEpoch!,\n      endMsSinceEpoch: this.#lastUpdateMsSinceEpoch ?? Date.now(),\n    }\n    this.#updatedModules = new Set()\n    this.#reportedHmrStart = false\n    return result\n  }\n}\n\nfunction extractModulesFromTurbopackMessage(\n  data: TurbopackUpdate | TurbopackUpdate[]\n): Set<string> {\n  const updatedModules: Set<string> = new Set()\n\n  const updates = Array.isArray(data) ? data : [data]\n  for (const update of updates) {\n    // TODO this won't capture changes to CSS since they don't result in a \"merged\" update\n    if (\n      update.type !== 'partial' ||\n      update.instruction.type !== 'ChunkListUpdate' ||\n      update.instruction.merged === undefined\n    ) {\n      continue\n    }\n\n    for (const mergedUpdate of update.instruction.merged) {\n      if (!mergedUpdate.entries) continue\n      for (const name of Object.keys(mergedUpdate.entries)) {\n        const res = /(.*)\\s+[([].*/.exec(name)\n        if (res === null) {\n          continue\n        }\n\n        updatedModules.add(res[1])\n      }\n    }\n  }\n\n  return updatedModules\n}\n"],"names":["TurbopackHmr","TURBOPACK_HMR_START_DELAY_MS","constructor","Set","DeferredEmit","onBuilding","undefined","cancel","Date","now","schedule","self","__NEXT_HMR_TURBOPACK_REPORT_NOISY_NOOP_EVENTS","console","log","flush","onTurbopackMessage","msg","updatedModules","extractModulesFromTurbopackMessage","data","module","add","onServerComponentChanges","onReloadPage","onPageAddRemove","onBuilt","hasUpdates","result","startMsSinceEpoch","endMsSinceEpoch","updates","Array","isArray","update","type","instruction","merged","mergedUpdate","entries","name","Object","keys","res","exec"],"mappings":"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","ignoreList":[0]}