Skip to content

Instantly share code, notes, and snippets.

@myobie

myobie/README.md Secret

Last active December 3, 2022 20:48
Show Gist options
  • Save myobie/021fc07f09e013b1e5c137ec09282aeb to your computer and use it in GitHub Desktop.
Save myobie/021fc07f09e013b1e5c137ec09282aeb to your computer and use it in GitHub Desktop.
Files written to OPFS through a sync access handle in Safari are read back out with a size of zero bytes.

Files written to OPFS through a sync access handle in Safari are read back out with a size of zero bytes.

Run this project:

$ npx serve # or boot a server another way
$ open 'http://localhost:3000'

Logs will print out inside the HTML.

<!doctype html>
<html>
<head>
<title>Safari OPFS bug demo</title>
</head>
<body>
<pre id="log">Log:
</pre>
<script>
const pre = document.getElementById('log')
const worker = new Worker('worker.js')
worker.addEventListener('message', e => { pre.innerText += e.data + '\n' })
worker.postMessage('start')
</script>
</body>
</html>
addEventListener('message', e => {
if (e.data === 'start') { start() }
})
const contents = 'Contents of the file'
const encoded = (new TextEncoder()).encode(contents)
async function start() {
postMessage('starting...')
const root = await navigator.storage.getDirectory()
await writeFile(root)
const contentsFromDisk = await readFile(root)
if (contents !== contentsFromDisk) {
postMessage('contents from disk do not match originally written contents')
}
}
async function writeFile(root) {
const fileHandle = await root.getFileHandle('test.txt', { create: true })
const accessHandle = await fileHandle.createSyncAccessHandle()
const byteLength = accessHandle.write(encoded, { at: 0 })
await accessHandle.flush()
postMessage(`wrote ${byteLength} bytes to file`)
const checkBuffer = new Uint8Array(encoded.byteLength)
accessHandle.read(checkBuffer, { at: 0 })
const check = (new TextDecoder()).decode(checkBuffer)
postMessage(`checked contents written to file: '${check}'`)
await accessHandle.close()
postMessage('closed access handle')
}
async function readFile(root) {
const fileHandle = await root.getFileHandle('test.txt', { create: false })
const file = await fileHandle.getFile()
postMessage(`found file - name: ${file.name}, size: ${file.size}, type: ${file.type}`)
const bytesFromDisk = await file.arrayBuffer()
const contentsFromDisk = (new TextDecoder()).decode(bytesFromDisk)
postMessage(`contents of file from disk: '${contentsFromDisk}'`)
return contentsFromDisk
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment