independent spinoff project, conceived for the sqlite3 project but
maintained separately.
- `sqlite3-api-glue.js`\
- Invokes the function exposed by `sqlite3-api-prologue.js`, passing
- it a configuration object to configure it for the current WASM
- toolchain (noting that it currently requires Emscripten), then
- removes that function from the global scope. The result of this file
- is a global-scope `sqlite3` object which acts as a namespace for the
- API's functionality. This object gets removed from the global scope
- after the following files have attached their own features to it.
+ 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-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
};
}/*sqlite3_exec() proxy*/;
+ if(1){/* Special-case handling of sqlite3_create_function_v2() */
+ const sqlite3CreateFunction = wasm.xWrap(
+ "sqlite3_create_function_v2", "int",
+ ["sqlite3*", "string", "int", "int", "*",
+ "*", "*", "*", "*"]
+ );
+ const __setResult = function(pCx, val){
+ switch(typeof val) {
+ case 'boolean':
+ capi.sqlite3_result_int(pCx, val ? 1 : 0);
+ break;
+ case 'number': {
+ (util.isInt32(val)
+ ? capi.sqlite3_result_int
+ : capi.sqlite3_result_double)(pCx, val);
+ break;
+ }
+ case 'string':
+ capi.sqlite3_result_text(pCx, val, -1, capi.SQLITE_TRANSIENT);
+ break;
+ case 'object':
+ if(null===val) {
+ capi.sqlite3_result_null(pCx);
+ break;
+ }else if(util.isBindableTypedArray(val)){
+ const pBlob = wasm.allocFromTypedArray(val);
+ capi.sqlite3_result_blob(pCx, pBlob, val.byteLength,
+ capi.SQLITE_TRANSIENT);
+ wasm.dealloc(pBlob);
+ break;
+ }
+ // else fall through
+ default:
+ toss3("Don't not how to handle this UDF result value:",val);
+ };
+ }/*__setResult()*/;
+ const __extractArgs = function(argc, pArgv){
+ let i, pVal, valType, arg;
+ const tgt = [];
+ for(i = 0; i < argc; ++i){
+ pVal = wasm.getPtrValue(pArgv + (wasm.ptrSizeof * i));
+ /**
+ Curiously: despite ostensibly requiring 8-byte
+ alignment, the pArgv array is parcelled into chunks of
+ 4 bytes (1 pointer each). The values those point to
+ have 8-byte alignment but the individual argv entries
+ do not.
+ */
+ valType = capi.sqlite3_value_type(pVal);
+ switch(valType){
+ case capi.SQLITE_INTEGER:
+ case capi.SQLITE_FLOAT:
+ arg = capi.sqlite3_value_double(pVal);
+ break;
+ case capi.SQLITE_TEXT:
+ arg = capi.sqlite3_value_text(pVal);
+ break;
+ case capi.SQLITE_BLOB:{
+ const n = capi.sqlite3_value_bytes(pVal);
+ const pBlob = capi.sqlite3_value_blob(pVal);
+ arg = new Uint8Array(n);
+ let i;
+ const heap = n ? wasm.heap8() : false;
+ for(i = 0; i < n; ++i) arg[i] = heap[pBlob+i];
+ break;
+ }
+ case capi.SQLITE_NULL:
+ arg = null; break;
+ default:
+ toss3("Unhandled sqlite3_value_type()",valType,
+ "is possibly indicative of incorrect",
+ "pointer size assumption.");
+ }
+ tgt.push(arg);
+ }
+ return tgt;
+ }/*__extractArgs()*/;
+
+ const __setCxErr = (pCx, e)=>{
+ if(e instanceof capi.WasmAllocError){
+ capi.sqlite3_result_error_nomem(pCx);
+ }else{
+ capi.sqlite3_result_error(pCx, e.message, -1);
+ }
+ };
+
+ const __xFunc = function(callback){
+ return function(pCx, argc, pArgv){
+ try{__setResult(pCx, callback(...__extractArgs(argc, pArgv)))}
+ catch(e){ __setCxErr(pCx, e) }
+ };
+ };
+
+ const __xStep = function(callback){
+ return function(pCx, argc, pArgv){
+ try{ callback(...__extractArgs(argc, pArgv)) }
+ catch(e){ __setCxErr(pCx, e) }
+ };
+ };
+
+ const __xFinal = function(callback){
+ return function(pCx){
+ try{ __setResult(pCx, callback()) }
+ catch(e){ __setCxErr(pCx, e) }
+ };
+ };
+
+ const __xDestroy = function(callback){
+ return function(pVoid){
+ try{ callback(pVoid) }
+ catch(e){
+ console.error("UDF xDestroy method threw:",e);
+ }
+ };
+ };
+ /* Documented in the api object's initializer. */
+ capi.sqlite3_create_function_v2 = function f(
+ pDb, funcName, nArg, eTextRep, pApp,
+ xFunc, //void (*xFunc)(sqlite3_context*,int,sqlite3_value**)
+ xStep, //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
+ xFinal, //void (*xFinal)(sqlite3_context*)
+ xDestroy //void (*xDestroy)(void*)
+ ){
+ if(9!==arguments.length){
+ return __dbArgcMismatch(pDb,"sqlite3_create_function_v2",9);
+ }
+ if(!f._sigs){
+ f._wrap = Object.assign(Object.create(null), {
+ xFunc: {sig:'v(pip)', f:__xFunc},
+ xStep: {sig:'v(pip)', f:__xStep},
+ xFinal: {sig:'v(p)', f:__xFinal},
+ xDestroy: {sig:'v(p)', f:__xDestroy}
+ });
+ }
+ const callbacks = [];
+ /* Wrap the callbacks in a WASM-bound functions... */
+ const wasm = capi.wasm;
+ const funcArgs = [], uninstall = [/*funcs to uninstall on error*/],
+ theFuncs = {xFunc, xStep, xFinal, xDestroy};
+ let rc;
+ try{
+ let k;
+ for(k in theFuncs){
+ let fArg = theFuncs[k];
+ if('function'===typeof fArg){
+ const w = f._wrap[k];
+ fArg = wasm.installFunction(w.sig, w.f(fArg));
+ uninstall.push(fArg);
+ }
+ funcArgs.push(fArg);
+ }
+ rc = sqlite3CreateFunction(pDb, funcName, nArg, eTextRep,
+ pApp, ...funcArgs);
+ }catch(e){
+ console.error("sqlite3_create_function_v2() setup threw:",e);
+ for(let v of uninstall){
+ wasm.uninstallFunction(v);
+ }
+ rc = util.sqlite3_wasm_db_error(pDb, capi.SQLITE_ERROR,
+ "Creation of UDF threw: "+e.message);
+ }
+ return rc;
+ };
+
+ capi.sqlite3_create_function = function(
+ pDb, funcName, nArg, eTextRep, pApp,
+ xFunc, xStep, xFinal
+ ){
+ if(8!==arguments.length){
+ return __dbArgcMismatch(pDb,"sqlite3_create_function",8);
+ }
+ return capi.sqlite3_create_function_v2(pDb, funcName, nArg, eTextRep,
+ pApp, xFunc, xStep, xFinal, 0);
+
+ };
+ }/*sqlite3_create_function_v2() proxy*/;
+
if(1){/* Special-case handling of sqlite3_prepare_v2() and
sqlite3_prepare_v3() */
/**
it.
*/
const __ptrMap = new WeakMap();
- /**
- Map of DB instances to objects, each object being a map of UDF
- names to wasm function _pointers_ added to that DB handle via
- createFunction().
- */
- const __udfMap = new WeakMap();
/**
Map of DB instances to objects, each object being a map of Stmt
wasm pointers to Stmt objects.
this.filename = fnJs;
__ptrMap.set(this, ptr);
__stmtMap.set(this, Object.create(null));
- __udfMap.set(this, Object.create(null));
};
/**
Object.keys(__stmtMap.get(this)).forEach((k,s)=>{
if(s && s.pointer) s.finalize();
});
- Object.values(__udfMap.get(this)).forEach(
- wasm.uninstallFunction.bind(capi.wasm)
- );
__ptrMap.delete(this);
__stmtMap.delete(this);
- __udfMap.delete(this);
capi.sqlite3_close_v2(pDb);
if(this.onclose && (this.onclose.after instanceof Function)){
try{this.onclose.after(this)}
On success, returns this object. Throws on error.
- When called from SQL, arguments to the UDF, and its result,
- will be converted between JS and SQL with as much fidelity
- as is feasible, triggering an exception if a type
- conversion cannot be determined. Some freedom is afforded
- to numeric conversions due to friction between the JS and C
- worlds: integers which are larger than 32 bits will be
- treated as doubles, as JS does not support 64-bit integers
- and it is (as of this writing) illegal to use WASM
- functions which take or return 64-bit integers from JS.
+ When called from SQL arguments to the UDF, and its result,
+ will be converted between JS and SQL with as much fidelity as
+ is feasible, triggering an exception if a type conversion
+ cannot be determined. The docs for sqlite3_create_function_v2()
+ describe the conversions in more detail.
The optional options object may contain flags to modify how
the function is defined:
- .deterministic = SQLITE_DETERMINISTIC
- .directOnly = SQLITE_DIRECTONLY
- .innocuous = SQLITE_INNOCUOUS
-
- Maintenance reminder: the ability to add new
- WASM-accessible functions to the runtime requires that the
- WASM build is compiled with emcc's `-sALLOW_TABLE_GROWTH`
- flag.
*/
createFunction: function f(name, callback,opt){
switch(arguments.length){
}else if('string' !== typeof name){
toss3("Invalid arguments: missing function name.");
}
- if(!f._extractArgs){
- /* Static init */
- f._extractArgs = function(argc, pArgv){
- let i, pVal, valType, arg;
- const tgt = [];
- for(i = 0; i < argc; ++i){
- pVal = wasm.getPtrValue(pArgv + (wasm.ptrSizeof * i));
- /**
- Curiously: despite ostensibly requiring 8-byte
- alignment, the pArgv array is parcelled into chunks of
- 4 bytes (1 pointer each). The values those point to
- have 8-byte alignment but the individual argv entries
- do not.
- */
- valType = capi.sqlite3_value_type(pVal);
- switch(valType){
- case capi.SQLITE_INTEGER:
- case capi.SQLITE_FLOAT:
- arg = capi.sqlite3_value_double(pVal);
- break;
- case capi.SQLITE_TEXT:
- arg = capi.sqlite3_value_text(pVal);
- break;
- case capi.SQLITE_BLOB:{
- const n = capi.sqlite3_value_bytes(pVal);
- const pBlob = capi.sqlite3_value_blob(pVal);
- arg = new Uint8Array(n);
- let i;
- const heap = n ? wasm.heap8() : false;
- for(i = 0; i < n; ++i) arg[i] = heap[pBlob+i];
- break;
- }
- case capi.SQLITE_NULL:
- arg = null; break;
- default:
- toss3("Unhandled sqlite3_value_type()",valType,
- "is possibly indicative of incorrect",
- "pointer size assumption.");
- }
- tgt.push(arg);
- }
- return tgt;
- }/*_extractArgs()*/;
- f._setResult = function(pCx, val){
- switch(typeof val) {
- case 'boolean':
- capi.sqlite3_result_int(pCx, val ? 1 : 0);
- break;
- case 'number': {
- (util.isInt32(val)
- ? capi.sqlite3_result_int
- : capi.sqlite3_result_double)(pCx, val);
- break;
- }
- case 'string':
- capi.sqlite3_result_text(pCx, val, -1, capi.SQLITE_TRANSIENT);
- break;
- case 'object':
- if(null===val) {
- capi.sqlite3_result_null(pCx);
- break;
- }else if(util.isBindableTypedArray(val)){
- const pBlob = wasm.allocFromTypedArray(val);
- capi.sqlite3_result_blob(pCx, pBlob, val.byteLength,
- capi.SQLITE_TRANSIENT);
- wasm.dealloc(pBlob);
- break;
- }
- // else fall through
- default:
- toss3("Don't not how to handle this UDF result value:",val);
- };
- }/*_setResult()*/;
- }/*static init*/
- const wrapper = function(pCx, argc, pArgv){
- try{
- f._setResult(pCx, callback.apply(null, f._extractArgs(argc, pArgv)));
- }catch(e){
- if(e instanceof capi.WasmAllocError){
- capi.sqlite3_result_error_nomem(pCx);
- }else{
- capi.sqlite3_result_error(pCx, e.message, -1);
- }
- }
- };
- const pUdf = wasm.installFunction(wrapper, "v(iii)");
let fFlags = 0 /*flags for sqlite3_create_function_v2()*/;
if(getOwnOption(opt, 'deterministic')) fFlags |= capi.SQLITE_DETERMINISTIC;
if(getOwnOption(opt, 'directOnly')) fFlags |= capi.SQLITE_DIRECTONLY;
if(getOwnOption(opt, 'innocuous')) fFlags |= capi.SQLITE_INNOCUOUS;
name = name.toLowerCase();
- try {
- DB.checkRc(this, capi.sqlite3_create_function_v2(
- this.pointer, name,
- (opt.hasOwnProperty('arity') ? +opt.arity : callback.length),
- capi.SQLITE_UTF8 | fFlags, null/*pApp*/, pUdf,
- null/*xStep*/, null/*xFinal*/, null/*xDestroy*/));
- }catch(e){
- wasm.uninstallFunction(pUdf);
- throw e;
- }
- const udfMap = __udfMap.get(this);
- if(udfMap[name]){
- try{wasm.uninstallFunction(udfMap[name])}
- catch(e){/*ignore*/}
- }
- udfMap[name] = pUdf;
+ DB.checkRc(this, capi.sqlite3_create_function_v2(
+ this.pointer, name,
+ (opt.hasOwnProperty('arity') ? +opt.arity : callback.length),
+ capi.SQLITE_UTF8 | fFlags, null/*pApp*/, callback,
+ null/*xStep*/, null/*xFinal*/, null/*xDestroy*/));
return this;
}/*createFunction()*/,
/**
*/
const capi = {
/**
- When using sqlite3_open_v2() it is important to keep the following
- in mind:
-
- https://www.sqlite.org/c3ref/open.html
-
- - The flags for use with its 3rd argument are installed in this
- object using their C-side names, e.g. SQLITE_OPEN_CREATE.
-
- - If the combination of flags passed to it are invalid,
- behavior is undefined. Thus is is never okay to call this
- with fewer than 3 arguments, as JS will default the
- missing arguments to `undefined`, which will result in a
- flag value of 0. Most of the available SQLITE_OPEN_xxx
- flags are meaningless in the WASM build, e.g. the mutext-
- and cache-related flags, but they are retained in this
- API for consistency's sake.
-
- - The final argument to this function specifies the VFS to use,
- which is largely (but not entirely!) meaningless in the WASM
- environment. It may be null, undefined, or 0 to denote the
- default.
+ sqlite3_create_function_v2() differs from its native
+ counterpart only in the following ways:
+
+ 1) The fourth argument (`eTextRep`) argument must not specify
+ any encoding other than sqlite.SQLITE_UTF8. The JS API does not
+ currently support any other encoding and likely never
+ will. This function does not replace that argument on its own
+ because it may contain other flags.
+
+ 2) Any of the four final arguments may be either WASM pointers
+ (assumed to be function pointers) or JS Functions. In the
+ latter case, each gets bound to WASM using
+ sqlite3.capi.wasm.installFunction() and that wrapper is passed
+ on to the native implementation.
+
+ The semantics of JS functions are:
+
+ xFunc: is passed `(arrayOfValues)`. Its return value becomes
+ the new SQL function's result.
+
+ xStep: is passed `(arrayOfValues)`. Its return value is
+ ignored.
+
+ xFinal: is passed no arguments. Its return value becomes the
+ new aggragate SQL function's result.
+
+ xDestroy: is passed `(void*)`. Its return value is ignored. The
+ pointer passed to it is the one from the 5th argument to
+ sqlite3_create_function_v2().
+
+ Note that JS callback implementations have different call
+ signatures than their native counterparts (namely, they do not
+ get passed an `sqlite3_context*` argument) because practice has
+ shown that this is almost always more convenient and desirable
+ in JS code. Clients which need access to the full range of
+ native arguments will have to create a WASM-bound function
+ themselves (using wasm.installFunction() or equivalent) and
+ pass that function's WASM pointer to this function, rather than
+ passing a JS function. Be warned, however, that working with
+ UDFs at that level from JS is quite tedious.
+
+ For xFunc(), xStep(), and xFinal():
+
+ - When called from SQL, arguments to the UDF, and its result,
+ will be converted between JS and SQL with as much fidelity as
+ is feasible, triggering an exception if a type conversion
+ cannot be determined. Some freedom is afforded to numeric
+ conversions due to friction between the JS and C worlds:
+ integers which are larger than 32 bits will be treated as
+ doubles. TODO: use BigInt support if enabled. That feature
+ was added after this functionality was implemented.
+
+ If any JS-side functions throw, those exceptions are
+ intercepted and converted to database-side errors with
+ the exception of xFinal(): any exception from it is
+ ignored, possibly generating a console.error() message.
+ Destructors must not throw.
+
+ Once installed, there is currently no way to uninstall the
+ bound methods from WASM. They can be uninstalled from the
+ database as documented in the C API, but this wrapper currently
+ has no infrastructure in place to also free the WASM-bound JS
+ wrappers, effectively resulting in a memory leak if the client
+ uninstalls the UDF. Improving that is a potential TODO, but
+ removing client-installed UDFs is rare in practice.
+
+ Maintenance reminder: the ability to add new
+ WASM-accessible functions to the runtime requires that the
+ WASM build is compiled with emcc's `-sALLOW_TABLE_GROWTH`
+ flag.
*/
- sqlite3_open_v2: function(filename,dbPtrPtr,flags,vfsStr){}/*installed later*/,
+ sqlite3_create_function_v2: function(
+ pDb, funcName, nArg, eTextRep, pApp,
+ xFunc, //function(arrayOfValues)
+ xStep, //function(arrayOfValues)
+ xFinal, //function()
+ xDestroy //function(void*)
+ ){/*installed later*/},
+ /**
+ Equivalent to passing the same arguments to
+ sqlite3_create_function_v2(), with 0 as the final argument.
+ */
+ sqlite3_create_function:function(
+ pDb, funcName, nArg, eTextRep, pApp,
+ xFunc, //function(arrayOfValues)
+ xStep, //function(arrayOfValues)
+ xFinal //function()
+ ){/*installed later*/},
/**
The sqlite3_prepare_v3() binding handles two different uses
with differing JS/WASM semantics:
["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
["sqlite3_compileoption_get", "string", "int"],
["sqlite3_compileoption_used", "int", "string"],
- ["sqlite3_create_function_v2", "int",
- "sqlite3*", "string", "int", "int", "*", "*", "*", "*", "*"],
+ /* sqlite3_create_function_v2() is handled separate to simplify conversion
+ of its callback argument */
["sqlite3_data_count", "int", "sqlite3_stmt*"],
["sqlite3_db_filename", "string", "sqlite3*", "string"],
["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
https://fossil.wanderinghorse.net/r/jaccwabyt
+ and sqlite3:
+
+ https://sqlite.org
+
+ This file is kept in sync between both of those trees.
+
Maintenance reminder: If you're reading this in a tree other than
- the Jaccwabyt tree, note that this copy may be replaced with
+ one of those listed above, note that this copy may be replaced with
upstream copies of that one from time to time. Thus the code
- installed by this function "should not" be edited outside of that
- project, else it risks getting overwritten.
+ installed by this function "should not" be edited outside of those
+ projects, else it risks getting overwritten.
*/
/**
This function is intended to simplify porting around various bits
following symbols:
- `memory`: a WebAssembly.Memory object representing the WASM
- memory. _Alternately_, the `memory` property can be set on the
- target instance, in particular if the WASM heap memory is
+ memory. _Alternately_, the `memory` property can be set as
+ `target.memory`, in particular if the WASM heap memory is
initialized in JS an _imported_ into WASM, as opposed to being
initialized in WASM and exported to JS.
false. If it is false, certain BigInt-related features will trigger
an exception if invoked. This property, if not set when this is
called, will get a default value of true only if the BigInt64Array
- constructor is available, else it will default to false.
+ constructor is available, else it will default to false. Note that
+ having the BigInt type is not sufficient for full int64 integration
+ with WASM: the target WASM file must also have been built with
+ that support. In Emscripten that's done using the `-sWASM_BIGINT`
+ flag.
Some optional APIs require that the target have the following
methods:
an integer as the first argument and unsigned is truthy then
the "U" (unsigned) variant of that view is returned, else the
signed variant is returned. If passed a TypedArray value, the
- 2nd argument is ignores. Note that Float32Array and
+ 2nd argument is ignored. Note that Float32Array and
Float64Array views are not supported by this function.
Note that growth of the heap will invalidate any references to
if(2!==arguments.length){
toss("installFunction() requires exactly 2 arguments");
}
- if('string'===typeof func && sig instanceof Function){
+ if('string'===typeof func){
const x = sig;
sig = func;
func = x;
e.g. using setMemValue() or getMemValue(), it is important that
the pointer in question be aligned to an 8-byte boundary or else
it will not be fetched or written properly and will corrupt or
- read neighboring memory. It i only safe to pass false when the
+ read neighboring memory. It is only safe to pass false when the
client code is certain that it will only get/fetch 4-byte values
(or smaller).
*/
return v ? xcv.arg[ptrIR](v) : null;
};
xcv.result.string = (i)=>target.cstringToJs(i);
- xcv.result['string:free'] = function(i){
+ xcv.result['string:free'] = (i)=>{
try { return i ? target.cstringToJs(i) : null }
finally{ target.dealloc(i) }
};
xcv.result.json = (i)=>JSON.parse(target.cstringToJs(i));
- xcv.result['json:free'] = function(i){
+ xcv.result['json:free'] = (i)=>{
try{ return i ? JSON.parse(target.cstringToJs(i)) : null }
finally{ target.dealloc(i) }
}
C-string, ownership of which has just been transfered to the
caller. It copies the C-string to a JS string, frees the
C-string, and returns the JS string. If such a result value is
- NULL, the JS result is `null`.
+ NULL, the JS result is `null`. Achtung: when using an API which
+ returns results from a specific allocator, e.g. `my_malloc()`,
+ this conversion _is not legal_. Instead, an equivalent conversion
+ which uses the appropriate deallocator is required. For example:
+
+```js
+ target.xWrap.resultAdaptor('string:my_free',(i)=>{
+ try { return i ? target.cstringToJs(i) : null }
+ finally{ target.exports.my_free(i) }
+ };
+```
- `json` (results): treats the result as a const C-string and
returns the result of passing the converted-to-JS string to
JSON.parse(). Returns `null` if the C-string is a NULL pointer.
- `json:free` (results): works exactly like `string:free` but
- returns the same thing as the `json` adapter.
+ returns the same thing as the `json` adapter. Note the
+ warning in `string:free` regarding maching allocators and
+ deallocators.
The type names for results and arguments are validated when
xWrap() is called and any unknown names will trigger an
type name, as documented for xWrap() (use a falsy value or an
empty array for nullary functions). The 4th+ arguments are
arguments for the call, with the special case that if the 4th
- argument is an array, it is used as the arguments for the call
- (again, falsy or an empty array for nullary functions). Returns
- the converted result of the call.
+ argument is an array, it is used as the arguments for the
+ call. Returns the converted result of the call.
- This is just a thin wrapp around xWrap(). If the given function
+ This is just a thin wrapper around xWrap(). If the given function
is to be called more than once, it's more efficient to use
xWrap() to create a wrapper, then to call that wrapper as many
times as needed. For one-shot calls, however, this variant is
-C Doc\stypo\sfixes.
-D 2022-10-02T03:14:38.605
+C js:\simplement\sa\shand-written\swrapper\sfor\ssqlite3_create_function_v2()\swhich\sconverts,\sif\snecessary,\sJS-function-type\sargs\sto\sWASM\sfunction\swrappers.\sReplace\sDB.createFunction()\simpl\swith\sthe\snew\sone.
+D 2022-10-02T18:47:39.889
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/wasm/README.md 1e5b28158b74ab3ffc9d54fcbc020f0bbeb82c2ff8bbd904214c86c70e8a3066
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api c6b05641d733227a995cc05a2ba7ddc9ef2323081ae0cae5ed1d1f83d5b54b36
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
-F ext/wasm/api/README.md b6d19392984fdd428ae7260512d45742160c06baefed9da703da3fdeb68e7124
+F ext/wasm/api/README.md 1e350b611465566cfa2e5eccf7c9b29a34f48ee38bbf6d5fb086dd06ce32b3ff
F ext/wasm/api/extern-post-js.js dc68cbf552d8ea085181400a6963907c32e0b088b03ffd8969b1869fea246629
F ext/wasm/api/extern-pre-js.js 20143b16b672d0a576fbf768a786d12ee1f84e222126477072389b992542a5b2
F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba81456260a713ed04900c
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
F ext/wasm/api/pre-js.js 2db711eb637991b383fc6b5c0f3df65ec48a7201e5730e304beba8de2d3f9b0b
F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb48c8bc4bbd463f05b021a99
-F ext/wasm/api/sqlite3-api-glue.js 20b98987dd0c6d02ca308e0cf9299750d618459e0876b354380b87ae2dc5cba0
-F ext/wasm/api/sqlite3-api-oo1.js 066e67f3033e1b300140d431557c468f5cd0a4c17253f156e05b8a2e2c802da7
+F ext/wasm/api/sqlite3-api-glue.js d834733fbdc216beb65382655e61a436e29018412005aab413ff022d4e5c25eb
+F ext/wasm/api/sqlite3-api-oo1.js 48d2269544301cd97726ef2d9a82e4384350d12dcf832fa417f211811ae5272d
F ext/wasm/api/sqlite3-api-opfs.js 1b097808b7b081b0f0700cf97d49ef19760e401706168edff9cd45cf9169f541
-F ext/wasm/api/sqlite3-api-prologue.js 9b0c5150f0129b3dc558fec0bfc9c8bf7ebda402b58965bcf98b2ed117b55239
+F ext/wasm/api/sqlite3-api-prologue.js 32795679b72a5ad685c58a9599d10dac04787907f623825408d539b703e080a4
F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 2a0f9e4bf1b141a787918951360601128d6a0a190a31a8e5cfe237c99fa640c6
F ext/wasm/common/SqliteTestUtil.js 647bf014bd30bdd870a7e9001e251d12fc1c9ec9ce176a1004b838a4b33c5c05
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962
-F ext/wasm/common/whwasmutil.js af9bb6586d8a2ab7c55c7f1554bb6b0328a7bd6a86ea5fa9ef5273a738156ac3
+F ext/wasm/common/whwasmutil.js 427eb8b695bd5f38497601a6bda933e83d1a5900b75f5f1af8dbb381898d2ee4
F ext/wasm/demo-123-worker.html e419b66495d209b5211ec64903b4cfb3ca7df20d652b41fcd28bf018a773234f
F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4
F ext/wasm/demo-123.js 536579fd587974c2511c5bf82034b253d4fdeceabb726927ad7599ef6b7578e8
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P eb5726677a727a958df11f1fba078d30c7c0ba2a9bdb158e8641b35b5f971af3
-R c02b54a31af3ce39f04c3d79de05d508
+P e528675da3971907666c7d2d09763975a105ec585dc5122145f65905d535bed8
+R 905afd6e962345097748ac52db8a0889
U stephan
-Z a6c5eed947d3361089be1f642079a7a3
+Z 8de102f5519af227a27849d21742ab64
# Remove this line to create a well-formed Fossil manifest.
-e528675da3971907666c7d2d09763975a105ec585dc5122145f65905d535bed8
\ No newline at end of file
+435ab33384017967e46f52b70bee851a85a28808990a0e58dd5288f606b89c9c
\ No newline at end of file