]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Experimentally add sqlite3.oo1.DB/Stmt.wrapHandle(), which allow DB/Stmt instances...
authorstephan <stephan@noemail.net>
Sun, 6 Jul 2025 15:01:44 +0000 (15:01 +0000)
committerstephan <stephan@noemail.net>
Sun, 6 Jul 2025 15:01:44 +0000 (15:01 +0000)
FossilOrigin-Name: 1227543b87c3320d6b80e0f61b88ea53b68779966a0295c4d6a1db6369c48207

ext/wasm/api/sqlite3-api-oo1.c-pp.js
ext/wasm/tester1.c-pp.js
manifest
manifest.uuid

index 06f91600212d0f133436dcaedd44c2de796d6f93..91d8bc544dd2d7ce7e2cfed324495960fb0951f6 100644 (file)
@@ -37,6 +37,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
      it.
   */
   const __ptrMap = new WeakMap();
+  /**
+     A Set of oo1.DB objects which are proxies for (A) (sqlite3*) or
+     another oo1.DB object or (B) oo1.Stmt objects which are proxies
+     for (sqlite3_stmt*) pointers. Such objects do not own their
+     underlying handle and that handle must be guaranteed (by the
+     client) to outlive the proxy. These proxies are primarily
+     intended as a way to briefly wrap an (sqlite3[_stmt]*) object as
+     an oo1.DB/Stmt without taking over ownership.
+  */
+  const __doesNotOwnHandle = new Set();
   /**
      Map of DB instances to objects, each object being a map of Stmt
      wasm pointers to Stmt objects.
@@ -234,73 +244,89 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       };
     }
     const opt = ctor.normalizeArgs(...args);
-    let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags;
-    if(('string'!==typeof fn && 'number'!==typeof fn)
-       || 'string'!==typeof flagsStr
-       || (vfsName && ('string'!==typeof vfsName && 'number'!==typeof vfsName))){
-      sqlite3.config.error("Invalid DB ctor args",opt,arguments);
-      toss3("Invalid arguments for DB constructor.");
-    }
-    let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn;
-    const vfsCheck = ctor._name2vfs[fnJs];
-    if(vfsCheck){
-      vfsName = vfsCheck.vfs;
-      fn = fnJs = vfsCheck.filename(fnJs);
-    }
-    let pDb, oflags = 0;
-    if( flagsStr.indexOf('c')>=0 ){
-      oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
-    }
-    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 = wasm.pstack.pointer;
-    try {
-      const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */;
-      let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || 0);
-      pDb = wasm.peekPtr(pPtr);
-      checkSqlite3Rc(pDb, rc);
-      capi.sqlite3_extended_result_codes(pDb, 1);
-      if(flagsStr.indexOf('t')>=0){
-        capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
-                              __dbTraceToConsole, pDb);
+    //sqlite3.config.debug("DB ctor",opt);
+    let pDb;
+    if( (pDb = opt['sqlite3*']) ){
+      /* This property ^^^^^ is very specifically NOT DOCUMENTED and
+         NOT part of the public API. This is a back door for functions
+         like DB.wrapDbHandle(). */
+      //sqlite3.config.debug("creating proxy db from",opt);
+      if( !opt['sqlite3*:takeOwnership'] ){
+        /* This is object does not own its handle. */
+        __doesNotOwnHandle.add(this);
       }
-    }catch( e ){
-      if( pDb ) capi.sqlite3_close_v2(pDb);
-      throw e;
-    }finally{
-      wasm.pstack.restore(stack);
+      this.filename = capi.sqlite3_db_filename(pDb,'main');
+    }else{
+      let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags;
+      if(('string'!==typeof fn && 'number'!==typeof fn)
+         || 'string'!==typeof flagsStr
+         || (vfsName && ('string'!==typeof vfsName && 'number'!==typeof vfsName))){
+        sqlite3.config.error("Invalid DB ctor args",opt,arguments);
+        toss3("Invalid arguments for DB constructor.");
+      }
+      let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn;
+      const vfsCheck = ctor._name2vfs[fnJs];
+      if(vfsCheck){
+        vfsName = vfsCheck.vfs;
+        fn = fnJs = vfsCheck.filename(fnJs);
+      }
+      let oflags = 0;
+      if( flagsStr.indexOf('c')>=0 ){
+        oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
+      }
+      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 = wasm.pstack.pointer;
+      try {
+        const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */;
+        let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || 0);
+        pDb = wasm.peekPtr(pPtr);
+        checkSqlite3Rc(pDb, rc);
+        capi.sqlite3_extended_result_codes(pDb, 1);
+        if(flagsStr.indexOf('t')>=0){
+          capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
+                                __dbTraceToConsole, pDb);
+        }
+      }catch( e ){
+        if( pDb ) capi.sqlite3_close_v2(pDb);
+        throw e;
+      }finally{
+        wasm.pstack.restore(stack);
+      }
+      this.filename = fnJs;
     }
