{"version":3,"sources":["../../../../../src/client/dev/hot-reloader/app/web-socket.ts"],"sourcesContent":["import { useContext, useEffect } from 'react'\nimport { GlobalLayoutRouterContext } from '../../../../shared/lib/app-router-context.shared-runtime'\nimport { getSocketUrl } from '../get-socket-url'\nimport {\n  HMR_MESSAGE_SENT_TO_BROWSER,\n  type HmrMessageSentToBrowser,\n  type TurbopackMessageSentToBrowser,\n} from '../../../../server/dev/hot-reloader-types'\nimport { reportInvalidHmrMessage } from '../shared'\nimport {\n  performFullReload,\n  processMessage,\n  type StaticIndicatorState,\n} from './hot-reloader-app'\nimport { logQueue } from '../../../../next-devtools/userspace/app/forward-logs'\nimport { InvariantError } from '../../../../shared/lib/invariant-error'\nimport { WEB_SOCKET_MAX_RECONNECTIONS } from '../../../../lib/constants'\n\nlet reconnections = 0\nlet reloading = false\nlet serverSessionId: number | null = null\nlet mostRecentCompilationHash: string | null = null\n\nexport function createWebSocket(\n  assetPrefix: string,\n  staticIndicatorState: StaticIndicatorState\n) {\n  if (!self.__next_r) {\n    throw new InvariantError(\n      `Expected a request ID to be defined for the document via self.__next_r.`\n    )\n  }\n\n  let webSocket: WebSocket\n  let timer: ReturnType<typeof setTimeout>\n\n  const sendMessage = (data: string) => {\n    if (webSocket && webSocket.readyState === webSocket.OPEN) {\n      webSocket.send(data)\n    }\n  }\n\n  const processTurbopackMessage = createProcessTurbopackMessage(sendMessage)\n\n  function init() {\n    if (webSocket) {\n      webSocket.close()\n    }\n\n    const newWebSocket = new window.WebSocket(\n      `${getSocketUrl(assetPrefix)}/_next/webpack-hmr?id=${self.__next_r}`\n    )\n\n    newWebSocket.binaryType = 'arraybuffer'\n\n    function handleOnline() {\n      logQueue.onSocketReady(newWebSocket)\n\n      reconnections = 0\n      window.console.log('[HMR] connected')\n    }\n\n    function handleMessage(event: MessageEvent) {\n      // While the page is reloading, don't respond to any more messages.\n      if (reloading) {\n        return\n      }\n\n      try {\n        const message: HmrMessageSentToBrowser =\n          event.data instanceof ArrayBuffer\n            ? parseBinaryMessage(event.data)\n            : JSON.parse(event.data)\n\n        // Check for server restart in Turbopack mode\n        if (message.type === HMR_MESSAGE_SENT_TO_BROWSER.TURBOPACK_CONNECTED) {\n          if (\n            serverSessionId !== null &&\n            serverSessionId !== message.data.sessionId\n          ) {\n            // Either the server's session id has changed and it's a new server, or\n            // it's been too long since we disconnected and we should reload the page.\n            window.location.reload()\n            reloading = true\n            return\n          }\n          serverSessionId = message.data.sessionId\n        }\n\n        // Track webpack compilation hash for server restart detection\n        if (\n          message.type === HMR_MESSAGE_SENT_TO_BROWSER.SYNC &&\n          'hash' in message\n        ) {\n          // If we had previously reconnected and the hash changed, the server may have restarted\n          if (\n            mostRecentCompilationHash !== null &&\n            mostRecentCompilationHash !== message.hash\n          ) {\n            window.location.reload()\n            reloading = true\n            return\n          }\n          mostRecentCompilationHash = message.hash\n        }\n\n        processMessage(\n          message,\n          sendMessage,\n          processTurbopackMessage,\n          staticIndicatorState\n        )\n      } catch (err: unknown) {\n        reportInvalidHmrMessage(event, err)\n      }\n    }\n\n    function handleDisconnect() {\n      newWebSocket.onerror = null\n      newWebSocket.onclose = null\n      newWebSocket.close()\n      reconnections++\n\n      // After 25 reconnects we'll want to reload the page as it indicates the dev server is no longer running.\n      if (reconnections > WEB_SOCKET_MAX_RECONNECTIONS) {\n        reloading = true\n        window.location.reload()\n        return\n      }\n\n      clearTimeout(timer)\n      // Try again after 5 seconds\n      timer = setTimeout(init, reconnections > 5 ? 5000 : 1000)\n    }\n\n    newWebSocket.onopen = handleOnline\n    newWebSocket.onerror = handleDisconnect\n    newWebSocket.onclose = handleDisconnect\n    newWebSocket.onmessage = handleMessage\n\n    webSocket = newWebSocket\n    return newWebSocket\n  }\n\n  return init()\n}\n\nexport function createProcessTurbopackMessage(\n  sendMessage: (data: string) => void\n): (msg: TurbopackMessageSentToBrowser) => void {\n  if (!process.env.TURBOPACK) {\n    return () => {}\n  }\n\n  let queue: TurbopackMessageSentToBrowser[] = []\n  let callback: ((msg: TurbopackMessageSentToBrowser) => void) | undefined\n\n  const processTurbopackMessage = (msg: TurbopackMessageSentToBrowser) => {\n    if (callback) {\n      callback(msg)\n    } else {\n      queue.push(msg)\n    }\n  }\n\n  import(\n    // @ts-expect-error requires \"moduleResolution\": \"node16\" in tsconfig.json and not .ts extension\n    '@vercel/turbopack-ecmascript-runtime/browser/dev/hmr-client/hmr-client.ts'\n  ).then(({ connect }) => {\n    connect({\n      addMessageListener(cb: (msg: TurbopackMessageSentToBrowser) => void) {\n        callback = cb\n\n        // Replay all Turbopack messages before we were able to establish the HMR client.\n        for (const msg of queue) {\n          cb(msg)\n        }\n        queue.length = 0\n      },\n      sendMessage,\n      onUpdateError: (err: unknown) => performFullReload(err, sendMessage),\n    })\n  })\n\n  return processTurbopackMessage\n}\n\nexport function useWebSocketPing(webSocket: WebSocket | undefined) {\n  const { tree } = useContext(GlobalLayoutRouterContext)\n\n  useEffect(() => {\n    if (!webSocket) {\n      throw new InvariantError('Expected webSocket to be defined in dev mode.')\n    }\n\n    // Never send pings when using Turbopack as it's not used.\n    // Pings were originally used to keep track of active routes in on-demand-entries with webpack.\n    if (process.env.TURBOPACK) {\n      return\n    }\n\n    // Taken from on-demand-entries-client.js\n    const interval = setInterval(() => {\n      if (webSocket.readyState === webSocket.OPEN) {\n        webSocket.send(\n          JSON.stringify({\n            event: 'ping',\n            tree,\n            appDirRoute: true,\n          })\n        )\n      }\n    }, 2500)\n    return () => clearInterval(interval)\n  }, [tree, webSocket])\n}\n\nconst textDecoder = new TextDecoder()\n\nfunction parseBinaryMessage(data: ArrayBuffer): HmrMessageSentToBrowser {\n  assertByteLength(data, 1)\n  const view = new DataView(data)\n  const messageType = view.getUint8(0)\n\n  switch (messageType) {\n    case HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER: {\n      const serializedErrors = new Uint8Array(data, 1)\n\n      return {\n        type: HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER,\n        serializedErrors,\n      }\n    }\n    case HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK: {\n      assertByteLength(data, 2)\n      const requestIdLength = view.getUint8(1)\n      assertByteLength(data, 2 + requestIdLength)\n\n      const requestId = textDecoder.decode(\n        new Uint8Array(data, 2, requestIdLength)\n      )\n\n      const chunk =\n        data.byteLength > 2 + requestIdLength\n          ? new Uint8Array(data, 2 + requestIdLength)\n          : null\n\n      return {\n        type: HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK,\n        requestId,\n        chunk,\n      }\n    }\n    default: {\n      throw new InvariantError(\n        `Invalid binary HMR message of type ${messageType}`\n      )\n    }\n  }\n}\n\nfunction assertByteLength(data: ArrayBuffer, expectedLength: number) {\n  if (data.byteLength < expectedLength) {\n    throw new InvariantError(\n      `Invalid binary HMR message: insufficient data (expected ${expectedLength} bytes, got ${data.byteLength})`\n    )\n  }\n}\n"],"names":["createProcessTurbopackMessage","createWebSocket","useWebSocketPing","reconnections","reloading","serverSessionId","mostRecentCompilationHash","assetPrefix","staticIndicatorState","self","__next_r","InvariantError","webSocket","timer","sendMessage","data","readyState","OPEN","send","processTurbopackMessage","init","close","newWebSocket","window","WebSocket","getSocketUrl","binaryType","handleOnline","logQueue","onSocketReady","console","log","handleMessage","event","message","ArrayBuffer","parseBinaryMessage","JSON","parse","type","HMR_MESSAGE_SENT_TO_BROWSER","TURBOPACK_CONNECTED","sessionId","location","reload","SYNC","hash","processMessage","err","reportInvalidHmrMessage","handleDisconnect","onerror","onclose","WEB_SOCKET_MAX_RECONNECTIONS","clearTimeout","setTimeout","onopen","onmessage","process","env","TURBOPACK","queue","callback","msg","push","then","connect","addMessageListener","cb","length","onUpdateError","performFullReload","tree","useContext","GlobalLayoutRouterContext","useEffect","interval","setInterval","stringify","appDirRoute","clearInterval","textDecoder","TextDecoder","assertByteLength","view","DataView","messageType","getUint8","ERRORS_TO_SHOW_IN_BROWSER","serializedErrors","Uint8Array","REACT_DEBUG_CHUNK","requestIdLength","requestId","decode","chunk","byteLength","expectedLength"],"mappings":"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","ignoreList":[0]}