Skip to content

fix(browser): decode binary writes and keep download blobs alive - #72

Open
Aikiooo wants to merge 1 commit into
shellular-org:devfrom
Aikiooo:fix/browser-file-service
Open

fix(browser): decode binary writes and keep download blobs alive#72
Aikiooo wants to merge 1 commit into
shellular-org:devfrom
Aikiooo:fix/browser-file-service

Conversation

@Aikiooo

@Aikiooo Aikiooo commented Sep 10, 2026

Copy link
Copy Markdown

What

Two defects in the browser file service, both in the save/download path.

1. write() ignores the isBinary flag

src/bridge/file.ts implements writeBinary() by base64-encoding the bytes and passing true as the third argument:

writeBinary(path: string, data: Uint8Array) {
  return file("write", [path, bytesToBase64(data), true]);
}

The native handlers decode that payload, but the browser service accepted the argument and never used it, so it wrote the base64 text into OPFS. Any binary write on the browser platform was stored corrupted.

The browser service now decodes it too, so the third argument means the same thing on every platform.

2. saveToDevice() revokes the blob url too early

click() returns before the browser has handed the blob: url to the download manager, and on Android to an external app. Revoking on the next tick can kill the blob mid-handoff, so the download fails. The revoke is now delayed well past the handoff.

Tests

src/platforms/browser/services/file.test.ts covers the base64 decode, the plain-text path, write-error reporting, and that the url outlives the click. The two regression tests fail against the current code and pass with the fix.

pnpm typecheck passes and the suite is green (120 tests).

Notes

I left getContentType alone — it only maps a handful of extensions, and I did not want to widen the scope of this change. Happy to extend it in a separate PR if you want the common types mapped.

The browser file service ignored the third `write` argument — the
`isBinary` flag that `file.writeBinary()` sets alongside its
base64-encoded payload. The native handlers decode that payload, so
ignoring the flag stored the base64 text itself instead of the file's
contents and every binary write came out corrupted.

`saveToDevice` also revoked the blob url on the next tick. The url is
handed to the download manager, or to an external app on Android, after
`click()` returns, so the revoke could kill the blob mid-handoff and the
download failed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant