{"version":3,"sources":["../../../../src/server/dev/use-cache-probe-worker.ts"],"sourcesContent":["import type { NextConfigComplete } from '../config-shared'\nimport type { AppPageModule } from '../route-modules/app-page/module'\nimport type { WorkStore } from '../app-render/work-async-storage.external'\nimport type { UseCacheProbeRequestSnapshot } from '../use-cache/use-cache-probe-globals'\n\nimport '../require-hook'\nimport '../node-environment'\n\nimport { AfterContext } from '../after/after-context'\nimport { loadComponents } from '../load-components'\nimport { setHttpClientAndAgentOptions } from '../setup-http-agent-env'\nimport { workAsyncStorage } from '../app-render/work-async-storage.external'\nimport { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external'\nimport { getServerModuleMap } from '../app-render/manifests-singleton'\nimport { createSnapshot } from '../app-render/async-local-storage'\nimport { createRequestStore } from '../async-storage/request-store'\n/* eslint-disable import/no-extraneous-dependencies */\nimport {\n  decodeReply,\n  decodeReplyFromAsyncIterable,\n  createTemporaryReferenceSet,\n} from 'react-server-dom-webpack/server'\nimport type { CacheKeyParts } from '../use-cache/use-cache-wrapper'\n/* eslint-enable import/no-extraneous-dependencies */\n\n// Round-trippable view of `encodedArguments: FormData | string` from\n// `generateCacheEntryImpl`. The flattened `encodeFormData()` string used as a\n// cache-map key isn't usable here — it's lossy and only valid for equality\n// comparisons; the worker needs to call `decodeReply` on the original\n// `encodeReply` output.\nexport type EncodedArgumentsForProbe =\n  | {\n      kind: 'string'\n      data: string\n    }\n  | {\n      kind: 'formdata'\n      // Blobs are base64-encoded so the payload survives both `worker_threads`\n      // structured clone AND the child-process JSON-only fallback transport.\n      entries: Array<\n        | [string, string]\n        | [string, { kind: 'blob'; bytes: string; type: string }]\n      >\n    }\n\nexport type ProbeMessage = {\n  distDir: string\n  page: string\n  route: string\n  id: string\n  kind: string\n  encodedArguments: EncodedArgumentsForProbe\n  buildId: string\n  deploymentId: string\n  request: UseCacheProbeRequestSnapshot\n  nextConfigSerializable: {\n    httpAgentOptions: NextConfigComplete['httpAgentOptions']\n    cacheLifeProfiles: NextConfigComplete['cacheLife']\n    useCacheTimeout: number\n    staticPageGenerationTimeout: number\n  }\n  timeoutMs: number\n}\n\nexport async function probeUseCache(msg: ProbeMessage): Promise<boolean> {\n  try {\n    setHttpClientAndAgentOptions({\n      httpAgentOptions: msg.nextConfigSerializable.httpAgentOptions,\n    })\n\n    // Populates the manifests singleton for the route via\n    // `setManifestsSingleton` inside the compiled app-page module — same\n    // mechanism a real request uses. The dev server tears the pool down\n    // whenever it invalidates its own require/manifest caches (HMR, route\n    // recompile) so the next probe lazy-spawns a worker with empty\n    // `require.cache` and `loadManifest` caches. Without that teardown, a\n    // second probe in the same worker would resolve user modules and manifests\n    // from the first probe's cached state.\n    //\n    // Narrowed to `AppPageModule` because the probe is only set up from the dev\n    // block in `generateCacheEntryImpl`, which is gated on\n    // `outerWorkUnitStore.cacheSignal` — currently only set for app pages.\n    // `'use cache'` in route handlers has no dev-mode hang protection at all\n    // today (no probe, no dev-fill timeout); when that gate is broadened, this\n    // loader will need to handle `AppRouteModule` and a different require\n    // mechanism (route handlers don't expose `__next_app__`).\n    const { ComponentMod } = await loadComponents<AppPageModule>({\n      distDir: msg.distDir,\n      page: msg.page,\n      isAppPath: true,\n      isDev: true,\n      sriEnabled: false,\n      needsManifestsForLegacyReasons: true,\n    })\n\n    // Resolve the wrapped `'use cache'` function by its server reference\n    // id. Same path `action-handler.ts` takes for server actions: server\n    // module map → bundler module id → `__next_app__.require` → exported\n    // function keyed by the action id.\n    const serverModuleMap = getServerModuleMap()\n    const entry = serverModuleMap[msg.id]\n    if (!entry) {\n      return false\n    }\n\n    const actionMod = (await ComponentMod.__next_app__.require(\n      entry.id\n    )) as Record<string, (...args: unknown[]) => Promise<unknown>>\n    const wrappedFn = actionMod[msg.id]\n    if (typeof wrappedFn !== 'function') {\n      return false\n    }\n\n    // Decode the args with the worker's own server module map. See the\n    // `EncodedArgumentsForProbe` comment for why we don't use the cache-map key\n    // string here.\n    const temporaryReferences = createTemporaryReferenceSet()\n    let decoded: CacheKeyParts\n    if (msg.encodedArguments.kind === 'string') {\n      decoded = await decodeReply<CacheKeyParts>(\n        msg.encodedArguments.data,\n        serverModuleMap,\n        {\n          temporaryReferences,\n        }\n      )\n    } else {\n      const entries = msg.encodedArguments.entries.map<[string, string | File]>(\n        ([key, value]) => {\n          if (typeof value === 'string') {\n            return [key, value]\n          }\n          const bytes = Buffer.from(value.bytes, 'base64')\n          return [key, new File([bytes], '', { type: value.type })]\n        }\n      )\n      decoded = await decodeReplyFromAsyncIterable<CacheKeyParts>(\n        {\n          async *[Symbol.asyncIterator]() {\n            for (const pair of entries) {\n              yield pair\n            }\n          },\n        },\n        serverModuleMap,\n        { temporaryReferences }\n      )\n    }\n\n    const args = decoded[2]\n    const workStore: WorkStore = buildProbeWorkStore(msg)\n\n    // The outer store is `'request'`-typed and built from the forwarded\n    // snapshot so the cache body sees the same `headers` / `cookies` /\n    // `draftMode` it would in a real fill. `cacheSignal` defaults to undefined,\n    // which disables the dev-timeout/probe block in `generateCacheEntryImpl` —\n    // the primary guard against a probe inside the worker spawning another\n    // probe.\n    const workUnitStore = createRequestStore({\n      phase: 'render',\n      headers: new Headers(msg.request.headers),\n      onUpdateCookies: undefined,\n      url: { pathname: msg.request.urlPathname, search: msg.request.urlSearch },\n      rootParams: msg.request.rootParams,\n      implicitTags: { tags: [], expirationsByCacheKind: new Map() },\n      resumeDataCache: null,\n      previewProps: undefined,\n      isHmrRefresh: msg.request.isHmrRefresh,\n      serverComponentsHmrCache: undefined,\n      hmrRefreshHash: msg.request.hmrRefreshHash,\n      fallbackParams: null,\n    })\n\n    await workAsyncStorage.run(workStore, () =>\n      workUnitAsyncStorage.run(workUnitStore, wrappedFn.bind(null, ...args))\n    )\n\n    return true\n  } catch {\n    // Any error along the way — module resolution, decode, the actual run —\n    // collapses to \"the probe didn't complete in isolation,\" so the main thread\n    // won't false-positive a deadlock.\n    return false\n  }\n}\n\nfunction buildProbeWorkStore(msg: ProbeMessage): WorkStore {\n  // `after()` callbacks would duplicate the real fill's side effects — the\n  // probe is a throwaway re-execution, not a second request. Same shape as the\n  // validation-render `AfterContext` in `app-render.tsx`.\n  const afterContext = new AfterContext({\n    waitUntil(promise) {\n      promise.catch(() => {})\n    },\n    onClose() {},\n    onTaskError() {},\n  })\n\n  return {\n    isStaticGeneration: false,\n    page: msg.page,\n    route: msg.route,\n    useCacheProbeMode: { timeoutMs: msg.timeoutMs },\n    isDraftMode: msg.request.isDraftMode,\n    useCacheTimeout: msg.nextConfigSerializable.useCacheTimeout,\n    staticPageGenerationTimeout:\n      msg.nextConfigSerializable.staticPageGenerationTimeout,\n    cacheLifeProfiles: msg.nextConfigSerializable.cacheLifeProfiles,\n    buildId: msg.buildId,\n    deploymentId: msg.deploymentId,\n    requestStartTime: msg.request.requestStartTime,\n    // Empty values for cache-handler / RDC bookkeeping. The `useCacheProbeMode`\n    // branch in `cache()` returns before any code that reads or writes these\n    // fields, so the values can never be observed.\n    previouslyRevalidatedTags: [],\n    refreshTagsByCacheKind: new Map(),\n    runInCleanSnapshot: createSnapshot(),\n    shouldTrackFetchMetrics: false,\n    reactServerErrorsByDigest: new Map(),\n    afterContext,\n    cacheComponentsEnabled: true,\n    // In the probe the validation level is irrelevant because we do not perform validation\n    // in this context.\n    validationLevel: 'warning',\n  }\n}\n"],"names":["AfterContext","loadComponents","setHttpClientAndAgentOptions","workAsyncStorage","workUnitAsyncStorage","getServerModuleMap","createSnapshot","createRequestStore","decodeReply","decodeReplyFromAsyncIterable","createTemporaryReferenceSet","probeUseCache","msg","httpAgentOptions","nextConfigSerializable","ComponentMod","distDir","page","isAppPath","isDev","sriEnabled","needsManifestsForLegacyReasons","serverModuleMap","entry","id","actionMod","__next_app__","require","wrappedFn","temporaryReferences","decoded","encodedArguments","kind","data","entries","map","key","value","bytes","Buffer","from","File","type","Symbol","asyncIterator","pair","args","workStore","buildProbeWorkStore","workUnitStore","phase","headers","Headers","request","onUpdateCookies","undefined","url","pathname","urlPathname","search","urlSearch","rootParams","implicitTags","tags","expirationsByCacheKind","Map","resumeDataCache","previewProps","isHmrRefresh","serverComponentsHmrCache","hmrRefreshHash","fallbackParams","run","bind","afterContext","waitUntil","promise","catch","onClose","onTaskError","isStaticGeneration","route","useCacheProbeMode","timeoutMs","isDraftMode","useCacheTimeout","staticPageGenerationTimeout","cacheLifeProfiles","buildId","deploymentId","requestStartTime","previouslyRevalidatedTags","refreshTagsByCacheKind","runInCleanSnapshot","shouldTrackFetchMetrics","reactServerErrorsByDigest","cacheComponentsEnabled","validationLevel"],"mappings":"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","ignoreList":[0]}