import type {AnyNativeEvent} from '../PluginModuleType';
import type {DOMEventName} from '../DOMEventNames';
import type {DispatchQueue} from '../DOMPluginEventSystem';
import type {EventSystemFlags} from '../EventSystemFlags';
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
import type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
import {enableTrustedTypesIntegration} from 'shared/ReactFeatureFlags';
import {getFiberCurrentPropsFromNode} from '../../client/ReactDOMComponentTree';
import {startHostTransition} from 'react-reconciler/src/ReactFiberReconciler';
import {didCurrentEventScheduleTransition} from 'react-reconciler/src/ReactFiberRootScheduler';
import sanitizeURL from 'react-dom-bindings/src/shared/sanitizeURL';
import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
import {SyntheticEvent} from '../SyntheticEvent';
function coerceFormActionProp(
actionProp: mixed,
): string | (FormData => void | Promise<void>) | null {
if (
actionProp == null ||
typeof actionProp === 'symbol' ||
typeof actionProp === 'boolean'
) {
return null;
} else if (typeof actionProp === 'function') {
return (actionProp: any);
} else {
if (__DEV__) {
checkAttributeStringCoercion(actionProp, 'action');
}
return (sanitizeURL(
enableTrustedTypesIntegration ? actionProp : '' + (actionProp: any),
): any);
}
}
function extractEvents(
dispatchQueue: DispatchQueue,
domEventName: DOMEventName,
maybeTargetInst: null | Fiber,
nativeEvent: AnyNativeEvent,
nativeEventTarget: null | EventTarget,
eventSystemFlags: EventSystemFlags,
targetContainer: EventTarget,
) {
if (domEventName !== 'submit') {
return;
}
if (!maybeTargetInst || maybeTargetInst.stateNode !== nativeEventTarget) {
return;
}
const formInst = maybeTargetInst;
const form: HTMLFormElement = (nativeEventTarget: any);
let action = coerceFormActionProp(
(getFiberCurrentPropsFromNode(form): any).action,
);
let submitter: null | void | HTMLInputElement | HTMLButtonElement =
(nativeEvent: any).submitter;
let submitterAction;
if (submitter) {
const submitterProps = getFiberCurrentPropsFromNode(submitter);
submitterAction = submitterProps
? coerceFormActionProp((submitterProps: any).formAction)
:
((submitter.getAttribute('formAction'): any): string | null);
if (submitterAction !== null) {
action = submitterAction;
submitter = null;
}
}
const event = new SyntheticEvent(
'action',
'action',
null,
nativeEvent,
nativeEventTarget,
);
function submitForm() {
if (nativeEvent.defaultPrevented) {
if (didCurrentEventScheduleTransition()) {
const formData = new FormData(form, submitter);
const pendingState: FormStatus = {
pending: true,
data: formData,
method: form.method,
action: action,
};
if (__DEV__) {
Object.freeze(pendingState);
}
startHostTransition(
formInst,
pendingState,
null,
formData,
);
} else {
}
} else if (typeof action === 'function') {
event.preventDefault();
const formData = new FormData(form, submitter);
const pendingState: FormStatus = {
pending: true,
data: formData,
method: form.method,
action: action,
};
if (__DEV__) {
Object.freeze(pendingState);
}
startHostTransition(formInst, pendingState, action, formData);
} else {
}
}
dispatchQueue.push({
event,
listeners: [
{
instance: null,
listener: submitForm,
currentTarget: form,
},
],
});
}
export {extractEvents};
export function dispatchReplayedFormAction(
formInst: Fiber,
form: HTMLFormElement,
action: FormData => void | Promise<void>,
formData: FormData,
): void {
const pendingState: FormStatus = {
pending: true,
data: formData,
method: form.method,
action: action,
};
if (__DEV__) {
Object.freeze(pendingState);
}
startHostTransition(formInst, pendingState, action, formData);
}