if(1){// WhWasmUtil.xWrap() bindings...
/**
- Add some descriptive xWrap() aliases for '*' intended to
- (A) initially improve readability/correctness of capi.signatures
- and (B) eventually perhaps provide some sort of type-safety
- in their conversions.
+ Add some descriptive xWrap() aliases for '*' intended to (A)
+ initially improve readability/correctness of capi.signatures
+ and (B) eventually perhaps provide automatic conversion from
+ higher-level representations, e.g. capi.sqlite3_vfs to
+ `sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
*/
const aPtr = wasm.xWrap.argAdapter('*');
wasm.xWrap.argAdapter('sqlite3*', aPtr)('sqlite3_stmt*', aPtr);
};
}/*sqlite3_prepare_v2/v3()*/;
+ if(1){// Extend wasm.pstack, now that the wasm utils are installed
+ /**
+ Allocates n chunks, each sz bytes, as a single memory block and
+ returns the addresses as an array of n element, each holding
+ the address of one chunk.
+
+ Throws a WasmAllocError if allocation fails.
+
+ Example:
+
+ ```
+ const [p1, p2, p3] = wasm.pstack.allocChunks(3,4);
+ ```
+ */
+ wasm.pstack.allocChunks = (n,sz)=>{
+ const mem = wasm.pstack.alloc(n * sz);
+ const rc = [];
+ let i = 0, offset = 0;
+ for(; i < n; offset = (sz * ++i)){
+ rc.push(mem + offset);
+ }
+ return rc;
+ };
+
+ /**
+ A convenience wrapper for allocChunks() which sizes each chunks
+ as either 8 bytes (safePtrSize is truthy) or wasm.ptrSizeof (if
+ safePtrSize is truthy).
+
+ How it returns its result differs depending on its first
+ argument: if it's 1, it returns a single pointer value. If it's
+ more than 1, it returns the same as allocChunks().
+
+ When one of the pointers refers to a 64-bit value, e.g. a
+ double or int64, and that value must be written or fetch,
+ e.g. using wasm.setMemValue() or wasm.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.
+
+ However, when all pointers involved are "small", it is safe to
+ pass a falsy value to save to memory.
+ */
+ wasm.pstack.allocPtr = (n=1,safePtrSize=true) =>{
+ return 1===n
+ ? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof)
+ : wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof);
+ };
+ }/*wasm.pstack filler*/
+
/**
Install JS<->C struct bindings for the non-opaque struct types we
need... */
const toss = (...args)=>{throw new Error(args.join(' '))};
const toss3 = (...args)=>{throw new sqlite3.SQLite3Error(...args)};
- const capi = sqlite3.capi, util = capi.util;
+ const capi = sqlite3.capi, wasm = capi.wasm, util = capi.util;
/* What follows is colloquially known as "OO API #1". It is a
binding of the sqlite3 API which is designed to be run within
the same thread (main or worker) as the one in which the
accessor and store their real values in this map. Keys = DB/Stmt
objects, values = pointer values. This also unifies how those are
accessed, for potential use downstream via custom
- capi.wasm.xWrap() function signatures which know how to extract
+ wasm.xWrap() function signatures which know how to extract
it.
*/
const __ptrMap = new WeakMap();
being-construct DB object as its "this". See the DB constructor
for the argument docs. This is split into a separate function
in order to enable simple creation of special-case DB constructors,
- e.g. a hypothetical LocalStorageDB or OpfsDB.
+ e.g. JsStorageDB and OpfsDB.
Expects to be passed a configuration object with the following
properties:
console.error("Invalid DB ctor args",opt,arguments);
toss3("Invalid arguments for DB constructor.");
}
- let fnJs = ('number'===typeof fn) ? capi.wasm.cstringToJs(fn) : fn;
+ let fnJs = ('number'===typeof fn) ? wasm.cstringToJs(fn) : fn;
const vfsCheck = ctor._name2vfs[fnJs];
if(vfsCheck){
vfsName = vfsCheck.vfs;
if( flagsStr.indexOf('w')>=0 ) oflags |= capi.SQLITE_OPEN_READWRITE;
if( 0===oflags ) oflags |= capi.SQLITE_OPEN_READONLY;
oflags |= capi.SQLITE_OPEN_EXRESCODE;
- const stack = capi.wasm.scopedAllocPush();
+ const scope = wasm.scopedAllocPush();
try {
- const ppDb = capi.wasm.scopedAllocPtr() /* output (sqlite3**) arg */;
+ const ppDb = wasm.allocPtr() /* output (sqlite3**) arg */;
const pVfsName = vfsName ? (
- ('number'===typeof vfsName ? vfsName : capi.wasm.scopedAllocCString(vfsName))
+ ('number'===typeof vfsName ? vfsName : wasm.scopedAllocCString(vfsName))
): 0;
const rc = capi.sqlite3_open_v2(fn, ppDb, oflags, pVfsName);
- ptr = capi.wasm.getPtrValue(ppDb);
+ ptr = wasm.getPtrValue(ppDb);
checkSqlite3Rc(ptr, rc);
}catch( e ){
if( ptr ) capi.sqlite3_close_v2(ptr);
throw e;
}finally{
- capi.wasm.scopedAllocPop(stack);
+ wasm.scopedAllocPop(scope);
}
this.filename = fnJs;
__ptrMap.set(this, ptr);
blob: 5
};
BindTypes['undefined'] == BindTypes.null;
- if(capi.wasm.bigIntEnabled){
+ if(wasm.bigIntEnabled){
BindTypes.bigint = BindTypes.number;
}
if(s && s.pointer) s.finalize();
});
Object.values(__udfMap.get(this)).forEach(
- capi.wasm.uninstallFunction.bind(capi.wasm)
+ wasm.uninstallFunction.bind(capi.wasm)
);
__ptrMap.delete(this);
__stmtMap.delete(this);
*/
prepare: function(sql){
affirmDbOpen(this);
- const stack = capi.wasm.pstack.pointer;
+ const stack = wasm.pstack.pointer;
let ppStmt, pStmt;
try{
- ppStmt = capi.wasm.pstack.alloc(8)/* output (sqlite3_stmt**) arg */;
+ ppStmt = wasm.pstack.alloc(8)/* output (sqlite3_stmt**) arg */;
DB.checkRc(this, capi.sqlite3_prepare_v2(this.pointer, sql, -1, ppStmt, null));
- pStmt = capi.wasm.getPtrValue(ppStmt);
+ pStmt = wasm.getPtrValue(ppStmt);
}
finally {
- capi.wasm.pstack.restore(stack);
+ wasm.pstack.restore(stack);
}
if(!pStmt) toss3("Cannot prepare empty SQL.");
const stmt = new Stmt(this, pStmt, BindTypes);
let i, pVal, valType, arg;
const tgt = [];
for(i = 0; i < argc; ++i){
- pVal = capi.wasm.getPtrValue(pArgv + (capi.wasm.ptrSizeof * i));
+ pVal = wasm.getPtrValue(pArgv + (wasm.ptrSizeof * i));
/**
Curiously: despite ostensibly requiring 8-byte
alignment, the pArgv array is parcelled into chunks of
const pBlob = capi.sqlite3_value_blob(pVal);
arg = new Uint8Array(n);
let i;
- const heap = n ? capi.wasm.heap8() : false;
+ const heap = n ? wasm.heap8() : false;
for(i = 0; i < n; ++i) arg[i] = heap[pBlob+i];
break;
}
capi.sqlite3_result_null(pCx);
break;
}else if(util.isBindableTypedArray(val)){
- const pBlob = capi.wasm.allocFromTypedArray(val);
+ const pBlob = wasm.allocFromTypedArray(val);
capi.sqlite3_result_blob(pCx, pBlob, val.byteLength,
capi.SQLITE_TRANSIENT);
- capi.wasm.dealloc(pBlob);
+ wasm.dealloc(pBlob);
break;
}
// else fall through
}
}
};
- const pUdf = capi.wasm.installFunction(wrapper, "v(iii)");
+ 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;
capi.SQLITE_UTF8 | fFlags, null/*pApp*/, pUdf,
null/*xStep*/, null/*xFinal*/, null/*xDestroy*/));
}catch(e){
- capi.wasm.uninstallFunction(pUdf);
+ wasm.uninstallFunction(pUdf);
throw e;
}
const udfMap = __udfMap.get(this);
if(udfMap[name]){
- try{capi.wasm.uninstallFunction(udfMap[name])}
+ try{wasm.uninstallFunction(udfMap[name])}
catch(e){/*ignore*/}
}
udfMap[name] = pUdf;
case BindTypes.string:
return t;
case BindTypes.bigint:
- if(capi.wasm.bigIntEnabled) return t;
+ if(wasm.bigIntEnabled) return t;
/* else fall through */
default:
//console.log("isSupportedBindType",t,v);
const bindOne = function f(stmt,ndx,bindType,val){
affirmUnlocked(stmt, 'bind()');
if(!f._){
- if(capi.wasm.bigIntEnabled){
+ if(wasm.bigIntEnabled){
f._maxInt = BigInt("0x7fffffffffffffff");
f._minInt = ~f._maxInt;
}
string: function(stmt, ndx, val, asBlob){
if(1){
/* _Hypothetically_ more efficient than the impl in the 'else' block. */
- const stack = capi.wasm.scopedAllocPush();
+ const stack = wasm.scopedAllocPush();
try{
- const n = capi.wasm.jstrlen(val);
- const pStr = capi.wasm.scopedAlloc(n);
- capi.wasm.jstrcpy(val, capi.wasm.heap8u(), pStr, n, false);
+ const n = wasm.jstrlen(val);
+ const pStr = wasm.scopedAlloc(n);
+ wasm.jstrcpy(val, wasm.heap8u(), pStr, n, false);
const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_TRANSIENT);
}finally{
- capi.wasm.scopedAllocPop(stack);
+ wasm.scopedAllocPop(stack);
}
}else{
- const bytes = capi.wasm.jstrToUintArray(val,false);
- const pStr = capi.wasm.alloc(bytes.length || 1);
- capi.wasm.heap8u().set(bytes.length ? bytes : [0], pStr);
+ const bytes = wasm.jstrToUintArray(val,false);
+ const pStr = wasm.alloc(bytes.length || 1);
+ wasm.heap8u().set(bytes.length ? bytes : [0], pStr);
try{
const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
return f(stmt.pointer, ndx, pStr, bytes.length, capi.SQLITE_TRANSIENT);
}finally{
- capi.wasm.dealloc(pStr);
+ wasm.dealloc(pStr);
}
}
}
else if('bigint'===typeof val){
if(val<f._minInt || val>f._maxInt){
toss3("BigInt value is out of range for storing as int64: "+val);
- }else if(capi.wasm.bigIntEnabled){
+ }else if(wasm.bigIntEnabled){
m = capi.sqlite3_bind_int64;
}else if(val >= Number.MIN_SAFE_INTEGER && val <= Number.MAX_SAFE_INTEGER){
val = Number(val);
}
}else{ // !int32, !bigint
val = Number(val);
- if(capi.wasm.bigIntEnabled && Number.isInteger(val)){
+ if(wasm.bigIntEnabled && Number.isInteger(val)){
m = capi.sqlite3_bind_int64;
}else{
m = capi.sqlite3_bind_double;
"that it be a string, Uint8Array, or Int8Array.");
}else if(1){
/* _Hypothetically_ more efficient than the impl in the 'else' block. */
- const stack = capi.wasm.scopedAllocPush();
+ const stack = wasm.scopedAllocPush();
try{
- const pBlob = capi.wasm.scopedAlloc(val.byteLength || 1);
- capi.wasm.heap8().set(val.byteLength ? val : [0], pBlob)
+ const pBlob = wasm.scopedAlloc(val.byteLength || 1);
+ wasm.heap8().set(val.byteLength ? val : [0], pBlob)
rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
capi.SQLITE_TRANSIENT);
}finally{
- capi.wasm.scopedAllocPop(stack);
+ wasm.scopedAllocPop(stack);
}
}else{
- const pBlob = capi.wasm.allocFromTypedArray(val);
+ const pBlob = wasm.allocFromTypedArray(val);
try{
rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
capi.SQLITE_TRANSIENT);
}finally{
- capi.wasm.dealloc(pBlob);
+ wasm.dealloc(pBlob);
}
}
break;
: asType){
case capi.SQLITE_NULL: return null;
case capi.SQLITE_INTEGER:{
- if(capi.wasm.bigIntEnabled){
+ if(wasm.bigIntEnabled){
const rc = capi.sqlite3_column_int64(this.pointer, ndx);
if(rc>=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){
/* Coerce "normal" number ranges to normal number values,
const n = capi.sqlite3_column_bytes(this.pointer, ndx),
ptr = capi.sqlite3_column_blob(this.pointer, ndx),
rc = new Uint8Array(n);
- //heap = n ? capi.wasm.heap8() : false;
- if(n) rc.set(capi.wasm.heap8u().slice(ptr, ptr+n), 0);
+ //heap = n ? wasm.heap8() : false;
+ if(n) rc.set(wasm.heap8u().slice(ptr, ptr+n), 0);
//for(let i = 0; i < n; ++i) rc[i] = heap[ptr + i];
if(n && this.db._blobXfer instanceof Array){
/* This is an optimization soley for the
this.name = 'WasmAllocError';
}
};
+ WasmAllocError.toss = (...args)=>{
+ throw new WasmAllocError(args.join(' '));
+ };
/**
The main sqlite3 binding API gets installed into this object,
Functions which are intended solely for API-internal use by the
WASM components, not client code. These get installed into
capi.wasm.
+
+ TODO: get rid of sqlite3_wasm_vfs_unlink(). It is ill-conceived
+ and only rarely actually useful.
*/
capi.wasm.bindingSignatures.wasm = [
["sqlite3_wasm_vfs_unlink", "int", "string"]
Attempts to allocate the given number of bytes from the
pstack. On success, it zeroes out a block of memory of the
given size, adjusts the pstack pointer, and returns a pointer
- to the memory. On error, returns 0. The memory must eventually
- be released using restore().
+ to the memory. On error, returns throws a WasmAllocError. The
+ memory must eventually be released using restore().
This method always adjusts the given value to be a multiple
of 8 bytes because failing to do so can lead to incorrect
results when reading and writing 64-bit values from/to the WASM
heap.
*/
- alloc: capi.wasm.exports.sqlite3_wasm_pstack_alloc
+ alloc: (n)=>{
+ return capi.wasm.exports.sqlite3_wasm_pstack_alloc(n)
+ || WasmAllocError.toss("Could not allocate",n,
+ "bytes from the pstack.");
+ }
+ // More methods get added after the capi.wasm object is populated
+ // by WhWasmUtilInstaller.
});
/**
sqlite3.capi.wasm.pstack.pointer resolves to the current pstack
this.name = 'SQLite3Error';
}
};
-
+ SQLite3Error.toss = (...args)=>{
+ throw new SQLite3Error(args.join(' '));
+ };
/** State for sqlite3_wasmfs_opfs_dir(). */
let __persistentDir = undefined;
#include <assert.h>
#include "sqlite3.c" /* yes, .c instead of .h. */
+#if defined(__EMSCRIPTEN__)
+# include <emscripten/console.h>
+#endif
+
/*
** WASM_KEEP is identical to EMSCRIPTEN_KEEPALIVE but is not
** Emscripten-specific. It explicitly marks functions for export into
int sqlite3_wasm_vfs_unlink(const char * zName){
int rc = SQLITE_MISUSE /* ??? */;
sqlite3_vfs * const pVfs = sqlite3_vfs_find(0);
+#if defined(__EMSCRIPTEN__)
+ emscripten_console_warn("sqlite3_wasm_vfs_unlink() will be removed.");
+#endif
if( zName && pVfs && pVfs->xDelete ){
rc = pVfs->xDelete(pVfs, zName, 1);
}
}
-#if defined(__EMSCRIPTEN__)
-#include <emscripten/console.h>
-#if defined(SQLITE_WASM_WASMFS)
+#if defined(__EMSCRIPTEN__) && defined(SQLITE_WASM_WASMFS)
#include <emscripten/wasmfs.h>
/*
return SQLITE_NOTFOUND;
}
#endif /* __EMSCRIPTEN__ && SQLITE_WASM_WASMFS */
-#endif
#undef WASM_KEEP
};
/** Internal impl for allocPtr() and scopedAllocPtr(). */
- const __allocPtr = function(howMany, method){
+ const __allocPtr = function(howMany, safePtrSize, method){
__affirmAlloc(target, method);
- let m = target[method](howMany * ptrSizeof);
- target.setMemValue(m, 0, ptrIR)
+ const pIr = safePtrSize ? 'i64' : ptrIR;
+ let m = target[method](howMany * (safePtrSize ? 8 : ptrSizeof));
+ target.setMemValue(m, 0, pIr)
if(1===howMany){
return m;
}
const a = [m];
for(let i = 1; i < howMany; ++i){
- m += ptrSizeof;
+ m += (safePtrSize ? 8 : ptrSizeof);
a[i] = m;
- target.setMemValue(m, 0, ptrIR);
+ target.setMemValue(m, 0, pIr);
}
return a;
};
/**
- Allocates a single chunk of memory capable of holding `howMany`
- pointers and zeroes them out. If `howMany` is 1 then the memory
- chunk is returned directly, else an array of pointer addresses is
- returned, which can optionally be used with "destructuring
- assignment" like this:
+ Allocates one or more pointers as a single chunk of memory and
+ zeroes them out.
+
+ The first argument is the number of pointers to allocate. The
+ second specifies whether they should use a "safe" pointer size (8
+ bytes) or whether they may use the default pointer size
+ (typically 4 but also possibly 8).
+
+ How the result is returned depends on its first argument: if
+ passed 1, it returns the allocated memory address. If passed more
+ than one then an array of pointer addresses is returned, which
+ can optionally be used with "destructuring assignment" like this:
```
const [p1, p2, p3] = allocPtr(3);
ACHTUNG: when freeing the memory, pass only the _first_ result
value to dealloc(). The others are part of the same memory chunk
and must not be freed separately.
+
+ The reason for the 2nd argument is..
+
+ When one of the pointers will refer to a 64-bit value, e.g. a
+ double or int64, an that value must be written or fetch,
+ 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
+ client code is certain that it will only get/fetch 4-byte values
+ (or smaller).
*/
- target.allocPtr = (howMany=1)=>__allocPtr(howMany, 'alloc');
+ target.allocPtr =
+ (howMany=1, safePtrSize=true)=>__allocPtr(howMany, safePtrSize, 'alloc');
/**
Identical to allocPtr() except that it allocates using scopedAlloc()
instead of alloc().
*/
- target.scopedAllocPtr = (howMany=1)=>__allocPtr(howMany, 'scopedAlloc');
+ target.scopedAllocPtr =
+ (howMany=1, safePtrSize=true)=>__allocPtr(howMany, safePtrSize, 'scopedAlloc');
/**
If target.exports[name] exists, it is returned, else an
*/
const testPstack = function(db,sqlite3){
const w = sqlite3.capi.wasm, P = w.pstack;
+ const isAllocErr = (e)=>e instanceof sqlite3.WasmAllocError;
const stack = P.pointer;
T.assert(0===stack % 8 /* must be 8-byte aligned */);
try{
const quota = P.remaining;
log("pstack quota",quota);
T.assert(quota >= 4096)
- .assert(0 === P.alloc(0))
- .assert(0 === P.alloc(-1));
+ .mustThrowMatching(()=>P.alloc(0), isAllocErr)
+ .mustThrowMatching(()=>P.alloc(-1), isAllocErr);
let p1 = P.alloc(12);
T.assert(p1 === stack - 16/*8-byte aligned*/)
.assert(P.pointer === p1);
let p2 = P.alloc(7);
T.assert(p2 === p1-8/*8-byte aligned, stack grows downwards*/)
- .assert(0 === P.alloc(quota))
+ .mustThrowMatching(()=>P.alloc(quota), isAllocErr)
.assert(24 === stack - p2)
.assert(P.pointer === p2);
let n = quota - (stack - p2);
let p3 = P.alloc(n);
T.assert(p3 === stack-quota)
- .assert(0 === P.alloc(1));
+ .mustThrowMatching(()=>P.alloc(1), isAllocErr);
}finally{
P.restore(stack);
- T.assert(P.pointer === stack);
}
- }/*testPstack()*/;
+
+ T.assert(P.pointer === stack);
+ try {
+ const [p1, p2, p3] = P.allocChunks(3,4);
+ T.assert(P.pointer === stack-16/*always rounded to multiple of 8*/)
+ .assert(p2 === p1 + 4)
+ .assert(p3 === p2 + 4);
+ T.mustThrowMatching(()=>P.allocChunks(1024, 1024 * 16),
+ (e)=>e instanceof sqlite3.WasmAllocError)
+ }finally{
+ P.restore(stack);
+ }
+
+ T.assert(P.pointer === stack);
+ try {
+ let [p1, p2, p3] = P.allocPtr(3,false);
+ let sPos = stack-16/*always rounded to multiple of 8*/;
+ T.assert(P.pointer === sPos)
+ .assert(p2 === p1 + 4)
+ .assert(p3 === p2 + 4);
+ [p1, p2, p3] = P.allocPtr(3);
+ T.assert(P.pointer === sPos-24/*3 x 8 bytes*/)
+ .assert(p2 === p1 + 8)
+ .assert(p3 === p2 + 8);
+ p1 = P.allocPtr();
+ T.assert('number'===typeof p1);
+ }finally{
+ P.restore(stack);
+ }
+}/*testPstack()*/;
const clearKvvfs = function(){
const sz = sqlite3.capi.sqlite3_web_kvvfs_size();
-C Document\sthe\sroles\sof\sthe\snew\s(this\spast\sweek)\sJS\sfiles\sadded\sto\sthe\sbuild\sprocess.
-D 2022-10-02T01:48:14.286
+C More\sfleshing\sout\sof\ssqlite3.capi.wasm.pstack.
+D 2022-10-02T03:11:13.806
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
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 b15a51b88aaa472d36bf82d5123dbfdafe8ddf6ca75fba934510e4a20bbe4adb
-F ext/wasm/api/sqlite3-api-oo1.js 7667d320f6b9fb5252050a2f9c0b1769e11b84dbc0763b999baf65b451b14369
+F ext/wasm/api/sqlite3-api-glue.js 474a5e0bf8016e22aefee44ca45408f08f4159c0b782295ac1d86c4556e91d9a
+F ext/wasm/api/sqlite3-api-oo1.js 066e67f3033e1b300140d431557c468f5cd0a4c17253f156e05b8a2e2c802da7
F ext/wasm/api/sqlite3-api-opfs.js 1b097808b7b081b0f0700cf97d49ef19760e401706168edff9cd45cf9169f541
-F ext/wasm/api/sqlite3-api-prologue.js a93bd69969eb8b8f9c4cb34e5d86dcbbe5adbeeea39c1cce57194256c5f28434
+F ext/wasm/api/sqlite3-api-prologue.js 9b0c5150f0129b3dc558fec0bfc9c8bf7ebda402b58965bcf98b2ed117b55239
F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
-F ext/wasm/api/sqlite3-wasm.c d72aecf0e50a4403402095ef4e8d6a814fdc2256589944c1dc974c70d2f65b7e
+F ext/wasm/api/sqlite3-wasm.c 2a0f9e4bf1b141a787918951360601128d6a0a190a31a8e5cfe237c99fa640c6
F ext/wasm/batch-runner.html c363032aba7a525920f61f8be112a29459f73f07e46f0ba3b7730081a617826e
F ext/wasm/batch-runner.js ce92650a6681586c89bef26ceae96674a55ca5a9727815202ca62e1a00ff5015
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 d2557d6ef1ebaaf3c9a0cea2231fd398b0d8ca8129b51580af1c92f8d04335e0
+F ext/wasm/common/whwasmutil.js cdb33775fdc55c9b1cbb617d22d24b4a29dc9c1389b827a5b14886a291480d70
F ext/wasm/demo-123-worker.html e419b66495d209b5211ec64903b4cfb3ca7df20d652b41fcd28bf018a773234f
F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4
F ext/wasm/demo-123.js 536579fd587974c2511c5bf82034b253d4fdeceabb726927ad7599ef6b7578e8
F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893
F ext/wasm/testing-worker1-promiser.js bd788e33c1807e0a6dda9c9a9d784bd3350ca49c9dd8ae2cc8719b506b6e013e
F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae
-F ext/wasm/testing1.js 51ef1ced0669f804787ce96f19dcf64367550a7923a998514be56076326988d7
+F ext/wasm/testing1.js bdea170b16189028c1f63023c620df52ddf31ed416bad56d729c60031b1e27ae
F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
F ext/wasm/testing2.js 88f40ef3cd8201bdadd120a711c36bbf0ce56cc0eab1d5e7debb71fed7822494
F ext/wasm/wasmfs.make 3cce1820006196de140f90f2da4b4ea657083fb5bfee7d125be43f7a85748c8f
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P f9db664f756f3707afcb5dce87f6d946625848f27ea84337af68de72d4ad6c6b
-R 8201c0f212d8f73dc23b363b8bdcd606
+P 8b3bc7313aff551e5ee0b7aeb927095cf19b9b96abbdd922066c130656b8aa7d
+R a0d2cb1d1b18288fcfda68347c547fdd
U stephan
-Z 7616e552f06f17aa339add7ed573ed79
+Z 5fc153c99e29258d724616b67e70d32b
# Remove this line to create a well-formed Fossil manifest.
-8b3bc7313aff551e5ee0b7aeb927095cf19b9b96abbdd922066c130656b8aa7d
\ No newline at end of file
+eb5726677a727a958df11f1fba078d30c7c0ba2a9bdb158e8641b35b5f971af3
\ No newline at end of file