From: stephan Date: Fri, 21 Nov 2025 22:13:35 +0000 (+0000) Subject: Get initial JS overrides of the kvvfs sqlite3_vfs and sqlite3_io_methods in place... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=92fa31bc5fb72159e892aa6910690a92a6452671;p=thirdparty%2Fsqlite.git Get initial JS overrides of the kvvfs sqlite3_vfs and sqlite3_io_methods in place. It now tracks a distinct Storage-ish object per sqlite3_file instance. FossilOrigin-Name: 19a3349a2031e2b7fae67847b55643e4f70f8dae863ebc1ace3b09d1f482c8eb --- diff --git a/ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js b/ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js index 03d170e6ab..2d69be891b 100644 --- a/ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js +++ b/ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js @@ -31,8 +31,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ if( !pKvvfs ) return /* nothing to do */; - const util = sqlite3.util, - wasm = sqlite3.wasm; + const util = sqlite3.util; if( !util.isUIThread() ){ /* One test currently relies on this VFS not being visible in @@ -43,18 +42,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return; } - const __hop = (o,k)=>Object.prototype.hasOwnProperty.call(o,k); + const wasm = sqlite3.wasm, + hop = (o,k)=>Object.prototype.hasOwnProperty.call(o,k); /** Implementation of JS's Storage interface for use as backing store of the kvvfs. */ - class ObjectStorage extends Storage { + class ObjectStorage /* extends Storage (ctor may not be legally called) */ { #map; #keys; #getKeys(){return this.#keys ??= Object.keys(this.#map);} constructor(){ - super(); this.clear(); } @@ -68,7 +67,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } setItem(k,v){ - if( !__hop(this.#map, k) ){ + if( !hop(this.#map, k) ){ this.#keys = null; } this.#map[k]=v; @@ -90,19 +89,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } }/*ObjectStorage*/; - const kvvfsState = Object.assign(Object.create(null),{ - jClassToStorage: new Map( - /* Map of JS-format KVVfsFile::zClass values to Storage - object. We can't use WeakMap because that requires an Object - or Symbol as a key, and we can't use Symbol in this - context. We don't use KVVfsFile::zClass pointers as keys only - because of some special-casing for local/session journal - files which remaps those pointers. */ - ) - }); - kvvfsState.jClassToStorage.set('local', localStorage); - kvvfsState.jClassToStorage.set('session', sessionStorage); - /** Internal helper for sqlite3_js_kvvfs_clear() and friends. Its argument should be one of ('local','session',""). @@ -111,20 +97,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const rc = Object.create(null); rc.prefix = 'kvvfs-'+which; rc.stores = []; - let got = 0; if( globalThis.sessionStorage && ('session'===which || ""===which)){ rc.stores.push(globalThis.sessionStorage); - ++got; } if( globalThis.localStorage && ('local'===which || ""===which) ){ rc.stores.push(globalThis.localStorage); - ++got; - } - if( !got && which ){ - const x = kvvfsState.jClassToStorage.get(which); - if( x ) rc.stores.push(x); } return rc; }; @@ -193,34 +172,74 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const kvvfsMakeKey = wasm.exports.sqlite3__wasm_kvvfsMakeKeyOnPstack; const pstack = wasm.pstack; + const cache = Object.create(null); + cache.jzClassToStorage = Object.assign(Object.create(null),{ + /* Map of JS-stringified KVVfsFile::zClass names to + reference-counted Storage objects. We refcount so that xClose() + does not pull one out from another instance. */ + local: {refc: 2, s: globalThis.localStorage}, + session: {refc: 2, s: globalThis.sessionStorage} + }); + cache.jzClassToStorage['local-journal'] = + cache.jzClassToStorage.local; + cache.jzClassToStorage['session-journal'] = + cache.jzClassToStorage.session; + + const kvvfsStorage = function(zClass){ const s = wasm.cstrToJs(zClass); - if( !this.rxSession ){ - this.rxSession = /^session(-journal)?$/; - this.rxLocal = /^local(-journal)?$/; + if( cache.jzClassToStorage[s] ){ + return cache.jzClassToStorage[s].s; + } + if( !cache.rxSession ){ + cache.rxSession = /^session(-journal)?$/; + cache.rxLocal = /^local(-journal)?$/; } - if( this.rxSession.test(s) ) return sessionStorage; - if( this.rxLocal.test(s) ) return localStorage; - return kvvfsStorage.jClassToStorage.get(s); + if( cache.rxSession.test(s) ) return sessionStorage; + if( cache.rxLocal.test(s) ) return localStorage; + return cache.jzClassToStorage(s)?.s; }.bind(Object.create(null)); - { /* Override native sqlite3_kvvfs_methods */ - const kvvfsMethods = new sqlite3_kvvfs_methods( - /* Wraps the static sqlite3_api_methods singleton */ - wasm.exports.sqlite3__wasm_kvvfs_methods() - ); - try{ - /** - Implementations for members of the object referred to by - sqlite3__wasm_kvvfs_methods(). We swap out the native - implementations with these, which use JS Storage for their - backing store. - - The interface docs for these methods are in - src/os_kv.c:kvrecordRead(), kvrecordWrite(), and - kvrecordDelete(). - */ - for(const e of Object.entries({ + const pFileHandles = new Map( + /* sqlite3_file pointers => objects, each of which has: + .s = Storage object + .f = KVVfsFile instance + .n = JS-string form of f.$zName + */ + ); + + const debug = sqlite3.config.debug.bind(sqlite3.config); + const warn = sqlite3.config.warn.bind(sqlite3.config); + + { + /** + Original WASM functions for methods we partially override. + */ + const originalMethods = { + vfs: Object.create(null), + ioDb: Object.create(null), + ioJrnl: Object.create(null) + }; + + /** Returns the appropriate originalMethods[X] instance for the + given a KVVfsFile instance. */ + const originalIoMethods = (kvvfsFile)=> + originalMethods[kvvfsFile.$isJournal ? 'ioJrnl' : 'ioDb']; + + /** + Implementations for members of the object referred to by + sqlite3__wasm_kvvfs_methods(). We swap out the native + implementations with these, which use JS Storage for their + backing store. + + The interface docs for these methods are in + src/os_kv.c:kvrecordRead(), kvrecordWrite(), and + kvrecordDelete(). + */ + sqlite3_kvvfs_methods.override = { + + /* sqlite3_kvvfs_methods's own direct methods */ + recordHandler: { xRcrdRead: (zClass, zKey, zBuf, nBuf)=>{ const stack = pstack.pointer, astack = wasm.scopedAllocPush(); @@ -253,6 +272,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ wasm.scopedAllocPop(astack); } }, + xRcrdWrite: (zClass, zKey, zData)=>{ const stack = pstack.pointer; try { @@ -268,6 +288,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ pstack.restore(stack); } }, + xRcrdDelete: (zClass, zKey)=>{ const stack = pstack.pointer; try { @@ -282,62 +303,96 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ pstack.restore(stack); } } - })){ - kvvfsMethods[kvvfsMethods.memberKey(e[0])] = - wasm.installFunction(kvvfsMethods.memberSignature(e[0]), e[1]); - } - }finally{ - kvvfsMethods.dispose(); - } - }/* Override native sqlite3_api_methods */ - - /** - After initial refactoring to support the use of arbitrary Storage - objects (the interface from which localStorage and sessionStorage - dervie), we will apparently need to override some of the - associated sqlite3_vfs and sqlite3_io_methods members. - - We can call back into the native impls when needed, but we need - to override certain operations here to bypass its strict - db-naming rules (which, funnily enough, are in place because - they're relevant (only) for what should soon be the previous - version of this browser-side implementation). Apropos: the port - to generic objects would also make non-persistent kvvfs available - in Worker threads and non-browser builds. They could optionally - be exported to/from JSON. - */ - const eventualTodo = { - vfsMethods:{ -//#if nope + }/*recordHandler*/, /** + After initial refactoring to support the use of arbitrary Storage + objects (the interface from which localStorage and sessionStorage + dervie), we will apparently need to override some of the + associated sqlite3_vfs and sqlite3_io_methods members. + + We can call back into the native impls when needed, but we + need to override certain operations here to bypass its strict + db-naming rules (which, funnily enough, are in place because + they're relevant (only) for what should soon be the previous + version of this browser-side implementation). Apropos: the + port to generic objects would also make non-persistent kvvfs + available in Worker threads and non-browser builds. They + could optionally be exported to/from JSON. */ - xOpen: function(pProtoVfs,zName,pProtoFile,flags,pOutFlags){ - }, - xDelete: function(pVfs, zName, iSyncFlag){}, - xAccess:function(pProtoVfs, zPath, flags, pResOut){}, - xFullPathname: function(pVfs, zPath, nOut, zOut){}, - xDlOpen: function(pVfs, zFilename){}, - xSleep: function(pVfs,usec){}, - xCurrentTime: function(pVfs,pOutDbl){}, - xCurrentTimeInt64: function(pVfs,pOutI64){}, - xRandomness: function(pVfs, nOut, pOut){ - const heap = wasm.heap8u(); - let i = 0; - const npOut = Number(pOut); - for(; i < nOut; ++i) heap[npOut + i] = (Math.random()*255000) & 0xFF; - return i; - } + /* sqlite3_kvvfs_methods::pVfs's methods */ + vfs:{ + /** + */ + xOpen: function(pProtoVfs,zName,pProtoFile,flags,pOutFlags){ + try{ + const rc = originalMethods.vfs.xOpen(pProtoVfs, zName, pProtoFile, + flags, pOutFlags); + if( 0==rc ){ + const jzName = wasm.cstrToJs(zName); + const f = new KVVfsFile(pProtoFile); + let s = cache.jzClassToStorage[jzName]; + if( s ){ + ++s.refc; + }else{ + s = cache.jzClassToStorage[jzName] = { + refc: 1, + s: new ObjectStorage + }; + } + debug("kvvfs xOpen", f, jzName, s); + pFileHandles.set(pProtoFile, {s,f,n:jzName}); + } + return rc; + }catch(e){ + warn("kvvfs xOpen:",e); + return capi.SQLITE_ERROR; + } + }, +//#if nope + xDelete: function(pVfs, zName, iSyncFlag){}, + xAccess:function(pProtoVfs, zPath, flags, pResOut){}, + xFullPathname: function(pVfs, zPath, nOut, zOut){}, + xDlOpen: function(pVfs, zFilename){}, + xSleep: function(pVfs,usec){}, + xCurrentTime: function(pVfs,pOutDbl){}, + xCurrentTimeInt64: function(pVfs,pOutI64){}, //#endif - }, - + xRandomness: function(pVfs, nOut, pOut){ + const heap = wasm.heap8u(); + let i = 0; + const npOut = Number(pOut); + for(; i < nOut; ++i) heap[npOut + i] = (Math.random()*255000) & 0xFF; + return i; + } + }, + /** + kvvfs has separate sqlite3_api_methods impls for some of the + methods, depending on whether it's a db or journal file. Some + of the methods use shared impls but others are specific to + either db or journal files. + */ + ioDb:{ + /* sqlite3_kvvfs_methods::pIoDb's methods */ + xClose: function(pFile){ + try{ + const h = pFileHandles.get(pFile); + debug("kvvfs xClose", pFile, h); + pFileHandles.delete(pFile); + const s = cache.jzClassToStorage[h.n]; + if( 0===--s.refc ){ + delete cache.jzClassToStorage[h.n]; + delete s.s; + delete s.refc; + } + originalIoMethods(h.f).xClose(pFile); + h.f.dispose(); + return 0; + }catch(e){ + warn("kvvfs xClose",e); + return capi.SQLITE_ERROR; + } + }, //#if nope - /** - kvvfs has separate impls for some of the I/O methods, - depending on whether it's a db or journal file. - */ - ioMethods:{ - db:{ - xClose: function(pFile){}, xRead: function(pFile,pTgt,n,iOff64){}, xWrite: function(pFile,pSrc,n,iOff64){}, xTruncate: function(pFile,i64){}, @@ -350,25 +405,88 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ xFileControl: function(pFile,iOp,pArg){}, xSectorSize: function(pFile){}, xDeviceCharacteristics: function(pFile){} +//#endif }, - jrnl:{ - xClose: todoIOMethodsDb.xClose, + ioJrnl:{ + /* sqlite3_kvvfs_methods::pIoJrnl's methods. Those set to true + are copied as-is from the ioDb objects. Others are specific + to journal files. */ + xClose: true, +//#if nope xRead: function(pFile,pTgt,n,iOff64){}, xWrite: function(pFile,pSrc,n,iOff64){}, xTruncate: function(pFile,i64){}, xSync: function(pFile,flags){}, xFileControl: function(pFile, opId, pArg){}, xFileSize: function(pFile,pi64Out){}, - xLock: todoIOMethodsDb.xLock, - xUnlock: todoIOMethodsDb.xUnlock, - xCheckReservedLock: todoIOMethodsDb.xCheckReservedLock, + xLock: true, + xUnlock: true, + xCheckReservedLock: true, xFileControl: function(pFile,iOp,pArg){}, - xSectorSize: todoIOMethodsDb.xSectorSize, - xDeviceCharacteristics: todoIOMethodsDb.xDeviceCharacteristics + xSectorSize: true, + xDeviceCharacteristics: true +//#endif } + }/*sqlite3_kvvfs_methods.override*/; + + const ov = sqlite3_kvvfs_methods.override; + const kvvfsMethods = new sqlite3_kvvfs_methods( + /* Wraps the static sqlite3_api_methods singleton */ + wasm.exports.sqlite3__wasm_kvvfs_methods() + ); + const pVfs = new capi.sqlite3_vfs(kvvfsMethods.$pVfs); + const pIoDb = new capi.sqlite3_io_methods(kvvfsMethods.$pIoDb); + const pIoJrnl = new capi.sqlite3_io_methods(kvvfsMethods.$pIoJrnl); + debug("pVfs and friends",pVfs, pIoDb, pIoJrnl); + try { + for(const e of Object.entries(ov.recordHandler)){ + // Overwrite kvvfsMethods's callbacks + kvvfsMethods[kvvfsMethods.memberKey(e[0])] = + wasm.installFunction(kvvfsMethods.memberSignature(e[0]), e[1]); + } + for(const e of Object.entries(ov.vfs)){ + // Overwrite some pVfs entries and stash the original impls + const k = e[0], + f = e[1], + km = pVfs.memberKey(k), + mbr = pVfs.structInfo.members[k] || util.toss("Missing pVfs member ",km); + originalMethods.vfs[k] = wasm.functionEntry(pVfs[km]); + pVfs[km] = wasm.installFunction(mbr.signature, f); + } + for(const e of Object.entries(ov.ioDb)){ + // Similar treatment for pVfs.$pIoDb a.k.a. pIoDb... + const k = e[0], + f = e[1], + km = pIoDb.memberKey(k), + mbr = pIoDb.structInfo.members[k]; + if( !mbr ){ + warn("Missinog pIoDb member",k,km,pIoDb.structInfo); + util.toss("Missing pIoDb member",k,km); + } + originalMethods.ioDb[k] = wasm.functionEntry(pIoDb[km]); + pIoDb[km] = wasm.installFunction(mbr.signature, f); + } + for(const e of Object.entries(ov.ioJrnl)){ + // Similar treatment for pVfs.$pIoJrnl a.k.a. pIoJrnl... + const k = e[0], + f = e[1], + km = pIoJrnl.memberKey(k); + originalMethods.ioJrnl[k] = wasm.functionEntry(pIoJrnl[km]); + if( true===f ){ + /* use pIoDb's copy */ + pIoJrnl[km] = pIoDb[km] || util.toss("Missing copied pIoDb member",km); + }else{ + const mbr = pIoJrnl.structInfo.members[k] || util.toss("Missing pIoJrnl member",km) + pIoJrnl[km] = wasm.installFunction(mbr.signature, f); + } + } + }finally{ + kvvfsMethods.dispose(); + pVfs.dispose(); + pIoDb.dispose(); + pIoJrnl.dispose(); } -//#endif - }/*eventualTodo*/; + }/*method overrides*/ if(sqlite3?.oo1?.DB){ /** @@ -393,7 +511,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const opt = sqlite3.oo1.DB.dbCtorHelper.normalizeArgs(...arguments); storageName = opt.filename; if('session'!==storageName && 'local'!==storageName){ - toss3("JsStorageDb db name must be one of 'session' or 'local'."); + util.toss3("JsStorageDb db name must be one of 'session' or 'local'."); } opt.vfs = 'kvvfs'; sqlite3.oo1.DB.dbCtorHelper.call(this, opt); diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c index a83bd52f7b..e6dc7590e0 100644 --- a/ext/wasm/api/sqlite3-wasm.c +++ b/ext/wasm/api/sqlite3-wasm.c @@ -1105,6 +1105,7 @@ const char * sqlite3__wasm_enum_json(void){ StructBinder { M(base, "p")/*sqlite3_file base*/; M(zClass, "s"); + M(zName, "s"); M(isJournal, "i"); M(nJrnl, "i")/*actually unsigned!*/; M(aJrnl, "p"); diff --git a/manifest b/manifest index 9e8a6bcc6a..13a51935e8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\swork\stowards\susing\sJS\sgeneric\sStorage\sobjects\sas\sdb\spage\sstorage\svia\skvvfs. -D 2025-11-21T18:55:33.689 +C Get\sinitial\sJS\soverrides\sof\sthe\skvvfs\ssqlite3_vfs\sand\ssqlite3_io_methods\sin\splace.\sIt\snow\stracks\sa\sdistinct\sStorage-ish\sobject\sper\ssqlite3_file\sinstance. +D 2025-11-21T22:13:35.200 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -600,11 +600,11 @@ F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1041dd645e8e821c082b628cd8d9acf70c667 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 e84a6ec93acb2f6f2a19378ec7d3317de65d37dc75b13b70ad2b51b512268468 +F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js b8e37020d69e09348e16111a989f29ffa41fc719412d0ea7ffd1e8f51db91417 F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 26cb41d5a62f46a106b6371eb00fef02de3cdbfaa51338ba087a45f53028e0d0 F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js aa330fa0e8ef35cbd92eb0d52e05fbaa07e61540c5cb164e693c82428ce1d763 F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 9097074724172e31e56ce20ccd7482259cf72a76124213cbc9469d757676da86 -F ext/wasm/api/sqlite3-wasm.c dea6f331a03a49b8613d1fd5afcb606e1d06e8ab1df8dd65ee967fbfdd43ca1a +F ext/wasm/api/sqlite3-wasm.c e10ae835b1d8cb3bbc0974200a8339a96e66caed96d45ca962a5cebfd1a04e36 F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bda1c75bd674a92a0e27cc2f3d46dbbf21e422413f8046814515a0bd7409328a F ext/wasm/api/sqlite3-worker1.c-pp.js 802d69ead8c38dc1be52c83afbfc77e757da8a91a2e159e7ed3ecda8b8dba2e7 F ext/wasm/c-pp-lite.c 943be1a36774d58385dca32de36fc18d4f432fe79f7aa35e6c85dd6a6b825bd0 @@ -717,7 +717,7 @@ F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878 F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63 F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06 -F src/os_kv.c 26191ac1cb171ec3fceade6018ef66309cefba65e41f5ffe4c5385f2cb682ba7 +F src/os_kv.c b5de11f31634c36ac5ab04b14f6da67801f331b73384f852de0d77c98009818d F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2 F src/os_unix.c 7945ede1e85b2d1b910e1b4af9ba342e964b1e30e79f4176480a60736445cb36 F src/os_win.c a89b501fc195085c7d6c9eec7f5bd782625e94bb2a96b000f4d009703df1083f @@ -2178,8 +2178,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 206275292217be4ff317d4c9186ecaf863ca69295e2f995ed175aa65d9ad11dc -R 113fe1254ac4b59119cf9c28e45f222e +P 90a33941c69b3581feaed271542f0238ca81ee34fe5b353ca7da48b81ac73a5f +R 831d8b062b833be06147d18462b6029d U stephan -Z bcdce04b0f6728fd8539031f7a059a7e +Z 6ff913830f5e095f3c74b6184f98d188 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 585f31466a..0d050e20e1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -90a33941c69b3581feaed271542f0238ca81ee34fe5b353ca7da48b81ac73a5f +19a3349a2031e2b7fae67847b55643e4f70f8dae863ebc1ace3b09d1f482c8eb diff --git a/src/os_kv.c b/src/os_kv.c index f4c1fc84b6..4960feedc0 100644 --- a/src/os_kv.c +++ b/src/os_kv.c @@ -51,6 +51,7 @@ typedef struct KVVfsFile KVVfsFile; struct KVVfsFile { sqlite3_file base; /* IO methods */ const char *zClass; /* Storage class */ + const char *zName; /* File name (used by the JS side) */ int isJournal; /* True if this is a journal file */ unsigned int nJrnl; /* Space allocated for aJrnl[] */ char *aJrnl; /* Journal content */ @@ -839,11 +840,11 @@ static int kvvfsOpen( SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName)); assert(!pFile->zClass); assert(!pFile->aData); - pFile->aData = 0; - pFile->aJrnl = 0; - pFile->nJrnl = 0; + assert(!pFile->aJrnl); + assert(!pFile->nJrnl); pFile->szPage = -1; pFile->szDb = -1; + pFile->zName = zName; if( 0==sqlite3_strglob("*-journal", zName) ){ pFile->isJournal = 1; pFile->base.pMethods = &kvvfs_jrnl_io_methods; @@ -863,6 +864,7 @@ static int kvvfsOpen( #ifndef SQLITE_WASM return SQLITE_CANTOPEN; #else + /* The JS impl maps these to Storage objects */ pFile->zClass = zName; #endif }