{"version":3,"sources":["../../../src/server/app-render/encryption.ts"],"sourcesContent":["/* eslint-disable import/no-extraneous-dependencies */\nimport 'server-only'\n\n/* eslint-disable import/no-extraneous-dependencies */\nimport { renderToReadableStream } from 'react-server-dom-webpack/server'\n/* eslint-disable import/no-extraneous-dependencies */\nimport { createFromReadableStream } from 'react-server-dom-webpack/client'\n\nimport { streamToString } from '../stream-utils/node-web-streams-helper'\nimport {\n  arrayBufferToString,\n  decrypt,\n  encrypt,\n  getActionEncryptionKey,\n  stringToUint8Array,\n} from './encryption-utils'\nimport {\n  getClientReferenceManifest,\n  getServerModuleMap,\n} from './manifests-singleton'\nimport {\n  getCacheSignal,\n  getResumeDataCache,\n  workUnitAsyncStorage,\n} from './work-unit-async-storage.external'\nimport { createHangingInputAbortSignal } from './dynamic-rendering'\nimport React from 'react'\n\nconst isEdgeRuntime = process.env.NEXT_RUNTIME === 'edge'\n\nconst textEncoder = new TextEncoder()\nconst textDecoder = new TextDecoder()\n\nconst filterStackFrame =\n  process.env.NODE_ENV !== 'production'\n    ? (require('../lib/source-maps') as typeof import('../lib/source-maps'))\n        .filterStackFrameDEV\n    : undefined\nconst findSourceMapURL =\n  process.env.NODE_ENV !== 'production'\n    ? (require('../lib/source-maps') as typeof import('../lib/source-maps'))\n        .findSourceMapURLDEV\n    : undefined\n\n/**\n * Decrypt the serialized string with the action id as the salt.\n */\nasync function decodeActionBoundArg(actionId: string, arg: string) {\n  const key = await getActionEncryptionKey()\n  if (typeof key === 'undefined') {\n    throw new Error(\n      `Missing encryption key for Server Action. This is a bug in Next.js`\n    )\n  }\n\n  // Get the iv (16 bytes) and the payload from the arg.\n  const originalPayload = atob(arg)\n  const ivValue = originalPayload.slice(0, 16)\n  const payload = originalPayload.slice(16)\n\n  const decrypted = textDecoder.decode(\n    await decrypt(key, stringToUint8Array(ivValue), stringToUint8Array(payload))\n  )\n\n  if (!decrypted.startsWith(actionId)) {\n    throw new Error('Invalid Server Action payload: failed to decrypt.')\n  }\n\n  return decrypted.slice(actionId.length)\n}\n\n/**\n * Encrypt the serialized string with the action id as the salt. Add a prefix to\n * later ensure that the payload is correctly decrypted, similar to a checksum.\n */\nasync function encodeActionBoundArg(actionId: string, arg: string) {\n  const key = await getActionEncryptionKey()\n  if (key === undefined) {\n    throw new Error(\n      `Missing encryption key for Server Action. This is a bug in Next.js`\n    )\n  }\n\n  // Get 16 random bytes as iv.\n  const randomBytes = new Uint8Array(16)\n  workUnitAsyncStorage.exit(() => crypto.getRandomValues(randomBytes))\n  const ivValue = arrayBufferToString(randomBytes.buffer)\n\n  const encrypted = await encrypt(\n    key,\n    randomBytes,\n    textEncoder.encode(actionId + arg)\n  )\n\n  return btoa(ivValue + arrayBufferToString(encrypted))\n}\n\nenum ReadStatus {\n  Ready,\n  Pending,\n  Complete,\n}\n\n// Encrypts the action's bound args into a string. For the same combination of\n// actionId and args the same cached promise is returned. This ensures reference\n// equality for returned objects from \"use cache\" functions when they're invoked\n// multiple times within one render pass using the same bound args.\nexport const encryptActionBoundArgs = React.cache(\n  async function encryptActionBoundArgs(actionId: string, ...args: any[]) {\n    const workUnitStore = workUnitAsyncStorage.getStore()\n    const cacheSignal = workUnitStore\n      ? getCacheSignal(workUnitStore)\n      : undefined\n\n    const { clientModules } = getClientReferenceManifest()\n\n    // Create an error before any asynchronous calls, to capture the original\n    // call stack in case we need it when the serialization errors.\n    const error = new Error()\n    Error.captureStackTrace(error, encryptActionBoundArgs)\n\n    let didCatchError = false\n\n    const hangingInputAbortSignal = workUnitStore\n      ? createHangingInputAbortSignal(workUnitStore)\n      : undefined\n\n    let readStatus = ReadStatus.Ready\n    function startReadOnce() {\n      if (readStatus === ReadStatus.Ready) {\n        readStatus = ReadStatus.Pending\n        cacheSignal?.beginRead()\n      }\n    }\n\n    function endReadIfStarted() {\n      if (readStatus === ReadStatus.Pending) {\n        cacheSignal?.endRead()\n      }\n      readStatus = ReadStatus.Complete\n    }\n\n    // streamToString might take longer than a microtask to resolve and then other things\n    // waiting on the cache signal might not realize there is another cache to fill so if\n    // we are no longer waiting on the bound args serialization via the hangingInputAbortSignal\n    // we should eagerly start the cache read to prevent other readers of the cache signal from\n    // missing this cache fill. We use a idempotent function to only start reading once because\n    // it's also possible that streamToString finishes before the hangingInputAbortSignal aborts.\n    if (hangingInputAbortSignal && cacheSignal) {\n      hangingInputAbortSignal.addEventListener('abort', startReadOnce, {\n        once: true,\n      })\n    }\n\n    const resumeDataCache = workUnitStore\n      ? getResumeDataCache(workUnitStore)\n      : null\n\n    // Using Flight to serialize the args into a string.\n    const serialized = await streamToString(\n      renderToReadableStream(args, clientModules, {\n        filterStackFrame,\n        signal: hangingInputAbortSignal,\n        debugChannel:\n          // In Cache Components, we want to cache the encrypted result,\n          // and we use the unencrypted bound args as a cache key.\n          // In order to do that we need to strip debug info, because it\n          // contains timing information and thus changes each time we serialize the args.\n          // We can do this by piping debug info into a debug channel that throws it away.\n          //\n          // Note that this can result in dangling debug info references when we decode the bound args,\n          // but React ignores those as long as no debug channel is passed on the decode side, so it's fine:\n          // https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/react-client/src/ReactFlightClient.js#L1711-L1729\n          // https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/react-client/src/ReactFlightClient.js#L4005-L4025\n          process.env.NODE_ENV === 'development' && resumeDataCache\n            ? {\n                writable: new WritableStream(),\n              }\n            : undefined,\n        onError(err) {\n          if (hangingInputAbortSignal?.aborted) {\n            return\n          }\n\n          // We're only reporting one error at a time, starting with the first.\n          if (didCatchError) {\n            return\n          }\n\n          didCatchError = true\n\n          // Use the original error message together with the previously created\n          // stack, because err.stack is a useless Flight Server call stack.\n          error.message = err instanceof Error ? err.message : String(err)\n        },\n      }),\n      // We pass the abort signal to `streamToString` so that no chunks are\n      // included that are emitted after the signal was already aborted. This\n      // ensures that we can encode hanging promises.\n      hangingInputAbortSignal\n    )\n\n    if (didCatchError) {\n      if (process.env.NODE_ENV === 'development') {\n        // Logging the error is needed for server functions that are passed to the\n        // client where the decryption is not done during rendering. Console\n        // replaying allows us to still show the error dev overlay in this case.\n        console.error(error)\n      }\n\n      endReadIfStarted()\n      throw error\n    }\n\n    if (!workUnitStore) {\n      // We don't need to call cacheSignal.endRead here because we can't have a cacheSignal\n      // if we do not have a workUnitStore.\n      return encodeActionBoundArg(actionId, serialized)\n    }\n\n    startReadOnce()\n\n    const cacheKey = actionId + serialized\n\n    const cachedEncrypted = resumeDataCache?.encryptedBoundArgs.get(cacheKey)\n\n    if (cachedEncrypted) {\n      return cachedEncrypted\n    }\n\n    const encrypted = await encodeActionBoundArg(actionId, serialized)\n\n    endReadIfStarted()\n    if (resumeDataCache?.mutable) {\n      resumeDataCache.encryptedBoundArgs.set(cacheKey, encrypted)\n    }\n\n    return encrypted\n  }\n)\n\n// Decrypts the action's bound args from the encrypted string.\nexport async function decryptActionBoundArgs(\n  actionId: string,\n  encryptedPromise: Promise<string>\n) {\n  const encrypted = await encryptedPromise\n  const workUnitStore = workUnitAsyncStorage.getStore()\n\n  let decrypted: string | undefined\n\n  if (workUnitStore) {\n    const cacheSignal = getCacheSignal(workUnitStore)\n    const resumeDataCache = getResumeDataCache(workUnitStore)\n\n    decrypted = resumeDataCache?.decryptedBoundArgs.get(encrypted)\n\n    if (!decrypted) {\n      cacheSignal?.beginRead()\n      decrypted = await decodeActionBoundArg(actionId, encrypted)\n      cacheSignal?.endRead()\n      if (resumeDataCache?.mutable) {\n        resumeDataCache.decryptedBoundArgs.set(encrypted, decrypted)\n      }\n    }\n  } else {\n    decrypted = await decodeActionBoundArg(actionId, encrypted)\n  }\n\n  const { edgeRscModuleMapping, rscModuleMapping } =\n    getClientReferenceManifest()\n\n  // Using Flight to deserialize the args from the string.\n  const deserialized = await createFromReadableStream(\n    new ReadableStream({\n      start(controller) {\n        controller.enqueue(textEncoder.encode(decrypted))\n\n        switch (workUnitStore?.type) {\n          case 'prerender':\n          case 'prerender-runtime':\n            // Explicitly don't close the stream here (until prerendering is\n            // complete) so that hanging promises are not rejected.\n            if (workUnitStore.renderSignal.aborted) {\n              controller.close()\n            } else {\n              workUnitStore.renderSignal.addEventListener(\n                'abort',\n                () => controller.close(),\n                { once: true }\n              )\n            }\n            break\n          case 'prerender-client':\n          case 'validation-client':\n          case 'prerender-ppr':\n          case 'prerender-legacy':\n          case 'request':\n          case 'cache':\n          case 'private-cache':\n          case 'unstable-cache':\n          case 'generate-static-params':\n          case undefined:\n            return controller.close()\n          default:\n            workUnitStore satisfies never\n        }\n      },\n    }),\n    {\n      findSourceMapURL,\n      // NOTE: When we serialized the bound args, we may have used a dummy debug channel to strip debug info.\n      // In that case, it's important that we also *don't* pass a debug channel here, because that will make\n      // the Flight Client ignore the dangling references:\n      // https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/react-client/src/ReactFlightClient.js#L1711-L1729\n      // https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/react-client/src/ReactFlightClient.js#L4005-L4025\n      debugChannel: undefined,\n      serverConsumerManifest: {\n        // moduleLoading must be null because we don't want to trigger preloads of ClientReferences\n        // to be added to the current execution. Instead, we'll wait for any ClientReference\n        // to be emitted which themselves will handle the preloading.\n        moduleLoading: null,\n        moduleMap: isEdgeRuntime ? edgeRscModuleMapping : rscModuleMapping,\n        serverModuleMap: getServerModuleMap(),\n      },\n    }\n  )\n\n  return deserialized\n}\n"],"names":["decryptActionBoundArgs","encryptActionBoundArgs","isEdgeRuntime","process","env","NEXT_RUNTIME","textEncoder","TextEncoder","textDecoder","TextDecoder","filterStackFrame","NODE_ENV","require","filterStackFrameDEV","undefined","findSourceMapURL","findSourceMapURLDEV","decodeActionBoundArg","actionId","arg","key","getActionEncryptionKey","Error","originalPayload","atob","ivValue","slice","payload","decrypted","decode","decrypt","stringToUint8Array","startsWith","length","encodeActionBoundArg","randomBytes","Uint8Array","workUnitAsyncStorage","exit","crypto","getRandomValues","arrayBufferToString","buffer","encrypted","encrypt","encode","btoa","ReadStatus","React","cache","args","workUnitStore","getStore","cacheSignal","getCacheSignal","clientModules","getClientReferenceManifest","error","captureStackTrace","didCatchError","hangingInputAbortSignal","createHangingInputAbortSignal","readStatus","startReadOnce","beginRead","endReadIfStarted","endRead","addEventListener","once","resumeDataCache","getResumeDataCache","serialized","streamToString","renderToReadableStream","signal","debugChannel","writable","WritableStream","onError","err","aborted","message","String","console","cacheKey","cachedEncrypted","encryptedBoundArgs","get","mutable","set","encryptedPromise","decryptedBoundArgs","edgeRscModuleMapping","rscModuleMapping","deserialized","createFromReadableStream","ReadableStream","start","controller","enqueue","type","renderSignal","close","serverConsumerManifest","moduleLoading","moduleMap","serverModuleMap","getServerModuleMap"],"mappings":"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","ignoreList":[0]}