Repository: facebook/react
File: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js (JavaScript)

Code before:
}

export function canHydrateFormStateMarker(
  instance: HydratableInstance,
): null | FormStateMarkerInstance {
  const nodeData = (instance: any).data;
  if (
    nodeData === FORM_STATE_IS_MATCHING ||
    nodeData === FORM_STATE_IS_NOT_MATCHING
  ) {
    const markerInstance: FormStateMarkerInstance = (instance: any);
    return markerInstance;
  }
  return null;
}

export function isFormStateMarkerMatching(
  markerInstance: FormStateMarkerInstance,
): boolean {
  return markerInstance.data === FORM_STATE_IS_MATCHING;
}

function getNextHydratable(node: ?Node) {
  // Skip non-hydratable nodes.
  for (; node != null; node = ((node: any): Node).nextSibling) {
    const nodeType = node.nodeType;
    if (nodeType === ELEMENT_NODE || nodeType === TEXT_NODE) {
      break;
    }
    if (nodeType === COMMENT_NODE) {
      const nodeData = (node: any).data;
      if (
        nodeData === SUSPENSE_START_DATA ||
        nodeData === SUSPENSE_FALLBACK_START_DATA ||
        nodeData === SUSPENSE_PENDING_START_DATA ||
        (enableFormActions &&
          enableAsyncActions &&
          (nodeData === FORM_STATE_IS_MATCHING ||
            nodeData === FORM_STATE_IS_NOT_MATCHING))
      ) {
        break;
      }
      if (nodeData === SUSPENSE_END_DATA) {
        return null;
      }
    }
  }
  return (node: any);
}

export function getNextHydratableSibling(

Review comment (bug):
There is this unfortunate forking of behavior in the `canHydrate...` functions where if we are in a Singleton like `<body>` or are in the container scope we assume there may be 3rd party nodes we need to skip over. If our `nextHydratable` was some injected 3rd party stylesheet then hydration would fail as this is currently implemented. I think this function needs. a similar treatment as `canHydrateSuspenseInstance`

This will make your optimization where we omit the marker when the hook is normal harder too b/c it'll need to be able to scan forward but also jump back to where it was if it doesn't find anything

Code after:
}

export function canHydrateFormStateMarker(
  instance: HydratableInstance,
  inRootOrSingleton: boolean,
): null | FormStateMarkerInstance {
  while (instance.nodeType !== COMMENT_NODE) {
    if (!inRootOrSingleton || !enableHostSingletons) {
      return null;
    }
    const nextInstance = getNextHydratableSibling(instance);
    if (nextInstance === null) {
      return null;
    }
    instance = nextInstance;
  }
  const nodeData = (instance: any).data;
  if (
    nodeData === FORM_STATE_IS_MATCHING ||
    nodeData === FORM_STATE_IS_NOT_MATCHING
  ) {
    const markerInstance: FormStateMarkerInstance = (instance: any);
    return markerInstance;
  }
  return null;
}

export function isFormStateMarkerMatching(
  markerInstance: FormStateMarkerInstance,
): boolean {
  return markerInstance.data === FORM_STATE_IS_MATCHING;
}

function getNextHydratable(node: ?Node) {
  // Skip non-hydratable nodes.
  for (; node != null; node = ((node: any): Node).nextSibling) {
    const nodeType = node.nodeType;
    if (nodeType === ELEMENT_NODE || nodeType === TEXT_NODE) {
      break;
    }
    if (nodeType === COMMENT_NODE) {
      const nodeData = (node: any).data;
      if (
        nodeData === SUSPENSE_START_DATA ||
        nodeData === SUSPENSE_FALLBACK_START_DATA ||
        nodeData === SUSPENSE_PENDING_START_DATA ||
        (enableFormActions &&
          enableAsyncActions &&
          (nodeData === FORM_STATE_IS_MATCHING ||
            nodeData === FORM_STATE_IS_NOT_MATCHING))
      ) {