mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Fix escaping in action error URL (#27273)
This URL is generated on the client (there's an equivalent but shorter SSR version too) when a function is used as an action. It should never happen but it'll be invoked if a form is manually submitted or event is stopped early. The `'` wasn't escaped so this yielded invalid syntax. Which is an error too but much less helpful. `missing ) after argument list`. Added a test that evals to make sure it's correct syntax.
This commit is contained in:
@@ -501,7 +501,7 @@ function setProp(
|
||||
// eslint-disable-next-line no-script-url
|
||||
"javascript:throw new Error('" +
|
||||
'A React form was unexpectedly submitted. If you called form.submit() manually, ' +
|
||||
"consider using form.requestSubmit() instead. If you're trying to use " +
|
||||
"consider using form.requestSubmit() instead. If you\\'re trying to use " +
|
||||
'event.stopPropagation() in a submit event handler, consider also calling ' +
|
||||
'event.preventDefault().' +
|
||||
"')",
|
||||
|
||||
@@ -922,4 +922,51 @@ describe('ReactDOMForm', () => {
|
||||
await act(() => resolveText('Wait'));
|
||||
assertLog(['Async action finished', 'No pending action']);
|
||||
});
|
||||
|
||||
// @gate enableFormActions
|
||||
it('should error if submitting a form manually', async () => {
|
||||
const ref = React.createRef();
|
||||
|
||||
let error = null;
|
||||
let result = null;
|
||||
|
||||
function emulateForceSubmit(submitter) {
|
||||
const form = submitter.form || submitter;
|
||||
const action =
|
||||
(submitter && submitter.getAttribute('formaction')) || form.action;
|
||||
try {
|
||||
if (!/\s*javascript:/i.test(action)) {
|
||||
throw new Error('Navigate to: ' + action);
|
||||
} else {
|
||||
// eslint-disable-next-line no-new-func
|
||||
result = Function(action.slice(11))();
|
||||
}
|
||||
} catch (x) {
|
||||
error = x;
|
||||
}
|
||||
}
|
||||
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<form
|
||||
action={() => {}}
|
||||
ref={ref}
|
||||
onSubmit={e => {
|
||||
e.preventDefault();
|
||||
emulateForceSubmit(e.target);
|
||||
}}>
|
||||
<input type="text" name="foo" defaultValue="bar" />
|
||||
</form>,
|
||||
);
|
||||
});
|
||||
|
||||
// This submits the form, which gets blocked and then resubmitted. It's a somewhat
|
||||
// common idiom but we don't support this pattern unless it uses requestSubmit().
|
||||
await submit(ref.current);
|
||||
expect(result).toBe(null);
|
||||
expect(error.message).toContain(
|
||||
'A React form was unexpectedly submitted. If you called form.submit()',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user