}
wasm.ctype = JSON.parse(wasm.cstringToJs(cJson));
//console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
- for(const t of ['access', 'blobFinalizers', 'dataTypes',
- 'encodings', 'fcntl', 'flock', 'ioCap',
- 'limits',
- 'openFlags', 'prepareFlags', 'resultCodes',
- 'serialize', 'syncFlags', 'trace', 'udfFlags',
- 'version'
- ]){
+ const defineGroups = ['access', 'blobFinalizers', 'dataTypes',
+ 'encodings', 'fcntl', 'flock', 'ioCap',
+ 'limits',
+ 'openFlags', 'prepareFlags', 'resultCodes',
+ 'serialize', 'syncFlags', 'trace', 'udfFlags',
+ 'version' ];
+ if(wasm.bigIntEnabled){
+ defineGroups.push('vtab');
+ }
+ for(const t of defineGroups){
for(const e of Object.entries(wasm.ctype[t])){
// ^^^ [k,v] there triggers a buggy code transformation via
// one of the Emscripten-driven optimizers.
capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc];
/* Bind all registered C-side structs... */
const notThese = Object.assign(Object.create(null),{
- // Structs NOT to register
- WasmTestStruct: true
- });
- if(!util.isUIThread()){
+ // For each struct to NOT register, map its name to false:
+ WasmTestStruct: true,
/* We remove the kvvfs VFS from Worker threads below. */
- notThese.sqlite3_kvvfs_methods = true;
- }
+ sqlite3_kvvfs_methods: !util.isUIThread(),
+ sqlite3_index_info: !wasm.bigIntEnabled,
+ sqlite3_index_constraint: !wasm.bigIntEnabled,
+ sqlite3_index_orderby: !wasm.bigIntEnabled,
+ sqlite3_index_constraint_usage: !wasm.bigIntEnabled
+ });
for(const s of wasm.ctype.structs){
if(!notThese[s.name]){
capi[s.name] = sqlite3.StructBinder(s);
}
}
- }/*end C constant imports*/
+ if(capi.sqlite3_index_info){
+ /* Move these inner structs into sqlite3_index_info. Binding
+ ** them to WASM requires that we create global-scope structs to
+ ** model them with, but those are no longer needed after we've
+ ** passed them to StructBinder. */
+ for(const k of ['sqlite3_index_constraint',
+ 'sqlite3_index_orderby',
+ 'sqlite3_index_constraint_usage']){
+ capi.sqlite3_index_info[k] = capi[k];
+ delete capi[k];
+ }
+ }
+ }/*end C constant and struct imports*/
const pKvvfs = capi.sqlite3_vfs_find("kvvfs");
if( pKvvfs ){/* kvvfs-specific glue */
delete capi.sqlite3_kvvfs_methods;
const kvvfsMakeKey = wasm.exports.sqlite3_wasm_kvvfsMakeKeyOnPstack,
- pstack = wasm.pstack,
- pAllocRaw = wasm.exports.sqlite3_wasm_pstack_alloc;
+ pstack = wasm.pstack;
const kvvfsStorage = (zClass)=>
((115/*=='s'*/===wasm.getMemValue(zClass))
*/
SQLITE_WASM_KEEP
const char * sqlite3_wasm_enum_json(void){
- static char aBuffer[1024 * 12] = {0} /* where the JSON goes */;
+ static char aBuffer[1024 * 16] = {0} /* where the JSON goes */;
int n = 0, nChildren = 0, nStruct = 0
/* output counters for figuring out where commas go */;
char * zPos = &aBuffer[1] /* skip first byte for now to help protect
DefInt(SQLITE_ACCESS_READ)/*docs say this is unused*/;
} _DefGroup;
+#if 0
+ /* TODO? Authorizer... */
+ DefGroup(authorizer){
+ DefInt(SQLITE_DENY);
+ DefInt(SQLITE_IGNORE);
+ } _DefGroup;
+#endif
+
DefGroup(blobFinalizers) {
/* SQLITE_STATIC/TRANSIENT need to be handled explicitly as
** integers to avoid casting-related warnings. */
DefStr(SQLITE_VERSION);
DefStr(SQLITE_SOURCE_ID);
} _DefGroup;
-
+
+ DefGroup(vtab) {
+ DefInt(SQLITE_INDEX_SCAN_UNIQUE);
+ DefInt(SQLITE_INDEX_CONSTRAINT_EQ);
+ DefInt(SQLITE_INDEX_CONSTRAINT_GT);
+ DefInt(SQLITE_INDEX_CONSTRAINT_LE);
+ DefInt(SQLITE_INDEX_CONSTRAINT_LT);
+ DefInt(SQLITE_INDEX_CONSTRAINT_GE);
+ DefInt(SQLITE_INDEX_CONSTRAINT_MATCH);
+ DefInt(SQLITE_INDEX_CONSTRAINT_LIKE);
+ DefInt(SQLITE_INDEX_CONSTRAINT_GLOB);
+ DefInt(SQLITE_INDEX_CONSTRAINT_REGEXP);
+ DefInt(SQLITE_INDEX_CONSTRAINT_NE);
+ DefInt(SQLITE_INDEX_CONSTRAINT_ISNOT);
+ DefInt(SQLITE_INDEX_CONSTRAINT_ISNOTNULL);
+ DefInt(SQLITE_INDEX_CONSTRAINT_ISNULL);
+ DefInt(SQLITE_INDEX_CONSTRAINT_IS);
+ DefInt(SQLITE_INDEX_CONSTRAINT_LIMIT);
+ DefInt(SQLITE_INDEX_CONSTRAINT_OFFSET);
+ DefInt(SQLITE_INDEX_CONSTRAINT_FUNCTION);
+ } _DefGroup;
+
#undef DefGroup
#undef DefStr
#undef DefInt
} _StructBinder;
#undef CurrentStruct
+
+#define CurrentStruct sqlite3_vtab
+ StructBinder {
+ M(pModule, "p");
+ M(nRef, "i");
+ M(zErrMsg, "p");
+ } _StructBinder;
+#undef CurrentStruct
+
+#define CurrentStruct sqlite3_vtab_cursor
+ StructBinder {
+ M(pVtab, "p");
+ } _StructBinder;
+#undef CurrentStruct
+
+#define CurrentStruct sqlite3_module
+ StructBinder {
+ M(iVersion, "i");
+ M(xCreate, "i(ppippp)");
+ M(xConnect, "i(ppippp)");
+ M(xBestIndex, "i(pp)");
+ M(xDisconnect, "i(p)");
+ M(xDestroy, "i(p)");
+ M(xOpen, "i(pp)");
+ M(xClose, "i(p)");
+ M(xFilter, "i(pisip)");
+ M(xNext, "i(p)");
+ M(xEof, "i(p)");
+ M(xColumn, "i(ppi)");
+ M(xRowid, "i(pp)");
+ M(xUpdate, "i(pipp)");
+ M(xBegin, "i(p)");
+ M(xSync, "i(p)");
+ M(xCommit, "i(p)");
+ M(xRollback, "i(p)");
+ M(xFindFunction, "i(pispp)");
+ M(xRename, "i(ps)");
+ // ^^^ v1. v2+ follows...
+ M(xSavepoint, "i(pi)");
+ M(xRelease, "i(pi)");
+ M(xRollbackTo, "i(pi)");
+ // ^^^ v2. v3+ follows...
+ M(xShadowName, "i(s)");
+ } _StructBinder;
+#undef CurrentStruct
+ /*
+ module/vtab todos:
+
+ - sqlite3_create_module()
+ - sqlite3_create_module_v2()
+ - sqlite3_drop_modules()
+ - sqlite3_declare_vtab()
+ - sqlite3_overload_function()
+ */
+
+ /**
+ ** Workaround: in order to map the various inner structs from
+ ** sqlite3_index_info, we have to uplift those into constructs we
+ ** can access by type name. These structs _must_ match their
+ ** in-sqlite3_index_info counterparts byte for byte.
+ */
+ typedef struct {
+ int iColumn;
+ unsigned char op;
+ unsigned char usable;
+ int iTermOffset;
+ } sqlite3_index_constraint;
+ typedef struct {
+ int iColumn;
+ unsigned char desc;
+ } sqlite3_index_orderby;
+ typedef struct {
+ int argvIndex;
+ unsigned char omit;
+ } sqlite3_index_constraint_usage;
+ { /* Validate that the above struct sizeof()s match
+ ** expectations. We could improve upon this by
+ ** checking the offsetof() for each member. */
+ const sqlite3_index_info siiCheck;
+#define IndexSzCheck(T,M) \
+ (sizeof(T) == sizeof(*siiCheck.M))
+ if(!IndexSzCheck(sqlite3_index_constraint,aConstraint)
+ || !IndexSzCheck(sqlite3_index_orderby,aOrderBy)
+ || !IndexSzCheck(sqlite3_index_constraint_usage,aConstraintUsage)){
+ assert(!"sizeof mismatch in sqlite3_index_... struct(s)");
+ return 0;
+ }
+#undef IndexSzCheck
+ }
+
+#define CurrentStruct sqlite3_index_constraint
+ StructBinder {
+ M(iColumn, "i");
+ M(op, "C");
+ M(usable, "C");
+ M(iTermOffset, "i");
+ } _StructBinder;
+#undef CurrentStruct
+
+#define CurrentStruct sqlite3_index_orderby
+ StructBinder {
+ M(iColumn, "i");
+ M(desc, "C");
+ } _StructBinder;
+#undef CurrentStruct
+
+#define CurrentStruct sqlite3_index_constraint_usage
+ StructBinder {
+ M(argvIndex, "i");
+ M(omit, "C");
+ } _StructBinder;
+#undef CurrentStruct
+
+#define CurrentStruct sqlite3_index_info
+ StructBinder {
+ M(nConstraint, "i");
+ M(aConstraint, "p");
+ M(nOrderBy, "i");
+ M(aOrderBy, "p");
+ M(aConstraintUsage, "p");
+ M(idxNum, "i");
+ M(idxStr, "p");
+ M(needToFreeIdxStr, "i");
+ M(orderByConsumed, "i");
+ M(estimatedCost, "d");
+ M(estimatedRows, "j");
+ M(idxFlags, "i");
+ M(colUsed, "j");
+ } _StructBinder;
+#undef CurrentStruct
+
#if SQLITE_WASM_TESTS
#define CurrentStruct WasmTestStruct
StructBinder {
// impl for allocMainArgv() and scopedAllocMainArgv().
const __allocMainArgv = function(isScoped, list){
- if(!list.length) toss("Cannot allocate empty array.");
const pList = target[
isScoped ? 'scopedAlloc' : 'alloc'
- ](list.length * target.ptrSizeof);
+ ]((list.length + 1) * target.ptrSizeof);
let i = 0;
list.forEach((e)=>{
target.setPtrValue(pList + (target.ptrSizeof * i++),
isScoped ? 'scopedAllocCString' : 'allocCString'
](""+e));
});
+ target.setPtrValue(pList + (target.ptrSizeof * i), 0);
return pList;
};
/**
Creates an array, using scopedAlloc(), suitable for passing to a
C-level main() routine. The input is a collection with a length
- property and a forEach() method. A block of memory list.length
- entries long is allocated and each pointer-sized block of that
- memory is populated with a scopedAllocCString() conversion of the
- (""+value) of each element. Returns a pointer to the start of the
- list, suitable for passing as the 2nd argument to a C-style
- main() function.
-
- Throws if list.length is falsy or scopedAllocPush() is not active.
+ property and a forEach() method. A block of memory
+ (list.length+1) entries long is allocated and each pointer-sized
+ block of that memory is populated with a scopedAllocCString()
+ conversion of the (""+value) of each element, with the exception
+ that the final entry is a NULL pointer. Returns a pointer to the
+ start of the list, suitable for passing as the 2nd argument to a
+ C-style main() function.
+
+ Throws if scopedAllocPush() is not active.
+
+ Design note: the returned array is allocated with an extra NULL
+ pointer entry to accommodate certain APIs, but client code which
+ does not need that functionality should treat the returned array
+ as list.length entries long.
*/
target.scopedAllocMainArgv = (list)=>__allocMainArgv(true, list);
/**
Identical to scopedAllocMainArgv() but uses alloc() instead of
- scopedAllocMainArgv
+ scopedAlloc().
*/
target.allocMainArgv = (list)=>__allocMainArgv(false, list);
at SIG s[0]. Throws for an unknown SIG. */
const sigIR = function(s){
switch(sigLetter(s)){
+ case 'c': case 'C': return 'i8';
case 'i': return 'i32';
case 'p': case 'P': case 's': return ptrIR;
case 'j': return 'i64';
unknown SIG. */
const sigSizeof = function(s){
switch(sigLetter(s)){
+ case 'c': case 'C': return 1;
case 'i': return 4;
case 'p': case 'P': case 's': return ptrSizeof;
case 'j': return 8;
break;
}
case 'i': return 'getInt32';
+ case 'c': return 'getInt8';
+ case 'C': return 'getUint8';
case 'j': return affirmBigIntArray() && 'getBigInt64';
case 'f': return 'getFloat32';
case 'd': return 'getFloat64';
break;
}
case 'i': return 'setInt32';
+ case 'c': return 'setInt8';
+ case 'C': return 'setUint8';
case 'j': return affirmBigIntArray() && 'setBigInt64';
case 'f': return 'setFloat32';
case 'd': return 'setFloat64';
*/
const sigDVSetWrapper = function(s){
switch(sigLetter(s)) {
- case 'i': case 'f': case 'd': return Number;
+ case 'i': case 'f': case 'c': case 'C': case 'd': return Number;
case 'j': return affirmBigIntArray() && BigInt;
case 'p': case 'P': case 's':
switch(ptrSizeof){
framework's native format or in Emscripten format.
*/
const __memberSignature = function f(obj,memberName,emscriptenFormat=false){
- if(!f._) f._ = (x)=>x.replace(/[^vipPsjrd]/g,"").replace(/[pPs]/g,'i');
+ if(!f._) f._ = (x)=>x.replace(/[^vipPsjrdcC]/g,"").replace(/[pPscC]/g,'i');
const m = __lookupMember(obj.structInfo, memberName, true);
return emscriptenFormat ? f._(m.signature) : m.signature;
};
/*cache all available getters/setters/set-wrappers for
direct reuse in each accessor function. */
f._ = {getters: {}, setters: {}, sw:{}};
- const a = ['i','p','P','s','f','d','v()'];
+ const a = ['i','c','C','p','P','s','f','d','v()'];
if(bigIntEnabled) a.push('j');
a.forEach(function(v){
//const ir = sigIR(v);
f._.sw[v] = sigDVSetWrapper(v) /* BigInt or Number ctor to wrap around values
for conversion */;
});
- const rxSig1 = /^[ipPsjfd]$/,
- rxSig2 = /^[vipPsjfd]\([ipPsjfd]*\)$/;
+ const rxSig1 = /^[ipPsjfdcC]$/,
+ rxSig2 = /^[vipPsjfdcC]\([ipPsjfdcC]*\)$/;
f.sigCheck = function(obj, name, key,sig){
if(Object.prototype.hasOwnProperty.call(obj, key)){
toss(obj.structName,'already has a property named',key+'.');
f.sigCheck(ctor.prototype, name, key, descr.signature);
descr.key = key;
descr.name = name;
- const sizeOf = sigSizeof(descr.signature);
const sigGlyph = sigLetter(descr.signature);
const xPropName = sPropName(ctor.prototype.structName,key);
const dbg = ctor.prototype.debugFlags.__flags;
prop.get = function(){
if(dbg.getter){
log("debug.getter:",f._.getters[sigGlyph],"for", sigIR(sigGlyph),
- xPropName,'@', this.pointer,'+',descr.offset,'sz',sizeOf);
+ xPropName,'@', this.pointer,'+',descr.offset,'sz',descr.sizeof);
}
let rc = (
- new DataView(heap().buffer, this.pointer + descr.offset, sizeOf)
+ new DataView(heap().buffer, this.pointer + descr.offset, descr.sizeof)
)[f._.getters[sigGlyph]](0, isLittleEndian);
if(dbg.getter) log("debug.getter:",xPropName,"result =",rc);
if(rc && isAutoPtrSig(descr.signature)){
prop.set = function(v){
if(dbg.setter){
log("debug.setter:",f._.setters[sigGlyph],"for", sigIR(sigGlyph),
- xPropName,'@', this.pointer,'+',descr.offset,'sz',sizeOf, v);
+ xPropName,'@', this.pointer,'+',descr.offset,'sz',descr.sizeof, v);
}
if(!this.pointer){
toss("Cannot set struct property on disposed instance.");
toss("Invalid value for pointer-type",xPropName+'.');
}
(
- new DataView(heap().buffer, this.pointer + descr.offset, sizeOf)
+ new DataView(heap().buffer, this.pointer + descr.offset, descr.sizeof)
)[f._.setters[sigGlyph]](0, f._.sw[sigGlyph](v), isLittleEndian);
};
}
if(!structName) toss("Struct name is required.");
let lastMember = false;
Object.keys(structInfo.members).forEach((k)=>{
+ // Sanity checks of sizeof/offset info...
const m = structInfo.members[k];
if(!m.sizeof) toss(structName,"member",k,"is missing sizeof.");
- else if(0!==(m.sizeof%4)){
- toss(structName,"member",k,"sizeof is not aligned.");
- }
- else if(0!==(m.offset%4)){
- toss(structName,"member",k,"offset is not aligned.");
+ else if(m.sizeof>1){ // offsets of size-1 members may be odd values.
+ if(0!==(m.sizeof%4)){
+ console.warn("Invalid struct description =",m,"from",structInfo.members);
+ toss(structName,"member",k,"sizeof is not aligned. sizeof="+m.sizeof);
+ }
+ if(0!==(m.offset%4)){
+ console.warn("Invalid struct description =",m,"from",structInfo.members);
+ toss(structName,"member",k,"offset is not aligned. offset="+m.offset);
+ }
}
if(!lastMember || lastMember.offset < m.offset) lastMember = m;
});
signature entry.
- **`f`** = `float` (4 bytes)
- **`d`** = `double` (8 bytes)
-- **`p`** = `int32` (but see below!)
+- **`c`** = `int8` (char - see notes below!)
+- **`C`** = `int8` (unsigned char - see notes below!)
+- **`p`** = `int32` (see notes below!)
- **`P`** = Like `p` but with extra handling. Described below.
-- **`s`** = like `int32` but is a _hint_ that it's a pointer to a string
- so that _some_ (very limited) contexts may treat it as such, noting
- such algorithms must, for lack of information to the contrary,
- assume both that the encoding is UTF-8 and that the pointer's member
- is NUL-terminated. If that is _not_ the case for a given string
- member, do not use `s`: use `i` or `p` instead and do any string
- handling yourself.
+- **`s`** = like `int32` but is a _hint_ that it's a pointer to a
+ string so that _some_ (very limited) contexts may treat it as such,
+ noting that such algorithms must, for lack of information to the
+ contrary, assume both that the encoding is UTF-8 and that the
+ pointer's member is NUL-terminated. If that is _not_ the case for a
+ given string member, do not use `s`: use `i` or `p` instead and do
+ any string handling yourself.
Noting that:
- All of these types are numeric. Attempting to set any struct-bound
property to a non-numeric value will trigger an exception except in
cases explicitly noted otherwise.
+- "Char" types: WASM does not define an `int8` type, nor does it
+ distinguish between signed and unsigned. This API treats `c` as
+ `int8` and `C` as `uint8` for purposes of getting and setting values
+ when using the `DataView` class. It is _not_ recommended that client
+ code use these types in new WASM-capable code, but they were added
+ for the sake of binding some immutable legacy code to WASM.
> Sidebar: Emscripten's public docs do not mention `p`, but their
generated code includes `p` as an alias for `i`, presumably to mean
form `x()`. For function-type signatures, the strings are formulated
such that they can be passed to Emscripten's `addFunction()` after
stripping out the `(` and `)` characters. For good measure, to match
-the public Emscripten docs, `p` should also be replaced with `i`. In
-JavaScript that might look like:
+the public Emscripten docs, `p`, `c`, and `C`, should also be replaced
+with `i`. In JavaScript that might look like:
>
```
-signature.replace(/[^vipPsjfd]/g,'').replace(/[pPs]/g,'i');
+signature.replace(/[^vipPsjfdcC]/g,'').replace(/[pPscC]/g,'i');
```
<a name='step-2-pvsp'></a>
-C Improved\squery\splanner\scost\sestimates.\s\sFix\sfor\sticket\s[e8b674241947eb3b].
-D 2022-12-05T02:52:37.959
+C Initial\sinfrastructure\sfor\sadding\svirtual\stable/table-valued\sfunction\ssupport\sto\sWASM.
+D 2022-12-05T05:30:03.152
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
-F ext/wasm/api/sqlite3-api-glue.js 6fe39964605fda3b699f69365eed565b5172d29cab2c49bc057a43f9a93f9f36
+F ext/wasm/api/sqlite3-api-glue.js 6028d0c3e6f475a513040a45612238b749ec6c155181d5bd029d66577ab4d0d6
F ext/wasm/api/sqlite3-api-oo1.js 91a7d7b9203fb0f031e6ba380a644a7f871e1798b388de399c01ed4087bac9e0
F ext/wasm/api/sqlite3-api-prologue.js 697a5989ad52a9ba7bc60b5436589bd05885ee2201d84c38c5e9af3876af3ba4
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
F ext/wasm/api/sqlite3-vfs-helper.js 4ad4faf02e1524bf0296be8452c00b5708dce6faf649468d0377e26a0b299263
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 29d6487a26b2fb6a471cde52c37ffee7c27ed6a91914b308c247e0706f454ffb
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
-F ext/wasm/api/sqlite3-wasm.c b0babf8435f31d21f28454fb81433aa538c68b23d0a4a251f0666fdec4e71f59
+F ext/wasm/api/sqlite3-wasm.c 5120fb3419aba02d20cbe1e645b58dae5faeaaae8ccd46b8931ae04d311df9e5
F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/common/testing.css 35889709547d89a6109ff83b25c11bbc91d8dd43aab8722e428655ca98880a06
-F ext/wasm/common/whwasmutil.js c1bc5715cd96728929cc31d788b16152ccbd6b2e111d2e88fbc9725247e67b4f
+F ext/wasm/common/whwasmutil.js 1bc1c973662db7d52763512e67c2369fdbfe9e8bae33069ac89f4fbe40d678b2
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/index-dist.html c806b6005145b71d64240606e9c6e0bf56878ee8829c66fe7486cebf34b0e6b1
F ext/wasm/index.html f151b7c7b5cfdc066567d556acd168e769efd4e982286dc5f849a5ee69ecd0ff
-F ext/wasm/jaccwabyt/jaccwabyt.js 95f573de1826474c9605dda620ee622fcb1673ae74f191eb324c0853aa4dcb66
-F ext/wasm/jaccwabyt/jaccwabyt.md 9aa6951b529a8b29f578ec8f0355713c39584c92cf1708f63ba0cf917cb5b68e
+F ext/wasm/jaccwabyt/jaccwabyt.js 7c41784c442aa67f0e86e7c14aa51b3a28e3b21eb579c71c16af3c988fbf966f
+F ext/wasm/jaccwabyt/jaccwabyt.md 50df3ccb7a773634000496a2ccb805dd25cf8cd963696a7deec3209a68c6093b
F ext/wasm/module-symbols.html 980680c8acfa3c8ae6a5aa223512d1b8e78040ced20f8ba2c382129bc73ec028
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
F ext/wasm/scratchpad-wasmfs-main.js 4c140457f4d6da9d646a49addd91edb6e9ad1643c6c48e3258b5bce24725dc18
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P cefc032473ac5ad244c0b6402c541b2f76c0c65a041bda03bfbe7c0e2c11fac2 df3818997b822743ac407dde45c5fd75845ca40f461e31350d86963dffec6cd6
-R 3c93957174c9bb89beba8a6d7c9fdaab
-T +closed df3818997b822743ac407dde45c5fd75845ca40f461e31350d86963dffec6cd6
-U drh
-Z 2d83b2d52ce6d0637e1b84504b86ac00
+P 1b779afa3ed2f35a110e460fc6ed13cba744db85b9924149ab028b100d1e1e12
+R b429259a443dd7b0ac8ceede26128588
+T *branch * wasm-vtab
+T *sym-wasm-vtab *
+T -sym-trunk * Cancelled\sby\sbranch.
+U stephan
+Z bd980b10d448d088ee0cbb8238fc2a43
# Remove this line to create a well-formed Fossil manifest.
-1b779afa3ed2f35a110e460fc6ed13cba744db85b9924149ab028b100d1e1e12
\ No newline at end of file
+c202d7a0398b9aabc2babba5c4c91a313f32bbf37549d419775642bb4aa3936a
\ No newline at end of file