Repository: remix-run/react-router
File: packages/router/router.ts (TypeScript)

Code before:
    statusCode: 500,
    errors: {
      [context._deepestRenderedBoundaryId || routes[0].id]: error,
    },
  };
  return newContext;
}

function throwStaticHandlerAbortedError(
  request: Request,
  isRouteRequest: boolean,
  future: StaticHandlerFutureConfig
) {
  let method = isRouteRequest ? "queryRoute" : "query";
  if (future.v7_throwAbortReason && request.signal.reason !== undefined) {
    throw request.signal.reason;
  } else {
    throw new Error(
      `${method}() call aborted: ${request.method} ${request.url}`
    );
  }
}

function isSubmissionNavigation(
  opts: BaseNavigateOrFetchOptions
): opts is SubmissionNavigateOptions {
  return (
    opts != null &&
    (("formData" in opts && opts.formData != null) ||
      ("body" in opts && opts.body !== undefined))
  );
}

function normalizeTo(
  location: Path,
  matches: AgnosticDataRouteMatch[],
  basename: string,
  prependBasename: boolean,
  to: To | null,
  v7_relativeSplatPath: boolean,
  fromRouteId?: string,
  relative?: RelativeRoutingType
) {
  let contextualMatches: AgnosticDataRouteMatch[];
  let activeRouteMatch: AgnosticDataRouteMatch | undefined;
  if (fromRouteId) {
    // Grab matches up to the calling route so our route-relative logic is
    // relative to the correct source route
    contextualMatches = [];
    for (let match of matches) {
      contextualMatches.push(match);

Review comment (suggestion):
The only downside I see here is that we lose the request method/URL that we include in the custom error, but I think if folks need that then they should be passing a custom reason when they call `controller.abort`.  Right now, in Remix we don't expose that for customization - but we could send our own `DOMException` with the method/URL in the message if we wanted to.

Code after:
/**
 * Given an existing StaticHandlerContext and an error thrown at render time,
 * provide an updated StaticHandlerContext suitable for a second SSR render
 */
export function getStaticContextFromError(
  routes: AgnosticDataRouteObject[],
  context: StaticHandlerContext,
  error: any
) {
  let newContext: StaticHandlerContext = {
    ...context,
    statusCode: 500,
    errors: {
      [context._deepestRenderedBoundaryId || routes[0].id]: error,
    },
  };
  return newContext;
}

function throwStaticHandlerAbortedError(
  request: Request,
  isRouteRequest: boolean,
  future: StaticHandlerFutureConfig
) {
  if (future.v7_throwAbortReason && request.signal.reason !== undefined) {
    throw request.signal.reason;
  }

  let method = isRouteRequest ? "queryRoute" : "query";
  throw new Error(`${method}() call aborted: ${request.method} ${request.url}`);
}

function isSubmissionNavigation(
  opts: BaseNavigateOrFetchOptions
): opts is SubmissionNavigateOptions {
  return (
    opts != null &&
    (("formData" in opts && opts.formData != null) ||
      ("body" in opts && opts.body !== undefined))
  );
}

function normalizeTo(
  location: Path,
  matches: AgnosticDataRouteMatch[],
  basename: string,
  prependBasename: boolean,
  to: To | null,
  v7_relativeSplatPath: boolean,
  fromRouteId?: string,
  relative?: RelativeRoutingType