From 515ae564d84cc2c1ad027920d3b0f81cee2d5ee6 Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Sun, 27 Nov 2022 12:55:32 -0500 Subject: [PATCH] Re-use `getVisitAction` utility function (#799) The logic for reading an `Action` from a list of `Element` instances' `[data-turbo-action]` attribute is still scattered across several modules, in spite of the `getVisitAction` declared in the `util` module. This commit replaces duplicate implementations of the `getVisitAction` method with the utility function. With those calls added, the `isAction` type checking utility is only ever invoked by `getVisitAction`, so this commit moves its implementation to the `util` module, and removes all other invocations. --- src/core/drive/navigator.ts | 10 ++++------ src/core/frames/frame_controller.ts | 4 ++-- src/core/session.ts | 7 +++---- src/core/types.ts | 4 ---- src/observers/form_link_click_observer.ts | 3 ++- src/util.ts | 6 +++++- 6 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/core/drive/navigator.ts b/src/core/drive/navigator.ts index 8a9943152..5165f505d 100644 --- a/src/core/drive/navigator.ts +++ b/src/core/drive/navigator.ts @@ -1,9 +1,9 @@ -import { Action, isAction } from "../types" +import { Action } from "../types" +import { getVisitAction } from "../../util" import { FetchMethod } from "../../http/fetch_request" import { FetchResponse } from "../../http/fetch_response" import { FormSubmission } from "./form_submission" import { expandURL, getAnchor, getRequestURL, Locatable, locationIsVisitable } from "../url" -import { getAttribute } from "../../util" import { Visit, VisitDelegate, VisitOptions } from "./visit" import { PageSnapshot } from "./page_snapshot" @@ -164,9 +164,7 @@ export class Navigator { return this.history.restorationIdentifier } - getActionForFormSubmission(formSubmission: FormSubmission): Action { - const { formElement, submitter } = formSubmission - const action = getAttribute("data-turbo-action", submitter, formElement) - return isAction(action) ? action : "advance" + getActionForFormSubmission({ submitter, formElement }: FormSubmission): Action { + return getVisitAction(submitter, formElement) || "advance" } } diff --git a/src/core/frames/frame_controller.ts b/src/core/frames/frame_controller.ts index 86fa98aa8..94704f487 100644 --- a/src/core/frames/frame_controller.ts +++ b/src/core/frames/frame_controller.ts @@ -27,7 +27,7 @@ import { LinkInterceptor, LinkInterceptorDelegate } from "./link_interceptor" import { FormLinkClickObserver, FormLinkClickObserverDelegate } from "../../observers/form_link_click_observer" import { FrameRenderer } from "./frame_renderer" import { session } from "../index" -import { isAction, Action } from "../types" +import { Action } from "../types" import { VisitOptions } from "../drive/visit" import { TurboBeforeFrameRenderEvent } from "../session" import { StreamMessage } from "../streams/stream_message" @@ -381,7 +381,7 @@ export class FrameController proposeVisitIfNavigatedWithAction(frame: FrameElement, element: Element, submitter?: HTMLElement) { this.action = getVisitAction(submitter, element, frame) - if (isAction(this.action)) { + if (this.action) { const { visitCachedSnapshot } = frame.delegate frame.delegate.fetchResponseLoaded = (fetchResponse: FetchResponse) => { diff --git a/src/core/session.ts b/src/core/session.ts index 2d1cb3685..ee94b5043 100644 --- a/src/core/session.ts +++ b/src/core/session.ts @@ -13,8 +13,8 @@ import { ScrollObserver } from "../observers/scroll_observer" import { StreamMessage } from "./streams/stream_message" import { StreamMessageRenderer } from "./streams/stream_message_renderer" import { StreamObserver } from "../observers/stream_observer" -import { Action, Position, StreamSource, isAction } from "./types" -import { clearBusyState, dispatch, markAsBusy } from "../util" +import { Action, Position, StreamSource } from "./types" +import { clearBusyState, dispatch, getVisitAction, markAsBusy } from "../util" import { PageView, PageViewDelegate, PageViewRenderOptions } from "./drive/page_view" import { Visit, VisitOptions } from "./drive/visit" import { PageSnapshot } from "./drive/page_snapshot" @@ -427,8 +427,7 @@ export class Session // Private getActionForLink(link: Element): Action { - const action = link.getAttribute("data-turbo-action") - return isAction(action) ? action : "advance" + return getVisitAction(link) || "advance" } get snapshot() { diff --git a/src/core/types.ts b/src/core/types.ts index 673ebdfff..90d1817ea 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -1,9 +1,5 @@ export type Action = "advance" | "replace" | "restore" -export function isAction(action: any): action is Action { - return action == "advance" || action == "replace" || action == "restore" -} - export type Position = { x: number; y: number } export type StreamSource = { diff --git a/src/observers/form_link_click_observer.ts b/src/observers/form_link_click_observer.ts index 6f177b8c8..108ee3911 100644 --- a/src/observers/form_link_click_observer.ts +++ b/src/observers/form_link_click_observer.ts @@ -1,4 +1,5 @@ import { LinkClickObserver, LinkClickObserverDelegate } from "./link_click_observer" +import { getVisitAction } from "../util" export type FormLinkClickObserverDelegate = { willSubmitFormLinkToLocation(link: Element, location: URL, event: MouseEvent): boolean @@ -42,7 +43,7 @@ export class FormLinkClickObserver implements LinkClickObserverDelegate { const turboFrame = link.getAttribute("data-turbo-frame") if (turboFrame) form.setAttribute("data-turbo-frame", turboFrame) - const turboAction = link.getAttribute("data-turbo-action") + const turboAction = getVisitAction(link) if (turboAction) form.setAttribute("data-turbo-action", turboAction) const turboConfirm = link.getAttribute("data-turbo-confirm") diff --git a/src/util.ts b/src/util.ts index 9d15aa505..4183351af 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,4 +1,4 @@ -import { Action, isAction } from "./core/types" +import { Action } from "./core/types" export type DispatchOptions = { target: EventTarget @@ -154,6 +154,10 @@ export function getHistoryMethodForAction(action: Action) { } } +export function isAction(action: any): action is Action { + return action == "advance" || action == "replace" || action == "restore" +} + export function getVisitAction(...elements: (Element | undefined)[]): Action | null { const action = getAttribute("data-turbo-action", ...elements)