From 6d93199fa2e60e887c51ff5630a10d81795805d2 Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Tue, 9 Jun 2026 23:22:28 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20HTMX/destroy=20race=20hypothesis=20inve?= =?UTF-8?q?stigation=20=E2=80=94=20REFUTED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Investigation verdict: - HTMX does NOT swap the FilePond container on the edit page; the htmx:targetError in the crash log is unrelated noise - The pre-destroy abort in destroyFilePondsIn has a wrong status check (filters for nonexistent status 4, misses status 7 LOADING) but is moot because no HTMX swap targets the FilePond container - The load-file-error -> DID_THROW_ITEM_INVALID path is vulnerable (passes t.status directly, unlike every other error handler which wraps it), but for local files the LOAD_FILE plugins always wrap rejections properly - Likely actual trigger: Firefox XHR abort edge case in server.load for the existing cover file, racing with addition of a new local file that replaces it in the single-file queue --- TODO.md | 5 +- docs/filepond-race-investigation.md | 278 ++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 docs/filepond-race-investigation.md diff --git a/TODO.md b/TODO.md index b6e5007..d343438 100644 --- a/TODO.md +++ b/TODO.md @@ -18,5 +18,6 @@ Reference: `docs/autosave-system.md` → "HTMX v2 Migration Plan" section. - [x] Analyze root cause → `docs/filepond-crash-analysis.md` - [x] Partial fixes (Content-Type headers, onerror cleanup, load object) — insufficient, crash still reproduces -- [ ] Replace `server.load` with custom function to bypass FilePond's buggy `load-file-error` → `DID_THROW_ITEM_INVALID` dispatch (see analysis doc, Option B) -- [ ] Implement `destroyFilePondsIn()` pre-destroy abort (defense in depth) +- [x] HTMX/destroy race hypothesis investigation → `docs/filepond-race-investigation.md` (verdict: REFUTED; likely cause: Firefox XHR abort edge in server.load racing with file replacement) +- [ ] Replace `server.load` with custom fetch-based function to bypass FilePond's `createResponse` path entirely (see investigation doc, recommended next step) +- [ ] Fix `destroyFilePondsIn()` status check: `f.status === 7` (LOADING) not caught; needs to also cover LOADING and PROCESSING_QUEUED (status 9) diff --git a/docs/filepond-race-investigation.md b/docs/filepond-race-investigation.md new file mode 100644 index 0000000..d626933 --- /dev/null +++ b/docs/filepond-race-investigation.md @@ -0,0 +1,278 @@ +# HTMX/destroy race hypothesis — investigation report + +## HTMX destroy triggers + +### What fires `destroy()` and when, relative to HTMX swap lifecycle + +The only code path that destroys FilePond instances is `destroyFilePondsIn(el)`, called by the `htmx:beforeSwap` listener: + +```js +window.htmx.on("htmx:beforeSwap", onHtmxBeforeSwap); +// → onHtmxBeforeSwap(evt) { destroyFilePondsIn(evt.detail.target); } +``` + +On the **edit page** (`/admin/edit.php`), the following HTMX targets exist on page load: + +| Element | Trigger | Target selector | Scope | +|---------|---------|-----------------|-------| +| `#toast-region` | `load` | `#toast-region` | Footer `