{"version":3,"sources":["../../../src/renderer/react/server.ts","../../../src/client/isolated-boundary.ts"],"sourcesContent":["import React from \"react\";\nimport {\n  renderToPipeableStream as reactRenderToPipeableStream,\n  renderToString as reactRenderToString,\n} from \"react-dom/server\";\nimport { wrapFarmIsolatedClientGraph } from \"../../client/isolated-boundary\";\n\nexport class ErrorBoundary extends React.Component<\n  {\n    Fallback: React.ComponentType<any>;\n    fallbackProps: Record<string, any>;\n    children: React.ReactNode;\n  },\n  { hasError: boolean; error: unknown }\n> {\n  constructor(props: any) {\n    super(props);\n    this.state = { hasError: false, error: null };\n  }\n\n  static getDerivedStateFromError(error: unknown) {\n    return { hasError: true, error };\n  }\n\n  render() {\n    if (this.state.hasError) {\n      const Fallback = this.props.Fallback;\n      return React.createElement(Fallback, {\n        ...this.props.fallbackProps,\n        error: this.state.error,\n        reset: () => this.setState({ hasError: false, error: null }),\n      });\n    }\n    return this.props.children as React.ReactElement;\n  }\n}\n\nexport const name = \"react\";\nexport const capabilities = {\n  streaming: { node: true, web: false },\n} as const;\nexport const Fragment = React.Fragment;\nexport const Suspense = React.Suspense;\nexport const createElement = React.createElement;\nexport const isValidElement = React.isValidElement;\nexport const wrapClientGraph = (element: React.ReactNode) =>\n  wrapFarmIsolatedClientGraph(React, element);\nexport const renderToString = reactRenderToString;\nexport const renderToPipeableStream = reactRenderToPipeableStream;\n\nexport default React;\n\n/**\n * React DOM's streaming runtime reveals a Suspense boundary with `$RC`/`$RS`/\n * `$RV`/`$RX` calls and labels the segments with Fizz ids such as `id=\"S:1\"`.\n * The first of those in a chunk is where the static shell ends.\n */\nexport function findStaticShellBoundary(chunk: string): number {\n  const markerIndexes = [\n    chunk.indexOf('id=\"S:'),\n    chunk.indexOf(\"id='S:\"),\n    chunk.indexOf(\"$RC(\"),\n    chunk.indexOf(\"$RS(\"),\n    chunk.indexOf(\"$RV(\"),\n    chunk.indexOf(\"$RX(\"),\n  ].filter((index) => index >= 0);\n\n  if (markerIndexes.length === 0) return -1;\n\n  const markerIndex = Math.min(...markerIndexes);\n  const tagStart = chunk.lastIndexOf(\"<\", markerIndex);\n  return tagStart >= 0 ? tagStart : markerIndex;\n}\n","import type React from \"react\";\nimport type { FarmIslandStrategy } from \"../island\";\n\nconst REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\");\nconst LEGACY_REACT_ELEMENT_TYPE = Symbol.for(\"react.element\");\nconst BOUNDARY_GRAPH_CONTEXT = Symbol.for(\"farm.isolated-hydration.client-graph-context\");\n\nfunction getBoundaryGraphContext(ReactRuntime: typeof React): React.Context<boolean> {\n  const shared = globalThis as typeof globalThis &\n    Record<symbol, WeakMap<object, React.Context<boolean>> | undefined>;\n  const contexts = shared[BOUNDARY_GRAPH_CONTEXT] ?? new WeakMap();\n  shared[BOUNDARY_GRAPH_CONTEXT] = contexts;\n  const runtimeIdentity = ReactRuntime.createElement;\n  const existing = contexts.get(runtimeIdentity);\n  if (existing) return existing;\n\n  const context = ReactRuntime.createContext(false);\n  contexts.set(runtimeIdentity, context);\n  return context;\n}\n\nfunction serializeBoundaryProps(value: unknown, seen = new Set<object>()): unknown {\n  if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n  if (typeof value === \"number\") {\n    if (!Number.isFinite(value)) throw new TypeError(\"non-finite numbers are not serializable\");\n    return value;\n  }\n  if (typeof value === \"undefined\") {\n    throw new TypeError(\"undefined values are not serializable\");\n  }\n  if (typeof value !== \"object\") {\n    throw new TypeError(`${typeof value} values are not serializable`);\n  }\n  if (\n    (value as { $$typeof?: symbol }).$$typeof === REACT_ELEMENT_TYPE ||\n    (value as { $$typeof?: symbol }).$$typeof === LEGACY_REACT_ELEMENT_TYPE\n  ) {\n    throw new TypeError(\"React elements cannot cross an isolated hydration boundary\");\n  }\n  if (seen.has(value)) throw new TypeError(\"circular props are not serializable\");\n  seen.add(value);\n  try {\n    if (Array.isArray(value)) return value.map((entry) => serializeBoundaryProps(entry, seen));\n    const prototype = Object.getPrototypeOf(value);\n    if (prototype !== Object.prototype && prototype !== null) {\n      throw new TypeError(\"class instances are not serializable\");\n    }\n    return Object.fromEntries(\n      Object.entries(value).map(([key, entry]) => [key, serializeBoundaryProps(entry, seen)]),\n    );\n  } finally {\n    seen.delete(value);\n  }\n}\n\nfunction serializeBoundaryPayload(value: unknown): string {\n  return JSON.stringify(serializeBoundaryProps(value))\n    .replace(/&/g, \"\\\\u0026\")\n    .replace(/</g, \"\\\\u003c\")\n    .replace(/>/g, \"\\\\u003e\")\n    .replace(/\\u2028/g, \"\\\\u2028\")\n    .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\n/** @internal Keeps client-to-client imports inside one isolated React root. */\nexport function wrapFarmIsolatedClientGraph(\n  ReactRuntime: typeof React,\n  element: React.ReactNode,\n): React.ReactElement {\n  const Context = getBoundaryGraphContext(ReactRuntime);\n  return ReactRuntime.createElement(Context.Provider, { value: true }, element);\n}\n\n/** @internal Generated by Farm's experimental isolated-hydration transform. */\nexport function createFarmIsolatedClientBoundary(\n  ReactRuntime: typeof React,\n  Component: React.ComponentType<any>,\n  moduleReference: string,\n  exportName: string,\n  islandStrategy: FarmIslandStrategy,\n): React.ComponentType<any> {\n  function FarmIsolatedClientBoundary(props: Record<string, unknown>) {\n    const Context = getBoundaryGraphContext(ReactRuntime);\n    const belongsToParentClientGraph = ReactRuntime.useContext(Context);\n    const boundaryId = ReactRuntime.useId();\n\n    if (belongsToParentClientGraph) {\n      return ReactRuntime.createElement(Component, props);\n    }\n\n    let serializedProps: string;\n    try {\n      serializedProps = serializeBoundaryPayload(props);\n    } catch (error) {\n      if (typeof window === \"undefined\") {\n        console.warn(\n          `[Farm.js] Could not isolate ${moduleReference}#${exportName}: ${\n            error instanceof Error ? error.message : String(error)\n          }. The server-rendered component was preserved without client hydration.`,\n        );\n      }\n      return ReactRuntime.createElement(Component, props);\n    }\n\n    return ReactRuntime.createElement(\n      ReactRuntime.Fragment,\n      null,\n      ReactRuntime.createElement(\n        \"farm-client-boundary\",\n        {\n          \"data-farm-client-boundary\": moduleReference,\n          \"data-farm-client-id\": boundaryId,\n          \"data-farm-client-export\": exportName,\n          \"data-farm-island-strategy\": islandStrategy,\n          style: { display: \"contents\" },\n        },\n        ReactRuntime.createElement(\n          Context.Provider,\n          { value: true },\n          ReactRuntime.createElement(Component, props),\n        ),\n      ),\n      ReactRuntime.createElement(\"script\", {\n        type: \"application/json\",\n        \"data-farm-client-props\": boundaryId,\n        dangerouslySetInnerHTML: { __html: serializedProps },\n      }),\n    );\n  }\n\n  FarmIsolatedClientBoundary.displayName = `FarmIsolated(${\n    Component.displayName || Component.name || exportName\n  })`;\n  return FarmIsolatedClientBoundary;\n}\n\ntype FarmIsolatedRoot = {\n  render(element: React.ReactNode): void;\n  unmount(): void;\n};\n\ninterface FarmIsolatedRootRecord {\n  root: FarmIsolatedRoot;\n  reference: string;\n  exportName: string;\n  props: Record<string, unknown>;\n  serverHTML: string;\n  restore(error: unknown): void;\n}\n\ninterface FarmIsolatedHydrationRootOptions {\n  onUncaughtError?: (error: unknown) => void;\n}\n\nexport interface FarmIsolatedHydrationRuntimeOptions {\n  ReactRuntime: typeof React;\n  hydrateRoot(\n    container: Element,\n    element: React.ReactNode,\n    options?: FarmIsolatedHydrationRootOptions,\n  ): FarmIsolatedRoot;\n  load(reference: string): Promise<Record<string, unknown>>;\n  schedule(options: {\n    container: Element;\n    strategy: FarmIslandStrategy;\n    signal?: AbortSignal;\n    hydrate(): Promise<void>;\n  }): Promise<unknown>;\n  wrap?(element: React.ReactElement): React.ReactNode;\n  report?(message: string, error?: unknown): void;\n}\n\nfunction findBoundaryPayload(container: Element, boundaryId: string): HTMLScriptElement | null {\n  const sibling = container.nextElementSibling;\n  if (\n    sibling instanceof HTMLScriptElement &&\n    sibling.type === \"application/json\" &&\n    sibling.getAttribute(\"data-farm-client-props\") === boundaryId\n  ) {\n    return sibling;\n  }\n\n  for (const candidate of container.ownerDocument.querySelectorAll<HTMLScriptElement>(\n    'script[type=\"application/json\"][data-farm-client-props]',\n  )) {\n    if (candidate.getAttribute(\"data-farm-client-props\") === boundaryId) return candidate;\n  }\n  return null;\n}\n\n/** @internal Shared development and production runtime for isolated React roots. */\nexport function createFarmIsolatedHydrationRuntime(options: FarmIsolatedHydrationRuntimeOptions) {\n  const roots = new Map<Element, FarmIsolatedRootRecord>();\n  const pending = new Map<Element, AbortController>();\n  const report =\n    options.report ??\n    ((message: string, error?: unknown) => console.warn(`[Farm.js] ${message}`, error));\n\n  const failRoot = (\n    container: Element,\n    reference: string,\n    exportName: string,\n    serverHTML: string,\n    error: unknown,\n  ) => {\n    report(\n      `Could not hydrate isolated client boundary ${reference}#${exportName}. ` +\n        \"The server-rendered HTML was restored.\",\n      error,\n    );\n    queueMicrotask(() => {\n      try {\n        roots.get(container)?.root.unmount();\n      } catch {\n        // React may already have detached a root that failed during hydration.\n      }\n      roots.delete(container);\n      container.removeAttribute(\"data-farm-hydrated\");\n      container.removeAttribute(\"data-farm-island-hydrated\");\n      container.innerHTML = serverHTML;\n    });\n  };\n\n  class FarmIsolatedRootErrorBoundary extends options.ReactRuntime.Component<\n    { children?: React.ReactNode; onError(error: unknown): void },\n    { failed: boolean }\n  > {\n    state = { failed: false };\n\n    static getDerivedStateFromError() {\n      return { failed: true };\n    }\n\n    componentDidCatch(error: unknown) {\n      this.props.onError(error);\n    }\n\n    render() {\n      return this.state.failed ? null : this.props.children;\n    }\n  }\n\n  const createBoundaryGraph = (\n    Component: React.ComponentType<any>,\n    props: Record<string, unknown>,\n    restore: (error: unknown) => void,\n  ) => {\n    const componentElement = options.ReactRuntime.createElement(Component, props);\n    const wrappedElement = options.wrap ? options.wrap(componentElement) : componentElement;\n    return wrapFarmIsolatedClientGraph(\n      options.ReactRuntime,\n      options.ReactRuntime.createElement(\n        FarmIsolatedRootErrorBoundary,\n        { onError: restore },\n        wrappedElement,\n      ),\n    );\n  };\n\n  async function hydrate(scope: ParentNode = document, signal?: AbortSignal): Promise<void> {\n    const candidates = Array.from(\n      scope.querySelectorAll<Element>(\"farm-client-boundary[data-farm-client-boundary]\"),\n    );\n    if (\n      scope instanceof Element &&\n      scope.matches(\"farm-client-boundary[data-farm-client-boundary]\")\n    ) {\n      candidates.unshift(scope);\n    }\n    const boundaries = candidates.filter((container) => {\n      if (roots.has(container) || pending.has(container)) return false;\n      return !container.parentElement?.closest(\"farm-client-boundary[data-farm-client-boundary]\");\n    });\n\n    await Promise.all(\n      boundaries.map(async (container) => {\n        const reference = container.getAttribute(\"data-farm-client-boundary\");\n        const boundaryId = container.getAttribute(\"data-farm-client-id\");\n        const exportName = container.getAttribute(\"data-farm-client-export\") || \"default\";\n        const strategy =\n          (container.getAttribute(\"data-farm-island-strategy\") as FarmIslandStrategy | null) ??\n          \"load\";\n        if (!reference || !boundaryId) {\n          report(\"An isolated client boundary is missing its module reference or payload ID.\");\n          return;\n        }\n\n        const controller = new AbortController();\n        pending.set(container, controller);\n        const abort = () => controller.abort();\n        if (signal?.aborted) abort();\n        else signal?.addEventListener(\"abort\", abort, { once: true });\n        const cleanup = () => {\n          signal?.removeEventListener(\"abort\", abort);\n          if (pending.get(container) === controller) pending.delete(container);\n        };\n\n        let scheduled: Promise<unknown>;\n        try {\n          scheduled = options.schedule({\n            container,\n            strategy,\n            signal: controller.signal,\n            hydrate: async () => {\n              if (controller.signal.aborted || !container.isConnected) return;\n              const serverHTML = container.innerHTML;\n              try {\n                const module = await options.load(reference);\n                if (controller.signal.aborted || !container.isConnected) return;\n                const originals = module.__farm_client_boundary_originals__ as\n                  | Record<string, unknown>\n                  | undefined;\n                const Component = originals?.[exportName];\n                if (typeof Component !== \"function\" && typeof Component !== \"object\") {\n                  throw new Error(\"compiled original export was not found\");\n                }\n                const payload = findBoundaryPayload(container, boundaryId);\n                if (!payload) throw new Error(`serialized props ${boundaryId} were not found`);\n                const props = JSON.parse(payload.textContent || \"{}\");\n                if (!props || typeof props !== \"object\" || Array.isArray(props)) {\n                  throw new Error(\"serialized props must be an object\");\n                }\n\n                let rootFailure: unknown;\n                const restore = (error: unknown) => {\n                  if (rootFailure !== undefined) return;\n                  rootFailure = error;\n                  failRoot(container, reference, exportName, serverHTML, error);\n                  controller.abort();\n                };\n                const graphElement = createBoundaryGraph(\n                  Component as React.ComponentType<any>,\n                  props as Record<string, unknown>,\n                  restore,\n                );\n                const root = options.hydrateRoot(container, graphElement, {\n                  onUncaughtError: restore,\n                });\n                roots.set(container, {\n                  root,\n                  reference,\n                  exportName,\n                  props: props as Record<string, unknown>,\n                  serverHTML,\n                  restore,\n                });\n                container.setAttribute(\"data-farm-hydrated\", \"true\");\n              } catch (error) {\n                failRoot(container, reference, exportName, serverHTML, error);\n                controller.abort();\n              }\n            },\n          });\n        } catch (error) {\n          failRoot(container, reference, exportName, container.innerHTML, error);\n          controller.abort();\n          cleanup();\n          return;\n        }\n\n        const tracked = Promise.resolve(scheduled)\n          .catch((error) => {\n            if (!controller.signal.aborted) {\n              failRoot(container, reference, exportName, container.innerHTML, error);\n              controller.abort();\n            }\n          })\n          .finally(cleanup);\n        if (strategy === \"load\") await tracked;\n        else void tracked;\n      }),\n    );\n  }\n\n  function updateModule(reference: string, module: Record<string, unknown>): number {\n    const originals = module.__farm_client_boundary_originals__ as\n      | Record<string, unknown>\n      | undefined;\n    let updated = 0;\n\n    for (const [container, record] of roots) {\n      if (record.reference !== reference) continue;\n      const Component = originals?.[record.exportName];\n      if (typeof Component !== \"function\" && typeof Component !== \"object\") {\n        failRoot(\n          container,\n          record.reference,\n          record.exportName,\n          record.serverHTML,\n          new Error(\"updated compiled original export was not found\"),\n        );\n        continue;\n      }\n\n      try {\n        record.root.render(\n          createBoundaryGraph(Component as React.ComponentType<any>, record.props, record.restore),\n        );\n        updated++;\n      } catch (error) {\n        failRoot(container, record.reference, record.exportName, record.serverHTML, error);\n      }\n    }\n\n    return updated;\n  }\n\n  function dispose(scope: Node): void {\n    for (const [container, controller] of pending) {\n      if (container === scope || scope.contains(container)) {\n        controller.abort();\n        pending.delete(container);\n      }\n    }\n    for (const [container, record] of roots) {\n      if (container === scope || scope.contains(container)) {\n        try {\n          record.root.unmount();\n        } catch {\n          // The DOM owner may already have removed a failed root.\n        }\n        roots.delete(container);\n        container.removeAttribute(\"data-farm-hydrated\");\n        container.removeAttribute(\"data-farm-island-hydrated\");\n      }\n    }\n  }\n\n  return {\n    hydrate,\n    updateModule,\n    dispose,\n    rootCount: () => roots.size,\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAClB,oBAGO;;;ACCP,IAAM,yBAAyB,uBAAO,IAAI,8CAA8C;AAExF,SAAS,wBAAwB,cAAoD;AACnF,QAAM,SAAS;AAEf,QAAM,WAAW,OAAO,sBAAsB,KAAK,oBAAI,QAAQ;AAC/D,SAAO,sBAAsB,IAAI;AACjC,QAAM,kBAAkB,aAAa;AACrC,QAAM,WAAW,SAAS,IAAI,eAAe;AAC7C,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,aAAa,cAAc,KAAK;AAChD,WAAS,IAAI,iBAAiB,OAAO;AACrC,SAAO;AACT;AAZS;AA0DF,SAAS,4BACd,cACA,SACoB;AACpB,QAAM,UAAU,wBAAwB,YAAY;AACpD,SAAO,aAAa,cAAc,QAAQ,UAAU,EAAE,OAAO,KAAK,GAAG,OAAO;AAC9E;AANgB;;;AD1DT,IAAM,iBAAN,MAAM,uBAAsB,aAAAA,QAAM,UAOvC;AAAA,EACA,YAAY,OAAY;AACtB,UAAM,KAAK;AACX,SAAK,QAAQ,EAAE,UAAU,OAAO,OAAO,KAAK;AAAA,EAC9C;AAAA,EAEA,OAAO,yBAAyB,OAAgB;AAC9C,WAAO,EAAE,UAAU,MAAM,MAAM;AAAA,EACjC;AAAA,EAEA,SAAS;AACP,QAAI,KAAK,MAAM,UAAU;AACvB,YAAM,WAAW,KAAK,MAAM;AAC5B,aAAO,aAAAA,QAAM,cAAc,UAAU;AAAA,QACnC,GAAG,KAAK,MAAM;AAAA,QACd,OAAO,KAAK,MAAM;AAAA,QAClB,OAAO,6BAAM,KAAK,SAAS,EAAE,UAAU,OAAO,OAAO,KAAK,CAAC,GAApD;AAAA,MACT,CAAC;AAAA,IACH;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AArBE;AAPK,IAAM,gBAAN;AA8BA,IAAM,OAAO;AACb,IAAM,eAAe;AAAA,EAC1B,WAAW,EAAE,MAAM,MAAM,KAAK,MAAM;AACtC;AACO,IAAM,WAAW,aAAAA,QAAM;AACvB,IAAM,WAAW,aAAAA,QAAM;AACvB,IAAM,gBAAgB,aAAAA,QAAM;AAC5B,IAAM,iBAAiB,aAAAA,QAAM;AAC7B,IAAM,kBAAkB,wBAAC,YAC9B,4BAA4B,aAAAA,SAAO,OAAO,GADb;AAExB,IAAM,iBAAiB,cAAAC;AACvB,IAAM,yBAAyB,cAAAC;AAEtC,IAAO,iBAAQ,aAAAF;AAOR,SAAS,wBAAwB,OAAuB;AAC7D,QAAM,gBAAgB;AAAA,IACpB,MAAM,QAAQ,QAAQ;AAAA,IACtB,MAAM,QAAQ,QAAQ;AAAA,IACtB,MAAM,QAAQ,MAAM;AAAA,IACpB,MAAM,QAAQ,MAAM;AAAA,IACpB,MAAM,QAAQ,MAAM;AAAA,IACpB,MAAM,QAAQ,MAAM;AAAA,EACtB,EAAE,OAAO,CAAC,UAAU,SAAS,CAAC;AAE9B,MAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,QAAM,cAAc,KAAK,IAAI,GAAG,aAAa;AAC7C,QAAM,WAAW,MAAM,YAAY,KAAK,WAAW;AACnD,SAAO,YAAY,IAAI,WAAW;AACpC;AAfgB;","names":["React","reactRenderToString","reactRenderToPipeableStream"]}