diff --git a/src/core/drive/form_submission.ts b/src/core/drive/form_submission.ts index 1fb14af37..a433f0d0b 100644 --- a/src/core/drive/form_submission.ts +++ b/src/core/drive/form_submission.ts @@ -3,6 +3,7 @@ import { FetchResponse } from "../../http/fetch_response" import { expandURL } from "../url" import { dispatch, getMetaContent } from "../../util" import { StreamMessage } from "../streams/stream_message" +import { TurboFetchErrorEvent } from "../session" export interface FormSubmissionDelegate { formSubmissionStarted(formSubmission: FormSubmission): void @@ -199,6 +200,11 @@ export class FormSubmission { requestErrored(request: FetchRequest, error: Error) { this.result = { success: false, error } + dispatch("turbo:fetch-error", { + target: this.formElement, + detail: { request, error }, + cancelable: true, + }) this.delegate.formSubmissionErrored(this, error) } diff --git a/src/core/frames/frame_controller.ts b/src/core/frames/frame_controller.ts index 5a29907c3..78b310195 100644 --- a/src/core/frames/frame_controller.ts +++ b/src/core/frames/frame_controller.ts @@ -29,7 +29,7 @@ import { FrameRenderer } from "./frame_renderer" import { session } from "../index" import { isAction, Action } from "../types" import { VisitOptions } from "../drive/visit" -import { TurboBeforeFrameRenderEvent } from "../session" +import { TurboBeforeFrameRenderEvent, TurboFetchErrorEvent } from "../session" export class FrameController implements @@ -241,6 +241,11 @@ export class FrameController requestErrored(request: FetchRequest, error: Error) { console.error(error) + dispatch("turbo:fetch-error", { + target: this.element, + detail: { request, error }, + cancelable: true, + }) this.resolveVisitPromise() } diff --git a/src/core/session.ts b/src/core/session.ts index a6d53540c..46ea7acbe 100644 --- a/src/core/session.ts +++ b/src/core/session.ts @@ -21,6 +21,7 @@ import { FrameElement } from "../elements/frame_element" import { FrameViewRenderOptions } from "./frames/frame_view" import { FetchResponse } from "../http/fetch_response" import { Preloader, PreloaderDelegate } from "./drive/preloader" +import { FetchRequest } from "../http/fetch_request" export type TimingData = unknown export type TurboBeforeCacheEvent = CustomEvent @@ -29,6 +30,7 @@ export type TurboBeforeVisitEvent = CustomEvent<{ url: string }> export type TurboClickEvent = CustomEvent<{ url: string; originalEvent: MouseEvent }> export type TurboFrameLoadEvent = CustomEvent export type TurboBeforeFrameRenderEvent = CustomEvent<{ newFrame: FrameElement } & FrameViewRenderOptions> +export type TurboFetchErrorEvent = CustomEvent<{ request: FetchRequest; error: Error }> export type TurboFrameRenderEvent = CustomEvent<{ fetchResponse: FetchResponse }> export type TurboLoadEvent = CustomEvent<{ url: string; timing: TimingData }> export type TurboRenderEvent = CustomEvent