From f96f89f4c6c229d6d66edb0022ce0465b0b29baa Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Tue, 9 Apr 2024 23:02:42 -0400 Subject: [PATCH] Scaffolding for requestFormReset API This sets adds a new ReactDOM export called requestFormReset, including setting up the export and creating a method on the internal ReactDOM dispatcher. It does not yet add any implementation. Doing this in its own commit for review purposes. The API itself is explained in the next commit. --- .../src/client/ReactFiberConfigDOM.js | 13 +++++++++++++ .../server/ReactDOMFlightServerHostDispatcher.js | 1 + .../src/server/ReactFizzConfigDOM.js | 1 + .../src/shared/ReactDOMFormActions.js | 6 ++++++ packages/react-dom/index.classic.fb.js | 1 + packages/react-dom/index.experimental.js | 1 + packages/react-dom/index.js | 1 + packages/react-dom/index.modern.fb.js | 1 + packages/react-dom/index.stable.js | 1 + packages/react-dom/src/ReactDOMSharedInternals.js | 1 + packages/react-dom/src/ReactDOMSharedInternalsFB.js | 1 + packages/react-dom/src/client/ReactDOM.js | 1 + packages/react-dom/src/client/ReactDOMFB.js | 1 + packages/react-dom/src/shared/ReactDOMTypes.js | 1 + packages/react-reconciler/src/ReactFiberHooks.js | 9 +++++++-- 15 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js index ac76fafd5ad86..cb16e40718878 100644 --- a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js +++ b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js @@ -102,6 +102,7 @@ import {listenToAllSupportedEvents} from '../events/DOMPluginEventSystem'; import {validateLinkPropsForStyleResource} from '../shared/ReactDOMResourceValidation'; import escapeSelectorAttributeValueInsideDoubleQuotes from './escapeSelectorAttributeValueInsideDoubleQuotes'; import {flushSyncWork as flushSyncWorkOnAllRoots} from 'react-reconciler/src/ReactFiberWorkLoop'; +import {requestFormReset as requestFormResetOnFiber} from 'react-reconciler/src/ReactFiberHooks'; import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; @@ -1928,6 +1929,7 @@ ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = { f /* flushSyncWork */: disableLegacyMode ? flushSyncWork : previousDispatcher.f /* flushSyncWork */, + r: requestFormReset, D /* prefetchDNS */: prefetchDNS, C /* preconnect */: preconnect, L /* preload */: preload, @@ -1951,6 +1953,17 @@ function flushSyncWork() { } } +function requestFormReset(form: HTMLFormElement) { + previousDispatcher.r(/* requestFormReset */ form); + const formInst = getInstanceFromNodeDOMTree(form); + if (formInst !== null) { + requestFormResetOnFiber(formInst); + } else { + // TODO: What if none of the dispatchers find a matching form instance? + // Should we detect this in dev and warn? + } +} + // We expect this to get inlined. It is a function mostly to communicate the special nature of // how we resolve the HoistableRoot for ReactDOM.pre*() methods. Because we support calling // these methods outside of render there is no way to know which Document or ShadowRoot is 'scoped' diff --git a/packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js b/packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js index 602452f67e2f3..3303c07cfb4f3 100644 --- a/packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js +++ b/packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js @@ -28,6 +28,7 @@ const previousDispatcher = ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */ ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = { f /* flushSyncWork */: previousDispatcher.f /* flushSyncWork */, + r /* requestFormReset */: previousDispatcher.r /* requestFormReset */, D /* prefetchDNS */: prefetchDNS, C /* preconnect */: preconnect, L /* preload */: preload, diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index 91baeef4a1bff..d246b4c487973 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -88,6 +88,7 @@ const previousDispatcher = ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */ ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = { f /* flushSyncWork */: previousDispatcher.f /* flushSyncWork */, + r /* requestFormReset */: previousDispatcher.r /* requestFormReset */, D /* prefetchDNS */: prefetchDNS, C /* preconnect */: preconnect, L /* preload */: preload, diff --git a/packages/react-dom-bindings/src/shared/ReactDOMFormActions.js b/packages/react-dom-bindings/src/shared/ReactDOMFormActions.js index 42967f7ce499b..0b3f478e33b19 100644 --- a/packages/react-dom-bindings/src/shared/ReactDOMFormActions.js +++ b/packages/react-dom-bindings/src/shared/ReactDOMFormActions.js @@ -12,6 +12,7 @@ import type {Awaited} from 'shared/ReactTypes'; import {enableAsyncActions} from 'shared/ReactFeatureFlags'; import ReactSharedInternals from 'shared/ReactSharedInternals'; +import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; type FormStatusNotPending = {| pending: false, @@ -87,3 +88,8 @@ export function useFormState( return dispatcher.useFormState(action, initialState, permalink); } } + +export function requestFormReset(form: HTMLFormElement) { + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .r(/* requestFormReset */ form); +} diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/index.classic.fb.js index a565a91f43b1f..63c20f7e51bfe 100644 --- a/packages/react-dom/index.classic.fb.js +++ b/packages/react-dom/index.classic.fb.js @@ -25,6 +25,7 @@ export { unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority. useFormStatus, useFormState, + requestFormReset, prefetchDNS, preconnect, preload, diff --git a/packages/react-dom/index.experimental.js b/packages/react-dom/index.experimental.js index f2d3c27aea0c5..0cc5ef13e3698 100644 --- a/packages/react-dom/index.experimental.js +++ b/packages/react-dom/index.experimental.js @@ -17,6 +17,7 @@ export { unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority. useFormStatus, useFormState, + requestFormReset, prefetchDNS, preconnect, preload, diff --git a/packages/react-dom/index.js b/packages/react-dom/index.js index 50ad087dfaf6c..b6f85ce628c57 100644 --- a/packages/react-dom/index.js +++ b/packages/react-dom/index.js @@ -20,6 +20,7 @@ export { unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority. useFormStatus, useFormState, + requestFormReset, prefetchDNS, preconnect, preload, diff --git a/packages/react-dom/index.modern.fb.js b/packages/react-dom/index.modern.fb.js index 0d2fa4b4dccbd..861febfa5e37b 100644 --- a/packages/react-dom/index.modern.fb.js +++ b/packages/react-dom/index.modern.fb.js @@ -16,6 +16,7 @@ export { unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority. useFormStatus, useFormState, + requestFormReset, prefetchDNS, preconnect, preload, diff --git a/packages/react-dom/index.stable.js b/packages/react-dom/index.stable.js index a9306083c0e61..f5ed138d67ab6 100644 --- a/packages/react-dom/index.stable.js +++ b/packages/react-dom/index.stable.js @@ -16,6 +16,7 @@ export { unstable_batchedUpdates, useFormStatus, useFormState, + requestFormReset, prefetchDNS, preconnect, preload, diff --git a/packages/react-dom/src/ReactDOMSharedInternals.js b/packages/react-dom/src/ReactDOMSharedInternals.js index 50f19f563c9ad..655f23acd6725 100644 --- a/packages/react-dom/src/ReactDOMSharedInternals.js +++ b/packages/react-dom/src/ReactDOMSharedInternals.js @@ -31,6 +31,7 @@ function noop() {} const DefaultDispatcher: HostDispatcher = { f /* flushSyncWork */: noop, + r /* requestFormReset */: noop, D /* prefetchDNS */: noop, C /* preconnect */: noop, L /* preload */: noop, diff --git a/packages/react-dom/src/ReactDOMSharedInternalsFB.js b/packages/react-dom/src/ReactDOMSharedInternalsFB.js index 7bd7a1ab8ae2b..4e425d5ddca79 100644 --- a/packages/react-dom/src/ReactDOMSharedInternalsFB.js +++ b/packages/react-dom/src/ReactDOMSharedInternalsFB.js @@ -27,6 +27,7 @@ function noop() {} const DefaultDispatcher: HostDispatcher = { f /* flushSyncWork */: noop, + r /* requestFormReset */: noop, D /* prefetchDNS */: noop, C /* preconnect */: noop, L /* preload */: noop, diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index 86979fa11f81d..61660e9843369 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -48,6 +48,7 @@ export { export { useFormStatus, useFormState, + requestFormReset, } from 'react-dom-bindings/src/shared/ReactDOMFormActions'; if (__DEV__) { diff --git a/packages/react-dom/src/client/ReactDOMFB.js b/packages/react-dom/src/client/ReactDOMFB.js index e24cba3a52b46..9b016b04d8dfd 100644 --- a/packages/react-dom/src/client/ReactDOMFB.js +++ b/packages/react-dom/src/client/ReactDOMFB.js @@ -48,6 +48,7 @@ export { export { useFormStatus, useFormState, + requestFormReset, } from 'react-dom-bindings/src/shared/ReactDOMFormActions'; if (__DEV__) { diff --git a/packages/react-dom/src/shared/ReactDOMTypes.js b/packages/react-dom/src/shared/ReactDOMTypes.js index 2da68cae2d3f3..dbfe07f9ec8f3 100644 --- a/packages/react-dom/src/shared/ReactDOMTypes.js +++ b/packages/react-dom/src/shared/ReactDOMTypes.js @@ -83,6 +83,7 @@ export type PreinitModuleScriptOptions = { export type HostDispatcher = { f /* flushSyncWork */: () => boolean | void, + r /* requestFormReset */: (form: HTMLFormElement) => void, D /* prefetchDNS */: (href: string) => void, C /* preconnect */: (href: string, crossOrigin?: ?CrossOriginEnum) => void, L /* preload */: ( diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index b32c9c120166d..c712eb6c387d8 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -3008,13 +3008,18 @@ export function startHostTransition( // once more of this function is implemented. () => { // Automatically reset the form when the action completes. - requestFormReset(formFiber); + requestFormResetImpl(formFiber); return callback(formData); }, ); } -function requestFormReset(formFiber: Fiber) { +export function requestFormReset(formFiber: Fiber) { + // TODO: Not yet implemented. Need to upgrade the fiber to be stateful + // before scheduling the form reset. +} + +function requestFormResetImpl(formFiber: Fiber) { const transition = requestCurrentTransition(); if (__DEV__) {