You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
OPFS never stores a playback fragment: every DownloadManager identifier contains "/" and is an invalid OPFS file name #132
The worker then calls sessionDir.getFileHandle(identifier, {create: true}). The File System standard forbids / in a file name, and Firefox's IsValidName (dom/fs/shared/FileSystemHelpers.cpp) rejects any name containing / with a TypeError: Invalid filename. Every identifier of a real fragment is https://host/path/seg.ts::undefined-undefined::arraybuffer, so every write fails. saveBlobInOPFSAsync catches it, logs OPFS write failed for this blob, keeping it in memory once per fragment, and keeps the Blob in RAM.
So the backend FSBlob prefers on Firefox has never held a single playback fragment. "Offloaded fragments leave RAM" only ever applied to the blob0-style names the save path uses. With "download entire video" (shouldDownloadAll()) a multi-GB video is buffered entirely in process memory, exactly what OPFS was added to avoid. deleteBlob -> deleteFile -> removeEntry(identifier) fails the same way (silently caught).
Why the tests did not see it
tests/e2e/specs/storage.e2e.mjs calls saveBlobAsync(new Blob([payload])) with no identifier, so it round-trips blob0, and no spec asserts that a real fragment's entry.data() is a File once offloaded.
Suggested fix
Map identifiers to OPFS-safe names inside OPFSManager (a Map<identifier, 'f' + counter> on the main thread, or a hex SHA-1/SHA-256 of the identifier) and use the mapped name in setFile, getFile/getSavedFile and deleteFile.
Add to storage.e2e.mjs a round trip with an identifier of the real shape ('https://a/b.ts::0-100::arraybuffer'), and a playback spec asserting downloadManager.getEntry(ctx).data() returns a File once offloaded.
Report "OPFS write failed" once per session rather than per fragment.
Confidence: high (the name rule is in the standard and in Gecko's source; the identifier shape is in the code).
From a line-by-line code review of the tree at 41363fd (2026-10-02). Each claim above was checked against the source before filing; the reproduction steps and line references are as of that commit.
Activity