-    this.filename = fnJs;
     __ptrMap.set(this, pDb);
     __stmtMap.set(this, Object.create(null));
-    try{
+    if( !opt['sqlite3*'] ){
+      try{
 //#if enable-see
-      dbCtorApplySEEKey(this,opt);
+        dbCtorApplySEEKey(this,opt);
 //#endif
-      // Check for per-VFS post-open SQL/callback...
-      const pVfs = capi.sqlite3_js_db_vfs(pDb)
-            || toss3("Internal error: cannot get VFS for new db handle.");
-      const postInitSql = __vfsPostOpenCallback[pVfs];
-      if(postInitSql){
-        /**
-           Reminder: if this db is encrypted and the client did _not_ pass
-           in the key, any init code will fail, causing the ctor to throw.
-           We don't actually know whether the db is encrypted, so we cannot
-           sensibly apply any heuristics which skip the init code only for
-           encrypted databases for which no key has yet been supplied.
-        */
-        if(postInitSql instanceof Function){
-          postInitSql(this, sqlite3);
-        }else{
-          checkSqlite3Rc(
-            pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
-          );
+        // Check for per-VFS post-open SQL/callback...
+        const pVfs = capi.sqlite3_js_db_vfs(pDb)
+              || toss3("Internal error: cannot get VFS for new db handle.");
+        const postInitSql = __vfsPostOpenCallback[pVfs];
+        if(postInitSql){
+          /**
+             Reminder: if this db is encrypted and the client did _not_ pass
+             in the key, any init code will fail, causing the ctor to throw.
+             We don't actually know whether the db is encrypted, so we cannot
+             sensibly apply any heuristics which skip the init code only for
+             encrypted databases for which no key has yet been supplied.
+          */
+          if(postInitSql instanceof Function){
+            postInitSql(this, sqlite3);
+          }else{
+            checkSqlite3Rc(
+              pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
+            );
+          }
         }
+      }catch(e){
+        this.close();
+        throw e;
       }
-    }catch(e){
-      this.close();
-      throw e;
     }
   };
 
@@ -486,26 +512,30 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
      - `db`: the DB object which created the statement.
 
      - `columnCount`: the number of result columns in the query, or 0
-     for queries which cannot return results. This property is a proxy
-     for sqlite3_column_count() and its use in loops should be avoided
-     because of the call overhead associated with that. The
-     `columnCount` is not cached when the Stmt is created because a
-     schema change made via a separate db connection between this
-     statement's preparation and when it is stepped may invalidate it.
+     for queries which cannot return results. This property is a
+     read-only proxy for sqlite3_column_count() and its use in loops
+     should be avoided because of the call overhead associated with
+     that. The `columnCount` is not cached when the Stmt is created
+     because a schema change made between this statement's preparation
+     and when it is stepped may invalidate it.
 
-     - `parameterCount`: the number of bindable parameters in the query.
+     - `parameterCount`: the number of bindable parameters in the
+     query.  Like `columnCount`, this property is ready-only and is a
+     proxy for a C API call.
 
      As a general rule, most methods of this class will throw if
      called on an instance which has been finalized. For brevity's
      sake, the method docs do not all repeat this warning.
   */
-  const Stmt = function(){
+  const Stmt = function(/*oo1db, stmtPtr, BindTypes [,takeOwnership=true] */){
     if(BindTypes!==arguments[2]){
       toss3(capi.SQLITE_MISUSE, "Do not call the Stmt constructor directly. Use DB.prepare().");
     }
     this.db = arguments[0];
     __ptrMap.set(this, arguments[1]);
-    this.parameterCount = capi.sqlite3_bind_parameter_count(this.pointer);
+    if( arguments.length>3 && false===arguments[3] ){
+      __doesNotOwnHandle.add(this);
+    }
   };
 
   /** Throws if the given DB has been closed, else it is returned. */
@@ -723,12 +753,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        a db.
     */
     close: function(){
-      if(this.pointer){
+      const pDb = this.pointer;
+      if(pDb){
         if(this.onclose && (this.onclose.before instanceof Function)){
           try{this.onclose.before(this)}
           catch(e){/*ignore*/}
         }
-        const pDb = this.pointer;
         Object.keys(__stmtMap.get(this)).forEach((k,s)=>{
           if(s && s.pointer){
             try{s.finalize()}
@@ -737,7 +767,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
         });
         __ptrMap.delete(this);
         __stmtMap.delete(this);
-        capi.sqlite3_close_v2(pDb);
+        if( !__doesNotOwnHandle.delete(this) ){
+          capi.sqlite3_close_v2(pDb);
+        }
         if(this.onclose && (this.onclose.after instanceof Function)){
           try{this.onclose.after(this)}
           catch(e){/*ignore*/}
@@ -1450,9 +1482,87 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     */
     checkRc: function(resultCode){
       return checkSqlite3Rc(this, resultCode);
-    }
+    },
   }/*DB.prototype*/;
 
+  /**
+     Returns a new oo1.DB instance which wraps the given db.
+
+     The first argument must be either a non-NULL (sqlite3*) WASM
+     pointer or a non-close()d instance of oo1.DB.
+
+     The second argument only applies if the first argument is a
+     (sqlite3*). If it is, the returned object will pass that pointer
+     to sqlite3_close() when its close() method is called, otherwise
+     it will not.
+
+     If the first argument is a oo1.DB object, the second argument is
+     disregarded and the returned object will be created as a
+     sqlite3.oo1.DB object (as opposed to the concrete derived DB
+     subclass from the first argument), so will not include any
+     derived-type behaviors,
+     e.g. JsStorageDb.prototype.clearStorage().
+
+     Throws if db cannot be resolved to one of the legal options.
+
+     The caller MUST GUARANTEE that the passed-in handle will outlive
+     the returned object, i.e. that it will not be closed. If it is closed,
+     this object will hold a stale pointer and results are undefined.
+
+     Aside from its lifetime, the proxy is to be treated as any other
+     DB instance, including the requirement of calling close() on
+     it. close() will free up internal resources owned by the proxy,
+     and disassociate the proxy from that handle, but will not
+     actually close the proxied db handle.
+
+     The following quirks and requirements apply when proxying another
+     DB instance, as opposed to a (sqlite3*):
+
+     - DO NOT call close() on the being-proxied instance while a proxy
+       is active.
+
+     - ALWAYS eventually call close() on the returned object BEFORE
+       the being-proxied handle is closed.
+
+    - For historical reasons, the filename property of the returned
+      object is captured at the time of this call, as opposed to being
+      dynamically proxied. e.g., if the filename property of the
+      being-proxied object is changed, this object will not reflect
+      that change. There is no good reason to ever modify that
+      property, so this distinction is not truly significant but it's
+      noted here because it's a client-visible discrepancy between the
+      proxy and its partner. (Sidebar: the filename property _should_
+      be a property access interceptor for sqlite3_db_filename(),
+      but making it so now may break existing code.)
+  */
+  DB.wrapHandle = function(db, takeOwnership=false){
+    let ptr, ctor = DB;
+    const oo1db = (db instanceof DB) ? db : undefined;
+    if( wasm.isPtr(db) ){
+      ptr = db;
+    }else if( oo1db ){
+      takeOwnership = false;
+      ptr = db.pointer;
+      //ctor = db.constructor;
+      // ^^^ that doesn't work, resulting in an Object-type value
+    }
+    //sqlite3.config.debug("wrapHandle()",'db',db,'ctor',ctor,
+    //'arguments',arguments,'db.constructor',db.constructor);
+    if( !ptr ){
+      throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE,
+                                     "Argument must be a WASM sqlite3 "+
+                                     "pointer or an sqlite3.oo1.DB instance");
+    }
+    const dc = new ctor({
+      "sqlite3*": ptr,
+      "sqlite3*:takeOwnership": !!takeOwnership
+    });
+    if( oo1db ){
+      dc.filename = oo1db.filename;
+    }//else dc.filename was captured by the ctor for legacy consistency
+    //sqlite3.config.debug("wrapHandle() dc",dc);
+    return dc;
+  }/*DB.wrapHandle()*/;
 
   /** Throws if the given Stmt has been finalized, else stmt is
       returned. */
@@ -1641,12 +1751,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        This method always throws if called when it is illegal to do
        so. Namely, when triggered via a per-row callback handler of a
        DB.exec() call.
+
+       If Stmt does not own its underlying (sqlite3_stmt*) (see
+       Stmt.wrapHandle()) then this function will not pass it to
+       sqlite3_finalize().
     */
     finalize: function(){
-      if(this.pointer){
+      const ptr = this.pointer;
+      if(ptr){
         affirmNotLockedByExec(this,'finalize()');
-        const rc = capi.sqlite3_finalize(this.pointer);
-        delete __stmtMap.get(this.db)[this.pointer];
+        const rc = (__doesNotOwnHandle.delete(this)
+                    ? 0
+                    : capi.sqlite3_finalize(ptr));
+        delete __stmtMap.get(this.db)[ptr];
         __ptrMap.delete(this);
         __execLock.delete(this);
         __stmtMayGet.delete(this);
@@ -2134,6 +2251,60 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     set: ()=>toss3("The columnCount property is read-only.")
   });
 
+  Object.defineProperty(Stmt.prototype, 'parameterCount', {
+    enumerable: false,
+    get: function(){return capi.sqlite3_bind_parameter_count(this.pointer)},
+    set: ()=>toss3("The parameterCount property is read-only.")
+  });
+
+  /**
+     The Stmt counterpart of oo1.DB.wrapHandle(), this creates a Stmt
+     instance which wraps a WASM (sqlite3_stmt*) in the oo1 API with
+     or without taking over ownership of that pointer.
+
+     The first argument must be an oo1.DB instance[^1].
+
+     The second argument must be a valid WASM (sqlite3_stmt*), as
+     produced by sqlite3_prepare_v2() and sqlite3_prepare_v3().
+
+     The third argument specifies whether the returned Stmt object
+     takes over ownership of the underlying (sqlite3_stmt*). If true,
+     the returned object's finalize() method will finalize that
+     handle, else it will not. If it is false, ownership of stmtPtr is
+     unchanged and stmtPtr MUST outlive the returned object or results
+     are undefined.
+
+     This function throws if the arguments are invalid. On success it
+     returns a new Stmt object which wraps the given statement
+     pointer.
+
+     Like all Stmt objects, the finalize() method must eventually be
+     called on the returned object to free up internal resources,
+     regardless of whether this function's third argument is true or
+     not.
+
+     [^1]: The first argument cannot be a (sqlite3*) because the
+     resulting Stmt object requires a parent DB object. It is not yet
+     determined whether it would be of general benefit to refactor the
+     DB/Stmt pair internals to communicate in terms of the underlying
+     (sqlite3*) rather than a DB object. If so, we could laxen the
+     first argument's requirement and allow an (sqlite3*).
+  */
+  Stmt.wrapHandle = function(oo1db, stmtPtr, takeOwnership=false){
+    let ctor = Stmt;
+    if( !(oo1db instanceof DB) || !oo1db.pointer ){
+      throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE,
+                                     "First argument must be an opened "+
+                                     "sqlite3.oo1.DB instance");
+    }
+    if( !stmtPtr || !wasm.isPtr(stmtPtr) ){
+      throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE,
+                                     "Second argument must be a WASM "+
+                                     "sqlite3_stmt pointer");
+    }
+    return new Stmt(oo1db, stmtPtr, BindTypes, !!takeOwnership);
+  }
+
   /** The OO API's public namespace. */
   sqlite3.oo1 = {
     DB,
index 5b94c7c05e1f43718ad76b197f8c0f3a4579d1a6..446437eef8482847cbe029d3cb18648df56dc806 100644 (file)
@@ -41,7 +41,7 @@
 
    ES6 worker module build:
 
-     ./c-pp -f tester1.c-pp.js -o tester1-esm.js -Dtarget=es6-module
+     ./c-pp -f tester1.c-pp.js -o tester1-esm.mjs -Dtarget=es6-module
 */
 //#if target=es6-module
 import {default as sqlite3InitModule} from './jswasm/sqlite3.mjs';
@@ -1209,6 +1209,94 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
         }
       }
     })
+
+  ////////////////////////////////////////////////////////////////////
+    .t({
+      name: "oo1.DB/Stmt.wrapDbHandle()",
+      test: function(sqlite3){
+        /* Maintenance reminder: this function is early in the list to
+           demonstrate that the wrappers for this.db created by this
+           function do not interfere with downstream tests, e.g. by
+           closing this.db.pointer. */
+        sqlite3.config.debug("Proxying",this.db);
+        let dw = sqlite3.oo1.DB.wrapHandle(this.db);
+        sqlite3.config.debug('dw',dw);
+        T.assert( dw, '!!dw' )
+          .assert( dw instanceof sqlite3.oo1.DB, 'dw is-a oo1.DB' )
+          .assert( dw.pointer, 'dw.pointer' )
+          .assert( dw.pointer === this.db.pointer, 'dw.pointer===db.pointer' )
+          .assert( dw.filename === this.db.filename, 'dw.filename===db.filename' );
+
+        T.assert( dw === dw.exec("select 1") );
+        let q;
+        try {
+          q = dw.prepare("select 1");
+          T.assert( q.step() )
+            .assert( !q.step() );
+        }finally{
+          if( q ) q.finalize();
+        }
+        dw.close();
+        T.assert( !dw.pointer )
+          .assert( this.db === this.db.exec("select 1") );
+        dw = undefined;
+
+        let pDb = 0, pStmt = 0;
+        const stack = wasm.pstack.pointer;
+        try {
+          const ppOut = wasm.pstack.allocPtr();
+          T.assert( 0===wasm.peekPtr(ppOut) );
+          let rc = capi.sqlite3_open_v2( ":memory:", ppOut,
+                                         capi.SQLITE_OPEN_CREATE
+                                         | capi.SQLITE_OPEN_READWRITE,
+                                         0);
+          T.assert( 0===rc, 'open_v2()' );
+          pDb = wasm.peekPtr(ppOut);
+          wasm.pokePtr(ppOut, 0);
+          T.assert( pDb>0, 'pDb>0' );
+          const pTmp = pDb;
+          dw = sqlite3.oo1.DB.wrapHandle(pDb, true);
+          pDb = 0;
+          //sqlite3.config.debug("dw",dw);
+          T.assert( pTmp===dw.pointer, 'pDb===dw.pointer' );
+          T.assert( dw.filename === "", "dw.filename == "+dw.filename );
+          let q = dw.prepare("select 1");
+          try {
+            T.assert( q.step(), "step()" );
+            T.assert( !q.step(), "!step()" );
+          }finally{
+            q.finalize();
+            q = undefined;
+          }
+          T.assert( dw===dw.exec("select 1") );
+          dw.affirmOpen();
+          rc = capi.sqlite3_prepare_v2( dw, "select 1", -1, ppOut, 0 );
+          T.assert( 0===rc, 'prepare_v2() rc='+rc );
+          pStmt = wasm.peekPtr(ppOut);
+          try {
+            q = sqlite3.oo1.Stmt.wrapHandle(dw, pStmt, false);
+            T.assert( q.step(), "step()" )
+              .assert( !q.step(), "!step()" );
+            q.finalize();
+            q = undefined;
+            q = sqlite3.oo1.Stmt.wrapHandle(dw, pStmt, true);
+            pStmt = 0;
+            q.reset();
+            T.assert( q.step(), "step()" )
+              .assert( !q.step(), "!step()" );
+          }finally{
+            if( pStmt ) capi.sqlite3_finalize(pStmt)
+            if( q ) q.finalize();
+          }
+
+        }finally{
+          wasm.pstack.restore(stack);
+          if( pDb ){ capi.sqlite3_close_v2(pDb); }
+          else if( dw ){ dw.close(); }
+        }
+      }
+    })/*oo1.DB/Stmt.wrapHandle()*/
+
   ////////////////////////////////////////////////////////////////////
     .t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){
       let rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, 0, 0);
