-
-
Save jlongster/ec00ddbb47b4b29897ab5939b8e32fbe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Reader, Writer} from '../shared-channel'; | |
let FS; | |
let rootEntry; | |
let openFiles = new Map(); | |
function openFile(filename) { | |
let opened = openFiles.get(filename); | |
if (opened) { | |
return opened; | |
} | |
return new Promise((resolve, reject) => { | |
rootEntry.getFile( | |
filename, | |
{create: true}, | |
(entry) => { | |
openFiles.set(filename, entry); | |
resolve(entry); | |
}, | |
(err) => reject(err), | |
); | |
}); | |
} | |
async function handleWrites(writer, name, writes) { | |
let entry = await openFile(name); | |
for (let w of writes) { | |
await new Promise((resolve, reject) => { | |
entry.createWriter((writer) => { | |
writer.onwrite = resolve; | |
writer.onerror = reject; | |
writer.seek(w.pos); | |
writer.write(new Blob([w.data], {type: 'octet/stream'})); | |
}); | |
}); | |
} | |
writer.int32(0); | |
writer.finalize(); | |
} | |
async function handleRead(writer, name, pos, length) { | |
let entry = await openFile(name); | |
let file = await new Promise((resolve, reject) => | |
entry.file(resolve, reject), | |
); | |
let bytes = await new Promise((resolve, reject) => { | |
let reader = new FileReader(); | |
reader.onload = (e) => resolve(e.target.result); | |
reader.onerror = reject; | |
reader.readAsArrayBuffer(file.slice(pos, pos + length)); | |
}); | |
writer.bytes(bytes); | |
writer.finalize(); | |
} | |
async function handleReadMeta(writer, name) { | |
let entry = await openFile(name); | |
let file = await new Promise((resolve, reject) => { | |
entry.file(resolve, reject); | |
}); | |
let meta = {size: file.size, blockSize: 4096}; | |
writer.int32(meta ? meta.size : -1); | |
writer.int32(meta ? meta.blockSize : -1); | |
writer.finalize(); | |
} | |
async function handleWriteMeta(writer, name, meta) { | |
let entry = await openFile(name); | |
try { | |
await new Promise((resolve, reject) => { | |
entry.createWriter((writer) => { | |
writer.onwrite = resolve; | |
writer.onerror = reject; | |
writer.truncate(meta.size); | |
}); | |
}); | |
writer.int32(0); | |
writer.finalize(); | |
} catch (err) { | |
console.log('handleWriteMeta err:', err); | |
writer.int32(-1); | |
writer.finalize(); | |
} | |
} | |
async function listen(reader, writer) { | |
while (1) { | |
let method = reader.string(); | |
switch (method) { | |
case 'writeBlocks': { | |
let name = reader.string(); | |
let writes = []; | |
while (!reader.done()) { | |
let pos = reader.int32(); | |
let data = reader.bytes(); | |
writes.push({pos, data}); | |
} | |
await handleWrites(writer, name, writes); | |
break; | |
} | |
case 'readBlock': { | |
let name = reader.string(); | |
let pos = reader.int32(); | |
let length = reader.int32(); | |
reader.done(); | |
await handleRead(writer, name, pos, length); | |
break; | |
} | |
case 'readMeta': { | |
let name = reader.string(); | |
reader.done(); | |
await handleReadMeta(writer, name); | |
break; | |
} | |
case 'writeMeta': { | |
let name = reader.string(); | |
let size = reader.int32(); | |
let blockSize = reader.int32(); | |
reader.done(); | |
await handleWriteMeta(writer, name, {size, blockSize}); | |
break; | |
} | |
} | |
} | |
} | |
self.onmessage = async (msg) => { | |
switch (msg.data.type) { | |
case 'init': { | |
let quota = msg.data.quota; | |
if (quota === 0) { | |
postMessage({type: 'no-filesystem'}); | |
return; | |
} | |
FS = await new Promise((resolve, reject) => { | |
self.webkitRequestFileSystem( | |
self.PERSISTENT, | |
quota, | |
(fs) => { | |
resolve(fs); | |
}, | |
(err) => { | |
postMessage({type: 'no-filesystem'}); | |
reject(err); | |
}, | |
); | |
}); | |
rootEntry = await new Promise((resolve, reject) => { | |
FS.root.getDirectory( | |
'dbs', | |
{create: true}, | |
(entry) => { | |
resolve(entry); | |
}, | |
(err) => { | |
postMessage({type: 'no-filesystem'}); | |
reject(err); | |
}, | |
); | |
}); | |
postMessage({type: 'worker-ready'}); | |
let [argBuffer, resultBuffer] = msg.data.buffers; | |
let reader = new Reader(argBuffer, {name: 'args', debug: false}); | |
let writer = new Writer(resultBuffer, {name: 'results', debug: false}); | |
listen(reader, writer); | |
break; | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment