max size from kvvfsMethods.$nKeySize. */
const pstack = wasm.pstack;
/**
- Returns the storage object mapped to the given C-string
- zClass.
+ Returns the storage object mapped to the given string zClass
+ (C-string pointer or JS string).
*/
- const storageForZClass =
- (zClass)=>cache.jzClassToStorage[wasm.cstrToJs(zClass)];
+ const storageForZClass = (zClass)=>{
+ return 'string'===typeof zClass
+ ? cache.jzClassToStorage[zClass]
+ : cache.jzClassToStorage[wasm.cstrToJs(zClass)];
+ };
/**
sqlite3_file pointers => objects, each of which has:
.s = Storage object
+
.f = KVVfsFile instance
+
.n = JS-string form of f.$zClass
*/
const pFileHandles = new Map();
xRcrdRead: (zClass, zKey, zBuf, nBuf)=>{
const stack = pstack.pointer /* keyForStorage() allocs from here */;
try{
- const store = storageForZClass(zClass);
+ const jzClass = wasm.cstrToJs(zClass);
+ const store = storageForZClass(jzClass);
if( 0 ){
- debug("xRcrdRead", wasm.cstrToJs(zClass),
- wasm.cstrToJs(zKey), zBuf, nBuf, store );
+ debug("xRcrdRead", jzClass, wasm.cstrToJs(zKey),
+ zBuf, nBuf, store );
}
if( !store ) return -1;
const zXKey = keyForStorage(store, zClass, zKey);
if(!zXKey) return -3/*OOM*/;
+ //debug("xRcrdRead zXKey", jzClass, wasm.cstrToJs(zXKey), store );
const jV = store.s.getItem(wasm.cstrToJs(zXKey));
if(null===jV) return -1;
const nV = jV.length /* We are relying 100% on v being
xRcrdWrite: (zClass, zKey, zData)=>{
const stack = pstack.pointer /* keyForStorage() allocs from here */;
try {
- const store = storageForZClass(zClass);
+ const jzClass = wasm.cstrToJs(zClass);
+ const store = storageForZClass(jzClass);
const zXKey = keyForStorage(store, zClass, zKey);
if(!zXKey) return SQLITE_NOMEM;
store.s.setItem(
if( s ){
++s.refc;
s.files.push(f);
+ if( false && !s.keyPrefix ){
+ /* this messes up the recordHandler methods. They have only
+ the key, not the sqlite3_file object, so cannot map
+ a prefixless key to a storage object. */
+ f.$zClass = null;
+ }
}else{
/* TODO: a url flag which tells it to keep the storage
around forever so that future xOpen()s get the same
Storage-ish objects. We can accomplish that by
simply increasing the refcount once more. */
util.assert( !f.$isJournal, "Opening a journal before its db? "+jzClass );
+ //breaks stuff f.$zClass = null /* causes the "kvvfs-" prefix to be elided from keys */;
const other = f.$isJournal
? jzClass.replace(cache.rxJournalSuffix,'')
: jzClass + '-journal';
refcount. If we start at 2 here, that
pending open will increment it again. */,
s: new TransientStorage,
+ keyPrefix: '',
files: [f]
});
debug("xOpen installed storage handles [",
sqlite3.oo1.JsStorageDb.defaultStorageName = 'session';
const jdb = sqlite3.oo1.JsStorageDb;
jdb.prototype = Object.create(DB.prototype);
- /** Equivalent to sqlite3_js_kvvfs_clear(). */
jdb.clearStorage = capi.sqlite3_js_kvvfs_clear;
/**
Clears this database instance's storage or throws if this
jdb.prototype.exportToObject = function(includeJournal=true){
this.affirmOpen();
const store = cache.jzClassToStorage[this.affirmOpen().filename];
- const rxTail = /^kvvfs(-(local|session))?-(\w+)/;
if( !store ){
util.toss3(capi.SQLITE_ERROR,"kvvfs db '",
this.filename,"' has no storage object.");
});
const pages = Object.create(null);
const keyPrefix = kvvfsKeyPrefix(rc.name);
+ const rxTail = keyPrefix
+ ? /^kvvfs-[^-]+-(\w+)/ /* X... part of kvvfs-NAME-X... */
+ : undefined;
let i = 0, n = s.length;
for( ; i < n; ++i ){
const k = s.key(i);
if( !keyPrefix || k.startsWith(keyPrefix) ){
- const m = rxTail.exec(k);
- let kk = m[3];
+ let kk = (keyPrefix ? rxTail.exec(k) : undefined)?.[1] ?? k;
switch( kk ){
case 'jrnl':
if( includeJournal ) rc.journal = s.getItem(k);
}finally{
if( db ) db.close();
}
+ //console.debug("sessionStorage",globalThis.sessionStorage);
}
}/*kvvfs sanity checks*/)
.t({
db = new JDb(filename);
db.clearStorage(/*must not throw*/);
db.exec(sqlSetup);
- const close = ()=>{
- db.close();
- db = undefined;
- };
T.assert(3 === db.selectValue('select count(*) from kvvfs'));
const duo = new JDb(filename);
duo.exec('insert into kvvfs(a) values(4),(5),(6)');
T.assert(6 === db.selectValue('select count(*) from kvvfs'));
console.debug("duo.exportToObject()",duo.exportToObject(false));
- close();
+ db.close();
T.assert(6 === duo.selectValue('select count(*) from kvvfs'));
duo.close();
T.mustThrowMatching(function(){
appropriate.
*/
}finally{
- if( db ) db.close();
- if( duo ) duo.close();
+ db?.close?.();
+ duo?.close?.();
}
}
}/*transient kvvfs*/)
//#if enable-see
.t({
- name: 'kvvfs with SEE encryption',
- predicate: ()=>(isUIThread()
- || "Only available in main thread."),
+ name: 'kvvfs SEE encryption in sessionStorage',
+ predicate: ()=>(!!globalThis.sessionStorage
+ || "sessionStorage is not available"),
test: function(sqlite3){
- T.seeBaseCheck(sqlite3.oo1.JsStorageDb, (isInit)=>{
- return {filename: "session"};
- }, ()=>this.kvvfsUnlink());
+ const JDb = sqlite3.oo1.JsStorageDb;
+ T.seeBaseCheck(JDb,
+ (isInit)=>return {filename: "session"},
+ ()=>JDb.clearStorage('session'));
}
})/*kvvfs with SEE*/
//#endif enable-see
-C Initial\swork\son\seliminating\sthe\ssuperfluous-for-transient-storage\skvvfs\skey\sprefixes\sand\simplementing\skvvfs\sdb\simport.
-D 2025-11-23T15:38:34.579
+C Eliminate\sthe\ssuperfluous\s'kvvfs-'\spart\sof\skeys\sfor\stransient\sstorage\sand\scleanup\stheir\sexport\sa\sbit.\sReminder\sfor\slater:\swe\scould\spotentially\suse\sthe\sdbpage\svtab\sto\sserialize\sany\sdb\sto\sthis\sJSON-friendly\sform.
+D 2025-11-23T16:35:18.976
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
-F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js fb8dd4228767a6cb8079a665e9b9d851e6f509a66852d50d498b9ccf3d98ee8d
+F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js d0c2ec2286ca5f9105de3492a8e26f7bbd574e57d7265f422bbbe1cf3938b9f8
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 26cb41d5a62f46a106b6371eb00fef02de3cdbfaa51338ba087a45f53028e0d0
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 88ce2078267a2d1af57525a32d896295f4a8db7664de0e17e82dc9ff006ed8d3
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 9097074724172e31e56ce20ccd7482259cf72a76124213cbc9469d757676da86
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.c-pp.html 0e432ec2c0d99cd470484337066e8d27e7aee4641d97115338f7d962bf7b081a
F ext/wasm/tester1.c-pp.html 52d88fe2c6f21a046030a36410b4839b632f4424028197a45a3d5669ea724ddb
-F ext/wasm/tester1.c-pp.js 5ff0909c667329a316fd6a5804530b6fae928ca73bc7f7ec78cff030f7829de8
+F ext/wasm/tester1.c-pp.js 43e48fd869532d8a335cb040e7987f8c4ba1d117686b492c581c0a1252c6a7ac
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P cbbb9e61ae81097625488d78c5cbc0065c0acc3c8a7fd819490bc697f9d808c5
-R 80b842cee7b429e5bac8fd43d7b43fce
+P 6bc64059410b1868b7a3576e16d03c02e7c007a2be8b313e386eeb2e2a35c258
+R e0e07027fde0a231888a4f23ac8cccb2
U stephan
-Z 30c61370f06e15e0c2021e7507249bff
+Z 9e765b52f44e0a91da1bd1e93d48590e
# Remove this line to create a well-formed Fossil manifest.