index 423c86528537749f99c5b0ada842b7b5f23a1f88..b818c616441c401e386fb3d2c8aa878e81634879 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\s'reconfigure'\starget\sto\sMakefile.in\sto\sre-run\sthe\sconfigure\sscript\swith\sthe\ssame\sflags\sit\swas\sgenerated\swith.
-D 2025-07-04T18:32:18.912
+C Experimentally\sadd\ssqlite3.oo1.DB/Stmt.wrapHandle(),\swhich\sallow\sDB/Stmt\sinstances\sto\swrap\sa\s(sqlite3*)/(sqlite3_stmt*)\soptionally\swith\sor\swithout\staking\sownership\sof\sit.\sThe\sintent\sis\sto\senable\smix-and-match\suse\sof\sthe\sC\sAPI,\sthe\soo1\sAPI,\sand\sany\sother\shypothetical\sAPI\swhich\sexposes\sthose\spointers.\soo1.Stmt.parameterCount\sis\snow\sa\sproperty\saccess\sinterceptor\slike\sStmt.columnCount\sis,\sbut\sthat\sdoesn't\schange\show\sit's\sused.
+D 2025-07-06T15:01:44.333
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -641,7 +641,7 @@ F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea
 F ext/wasm/api/pre-js.c-pp.js a614a2c82b12c4d96d8e3ba77330329efc53c4d56a8a7e60ade900f341866cfb
 F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
 F ext/wasm/api/sqlite3-api-glue.c-pp.js 0b76510f3650053bac67ca8947cb6ab9d050ad2218118a2e7796dd37be832ffa
