46a692c08b
FossilOrigin-Name: 2e2339bd9e4293bad04ece7673a3048b99c2143cf9573ade2ec082d95744b981
134 lines
4.9 KiB
JavaScript
134 lines
4.9 KiB
JavaScript
//#if not target:node
|
|
/*
|
|
2026-02-20
|
|
|
|
The author disclaims copyright to this source code. In place of a
|
|
legal notice, here is a blessing:
|
|
|
|
* May you do good and not evil.
|
|
* May you find forgiveness for yourself and forgive others.
|
|
* May you share freely, never taking more than you give.
|
|
|
|
***********************************************************************
|
|
|
|
This file is a reimplementation of the "opfs" VFS (as distinct from
|
|
"opfs-sahpool") which uses WebLocks for locking instead of a bespoke
|
|
custom Atomics.wait()/notify() protocol. This file holds the
|
|
"synchronous half" of the VFS, whereas it shares the "asynchronous
|
|
half" of the "opfs" VFS.
|
|
|
|
This file is intended to be appended to the main sqlite3 JS
|
|
deliverable somewhere after sqlite3-api-oo1.js.
|
|
|
|
TODOs (2026-03-03):
|
|
|
|
- For purposes of tester1.js we need to figure out which of these
|
|
VFSes will install the (internal-use-only) sqlite3.opfs utility code
|
|
namespace. We need that in order to clean up OPFS files during test
|
|
runs. Alternately, move those into their own
|
|
sqlite3ApiBootstrap.initializers entry which precedes both of the
|
|
VFSes, so they'll have access to it during bootstrapping. The
|
|
sqlite3.opfs namespace is removed at the end of bootstrapping unless
|
|
the library is told to run in testing mode (which is not a
|
|
documented feature).
|
|
*/
|
|
'use strict';
|
|
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|
if( !sqlite3.opfs || sqlite3.config.disable?.vfs?.['opfs-wl'] ){
|
|
return;
|
|
}
|
|
const util = sqlite3.util,
|
|
toss = sqlite3.util.toss;
|
|
const opfsUtil = sqlite3.opfs;
|
|
const vfsName = 'opfs-wl';
|
|
/**
|
|
installOpfsWlVfs() returns a Promise which, on success, installs an
|
|
sqlite3_vfs named "opfs-wl", suitable for use with all sqlite3 APIs
|
|
which accept a VFS. It is intended to be called via
|
|
sqlite3ApiBootstrap.initializers or an equivalent mechanism.
|
|
|
|
This VFS is essentially identical to the "opfs" VFS but uses
|
|
WebLocks for its xLock() and xUnlock() implementations.
|
|
|
|
Quirks specific to this VFS:
|
|
|
|
- The (officially undocumented) 'opfs-wl-disable' URL
|
|
argument will disable OPFS, making this function a no-op.
|
|
|
|
Aside from locking differences in the VFSes, this function
|
|
otherwise behaves the same as
|
|
sqlite3-vfs-opfs.c-pp.js:installOpfsVfs().
|
|
*/
|
|
const installOpfsWlVfs = async function(options){
|
|
options = opfsUtil.initOptions(vfsName,options);
|
|
if( !options ) return sqlite3;
|
|
const capi = sqlite3.capi,
|
|
state = opfsUtil.createVfsState(),
|
|
opfsVfs = state.vfs,
|
|
metrics = opfsVfs.metrics.counters,
|
|
mTimeStart = opfsVfs.mTimeStart,
|
|
mTimeEnd = opfsVfs.mTimeEnd,
|
|
opRun = opfsVfs.opRun,
|
|
debug = (...args)=>sqlite3.config.debug(vfsName+":",...args),
|
|
warn = (...args)=>sqlite3.config.warn(vfsName+":",...args),
|
|
__openFiles = opfsVfs.__openFiles;
|
|
|
|
//debug("state",JSON.stringify(options));
|
|
/*
|
|
At this point, createVfsState() has populated:
|
|
|
|
- state: the configuration object we share with the async proxy.
|
|
|
|
- opfsVfs: an sqlite3_vfs instance with lots of JS state attached
|
|
to it.
|
|
|
|
with any code common to both the "opfs" and "opfs-wl" VFSes. Now
|
|
comes the VFS-dependent work...
|
|
*/
|
|
return opfsVfs.bindVfs(util.nu({
|
|
xLock: function(pFile,lockType){
|
|
mTimeStart('xLock');
|
|
//debug("xLock()...");
|
|
const f = __openFiles[pFile];
|
|
const rc = opRun('xLock', pFile, lockType);
|
|
if( !rc ) f.lockType = lockType;
|
|
mTimeEnd();
|
|
return rc;
|
|
},
|
|
xUnlock: function(pFile,lockType){
|
|
mTimeStart('xUnlock');
|
|
const f = __openFiles[pFile];
|
|
const rc = opRun('xUnlock', pFile, lockType);
|
|
if( !rc ) f.lockType = lockType;
|
|
mTimeEnd();
|
|
return rc;
|
|
}
|
|
}), function(sqlite3, vfs){
|
|
/* Post-VFS-registration initialization... */
|
|
if(sqlite3.oo1){
|
|
const OpfsWlDb = function(...args){
|
|
const opt = sqlite3.oo1.DB.dbCtorHelper.normalizeArgs(...args);
|
|
opt.vfs = vfs.$zName;
|
|
sqlite3.oo1.DB.dbCtorHelper.call(this, opt);
|
|
};
|
|
OpfsWlDb.prototype = Object.create(sqlite3.oo1.DB.prototype);
|
|
sqlite3.oo1.OpfsWlDb = OpfsWlDb;
|
|
OpfsWlDb.importDb = opfsUtil.importDb;
|
|
/* The "opfs" VFS variant adds a
|
|
oo1.DB.dbCtorHelper.setVfsPostOpenCallback() callback to set
|
|
a high busy_timeout. That was a design mis-decision and is
|
|
inconsistent with sqlite3_open() and friends, but is retained
|
|
against the risk of introducing regressions if it's removed.
|
|
This variant does not repeat that mistake.
|
|
*/
|
|
}
|
|
})/*bindVfs()*/;
|
|
}/*installOpfsWlVfs()*/;
|
|
globalThis.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{
|
|
return installOpfsWlVfs().catch((e)=>{
|
|
sqlite3.config.warn("Ignoring inability to install the",vfsName,"sqlite3_vfs:",e);
|
|
});
|
|
});
|
|
}/*sqlite3ApiBootstrap.initializers.push()*/);
|
|
//#/if target:node
|