From 6302d52e5de313c5eda5f74ec23cd705ccd21397 Mon Sep 17 00:00:00 2001 From: Vivek Date: Sat, 1 Aug 2026 20:06:58 +0530 Subject: [PATCH 1/8] feat(core): support formaction=${action} on submitters (#1207) --- .../webjs/references/muscle-memory-gotchas.md | 3 +- AGENTS.md | 4 +- packages/core/src/form-action.js | 363 ++++++------------ packages/core/src/render-client.js | 148 ++++--- packages/core/src/render-server.js | 304 ++++++++------- .../form-action-attr-guard-client.test.js | 2 +- .../rendering/form-action-attr-guard.test.js | 28 +- .../form-action-binding-client.test.js | 2 +- .../rendering/form-action-binding.test.js | 43 ++- packages/server/src/check.js | 4 +- packages/server/src/form-dispatch.js | 3 +- .../server/test/routing/form-dispatch.test.js | 34 ++ test/bun/form-action-guard.mjs | 29 +- .../bun/form-action-submitter-parity.test.mjs | 44 +++ .../app/docs/migrating-from-nextjs/page.ts | 2 +- .../app/docs/progressive-enhancement/page.ts | 2 +- website/app/docs/server-actions/page.ts | 2 +- website/app/docs/troubleshooting/page.ts | 2 +- 18 files changed, 529 insertions(+), 490 deletions(-) create mode 100644 test/bun/form-action-submitter-parity.test.mjs diff --git a/.agents/skills/webjs/references/muscle-memory-gotchas.md b/.agents/skills/webjs/references/muscle-memory-gotchas.md index c4bd5808d..a06526679 100644 --- a/.agents/skills/webjs/references/muscle-memory-gotchas.md +++ b/.agents/skills/webjs/references/muscle-memory-gotchas.md @@ -83,7 +83,8 @@ The bound, refused, and allowed shapes in full. Every "no" row is a binding that | `action=${fn}` unquoted, on a `
` | **no, it BINDS** | the one supported shape: the identity is resolved and emitted as a hidden field, nothing is stringified | | `action=${fn}` on any other tag | yes | `action` submits nothing off a ``, so it is an ordinary attribute and the function would be stringified | | `action="${fn}"`, or a mixed `action="/x/${fn}"` | yes | quoting turns a binding hole back into a plain attribute | -| `formaction=` anywhere | yes | not supported YET rather than impossible (tracked in #1207). Today, write one form per action, or bind one action and dispatch on a submit button's `name="intent"` | +| `formaction=${fn}` unquoted, on a submitter inside a bound form | **no, it BINDS** | per-submitter server action binding (#1207): emits `