sqlite3-api.jses += $(dir.jacc)/jaccwabyt.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-glue.js
sqlite3-api.jses += $(sqlite3-api-build-version.js)
+sqlite3-api.jses += $(dir.api)/sqlite3-vfs-helper.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-opfs.js
together, in the listed order, the resulting file is loaded by a
browser client:
-- `sqlite3-api-prologue.js`\
+- **`sqlite3-api-prologue.js`**\
Contains the initial bootstrap setup of the sqlite3 API
objects. This is exposed as a function, rather than objects, so that
the next step can pass in a config object which abstracts away parts
of the WASM environment, to facilitate plugging it in to arbitrary
WASM toolchains.
-- `../common/whwasmutil.js`\
+- **`../common/whwasmutil.js`**\
A semi-third-party collection of JS/WASM utility code intended to
replace much of the Emscripten glue. The sqlite3 APIs internally use
these APIs instead of their Emscripten counterparts, in order to be
toolchains. It is "semi-third-party" in that it was created in order
to support this tree but is standalone and maintained together
with...
-- `../jaccwabyt/jaccwabyt.js`\
+- **`../jaccwabyt/jaccwabyt.js`**\
Another semi-third-party API which creates bindings between JS
and C structs, such that changes to the struct state from either JS
or C are visible to the other end of the connection. This is also an
independent spinoff project, conceived for the sqlite3 project but
maintained separately.
-- `sqlite3-api-glue.js`\
+- **`sqlite3-api-glue.js`**\
Invokes functionality exposed by the previous two files to
flesh out low-level parts of `sqlite3-api-prologue.js`. Most of
these pieces related to the `sqlite3.capi.wasm` object.
-- `sqlite3-api-build-version.js`\
+- **`sqlite3-api-build-version.js`**\
Gets created by the build process and populates the
`sqlite3.version` object. This part is not critical, but records the
version of the library against which this module was built.
-- `sqlite3-api-oo1.js`\
+- **`sqlite3-vfs-helper.js`**\
+ This internal-use-only file installs `sqlite3.VfsHelper` for use by
+ `sqlite3-api-*.js` files which create `sqlite3_vfs` implemenations.
+ `sqlite3.VfsHelper` gets removed from the the `sqlite3` object after
+ the library is finished initializing.
+- **`sqlite3-api-oo1.js`**\
Provides a high-level object-oriented wrapper to the lower-level C
API, colloquially known as OO API #1. Its API is similar to other
high-level sqlite3 JS wrappers and should feel relatively familiar
to anyone familiar with such APIs. That said, it is not a "required
component" and can be elided from builds which do not want it.
-- `sqlite3-api-worker1.js`\
+- **`sqlite3-api-worker1.js`**\
A Worker-thread-based API which uses OO API #1 to provide an
interface to a database which can be driven from the main Window
thread via the Worker message-passing interface. Like OO API #1,
this is an optional component, offering one of any number of
potential implementations for such an API.
- - `sqlite3-worker1.js`\
+ - **`sqlite3-worker1.js`**\
Is not part of the amalgamated sources and is intended to be
loaded by a client Worker thread. It loads the sqlite3 module
and runs the Worker #1 API which is implemented in
`sqlite3-api-worker1.js`.
- - `sqlite3-worker1-promiser.js`\
+ - **`sqlite3-worker1-promiser.js`**\
Is likewise not part of the amalgamated sources and provides
a Promise-based interface into the Worker #1 API. This is
a far user-friendlier way to interface with databases running
in a Worker thread.
-- `sqlite3-api-opfs.js`\
+- **`sqlite3-api-opfs.js`**\
is an sqlite3 VFS implementation which supports Google Chrome's
Origin-Private FileSystem (OPFS) as a storage layer to provide
persistent storage for database files in a browser. It requires...
- - `sqlite3-opfs-async-proxy.js`\
+ - **`sqlite3-opfs-async-proxy.js`**\
is the asynchronous backend part of the OPFS proxy. It speaks
directly to the (async) OPFS API and channels those results back
to its synchronous counterpart. This file, because it must be
initModuleState.sqlite3Dir = li.join('/') + '/';
}
- self.sqlite3InitModule = (...args)=>{
+ self.sqlite3InitModule = function ff(...args){
//console.warn("Using replaced sqlite3InitModule()",self.location);
return originalInit(...args).then((EmscriptenModule)=>{
if(self.window!==self &&
Emscripten details. */
return EmscriptenModule;
}
- EmscriptenModule.sqlite3.scriptInfo = initModuleState;
- //console.warn("sqlite3.scriptInfo =",EmscriptenModule.sqlite3.scriptInfo);
- const f = EmscriptenModule.sqlite3.asyncPostInit;
- delete EmscriptenModule.sqlite3.asyncPostInit;
+ const s = EmscriptenModule.sqlite3;
+ s.scriptInfo = initModuleState;
+ //console.warn("sqlite3.scriptInfo =",s.scriptInfo);
+ if(ff.__isUnderTest) s.__isUnderTest = true;
+ const f = s.asyncPostInit;
+ delete s.asyncPostInit;
return f();
}).catch((e)=>{
console.error("Exception loading sqlite3 module:",e);
self.S = sqlite3;
}
- /* Clean up temporary references to our APIs... */
- delete sqlite3.util /* arguable, but these are (currently) internal-use APIs */;
Module.sqlite3 = sqlite3 /* Needed for customized sqlite3InitModule() to be able to
pass the sqlite3 object off to the client. */;
}else{
const log = (...args)=>logImpl(2, ...args);
const warn = (...args)=>logImpl(1, ...args);
const error = (...args)=>logImpl(0, ...args);
- const toss = function(...args){throw new Error(args.join(' '))};
+ const toss = sqlite3.util.toss;
const capi = sqlite3.capi;
const wasm = sqlite3.wasm;
const sqlite3_vfs = capi.sqlite3_vfs;
s.count = s.time = 0;
}
}/*metrics*/;
+ const opfsVfs = new sqlite3_vfs();
+ const opfsIoMethods = new sqlite3_io_methods();
const promiseReject = function(err){
opfsVfs.dispose();
return promiseReject_(err);
? new sqlite3_vfs(pDVfs)
: null /* dVfs will be null when sqlite3 is built with
SQLITE_OS_OTHER. */;
- const opfsVfs = new sqlite3_vfs();
- const opfsIoMethods = new sqlite3_io_methods();
opfsVfs.$iVersion = 2/*yes, two*/;
opfsVfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof;
opfsVfs.$mxPathname = 1024/*sure, why not?*/;
*/
const __openFiles = Object.create(null);
- /**
- Installs a StructBinder-bound function pointer member of the
- given name and function in the given StructType target object.
- It creates a WASM proxy for the given function and arranges for
- that proxy to be cleaned up when tgt.dispose() is called. Throws
- on the slightest hint of error (e.g. tgt is-not-a StructType,
- name does not map to a struct-bound member, etc.).
-
- Returns a proxy for this function which is bound to tgt and takes
- 2 args (name,func). That function returns the same thing,
- permitting calls to be chained.
-
- If called with only 1 arg, it has no side effects but returns a
- func with the same signature as described above.
- */
- const installMethod = function callee(tgt, name, func){
- if(!(tgt instanceof sqlite3.StructBinder.StructType)){
- toss("Usage error: target object is-not-a StructType.");
- }
- if(1===arguments.length){
- return (n,f)=>callee(tgt,n,f);
- }
- if(!callee.argcProxy){
- callee.argcProxy = function(func,sig){
- return function(...args){
- if(func.length!==arguments.length){
- toss("Argument mismatch. Native signature is:",sig);
- }
- return func.apply(this, args);
- }
- };
- callee.removeFuncList = function(){
- if(this.ondispose.__removeFuncList){
- this.ondispose.__removeFuncList.forEach(
- (v,ndx)=>{
- if('number'===typeof v){
- try{wasm.uninstallFunction(v)}
- catch(e){/*ignore*/}
- }
- /* else it's a descriptive label for the next number in
- the list. */
- }
- );
- delete this.ondispose.__removeFuncList;
- }
- };
- }/*static init*/
- const sigN = tgt.memberSignature(name);
- if(sigN.length<2){
- toss("Member",name," is not a function pointer. Signature =",sigN);
- }
- const memKey = tgt.memberKey(name);
- const fProxy = 0
- /** This middle-man proxy is only for use during development, to
- confirm that we always pass the proper number of
- arguments. We know that the C-level code will always use the
- correct argument count. */
- ? callee.argcProxy(func, sigN)
- : func;
- const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name, true));
- tgt[memKey] = pFunc;
- if(!tgt.ondispose) tgt.ondispose = [];
- if(!tgt.ondispose.__removeFuncList){
- tgt.ondispose.push('ondispose.__removeFuncList handler',
- callee.removeFuncList);
- tgt.ondispose.__removeFuncList = [];
- }
- tgt.ondispose.__removeFuncList.push(memKey, pFunc);
- return (n,f)=>callee(tgt, n, f);
- }/*installMethod*/;
-
const opTimer = Object.create(null);
opTimer.op = undefined;
opTimer.start = undefined;
success) release a sync-handle for it, but doing so would
involve an inherent race condition. For the time being,
pending a better solution, we simply report whether the
- given pFile instance has a lock.
+ given pFile is open.
+
+ FIXME: we need to ask the async half whether a lock is
+ held, as it's possible (since long after this method was
+ implemented) that we do not hold a lock on an OPFS file.
*/
const f = __openFiles[pFile];
wasm.setMemValue(pOut, f.lockMode ? 1 : 0, 'i32');
};
}
- /* Install the vfs/io_methods into their C-level shared instances... */
- for(let k of Object.keys(ioSyncWrappers)){
- installMethod(opfsIoMethods, k, ioSyncWrappers[k]);
- }
- for(let k of Object.keys(vfsSyncWrappers)){
- installMethod(opfsVfs, k, vfsSyncWrappers[k]);
- }
-
/**
Expects an OPFS file path. It gets resolved, such that ".."
components are properly expanded, and returned. If the 2nd arg
Irrevocably deletes _all_ files in the current origin's OPFS.
Obviously, this must be used with great caution. It may throw
an exception if removal of anything fails (e.g. a file is
- locked), but the precise conditions under which it will throw
- are not documented (so we cannot tell you what they are).
+ locked), but the precise conditions under which the underlying
+ APIs will throw are not documented (so we cannot tell you what
+ they are).
*/
opfsUtil.rmfr = async function(){
const dir = opfsUtil.rootDirectory, opt = {recurse: true};
and has finished initializing, so the real work can
begin...*/
try {
- const rc = capi.sqlite3_vfs_register(opfsVfs.pointer, 0);
- if(rc){
- toss("sqlite3_vfs_register(OPFS) failed with rc",rc);
- }
- if(opfsVfs.pointer !== capi.sqlite3_vfs_find("opfs")){
- toss("BUG: sqlite3_vfs_find() failed for just-installed OPFS VFS");
- }
- capi.sqlite3_vfs_register.addReference(opfsVfs, opfsIoMethods);
+ sqlite3.VfsHelper.installVfs({
+ io: {struct: opfsIoMethods, methods: ioSyncWrappers},
+ vfs: {struct: opfsVfs, methods: vfsSyncWrappers}
+ });
state.sabOPView = new Int32Array(state.sabOP);
state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize);
state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize);
isBindableTypedArray,
isInt32, isSQLableTypedArray, isTypedArray,
typedArrayToString,
- isUIThread: ()=>'undefined'===typeof WorkerGlobalScope,
+ isUIThread: ()=>(self.window===self && !!self.document),
+ // is this true for ESM?: 'undefined'===typeof WorkerGlobalScope
isSharedTypedArray,
+ toss: function(...args){throw new Error(args.join(' '))},
+ toss3,
typedArrayPart
};
//let p = lip.shift();
//while(lip.length) p = p.then(lip.shift());
//return p.then(()=>sqlite3);
- return Promise.all(lip).then(()=>sqlite3);
+ return Promise.all(lip).then(()=>{
+ if(!sqlite3.__isUnderTest){
+ /* Delete references to internal-only APIs which are used by
+ some initializers. Retain them when running in test mode
+ so that we can add tests for them. */
+ delete sqlite3.util;
+ delete sqlite3.VfsHelper;
+ delete sqlite3.StructBinder;
+ }
+ return sqlite3;
+ });
},
/**
scriptInfo ideally gets injected into this object by the
--- /dev/null
+/*
+** 2022-11-30
+**
+** 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 installs sqlite.VfsHelper, an object which exists
+ to assist in the creation of JavaScript implementations of
+ sqlite3_vfs. It is NOT part of the public API, and is an
+ internal implemenation detail for use in this project's
+ own development of VFSes. It may be exposed to clients
+ at some point, provided there is value in doing so.
+*/
+'use strict';
+self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
+ const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss;
+ const vh = Object.create(null);
+
+ /**
+ Does nothing more than holds a permanent reference to each
+ argument. This is useful in some cases to ensure that, e.g., a
+ custom sqlite3_io_methods instance does not get
+ garbage-collected.
+
+ Returns this object.
+ */
+ vh.holdReference = function(...args){
+ for(const v of args) this.refs.add(v);
+ return vh;
+ }.bind({refs: new Set});
+
+ /**
+ Installs a StructBinder-bound function pointer member of the
+ given name and function in the given StructType target object.
+ It creates a WASM proxy for the given function and arranges for
+ that proxy to be cleaned up when tgt.dispose() is called. Throws
+ on the slightest hint of error, e.g. tgt is-not-a StructType,
+ name does not map to a struct-bound member, etc.
+
+ If applyArgcCheck is true then each method gets wrapped in a
+ proxy which asserts that it is passed the expected number of
+ arguments, throwing if the argument count does not match
+ expectations. That is only recommended for dev-time usage for
+ sanity checking. Once a VFS implementation is known to be
+ working, it is a given that the C API will never call it with the
+ wrong argument count.
+
+ Returns a proxy for this function which is bound to tgt and takes
+ 2 args (name,func). That function returns the same thing,
+ permitting calls to be chained.
+
+ If called with only 1 arg, it has no side effects but returns a
+ func with the same signature as described above.
+
+ If tgt.ondispose is set before this is called then it _must_
+ be an array, to which this function will append entries.
+ */
+ vh.installMethod = function callee(tgt, name, func,
+ applyArgcCheck=callee.installMethodArgcCheck){
+ if(!(tgt instanceof sqlite3.StructBinder.StructType)){
+ toss("Usage error: target object is-not-a StructType.");
+ }
+ if(1===arguments.length){
+ return (n,f)=>callee(tgt, n, f, applyArgcCheck);
+ }
+ if(!callee.argcProxy){
+ callee.argcProxy = function(func,sig){
+ return function(...args){
+ if(func.length!==arguments.length){
+ toss("Argument mismatch. Native signature is:",sig);
+ }
+ return func.apply(this, args);
+ }
+ };
+ /* An ondispose() callback for use with
+ sqlite3.StructBinder-created types. */
+ callee.removeFuncList = function(){
+ if(this.ondispose.__removeFuncList){
+ this.ondispose.__removeFuncList.forEach(
+ (v,ndx)=>{
+ if('number'===typeof v){
+ try{wasm.uninstallFunction(v)}
+ catch(e){/*ignore*/}
+ }
+ /* else it's a descriptive label for the next number in
+ the list. */
+ }
+ );
+ delete this.ondispose.__removeFuncList;
+ }
+ };
+ }/*static init*/
+ const sigN = tgt.memberSignature(name);
+ if(sigN.length<2){
+ toss("Member",name," is not a function pointer. Signature =",sigN);
+ }
+ const memKey = tgt.memberKey(name);
+ const fProxy = applyArgcCheck
+ /** This middle-man proxy is only for use during development, to
+ confirm that we always pass the proper number of
+ arguments. We know that the C-level code will always use the
+ correct argument count. */
+ ? callee.argcProxy(func, sigN)
+ : func;
+ const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name, true));
+ tgt[memKey] = pFunc;
+ if(!tgt.ondispose) tgt.ondispose = [];
+ if(!tgt.ondispose.__removeFuncList){
+ tgt.ondispose.push('ondispose.__removeFuncList handler',
+ callee.removeFuncList);
+ tgt.ondispose.__removeFuncList = [];
+ }
+ tgt.ondispose.__removeFuncList.push(memKey, pFunc);
+ return (n,f)=>callee(tgt, n, f, applyArgcCheck);
+ }/*installMethod*/;
+ vh.installMethod.installMethodArgcCheck = false;
+
+ /**
+ Installs methods into the given StructType-type object. Each
+ entry in the given methods object must map to a known member of
+ the given StructType, else an exception will be triggered.
+ See installMethod() for more details, including the semantics
+ of the 3rd argument.
+
+ On success, passes its first argument to holdRefence() and
+ returns this object. Throws on error.
+ */
+ vh.installMethods = function(structType, methods,
+ applyArgcCheck=vh.installMethod.installMethodArgcCheck){
+ for(const k of Object.keys(methods)){
+ vh.installMethod(structType, k, methods[k], applyArgcCheck);
+ }
+ return vh.holdReference(structType);
+ };
+
+ /**
+ Uses sqlite3_vfs_register() to register the
+ sqlite3.capi.sqlite3_vfs-type vfs, which must have already been
+ filled out properly. If the 2nd argument is truthy, the VFS is
+ registered as the default VFS, else it is not.
+
+ On success, passes its first argument to this.holdReference() and
+ returns this object. Throws on error.
+ */
+ vh.registerVfs = function(vfs, asDefault=false){
+ if(!(vfs instanceof sqlite3.capi.sqlite3_vfs)){
+ toss("Expecting a sqlite3_vfs-type argument.");
+ }
+ const rc = capi.sqlite3_vfs_register(vfs.pointer, asDefault ? 1 : 0);
+ if(rc){
+ toss("sqlite3_vfs_register(",vfs,") failed with rc",rc);
+ }
+ if(vfs.pointer !== capi.sqlite3_vfs_find(vfs.$zName)){
+ toss("BUG: sqlite3_vfs_find(vfs.$zName) failed for just-installed VFS",
+ vfs);
+ }
+ return vh.holdReference(vfs);
+ };
+
+ /**
+ A wrapper for installMethods() or registerVfs() to reduce
+ installation of a VFS and/or its I/O methods to a single
+ call.
+
+ Accepts an object which contains the properties "io" and/or
+ "vfs", each of which is itself an object with following properties:
+
+ - `struct`: an sqlite3.StructType-type struct. This must be a
+ populated (except for the methods) object of type
+ sqlite3_io_methods (for the "io" entry) or sqlite3_vfs (for the
+ "vfs" entry).
+
+ - `methods`: an object mapping sqlite3_io_methods method names
+ (e.g. 'xClose') to JS implementations of those methods.
+
+ For each of those object, this function passes its (`struct`,
+ `methods`, (optional) `applyArgcCheck`) properties to
+ this.installMethods().
+
+ If the `vfs` entry is set, its `struct` property is passed
+ to this.registerVfs(). The `vfs` entry may optionally have
+ an `asDefault` property, which gets passed as the 2nd
+ argument to registerVfs().
+
+ On success returns this object. Throws on error.
+ */
+ vh.installVfs = function(opt){
+ let count = 0;
+ for(const key of ['io','vfs']){
+ const o = opt[key];
+ if(o){
+ ++count;
+ this.installMethods(o.struct, o.methods, !!o.applyArgcCheck);
+ if('vfs'===key) this.registerVfs(o.struct, !!o.asDefault);
+ }
+ }
+ if(!count) toss("Misue: installVfs() options object requires at least",
+ "one of 'io' or 'vfs' properties.");
+ return this;
+ };
+
+ sqlite3.VfsHelper = vh;
+}/*sqlite3ApiBootstrap.initializers.push()*/);
}
importScripts(sqlite3Js);
}
+ self.sqlite3InitModule.__isUnderTest =
+ true /* disables certain API-internal cleanup so that we can
+ test internal APIs from here */;
self.sqlite3InitModule({
print: log,
printErr: error
-C Doc\sand\slogging\stext\stweaks\sin\sthe\sOPFS\sasync\sproxy\sand\stest\sapp.
-D 2022-11-30T03:08:50.289
+C Refactor\sa\ssignificant\schunk\sof\sthe\sOPFS\ssqlite3_vfs\sinit\scode\sinto\ssqlite3.VfsHelper,\sand\sinternal-use-only\sAPI\sencapsulating\scode\srelevant\sto\screating\snew\sVFSes\sin\sJS.\sIntended\sto\sassist\sin\spending\sexperimentation\swith\san\salternative\sOPFS\sVFS.
+D 2022-11-30T05:27:36.071
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
-F ext/wasm/GNUmakefile bc1696a1189f4c571b3d878b8f3a67c1f4b52c222f52d356027a5a0c707337c7
+F ext/wasm/GNUmakefile a1a94ff422be90c06263055aec4c569fe3e4ffb3e8cc7f954fd2739aefa52292
F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20
F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api b4d68c97d14944b48d55e06aa44f544a6f56a7fa2bcb6f9e030936a5b2a9479a
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
-F ext/wasm/api/README.md 29276a845e57004e82efba61fa5866fd05f9137380a1dc26dc4c6d65264cd81c
-F ext/wasm/api/extern-post-js.js 59e52f579cd3a332d73dae94c91b9579daafb10dd6ada03803f1afa6bdad7689
+F ext/wasm/api/README.md 44d1ea63a990678e373f17ff4b08c2f8599e5a5754b7394e76f7e52164f307c0
+F ext/wasm/api/extern-post-js.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08902f15c34720ee4a1
F ext/wasm/api/post-js-header.js d6ab3dfef4a06960d28a7eaa338d4e2a1a5981e9b38718168bbde8fdb2a439b8
F ext/wasm/api/pre-js.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
-F ext/wasm/api/sqlite3-api-cleanup.js ecdc69dbfccfe26146f04799fcfd4a6f5790d46e7e3b9b6e9b0491f92ed8ae34
+F ext/wasm/api/sqlite3-api-cleanup.js 6a22a3287b34a2b4b0f8127614242e8307cce31ac060eb705a89a6d04dcb1028
F ext/wasm/api/sqlite3-api-glue.js 056f44b82c126358a0175e08a892d56fadfce177b0d7a0012502a6acf67ea6d5
F ext/wasm/api/sqlite3-api-oo1.js 06ad2079368e16cb9f182c18cd37bdc3932536856dff4f60582d0ca5f6c491a8
-F ext/wasm/api/sqlite3-api-opfs.js 2f99c9b2c3c0f53bf40153de20db350378deed825ec0d5cf8f449e9e0081f08b
-F ext/wasm/api/sqlite3-api-prologue.js 7fce4c6a138ec3d7c285b7c125cee809e6b668d2cb0d2328a1b790b7037765bd
+F ext/wasm/api/sqlite3-api-opfs.js e36eec4535dab2da186c1fc743b8fb3a37b21a7c61425546d748a3038c25efab
+F ext/wasm/api/sqlite3-api-prologue.js 09fa4bf1e29596e599ead649003e01691419ffcb12d0f617152d577741973227
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
F ext/wasm/api/sqlite3-opfs-async-proxy.js 315582a4fe3b87ceaff69ad4a67d68a350b8014ac94d6a584d09ea922453c983
+F ext/wasm/api/sqlite3-vfs-helper.js 0b1de47e4407a414db1ee0ca3f9916ae74a9655fe1b1145d4a08e2b52f1ee25f
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 8b32787a3b6bb2990cbaba2304bd5b75a9652acbc8d29909b3279019b6cbaef5
F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
F ext/wasm/tester1-worker.html 5ef353348c37cf2e4fd0b23da562d3275523e036260b510734e9a3239ba8c987
F ext/wasm/tester1.c-pp.html 74aa9b31c75f12490653f814b53c3dd39f40cd3f70d6a53a716f4e8587107399
-F ext/wasm/tester1.c-pp.js a4b6a165aafcd3b86118efaec6b47c70fbb6c64b5ab86d21ca8c250d42617dfa
+F ext/wasm/tester1.c-pp.js 5820d578b67835aaf651230663dd207237071ee1f16f11a9c5168500aae04a50
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
F ext/wasm/tests/opfs/concurrency/test.js bfc3d7e27b207f0827f12568986b8d516a744529550b449314f5c21c9e9faf4a
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d0c8fa30a31c691bc1be5e98d806eeb1e23a8fc6cd54d87e5c1b720aa936e707
-R 05044488394ac3d7b358270198570ce0
+P 7ce8608e221924d2c7067687eb6eef0f3cab181d5b4132e55a67d8514b6ce94b
+R 51f96a0acaea8419465c60238f6c368c
U stephan
-Z cb806f606aa315e69c2e3fceeb852a45
+Z aa663f409b5ddaba03a8fcd513053db4
# Remove this line to create a well-formed Fossil manifest.
-7ce8608e221924d2c7067687eb6eef0f3cab181d5b4132e55a67d8514b6ce94b
\ No newline at end of file
+e25d7b080a807e35b32cb885ea75b384130e5c6e936dfef783c5b45d9bfe77d8
\ No newline at end of file