webkitFileSystem.backend.js
July 22, 2021 ยท View on GitHub
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;
}
} };