Skip to content

Instantly share code, notes, and snippets.

@frankier
Created April 16, 2020 10:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frankier/4bbc85f65ad3311ca5134fbc744db711 to your computer and use it in GitHub Desktop.
Save frankier/4bbc85f65ad3311ca5134fbc744db711 to your computer and use it in GitHub Desktop.
import * as Comlink from "https://unpkg.com/comlink/dist/esm/comlink.mjs";
Comlink.transferHandlers.set("WORKERSQLPROXIES", {
canHandle: obj => false,
serialize(obj) {
const { port1, port2 } = new MessageChannel();
Comlink.expose(obj, port1);
return [port2, [port2]];
},
deserialize: (port) => {
port.start();
return Comlink.wrap(port);
}
});
const worker = new Worker("js/worker.js");
const sql = Comlink.wrap(worker);
try {
db = await sql.new((new URL(conf['url'], window.location)).href);
//Get all table names from master table
tables = await db.prepare("SELECT * FROM sqlite_master WHERE type IN ('table', 'view') ORDER BY name");
while (await tables.step()) {
var rowObj = await tables.getAsObject();
console.log("Got rowObj", rowObj)
}
} finally {
await tables.free();
}
importScripts("https://unpkg.com/comlink/dist/umd/comlink.js");
importScripts("vendor/sqljs-wasm/sql-wasm.js");
function initTransferHandlers(sql) {
Comlink.transferHandlers.set("WORKERSQLPROXIES", {
canHandle: obj => {
let isDB = obj instanceof sql.Database;
let hasDB = obj.db && (obj.db instanceof sql.Database);
return isDB || hasDB;
},
serialize(obj) {
const { port1, port2 } = new MessageChannel();
Comlink.expose(obj, port1);
return [port2, [port2]];
},
deserialize: (port) => {
port.start();
return Comlink.wrap(port);
}
});
}
function dbFromUrl(sql, url) {
return new Promise((res, rej) => {
var xhr = new XMLHttpRequest();
xhr.open('GET', decodeURIComponent(url), true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status !== 200) {
rej(e);
}
let arrayBuffer = this.response;
res(new sql.Database(new Uint8Array(arrayBuffer)));
};
xhr.onerror = function (e) {
rej(e);
};
xhr.send();
});
}
const mod = {
async new(url) {
const sql = await initSqlJs({
locateFile: file => "vendor/sqljs-wasm/" + file
});
initTransferHandlers(sql);
return dbFromUrl(sql, url);
}
};
Comlink.expose(mod);
@rhashimoto
Copy link

Just a caution that Comlink proxies currently leak resources if you're not careful to call the [Comlink.releaseProxy] method on each one. Since you do take care to call tables.free() in main.js you probably also want to release the proxy there as well.

@frankier
Copy link
Author

Thanks for the info. Good to know!

@frankier
Copy link
Author

Yeah thinking about it, ComLink seems like potentially a nice abstraction, but until WeakRefs come along, it's such a leaky one that there's a pretty good argument that dealing directly with postMessage is less hassle. That seems to be the conclusion that sql.js discussion is heading towards sql-js/sql.js#377

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment