diff options
author | stephan <stephan@noemail.net> | 2023-07-18 18:52:41 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2023-07-18 18:52:41 +0000 |
commit | b0dd9d427faac25681ba2cd4ba45b11fb7071ef5 (patch) | |
tree | 9814d0d434a063398e3d4f232310a10748aa6e29 /ext/wasm/api | |
parent | d69e6e6efb8a9204b332a188f05d05734f18f40d (diff) | |
download | sqlite-b0dd9d427faac25681ba2cd4ba45b11fb7071ef5.tar.gz sqlite-b0dd9d427faac25681ba2cd4ba45b11fb7071ef5.zip |
Further refactoring of opfs-sahpool and start integrating it into tester1.c-pp.js.
FossilOrigin-Name: 91c789234963b660ae900f0738906b28a477993709e286d8125b2f4d6101601c
Diffstat (limited to 'ext/wasm/api')
-rw-r--r-- | ext/wasm/api/extern-post-js.c-pp.js | 2 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-api-prologue.js | 38 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-vfs-opfs-sahpool.js | 82 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-vfs-opfs.c-pp.js | 2 |
4 files changed, 64 insertions, 60 deletions
diff --git a/ext/wasm/api/extern-post-js.c-pp.js b/ext/wasm/api/extern-post-js.c-pp.js index fac00370d..bd5225d11 100644 --- a/ext/wasm/api/extern-post-js.c-pp.js +++ b/ext/wasm/api/extern-post-js.c-pp.js @@ -59,7 +59,7 @@ const toExportForESM = initModuleState.sqlite3Dir = li.join('/') + '/'; } - globalThis.sqlite3InitModule = function ff(...args){ + globalThis.sqlite3InitModule = async function ff(...args){ //console.warn("Using replaced sqlite3InitModule()",globalThis.location); return originalInit(...args).then((EmscriptenModule)=>{ if('undefined'!==typeof WorkerGlobalScope && diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js index ac3253670..22ec87ff3 100644 --- a/ext/wasm/api/sqlite3-api-prologue.js +++ b/ext/wasm/api/sqlite3-api-prologue.js @@ -1876,26 +1876,28 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( then it must be called by client-level code, which must not use the library until the returned promise resolves. - Bug: if called while a prior call is still resolving, the 2nd - call will resolve prematurely, before the 1st call has finished - resolving. The current build setup precludes that possibility, - so it's only a hypothetical problem if/when this function - ever needs to be invoked by clients. + If called multiple times it will return the same promise on + subsequent calls. The current build setup precludes that + possibility, so it's only a hypothetical problem if/when this + function ever needs to be invoked by clients. In Emscripten-based builds, this function is called automatically and deleted from this object. */ - asyncPostInit: async function(){ + asyncPostInit: function ff(){ + if(ff.ready instanceof Promise) return ff.ready; let lip = sqlite3ApiBootstrap.initializersAsync; delete sqlite3ApiBootstrap.initializersAsync; - if(!lip || !lip.length) return Promise.resolve(sqlite3); + if(!lip || !lip.length){ + return ff.ready = Promise.resolve(sqlite3); + } lip = lip.map((f)=>{ - const p = (f instanceof Promise) ? f : f(sqlite3); - return p.catch((e)=>{ - console.error("an async sqlite3 initializer failed:",e); - throw e; - }); + return (f instanceof Promise) ? f : f(sqlite3); }); + const catcher = (e)=>{ + config.error("an async sqlite3 initializer failed:",e); + throw e; + }; const postInit = ()=>{ if(!sqlite3.__isUnderTest){ /* Delete references to internal-only APIs which are used by @@ -1911,16 +1913,16 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( return sqlite3; }; if(1){ - /* Run all initializers in sequence. The advantage is that it - allows us to have post-init cleanup defined outside of this - routine at the end of the list and have it run at a - well-defined time. */ + /* Run all initializers in the sequence they were added. The + advantage is that it allows us to have post-init cleanup + defined outside of this routine at the end of the list and + have it run at a well-defined time. */ let p = lip.shift(); while(lip.length) p = p.then(lip.shift()); - return p.then(postInit); + return ff.ready = p.then(postInit).catch(catcher); }else{ /* Run them in an arbitrary order. */ - return Promise.all(lip).then(postInit); + return ff.ready = Promise.all(lip).then(postInit).catch(catcher); } }, /** diff --git a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.js b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.js index 5ab58bef5..1f026c7cc 100644 --- a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.js +++ b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.js @@ -52,7 +52,7 @@ is not detected, the VFS is not registered. */ 'use strict'; -globalThis.sqlite3ApiBootstrap.initializersAsync.push(async function(sqlite3){ +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const toss = sqlite3.util.toss; const toss3 = sqlite3.util.toss3; const initPromises = Object.create(null); @@ -400,46 +400,47 @@ globalThis.sqlite3ApiBootstrap.initializersAsync.push(async function(sqlite3){ /** - A SAHPoolUtil instance is exposed to clients in order to - manipulate an OpfsSAHPool object without directly exposing that + A SAHPoolUtil instance is exposed to clients in order to manipulate an OpfsSAHPool object without directly exposing that object and allowing for some semantic changes compared to that class. + + Class docs are in the client-level docs for installOpfsSAHPoolVfs(). */ class SAHPoolUtil { + /* This object's associated OpfsSAHPool. */ + #p; constructor(sahPool){ - /* TODO: move the this-to-sahPool mapping into an external - WeakMap so as to not expose it to downstream clients. */ - this.$p = sahPool; + this.#p = sahPool; this.vfsName = sahPool.vfsName; } - addCapacity = async function(n){ - return this.$p.addCapacity(n); + async addCapacity(n){ + return this.#p.addCapacity(n); } - reduceCapacity = async function(n){ - return this.$p.reduceCapacity(n); + async reduceCapacity(n){ + return this.#p.reduceCapacity(n); } - getCapacity = function(){ - return this.$p.getCapacity(this.$p); + getCapacity(){ + return this.#p.getCapacity(this.#p); } - getActiveFileCount = function(){ - return this.$p.getFileCount(); + getActiveFileCount(){ + return this.#p.getFileCount(); } - reserveMinimumCapacity = async function(min){ - const c = this.$p.getCapacity(); - return (c < min) ? this.$p.addCapacity(min - c) : c; + async reserveMinimumCapacity(min){ + const c = this.#p.getCapacity(); + return (c < min) ? this.#p.addCapacity(min - c) : c; } - exportFile = function(name){ - const sah = this.$p.mapFilenameToSAH.get(name) || toss("File not found:",name); + exportFile(name){ + const sah = this.#p.mapFilenameToSAH.get(name) || toss("File not found:",name); const n = sah.getSize() - HEADER_OFFSET_DATA; const b = new Uint8Array(n>=0 ? n : 0); if(n>0) sah.read(b, {at: HEADER_OFFSET_DATA}); return b; } - importDb = function(name, bytes){ + importDb(name, bytes){ const n = bytes.byteLength; if(n<512 || n%512!=0){ toss("Byte array size is invalid for an SQLite db."); @@ -450,35 +451,33 @@ globalThis.sqlite3ApiBootstrap.initializersAsync.push(async function(sqlite3){ toss("Input does not contain an SQLite database header."); } } - const sah = this.$p.mapFilenameToSAH.get(name) - || this.$p.nextAvailableSAH() + const sah = this.#p.mapFilenameToSAH.get(name) + || this.#p.nextAvailableSAH() || toss("No available handles to import to."); sah.write(bytes, {at: HEADER_OFFSET_DATA}); - this.$p.setAssociatedPath(sah, name, capi.SQLITE_OPEN_MAIN_DB); + this.#p.setAssociatedPath(sah, name, capi.SQLITE_OPEN_MAIN_DB); } - wipeFiles = async function(){ - return this.$p.reset(true); - } + async wipeFiles(){return this.#p.reset(true)} - unlink = function(filename){ - return this.$p.deletePath(filename); + unlink(filename){ + return this.#p.deletePath(filename); } - removeVfs = async function(){ - if(!this.$p.cVfs.pointer) return false; - capi.sqlite3_vfs_unregister(this.$p.cVfs.pointer); - this.$p.cVfs.dispose(); + async removeVfs(){ + if(!this.#p.cVfs.pointer) return false; + capi.sqlite3_vfs_unregister(this.#p.cVfs.pointer); + this.#p.cVfs.dispose(); try{ - this.$p.releaseAccessHandles(); - if(this.$p.parentDirHandle){ - await this.$p.parentDirHandle.removeEntry( - this.$p.dirHandle.name, {recursive: true} + this.#p.releaseAccessHandles(); + if(this.#p.parentDirHandle){ + await this.#p.parentDirHandle.removeEntry( + this.#p.dirHandle.name, {recursive: true} ); - this.$p.dirHandle = this.$p.parentDirHandle = undefined; + this.#p.dirHandle = this.#p.parentDirHandle = undefined; } }catch(e){ - console.error(this.$p.vfsName,"removeVfs() failed:",e); + sqlite3.config.error(this.#p.vfsName,"removeVfs() failed:",e); /*otherwise ignored - there is no recovery strategy*/ } return true; @@ -679,7 +678,7 @@ globalThis.sqlite3ApiBootstrap.initializersAsync.push(async function(sqlite3){ throw new Error("Just testing rejection."); } if(initPromises[vfsName]){ - //console.warn("Returning same OpfsSAHPool result",vfsName,initPromises[vfsName]); + console.warn("Returning same OpfsSAHPool result",options,vfsName,initPromises[vfsName]); return initPromises[vfsName]; } if(!globalThis.FileSystemHandle || @@ -743,6 +742,9 @@ globalThis.sqlite3ApiBootstrap.initializersAsync.push(async function(sqlite3){ ensues. */ return initPromises[vfsName] = apiVersionCheck().then(async function(){ + if(options.$testThrowInInit){ + throw options.$testThrowInInit; + } const thePool = new OpfsSAHPool(opfsVfs, options); return thePool.isReady.then(async()=>{ /** @@ -1025,4 +1027,4 @@ globalThis.sqlite3ApiBootstrap.initializersAsync.push(async function(sqlite3){ }); }).catch(promiseReject); }/*installOpfsSAHPoolVfs()*/; -}/*sqlite3ApiBootstrap.initializersAsync*/); +}/*sqlite3ApiBootstrap.initializers*/); diff --git a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js index 35b7b8865..7d313a263 100644 --- a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js +++ b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js @@ -23,7 +23,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ installOpfsVfs() returns a Promise which, on success, installs an sqlite3_vfs named "opfs", suitable for use with all sqlite3 APIs which accept a VFS. It is intended to be called via - sqlite3ApiBootstrap.initializersAsync or an equivalent mechanism. + sqlite3ApiBootstrap.initializers or an equivalent mechanism. The installed VFS uses the Origin-Private FileSystem API for all file storage. On error it is rejected with an exception |