From: stephan Date: Thu, 8 Dec 2022 17:07:27 +0000 (+0000) Subject: Ease-of-use/legibility improvements in the virtual table JS helpers. X-Git-Tag: version-3.41.0~290 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=500fa7d518c3ee7154732d8c4ada707476944367;p=thirdparty%2Fsqlite.git Ease-of-use/legibility improvements in the virtual table JS helpers. FossilOrigin-Name: 54c7ad7e08bdb87579398ade366605bfa2e2538a94aabcc6e4cda8e173649760 --- diff --git a/ext/wasm/api/sqlite3-v-helper.js b/ext/wasm/api/sqlite3-v-helper.js index 264c606b41..a28fb389a3 100644 --- a/ext/wasm/api/sqlite3-v-helper.js +++ b/ext/wasm/api/sqlite3-v-helper.js @@ -308,12 +308,12 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ vt.sqlite3ValuesToJs = capi.sqlite3_create_function_v2.udfConvertArgs; /** - Factory function for xAbc() impls. + Internal factory function for xVtab and xCursor impls. */ - const __xWrapFactory = function(methodName,structType){ + const __xWrapFactory = function(methodName,StructType){ return function(ptr,removeMapping=false){ - if(0===arguments.length) ptr = new structType; - if(ptr instanceof structType){ + if(0===arguments.length) ptr = new StructType; + if(ptr instanceof StructType){ //T.assert(!this.has(ptr.pointer)); this.set(ptr.pointer, ptr); return ptr; @@ -325,52 +325,99 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return rc; }.bind(new Map); }; - /** - EXPERIMENTAL. DO NOT USE IN CLIENT CODE. - - Has 3 distinct uses: - - - wrapVtab() instantiates a new capi.sqlite3_vtab instance, maps - its pointer for later by-pointer lookup, and returns that - object. This is intended to be called from - sqlite3_module::xConnect() or xCreate() implementations. - - - wrapVtab(pVtab) accepts a WASM pointer to a C-level - (sqlite3_vtab*) instance and returns the capi.sqlite3_vtab - object created by the first form of this function, or undefined - if that form has not been used. This is intended to be called - from sqlite3_module methods which take a (sqlite3_vtab*) - pointer _except_ for xDestroy() (if there is a distinct - xCreate()) or xDisconnect() (if xCreate() is 0 or is the same - as xConnect()), in which case use... - - - wrapVtab(pVtab,true) as for the previous form, but removes the - pointer-to-object mapping before returning. The caller must - call dispose() on the returned object. This is intended to be - called from sqlite3_module::xDisconnect() implementations or - in error handling of a failed xCreate() or xConnect(). - */ - vt.xVtab = __xWrapFactory('xVtab',capi.sqlite3_vtab); /** - EXPERIMENTAL. DO NOT USE IN CLIENT CODE. + Internal helper for implementing xVtab and xCursor. + The first argument must be the logical name of the + handler ('xVtab' or 'xCursor') and the second must be + the capi.XYZ struct-type value, e.g. capi.sqlite3_vtab + or capi.sqlite3_vtab_cursor. + */ + const __xLifetimeManager = function(name, StructType){ + const __xWrap = __xWrapFactory(name,StructType); + /** + This object houses a small API for managing mappings of (`T*`) + to StructType objects, specifically within the lifetime + requirements of sqlite3_module methods. + */ + return Object.assign(Object.create(null),{ + /** The StructType object for this object's API. */ + StructType, + /** + Creates a new StructType object, writes its `pointer` + value to the given output pointer, and returns that + object. Its intended usage depends on StructType: + + sqlite3_vtab: to be called from sqlite3_module::xConnect() + or xCreate() implementations. + + sqlite3_vtab_cursor: to be called from xOpen(). + + This will throw if allocation of the StructType instance + fails or if ppOut is not a pointer-type value. + */ + create: (ppOut)=>{ + const rc = __xWrap(); + wasm.setPtrValue(ppOut, rc.pointer); + return rc; + }, + /** + Returns the StructType object previously mapped to the + given pointer using create(). Its intended usage depends + on StructType: + + sqlite3_vtab: to be called from sqlite3_module methods which + take a (sqlite3_vtab*) pointer _except_ for + xDestroy()/xDisconnect(), in which case unget() or dispose(). + + sqlite3_vtab_cursor: to be called from any sqlite3_module methods + which take a `sqlite3_vtab_cursor*` argument except xClose(), + in which case use unget() or dispose(). + */ + get: (pCObj)=>__xWrap(pCObj), + /** + Identical to get() but also disconnects the mapping between the + given pointer and the returned StructType object, such that + future calls to this function or get() with the same pointer + will return the undefined value. Its intended usage depends + on StructType: + + sqlite3_vtab: to be called from sqlite3_module::xDisconnect() or + xDestroy() implementations or in error handling of a failed + xCreate() or xConnect(). + + sqlite3_vtab_cursor: to be called from xClose() or during + cleanup in a failed xOpen(). + */ + unget: (pCObj)=>__xWrap(pCObj,true), + /** + Works like unget() plus it calls dispose() on the + StructType object. + */ + dispose: (pCObj)=>{ + const o = __xWrap(pCObj,true); + if(o) o.dispose(); + } + }); + }; - Works identically to wrapVtab() except that it deals with - sqlite3_cursor objects and pointers instead of sqlite3_vtab. + /** + A lifetime-management object for mapping `sqlite3_vtab*` + instances in sqlite3_module methods to capi.sqlite3_vtab + objects. - - wrapCursor() is intended to be called from sqlite3_module::xOpen() + The API docs are in the API-internal __xLifetimeManager(). + */ + vt.xVtab = __xLifetimeManager('xVtab', capi.sqlite3_vtab); - - wrapCursor(pCursor) is intended to be called from all sqlite3_module - methods which take a (sqlite3_vtab_cursor*) _except_ for - xClose(), in which case use... + /** + A lifetime-management object for mapping `sqlite3_vtab_cursor*` + instances in sqlite3_module methods to capi.sqlite3_vtab_cursor + objects. - - wrapCursor(pCursor, true) will remove the mapping of pCursor to a - capi.sqlite3_vtab_cursor object and return that object. The - caller must call dispose() on the returned object. This is - intended to be called from xClose() or in error handling of a - failed xOpen(). - */ - vt.xCursor = __xWrapFactory('xCursor',capi.sqlite3_vtab_cursor); + The API docs are in the API-internal __xLifetimeManager(). + */ + vt.xCursor = __xLifetimeManager('xCursor', capi.sqlite3_vtab_cursor); /** Convenience form of creating an sqlite3_index_info wrapper, @@ -466,16 +513,28 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /** A helper for sqlite3_vtab::xRowid() implementations. It must be - passed that function's 2nd argument and the value for that - pointer. Returns the same as wasm.setMemValue() and will throw + passed that function's 2nd argument (an output pointer to an + int64 row ID) and the value to store at the output pointer's + address. Returns the same as wasm.setMemValue() and will throw if the 1st or 2nd arguments are invalid for that function. + + Example xRowid impl: + + ``` + const xRowid = (pCursor, ppRowid64)=>{ + const c = VtabHelper.xCursor(pCursor); + VtabHelper.xRowid(ppRowid64, c.myRowId); + return 0; + }; + ``` */ vt.xRowid = (ppRowid64, value)=>wasm.setMemValue(ppRowid64, value, 'i64'); /** - Sets up an sqlite3_module() object for later installation into - individual databases using sqlite3_create_module(). Requires an - object with the following properties: + A helper to initialize and set up an sqlite3_module() object for + later installation into individual databases using + sqlite3_create_module(). Requires an object with the following + properties: - `methods`: an object containing a mapping of properties with the C-side names of the sqlite3_module methods, e.g. xCreate, @@ -506,16 +565,25 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ behavior. (VtabHelper.xError() is intended to assist in reporting such exceptions.) - If `methods.xConnect` is `true` then the value of - `methods.xCreate` is used in its place, and vice versa. This is - to facilitate creation of those methods inline in the passed-in - object without requiring the client to explicitly get a reference - to one of them in order to assign it to the other one. Note that - sqlite treats those two functions specially if they are exactly - the same function (same pointer value). The - `catchExceptions`-installed handlers will account for identical - references to those two functions and will install the same - wrapper function for both. + Certain methods may refer to the same implementation. To simplify + the definition of such methods: + + - If `methods.xConnect` is `true` then the value of + `methods.xCreate` is used in its place, and vice versa. sqlite + treats xConnect/xCreate functions specially if they are exactly + the same function (same pointer value). + + - If `methods.xDisconnect` is true then the value of + `methods.xDestroy` is used in its place, and vice versa. + + This is to facilitate creation of those methods inline in the + passed-in object without requiring the client to explicitly get a + reference to one of them in order to assign it to the other + one. + + The `catchExceptions`-installed handlers will account for + identical references to the above functions and will install the + same wrapper function for both. The given methods are expected to return integer values, as expected by the C API. If `catchExceptions` is truthy, the return @@ -525,7 +593,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ active, the method implementations must explicitly return integer values. - Throws on error. Returns the sqlite3_module object on success. + Throws on error. Returns the opt.struct sqlite3_module object on + success. */ vt.setupModule = function(opt){ const mod = opt.struct || new capi.sqlite3_module(); @@ -533,6 +602,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const methods = opt.methods || toss("Missing 'methods' object."); if(true===methods.xConnect) methods.xConnect = methods.xCreate; else if(true===methods.xCreate) methods.xCreate = methods.xConnect; + if(true===methods.xDisconnect) methods.xDisconnect = methods.xDestroy; + else if(true===methods.xDestroy) methods.xDestroy = methods.xDisconnect; if(opt.catchExceptions){ const fwrap = function(methodName, func){ if(['xConnect','xCreate'].indexOf(methodName) >= 0){ @@ -577,6 +648,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } this.installMethods(mod, remethods, false); }else{ + // No automatic exception handling. Trust the client + // to not throw. this.installMethods( mod, methods, !!opt.applyArgcCheck/*undocumented option*/ ); diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js index 61531cf87f..c8225568d5 100644 --- a/ext/wasm/tester1.c-pp.js +++ b/ext/wasm/tester1.c-pp.js @@ -999,7 +999,12 @@ self.sqlite3InitModule = sqlite3InitModule; const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c'); db.onclose = { disposeAfter: [], - disposeBefore: [], + disposeBefore: [ + (db)=>{ + //console.debug("db.onclose.before dropping modules"); + //sqlite3.capi.sqlite3_drop_modules(db.pointer, 0); + } + ], before: function(db){ while(this.disposeBefore.length){ const v = this.disposeBefore.shift(); @@ -1013,8 +1018,6 @@ self.sqlite3InitModule = sqlite3InitModule; } } } - console.debug("db.onclose.before dropping modules"); - sqlite3.capi.sqlite3_drop_modules(db.pointer, 0); }, after: function(){ while(this.disposeAfter.length){ @@ -1669,7 +1672,7 @@ self.sqlite3InitModule = sqlite3InitModule; //////////////////////////////////////////////////////////////////////// .t({ - name: 'virtual table #1', + name: 'virtual table #1: eponymous w/ manual exception handling', predicate: ()=>!!capi.sqlite3_index_info, test: function(sqlite3){ warn("The vtab/module JS bindings are experimental and subject to change."); @@ -1694,9 +1697,8 @@ self.sqlite3InitModule = sqlite3InitModule; pDb, "CREATE TABLE ignored(a,b)" ); if(0===rc){ - const t = vth.xVtab(); - wasm.setPtrValue(ppVtab, t.pointer); - T.assert(t === vth.xVtab(wasm.getPtrValue(ppVtab))); + const t = vth.xVtab.create(ppVtab); + T.assert(t === vth.xVtab.get(wasm.getPtrValue(ppVtab))); } return rc; }catch(e){ @@ -1709,8 +1711,7 @@ self.sqlite3InitModule = sqlite3InitModule; }, xDisconnect: function(pVtab){ try { - const t = vth.xVtab(pVtab, true); - t.dispose(); + vth.xVtab.unget(pVtab).dispose(); return 0; }catch(e){ return vth.xError('xDisconnect',e); @@ -1718,10 +1719,10 @@ self.sqlite3InitModule = sqlite3InitModule; }, xOpen: function(pVtab, ppCursor){ try{ - const t = vth.xVtab(pVtab), c = vth.xCursor(); + const t = vth.xVtab.get(pVtab), + c = vth.xCursor.create(ppCursor); T.assert(t instanceof capi.sqlite3_vtab) .assert(c instanceof capi.sqlite3_vtab_cursor); - wasm.setPtrValue(ppCursor, c.pointer); c._rowId = 0; return 0; }catch(e){ @@ -1730,9 +1731,9 @@ self.sqlite3InitModule = sqlite3InitModule; }, xClose: function(pCursor){ try{ - const c = vth.xCursor(pCursor,true); + const c = vth.xCursor.unget(pCursor); T.assert(c instanceof capi.sqlite3_vtab_cursor) - .assert(!vth.xCursor(pCursor)); + .assert(!vth.xCursor.get(pCursor)); c.dispose(); return 0; }catch(e){ @@ -1741,17 +1742,16 @@ self.sqlite3InitModule = sqlite3InitModule; }, xNext: function(pCursor){ try{ - const c = vth.xCursor(pCursor); + const c = vth.xCursor.get(pCursor); ++c._rowId; return 0; }catch(e){ return vth.xError('xNext',e); } - }, xColumn: function(pCursor, pCtx, iCol){ try{ - const c = vth.xCursor(pCursor); + const c = vth.xCursor.get(pCursor); switch(iCol){ case tmplCols.A: capi.sqlite3_result_int(pCtx, 1000 + c._rowId); @@ -1768,7 +1768,7 @@ self.sqlite3InitModule = sqlite3InitModule; }, xRowid: function(pCursor, ppRowid64){ try{ - const c = vth.xCursor(pCursor); + const c = vth.xCursor.get(pCursor); vth.xRowid(ppRowid64, c._rowId); return 0; }catch(e){ @@ -1776,7 +1776,7 @@ self.sqlite3InitModule = sqlite3InitModule; } }, xEof: function(pCursor){ - const c = vth.xCursor(pCursor), + const c = vth.xCursor.get(pCursor), rc = c._rowId>=10; c.dispose(); return rc; @@ -1784,7 +1784,7 @@ self.sqlite3InitModule = sqlite3InitModule; xFilter: function(pCursor, idxNum, idxCStr, argc, argv/* [sqlite3_value* ...] */){ try{ - const c = vth.xCursor(pCursor); + const c = vth.xCursor.get(pCursor); c._rowId = 0; const list = vth.sqlite3ValuesToJs(argc, argv); T.assert(argc === list.length); @@ -1797,7 +1797,7 @@ self.sqlite3InitModule = sqlite3InitModule; }, xBestIndex: function(pVtab, pIdxInfo){ try{ - //const t = vth.xVtab(pVtab); + //const t = vth.xVtab.get(pVtab); const sii = capi.sqlite3_index_info; const pii = new sii(pIdxInfo); pii.$estimatedRows = 10; @@ -1886,7 +1886,7 @@ self.sqlite3InitModule = sqlite3InitModule; //////////////////////////////////////////////////////////////////////// .t({ - name: 'virtual table #2 (non-eponymous w/ automated exception wrapping)', + name: 'virtual table #2: non-eponymous w/ automated exception wrapping', predicate: ()=>!!capi.sqlite3_index_info, test: function(sqlite3){ warn("The vtab/module JS bindings are experimental and subject to change."); @@ -1926,55 +1926,41 @@ self.sqlite3InitModule = sqlite3InitModule; pDb, "CREATE TABLE ignored(a,b)" ); if(0===rc){ - const t = vth.xVtab(); - wasm.setPtrValue(ppVtab, t.pointer); - T.assert(t === vth.xVtab(wasm.getPtrValue(ppVtab))); + const t = vth.xVtab.create(ppVtab); + T.assert(t === vth.xVtab.get(wasm.getPtrValue(ppVtab))); vtabTrace("xCreate",...arguments," ppVtab =",t.pointer); } return rc; }, + xConnect: true, xDestroy: function(pVtab){ - vtabTrace("sqlite3_xDestroy",pVtab); - const t = vth.xVtab(pVtab, true); - T.assert(t); - t.dispose(); - }, - /*xConnect: function(pDb, pAux, argc, argv, ppVtab, pzErr){ - vtabTrace("xConnect",...arguments); - const t = vth.xVtab(); - wasm.setPtrValue(ppVtab, t.pointer); - T.assert(t === vth.xVtab(wasm.getPtrValue(ppVtab))); - vtabTrace("xConnect",...arguments,"ppVtab =",t.pointer); + vtabTrace("xDestroy/xDisconnect",pVtab); + vth.xVtab.dispose(pVtab); }, - xDisconnect: function(pVtab){ - vtabTrace("xDisconnect",pVtab); - const t = vth.xVtab(pVtab, true); - T.assert(t); - t.dispose(); - },*/ + xDisconnect: true, xOpen: function(pVtab, ppCursor){ - const t = vth.xVtab(pVtab), c = vth.xCursor(); + const t = vth.xVtab.get(pVtab), + c = vth.xCursor.create(ppCursor); T.assert(t instanceof capi.sqlite3_vtab) .assert(c instanceof capi.sqlite3_vtab_cursor); - wasm.setPtrValue(ppCursor, c.pointer); vtabTrace("xOpen",...arguments," cursor =",c.pointer); c._rowId = 0; }, xClose: function(pCursor){ vtabTrace("xClose",...arguments); - const c = vth.xCursor(pCursor,true); + const c = vth.xCursor.unget(pCursor); T.assert(c instanceof capi.sqlite3_vtab_cursor) - .assert(!vth.xCursor(pCursor)); + .assert(!vth.xCursor.get(pCursor)); c.dispose(); }, xNext: function(pCursor){ vtabTrace("xNext",...arguments); - const c = vth.xCursor(pCursor); + const c = vth.xCursor.get(pCursor); ++c._rowId; }, xColumn: function(pCursor, pCtx, iCol){ vtabTrace("xColumn",...arguments); - const c = vth.xCursor(pCursor); + const c = vth.xCursor.get(pCursor); switch(iCol){ case tmplCols.A: capi.sqlite3_result_int(pCtx, 1000 + c._rowId); @@ -1987,24 +1973,24 @@ self.sqlite3InitModule = sqlite3InitModule; }, xRowid: function(pCursor, ppRowid64){ vtabTrace("xRowid",...arguments); - const c = vth.xCursor(pCursor); + const c = vth.xCursor.get(pCursor); vth.xRowid(ppRowid64, c._rowId); }, xEof: function(pCursor){ vtabTrace("xEof",...arguments); - return vth.xCursor(pCursor)._rowId>=10; + return vth.xCursor.get(pCursor)._rowId>=10; }, xFilter: function(pCursor, idxNum, idxCStr, argc, argv/* [sqlite3_value* ...] */){ vtabTrace("xFilter",...arguments); - const c = vth.xCursor(pCursor); + const c = vth.xCursor.get(pCursor); c._rowId = 0; const list = vth.sqlite3ValuesToJs(argc, argv); T.assert(argc === list.length); }, xBestIndex: function(pVtab, pIdxInfo){ vtabTrace("xBestIndex",...arguments); - //const t = vth.xVtab(pVtab); + //const t = vth.xVtab.get(pVtab); const pii = vth.xIndexInfo(pIdxInfo); pii.$estimatedRows = 10; pii.$estimatedCost = 10.0; @@ -2024,19 +2010,18 @@ self.sqlite3InitModule = sqlite3InitModule; modConfig.name, "(arg1 blah, arg2 bloop)" ]); - this.db.onclose.disposeBefore.push(function(db){ - console.debug("testvtab2 disposeBefore handler..."); - db.exec( - /** - DROP TABLE is the only way to get xDestroy() to be called. - If we DROP TABLE at the end of the containing - test function, xDestroy() is called. If we instead - delay it until db.onclose.before(), we're getting - "no such table"? - */ - "DROP TABLE testvtab2" - ); - }); + if(0){ + /* If we DROP TABLE then xDestroy() is called. If the + vtab is instead destroyed when the db is closed, + xDisconnect() is called. */ + this.db.onclose.disposeBefore.push(function(db){ + console.debug("Explicitly dropping testvtab2 via disposeBefore handler..."); + db.exec( + /** DROP TABLE is the only way to get xDestroy() to be called. */ + "DROP TABLE testvtab2" + ); + }); + } let list = this.db.selectArrays( "SELECT a,b FROM testvtab2 where a<9999 and b>1 order by a, b" /* Query is shaped so that it will ensure that some @@ -2052,6 +2037,15 @@ self.sqlite3InitModule = sqlite3InitModule; T.assert(5===list.length) .assert(1000===list[0][0]) .assert(2004===list[list.length-1][1]); + + // Call it as a table-valued function... + list = this.db.selectArrays([ + "SELECT a,b FROM ", modConfig.name, + " where a<9999 and b>1 order by b, a limit 1" + ]); + T.assert(1===list.length) + .assert(1000===list[0][0]) + .assert(2000===list[0][1]); } })/*custom vtab #2*/ diff --git a/manifest b/manifest index 2e44b4ee20..eb27511aeb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\ssupport\sfor\svirtual\stables\simplemented\sin\sJavaScript. -D 2022-12-08T15:00:53.415 +C Ease-of-use/legibility\simprovements\sin\sthe\svirtual\stable\sJS\shelpers. +D 2022-12-08T17:07:27.475 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -509,7 +509,7 @@ F ext/wasm/api/sqlite3-api-prologue.js 1380e933325c11786b2afc93fc8ff88c2fd1ffeac 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 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f -F ext/wasm/api/sqlite3-v-helper.js ec03a222ad3551764626f14f38de1b1081bda509e098849502b498c041993a0f w ext/wasm/api/sqlite3-vfs-helper.js +F ext/wasm/api/sqlite3-v-helper.js d0d647110f8595d26836951cfc5a47f15282f20e72584decc0b00e2a3f0d169c F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 8ec510fee735c646fb18a3b99f0ca5ca461f9e066c43cdc404d7144f12ae6ed6 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 F ext/wasm/api/sqlite3-wasm.c 97034ab4f40ec1fac71ccfaf3afffdca6b1ea2dcd95b7871527bad0f34e152b0 @@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555 F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9 F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406 -F ext/wasm/tester1.c-pp.js ecd0ecd6c9f0c5bce7f39a3ccb28151c7ae7b1042379a0c855e930661579f2e8 +F ext/wasm/tester1.c-pp.js ff147d87a1b6b827484da0bedf6f9f03ae027d6d4aec8ab9b22b22801c6df474 F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70 F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 @@ -2067,9 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 53dcb81b029e4422bdc0b5cf694183854b997195427d437b6154ed4dad7ad0ba 51e3c3b569dce2097063d39dc484f44b2f98cad0a902ef66765ca4cdc3e06f47 -R 8761e73b7826ed273f62994737b011e2 -T +closed 51e3c3b569dce2097063d39dc484f44b2f98cad0a902ef66765ca4cdc3e06f47 Closed\sby\sintegrate-merge. +P a1454744c770a30a32a6d7b7fc59ef7be48cf67348b238540592850d7c2c7757 +R 17cb094a6db22f136920052decf90bf5 U stephan -Z b6d983dab7ab65c0caebb5e5bbac6324 +Z fce05bcff7bc40d31cdbdf756e15ecfc # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5d13ad354e..83cd954639 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a1454744c770a30a32a6d7b7fc59ef7be48cf67348b238540592850d7c2c7757 \ No newline at end of file +54c7ad7e08bdb87579398ade366605bfa2e2538a94aabcc6e4cda8e173649760 \ No newline at end of file