-F ext/wasm/api/sqlite3-api-oo1.c-pp.js c68d6da0088c2527156fca9163a721abe08e7bd077b15404fd8d292f4612adc1
+F ext/wasm/api/sqlite3-api-oo1.c-pp.js 44d122b6d22ba9caa644193357a03bf5d2678a7815f1e2bbbdb086b14db11b7e
 F ext/wasm/api/sqlite3-api-prologue.js 8708570165f5b4bce9a78ccd91bc9ddf8735970ac1c4d659e36c9a7d9a644bb4
 F ext/wasm/api/sqlite3-api-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644f23e64b126e7ae113570587c0ab
 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
@@ -698,7 +698,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
 F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
 F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
 F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
-F ext/wasm/tester1.c-pp.js 766a2ba51a2619d41a49be7c6a1ad014c1d23fc97b67496e4f103038203eb17d
+F ext/wasm/tester1.c-pp.js e7176b2bc1228cf9a87833be7e53e20cb82dec2f104525f5cdd6cb1a53998ad6
 F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
 F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -2208,8 +2208,11 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 64f5f14322349b47451b8cac03bf8cd6f1ae45a8822e7f1ddee3d0b265047501
-R 2e84b390408477c8e70efdd22e84c169
+P c60907e77b32824aaaf024d299cdaf161b5f64fc927ffe5d5455eeb5754e6b01
+R 23984087c5c98e4f1ed7d33ca211546f
+T *branch * oo1-unowned-handles
+T *sym-oo1-unowned-handles *
+T -sym-trunk * Cancelled\sby\sbranch.
 U stephan
-Z a6be9728f4a0aec0de70108286e76b7e
+Z 3bad3f183e619bbd50d1bebd9118b331
 # Remove this line to create a well-formed Fossil manifest.
index 08e4c43bce86e1cbfb8957556feef93d920a0429..f6dbdc594cd04098fd291a9ca50e06e32a335935 100644 (file)
@@ -1 +1 @@
-c60907e77b32824aaaf024d299cdaf161b5f64fc927ffe5d5455eeb5754e6b01
+1227543b87c3320d6b80e0f61b88ea53b68779966a0295c4d6a1db6369c48207