1/* 2 2022-09-17 3 4 The author disclaims copyright to this source code. In place of a 5 legal notice, here is a blessing: 6 7 * May you do good and not evil. 8 * May you find forgiveness for yourself and forgive others. 9 * May you share freely, never taking more than you give. 10 11 *********************************************************************** 12 13 A testing ground for the OPFS VFS. 14 15 Summary of how this works: 16 17 This file uses the sqlite3.StructBinder-created struct wrappers for 18 sqlite3_vfs, sqlite3_io_methods, ans sqlite3_file to set up a 19 conventional sqlite3_vfs (except that it's implemented in JS). The 20 methods which require OPFS APIs use a separate worker (hereafter called the 21 OPFS worker) to access that functionality. This worker and that one 22 use SharedArrayBuffer. 23*/ 24'use strict'; 25const tryOpfsVfs = function(sqlite3){ 26 const toss = function(...args){throw new Error(args.join(' '))}; 27 const logPrefix = "OPFS tester:"; 28 const log = (...args)=>console.log(logPrefix,...args); 29 const warn = (...args)=>console.warn(logPrefix,...args); 30 const error = (...args)=>console.error(logPrefix,...args); 31 const opfs = sqlite3.opfs; 32 log("tryOpfsVfs()"); 33 if(!sqlite3.opfs){ 34 const e = toss("OPFS is not available."); 35 error(e); 36 throw e; 37 } 38 const capi = sqlite3.capi; 39 const pVfs = capi.sqlite3_vfs_find("opfs") || toss("Missing 'opfs' VFS."); 40 const oVfs = capi.sqlite3_vfs.instanceForPointer(pVfs) || toss("Unexpected instanceForPointer() result.");; 41 log("OPFS VFS:",pVfs, oVfs); 42 43 const urlArgs = new URL(self.location.href).searchParams; 44 const dbFile = "my-persistent.db"; 45 if(urlArgs.has('delete')) sqlite3.opfs.deleteEntry(dbFile); 46 47 const db = new opfs.OpfsDb(dbFile); 48 log("db file:",db.filename); 49 try{ 50 if(opfs.entryExists(dbFile)){ 51 let n = db.selectValue("select count(*) from sqlite_schema"); 52 log("Persistent data found. sqlite_schema entry count =",n); 53 } 54 db.transaction((db)=>{ 55 db.exec({ 56 sql:[ 57 "create table if not exists t(a);", 58 "insert into t(a) values(?),(?),(?);", 59 ], 60 bind: [performance.now() | 0, 61 (performance.now() |0) / 2, 62 (performance.now() |0) / 4] 63 }); 64 }); 65 log("count(*) from t =",db.selectValue("select count(*) from t")); 66 67 // Some sanity checks of the opfs utility functions... 68 const testDir = '/sqlite3-opfs-'+opfs.randomFilename(12); 69 const aDir = testDir+'/test/dir'; 70 opfs.mkdir(aDir) || toss("mkdir failed"); 71 opfs.mkdir(aDir) || toss("mkdir must pass if the dir exists"); 72 opfs.deleteEntry(testDir+'/test') && toss("delete 1 should have failed (dir not empty)"); 73 opfs.deleteEntry(testDir+'/test/dir') || toss("delete 2 failed"); 74 opfs.deleteEntry(testDir+'/test/dir') && toss("delete 2b should have failed (dir already deleted)"); 75 opfs.deleteEntry(testDir,true) || toss("delete 3 failed"); 76 opfs.entryExists(testDir) && toss("entryExists(",testDir,") should have failed"); 77 }finally{ 78 db.close(); 79 } 80 81 log("Done!"); 82}/*tryOpfsVfs()*/; 83 84importScripts('sqlite3.js'); 85self.sqlite3InitModule() 86 .then((sqlite3)=>tryOpfsVfs(sqlite3)) 87 .catch((e)=>{ 88 console.error("Error initializing module:",e); 89 }); 90