filepond: fix crash 'can't access property main, n.status is undefined'

Fixes three root causes of FilePond errors on TFE upload forms:

1. server.process.onerror accessed .status on a string (XHR response
   text body) — now extracts the body safely.

2. server.load was a bare URL string with no error handling — converted
   to object with onload/onerror to prevent FilePond internal _write
   crash when load.php returns HTTP errors.

3. destroyFilePondsIn now aborts in-flight processing before pond.destroy()
   to prevent stale XHR callbacks firing on a torn-down FilePond instance.

Server-side: FilepondHandler now emits Content-Type: text/plain on all
responses (PHP defaults to text/html on die(), confusing FilePond's
response parser).
This commit is contained in:
Pontoporeia
2026-06-09 21:53:08 +02:00
parent 38ef550397
commit 2829d13a16
4 changed files with 68 additions and 10 deletions

View File

@@ -252,17 +252,21 @@
},
onload: (response) => {
var id = response.trim();
// Guard: if the server returned an error message disguised as 200,
// treat it as a processing error so FilePond doesn't treat it as a serverId.
if (id.length > 64 || /[<>\n\r]/.test(id)) {
console.error("[filepond] process onload | unexpected response | body=" + id.substring(0, 200));
throw new Error("Réponse serveur inattendue.");
}
console.log(`[filepond] process onload | serverId=${id}`);
return id; // file_id stored as serverId
},
onerror: (response) => {
console.error(
"[filepond] process onerror | status=" +
response.status +
" | body=" +
response,
);
return response;
// response is the raw XHR response text (string), not an XHR object.
// Log it and return a human-readable error message.
var body = typeof response === 'string' ? response : (response && response.body ? response.body : String(response || ''));
console.error("[filepond] process onerror | body=" + body);
return body || "Erreur lors du téléversement.";
},
},
@@ -274,11 +278,25 @@
console.log("[filepond] revert OK");
},
onerror: (r) => {
console.error(`[filepond] revert ERROR | body=${r}`);
var body = typeof r === 'string' ? r : (r && r.body ? r.body : '');
console.error(`[filepond] revert ERROR | body=${body || r}`);
},
},
load: `${base}/load.php?id=`,
load: {
url: `${base}/load.php?id=`,
method: "GET",
onload: (response) => {
// response is the blob from the server; pass through unchanged
return response;
},
onerror: (response) => {
var body = typeof response === 'string' ? response : (response && response.body ? response.body : String(response || ''));
console.error("[filepond] load onerror | body=" + body);
// Return a descriptive error — FilePond will fire an error event.
return body || "Fichier introuvable.";
},
},
// FilePond appends the source value (db_id) automatically
remove: (source, load, error) => {
@@ -500,6 +518,19 @@
}
}
}
// Abort any in-flight uploads before destroying to prevent
// FilePond internal crashes when XHR callbacks fire on a
// torn-down instance ("can't access property main").
var files = pond.getFiles();
for (var i = 0; i < files.length; i++) {
var f = files[i];
if (f.status === 4 || f.status === 2 || f.status === 3) {
// FileStatus: PROCESSING=4, PROCESSING_QUEUED=2, PROCESSING=4
// (FilePond 4.x internal: 4 = processing)
// Abort processing to avoid stale XHR callbacks
try { pond.removeFile(f); } catch (_abort) {}
}
}
pond.destroy();
} catch (_) {}
}