]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Diverse cleanups and docs in the JS and kvvfs pieces. Functional changes: (A) ensure...
authorstephan <stephan@noemail.net>
Fri, 19 Sep 2025 17:24:47 +0000 (17:24 +0000)
committerstephan <stephan@noemail.net>
Fri, 19 Sep 2025 17:24:47 +0000 (17:24 +0000)
FossilOrigin-Name: 79af65a694fbbb3d501fb2ebd835c259ca644e0dafdd71eeb9f0a7c0e9128a1e

ext/wasm/api/sqlite3-api-glue.c-pp.js
ext/wasm/api/sqlite3-api-oo1.c-pp.js
ext/wasm/api/sqlite3-api-prologue.js
ext/wasm/api/sqlite3-wasm.c
ext/wasm/common/whwasmutil.js
ext/wasm/tester1.c-pp.js
manifest
manifest.uuid
src/os_kv.c

index 12c68c9d263569de221d22405e31770f4a7a3d6c..477a796f4a6272ec2ec5ab4d5c1944d301ffba3a 100644 (file)
@@ -243,21 +243,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
          purpose. For example:
 
          const pAuxDtor = wasm.installFunction('v(p)', function(ptr){
-         //free ptr
+           //free ptr
          });
          myDb.onclose = {
-         after: ()=>{
-         wasm.uninstallFunction(pAuxDtor);
-         }
+           after: ()=>{
+             wasm.uninstallFunction(pAuxDtor);
+           }
          };
 
          Then pass pAuxDtor as the final argument to appropriate
          sqlite3_set_auxdata() calls.
 
-         Note that versions prior to 3.49.0 ostensibly had automatic
+         Prior to 3.49.0 this binding ostensibly had automatic
          function conversion here but a typo prevented it from
-         working.  Rather than fix it, it was removed because testing the
-         fix brought the huge potential for memory leaks to the
+         working.  Rather than fix it, it was removed because testing
+         the fix brought the huge potential for memory leaks to the
          forefront.
       */
       ["sqlite3_set_auxdata", undefined, [
@@ -323,7 +323,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
       ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
 
-      /* This list gets extended below */
+      /* This list gets extended with optional pieces below */
     ]/*.core*/,
     /**
        Functions which require BigInt (int64) support are separated
@@ -375,7 +375,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       ]],
       ["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
       ["sqlite3_value_int64","i64", "sqlite3_value*"]
-      /* This list gets extended below */
+      /* This list gets extended with optional pieces below */
     ]/*.int64*/,
     /**
        Functions which are intended solely for API-internal use by the
@@ -435,12 +435,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
           name: "sqlite3_set_authorizer::xAuth",
           signature: "i(pi"+"ssss)",
           contextKey: (argv, argIndex)=>argv[0/*(sqlite3*)*/],
+          /**
+             We use callProxy here to ensure (A) that exceptions
+             thrown from callback() have well-defined behavior and (B)
+             that its result is coerced to an integer.
+          */
           callProxy: (callback)=>{
             return (pV, iCode, s0, s1, s2, s3)=>{
               try{
                 s0 = s0 && wasm.cstrToJs(s0); s1 = s1 && wasm.cstrToJs(s1);
                 s2 = s2 && wasm.cstrToJs(s2); s3 = s3 && wasm.cstrToJs(s3);
-                return callback(pV, iCode, s0, s1, s2, s3) || 0;
+                return callback(pV, iCode, s0, s1, s2, s3) | 0;
               }catch(e){
                 return e.resultCode || capi.SQLITE_ERROR;
               }
@@ -470,12 +475,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
 //#if enable-see
   if( !!wasm.exports.sqlite3_key_v2 ){
     /**
-       This code is capable of using an SEE build but note that an SEE
-       WASM build is generally incompatible with SEE's license
-       conditions. It is permitted for use internally in organizations
-       which have licensed SEE, but not for public sites because
-       exposing an SEE build of sqlite3.wasm effectively provides all
-       clients with a working copy of the commercial SEE code.
+       This code is capable of using an SEE build but an SEE WASM
+       build is generally incompatible with SEE's license conditions.
+       The project's official stance on WASM builds of SEE is: it is
+       permitted for use internally within organizations which have
+       licensed SEE, but not for public sites because exposing an SEE
+       build of sqlite3.wasm effectively provides all clients with a
+       working copy of SEE.
     */
     bindingSignatures.core.push(
       ["sqlite3_key", "int", "sqlite3*", "string", "int"],
@@ -496,12 +502,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       ["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
       ["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
       ["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
+      /*["sqlite3_vtab_config" is variadic and requires a hand-written
+        proxy.] */
       ["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
       ["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
       ["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"],
       ["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"],
-      /*["sqlite3_vtab_config" is variadic and requires a hand-written
-        proxy.] */
       ["sqlite3_vtab_nochange","int", "sqlite3_context*"],
       ["sqlite3_vtab_on_conflict","int", "sqlite3*"],
       ["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
@@ -713,7 +719,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
   }/*session/changeset APIs*/
 
   /**
-     Install JS<->C struct bindings for the non-opaque struct types we
+     Prepare JS<->C struct bindings for the non-opaque struct types we
      need...
   */
   sqlite3.StructBinder = globalThis.Jaccwabyt({
@@ -722,7 +728,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     dealloc: wasm.dealloc,
     bigIntEnabled: wasm.bigIntEnabled,
     memberPrefix: /* Never change this: this prefix is baked into any
-                     amount of code and client-facing docs. */ '$'
+                     amount of code and client-facing docs. (Much
+                     later: it probably should have been '$$', but see
+                     the previous sentence.) */ '$'
   });
   delete globalThis.Jaccwabyt;
 
@@ -745,16 +753,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        - Anything else: gets coerced to a JS string for use as a map
          key. If a matching entry is found (as described next), it is
          returned, else wasm.allocCString() is used to create a a new
-         string, map its pointer to (''+v) for the remainder of the
-         application's life, and returns that pointer value for this
-         call and all future calls which are passed a
+         string, map its pointer to a copy of (''+v) for the remainder
+         of the application's life, and returns that pointer value for
+         this call and all future calls which are passed a
          string-equivalent argument.
 
-       Use case: sqlite3_bind_pointer() and sqlite3_result_pointer()
-       call for "a static string and preferably a string
-       literal." This converter is used to ensure that the string
-       value seen by those functions is long-lived and behaves as they
-       need it to.
+       Use case: sqlite3_bind_pointer(), sqlite3_result_pointer(), and
+       sqlite3_value_pointer() call for "a static string and
+       preferably a string literal". This converter is used to ensure
+       that the string value seen by those functions is long-lived and
+       behaves as they need it to, at the cost of a one-time leak of
+       each distinct key.
     */
     wasm.xWrap.argAdapter(
       'string:static',
@@ -822,6 +831,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       );
     }
 
+    /**
+       Alias `T*` to `*` for return type conversions for common T
+       types, primarily to improve legibility of their binding
+       signatures.
+    */
     const __xRcPtr = wasm.xWrap.resultAdapter('*');
     wasm.xWrap.resultAdapter('sqlite3*', __xRcPtr)
     ('sqlite3_context*', __xRcPtr)
@@ -834,15 +848,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        Populate api object with sqlite3_...() by binding the "raw" wasm
        exports into type-converting proxies using wasm.xWrap().
     */
-    if(0 === wasm.exports.sqlite3_step.length){
-      /* This environment wraps exports in nullary functions, which means
-         we must disable the arg-count validation we otherwise perform
-         on the wrappers. */
-      wasm.xWrap.doArgcCheck = false;
-      sqlite3.config.warn(
-        "Disabling sqlite3.wasm.xWrap.doArgcCheck due to environmental quirks."
-      );
-    }
     for(const e of bindingSignatures.core){
       capi[e[0]] = wasm.xWrap.apply(null, e);
     }
@@ -854,18 +859,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        wasm.bigIntEnabled is true, install a bogus impl which throws
        if called when bigIntEnabled is false. The alternative would be
        to elide these functions altogether, which seems likely to
-       cause more confusion. */
-    const fI64Disabled = function(fname){
-      return ()=>toss(fname+"() is unavailable due to lack",
-                      "of BigInt support in this build.");
-    };
+       cause more confusion, as documented APIs would resolve to the
+       undefined value in incompatible builds. */
     for(const e of bindingSignatures.int64){
       capi[e[0]] = wasm.bigIntEnabled
         ? wasm.xWrap.apply(null, e)
-        : fI64Disabled(e[0]);
+        : ()=>toss(e[0]+"() is unavailable due to lack",
+                   "of BigInt support in this build.");
     }
 
-    /* We don't need these anymore... */
+    /* We're done with bindingSignatures but it's const, so... */
     delete bindingSignatures.core;
     delete bindingSignatures.int64;
     delete bindingSignatures.wasmInternal;
@@ -949,6 +952,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        string, or undefined if no such mapping is found.
     */
     capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc];
+
     /* Bind all registered C-side structs... */
     const notThese = Object.assign(Object.create(null),{
       // For each struct to NOT register, map its name to true:
@@ -968,7 +972,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     }
     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
+      ** them to WASM requires that we create top-level 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',
index 8663dcddecf9b50949d0473746725ee3c90c75e2..a0fac358faed02f1098f830e25dd283c44be1e9b 100644 (file)
@@ -747,12 +747,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        closed when onclose.after is called. If this db is not opened
        when close() is called, neither of the handlers are called. Any
        exceptions the handlers throw are ignored because "destructors
-       must not throw."
+       must not throw".
 
-       Note that garbage collection of a db handle, if it happens at
-       all, will never trigger close(), so onclose handlers are not a
-       reliable way to implement close-time cleanup or maintenance of
-       a db.
+       Garbage collection of a db handle, if it happens at all, will
+       never trigger close(), so onclose handlers are not a reliable
+       way to implement close-time cleanup or maintenance of a db.
 
        If this instance was created using DB.wrapHandle() and does not
        own this.pointer then it does not close the db handle but it
index 636e893d1fc17a13d98611c244dc3f147df78a57..36d22079512dc8f5fe2171a6f2d5e35bc7e0a554 100644 (file)
@@ -1046,10 +1046,16 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
   }/*compileOptionUsed()*/;
 
   /**
-     sqlite3.wasm.pstack (pseudo-stack) holds a special-case
-     stack-style allocator intended only for use with _small_ data of
-     not more than (in total) a few kb in size, managed as if it were
-     stack-based.
+     sqlite3.wasm.pstack (pseudo-stack) holds a special-case intended
+     solely for short-lived, small data. In practice, it's primarily
+     used to allocate output pointers. It mus not be used for any
+     memory which needs to outlive the scope in which it's obtained
+     from pstack.
+
+     The library guarantees only that a minimum of 2kb are available
+     in this allocator, and it may provide more (it's a build-time
+     value). pstack.quota and pstack.remaining can be used to get the
+     total resp. remaining amount of memory.
 
      It has only a single intended usage:
 
@@ -1081,6 +1087,9 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        Sets the current pstack position to the given pointer. Results
        are undefined if the passed-in value did not come from
        this.pointer.
+
+       In debug builds this may trigger an assert() in the WASM
+       environment if passed an illegal value.
     */
     restore: wasm.exports.sqlite3__wasm_pstack_restore,
     /**
@@ -1186,7 +1195,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
       configurable: false, iterable: true, writeable: false,
       get: wasm.exports.sqlite3__wasm_pstack_ptr
       //Whether or not a setter as an alternative to restore() is
-      //clearer or would just lead to confusion is unclear.
+      //clearer or would just lead to confusion or misuse is unclear.
       //set: wasm.exports.sqlite3__wasm_pstack_restore
     },
     /**
@@ -1209,8 +1218,9 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
   })/*wasm.pstack properties*/;
 
   capi.sqlite3_randomness = (...args)=>{
-    if(1===args.length && util.isTypedArray(args[0])
-      && 1===args[0].BYTES_PER_ELEMENT){
+    if(1===args.length
+       && util.isTypedArray(args[0])
+       && 1===args[0].BYTES_PER_ELEMENT){
       const ta = args[0];
       if(0===ta.byteLength){
         wasm.exports.sqlite3_randomness(0,0);
@@ -1231,8 +1241,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
           offset += j;
         } while(n > 0);
       }catch(e){
-        console.error("Highly unexpected (and ignored!) "+
-                      "exception in sqlite3_randomness():",e);
+        config.error("Highly unexpected (and ignored!) "+
+                     "exception in sqlite3_randomness():",e);
       }finally{
         wasm.pstack.restore(stack);
       }
@@ -1249,22 +1259,21 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
      does not then it returns "" (noting that "" is a falsy value).
 
      The first time this is called, this function inspects the current
-     environment to determine whether persistence support is available
-     and, if it is, enables it (if needed). After the first call it
-     always returns the cached result.
+     environment to determine whether WASMFS persistence support is
+     available and, if it is, enables it (if needed). After the first
+     call it always returns the cached result.
 
      If the returned string is not empty, any files stored under the
-     given path (recursively) are housed in OPFS storage. If the
+     returned path (recursively) are housed in OPFS storage. If the
      returned string is empty, this particular persistent storage
      option is not available on the client.
 
      Though the mount point name returned by this function is intended
-     to remain stable, clients should not hard-coded it
-     anywhere. Always call this function to get the path.
+     to remain stable, clients should not hard-coded it anywhere.
+     Always call this function to get the path.
 
-     Note that this function is a no-op in most builds of this
-     library, as the WASMFS capability requires a custom
-     build.
+     This function is a no-op in most builds of this library, as the
+     WASMFS capability requires a custom build.
   */
   capi.sqlite3_wasmfs_opfs_dir = function(){
     if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir;
@@ -1273,7 +1282,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     if(!pdir
        || !globalThis.FileSystemHandle
        || !globalThis.FileSystemDirectoryHandle
-       || !globalThis.FileSystemFileHandle){
+       || !globalThis.FileSystemFileHandle
+       || !wasm.exports.sqlite3__wasm_init_wasmfs){
       return __wasmfsOpfsDir = "";
     }
     try{
@@ -1305,11 +1315,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
      (defaulting to "main"), returns a truthy value (see below) if
      that db uses that VFS, else returns false. If pDb is falsy then
      the 3rd argument is ignored and this function returns a truthy
-     value if the default VFS name matches that of the 2nd
-     argument. Results are undefined if pDb is truthy but refers to an
-     invalid pointer. The 3rd argument specifies the database name of
-     the given database connection to check, defaulting to the main
-     db.
+     value if the default VFS name matches that of the 2nd argument.
+     Results are undefined if pDb is truthy but refers to an invalid
+     pointer. The 3rd argument specifies the database name of the
+     given database connection to check, defaulting to the main db.
 
      The 2nd and 3rd arguments may either be a JS string or a WASM
      C-string. If the 2nd argument is a NULL WASM pointer, the default
@@ -1320,9 +1329,9 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
      object.
 
      To permit safe use of this function from APIs which may be called
-     via the C stack (like SQL UDFs), this function does not throw: if
-     bad arguments cause a conversion error when passing into
-     wasm-space, false is returned.
+     via C (like SQL UDFs), this function does not throw: if bad
+     arguments cause a conversion error when passing into wasm-space,
+     false is returned.
   */
   capi.sqlite3_js_db_uses_vfs = function(pDb,vfsName,dbName=0){
     try{
@@ -1437,8 +1446,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
      It may behave differently in other environments.
 
      The first argument must be either a JS string or WASM C-string
-     holding the filename. Note that this routine does _not_ create
-     intermediary directories if the filename has a directory part.
+     holding the filename. This routine does _not_ create intermediary
+     directories if the filename has a directory part.
 
      The 2nd argument may either a valid WASM memory pointer, an
      ArrayBuffer, or a Uint8Array. The 3rd must be the length, in
@@ -1475,7 +1484,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
       if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
                                capi.sqlite3_js_rc_str(rc));
     }finally{
-       wasm.dealloc(pData);
+      if( pData && pData!==data ) wasm.dealloc(pData);
     }
   };
 
@@ -1484,12 +1493,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
      debug builds of sqlite3 because its out-of-scope use of the
      sqlite3_vfs API triggers assertions in the core library.  That
      was unfortunately not discovered until 2023-08-11. This function
-     is now deprecated and should not be used in new code.
+     is now deprecated. It should not be used in new code and should
+     be removed from existing code.
 
      Alternative options:
 
-     - "unix" VFS and its variants can get equivalent functionality
-       with sqlite3_js_posix_create_file().
+     - The "unix" VFS and its variants can get equivalent
+       functionality with sqlite3_js_posix_create_file().
 
      - OPFS: use either sqlite3.oo1.OpfsDb.importDb(), for the "opfs"
        VFS, or the importDb() method of the PoolUtil object provided
@@ -1498,6 +1508,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        from here because the former is necessarily asynchronous and
        the latter requires information not available to this function.
 
+     Historical (deprecated) behaviour:
+
      Creates a file using the storage appropriate for the given
      sqlite3_vfs.  The first argument may be a VFS name (JS string
      only, NOT a WASM C-string), WASM-managed `sqlite3_vfs*`, or
@@ -1540,7 +1552,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
 
      - "unix" and related: will use the WASM build's equivalent of the
        POSIX I/O APIs. This will work so long as neither a specific
-       VFS nor the WASM environment imposes requirements which break it.
+       VFS nor the WASM environment imposes requirements which break
+       it.  (Much later: it turns out that debug builds of the library
+       impose such requirements, in that they assert() that dataLen is
+       an even multiple of a valid db page size.)
 
      - "opfs": uses OPFS storage and creates directory parts of the
        filename. It can only be used to import an SQLite3 database
index 16545270df3a41224018012049a1717bdb9bdf32..a4d0f1c7bee6001a4ab4af730bc1a174aeb7b23f 100644 (file)
@@ -300,7 +300,10 @@ SQLITE_WASM_EXPORT void * sqlite3__wasm_stack_alloc(int n){
 ** enough for general-purpose string conversions because some of our
 ** tests use input files (strings) of 16MB+.
 */
-static unsigned char PStack_mem[512 * 8] = {0};
+static unsigned char PStack_mem[
+  1024 * 4 /* API docs guaranty at least 2kb and it's been set at 4kb
+              since it was introduced. */
+] = {0};
 static struct {
   unsigned const char * const pBegin;/* Start (inclusive) of memory */
   unsigned const char * const pEnd;  /* One-after-the-end of memory */
@@ -401,7 +404,10 @@ void sqlite3__wasm_test_struct(WasmTestStruct * s){
 */
 SQLITE_WASM_EXPORT
 const char * sqlite3__wasm_enum_json(void){
-  static char aBuffer[1024 * 20] = {0} /* where the JSON goes */;
+  static char aBuffer[1024 * 20] =
+    {0} /* where the JSON goes. 2025-09-19: output size=19295, but
+           that can vary slightly from build to build, so a little
+           leeway is needed here. */;
   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
@@ -971,8 +977,8 @@ const char * sqlite3__wasm_enum_json(void){
   **   }
   ** }
   **
-  ** Detailed documentation for those bits are in the docs for the
-  ** Jaccwabyt JS-side component.
+  ** Detailed documentation for those bits are in the Jaccwabyt
+  ** JS-side component.
   */
 
   /** Macros for emitting StructBinder description. */
index 48af31ceb057c35927166b24cd52cac92a2a990c..960ceb266b23d5db81500738d71c10558e7fcefb 100644 (file)
@@ -1352,7 +1352,7 @@ globalThis.WhWasmUtilInstaller = function(target){
      The reason for the 2nd argument is...
 
      When one of the returned pointers will refer to a 64-bit value,
-     e.g. a double or int64, an that value must be written or fetched,
+     e.g. a double or int64, and that value must be written or fetched,
      e.g. using poke() or peek(), 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
@@ -1401,9 +1401,11 @@ globalThis.WhWasmUtilInstaller = function(target){
   target.xCall = function(fname, ...args){
     const f = (fname instanceof Function) ? fname : target.xGet(fname);
     if(!(f instanceof Function)) toss("Exported symbol",fname,"is not a function.");
-    if(f.length!==args.length) __argcMismatch(((f===fname) ? f.name : fname),f.length)
-    /* This is arguably over-pedantic but we want to help clients keep
-       from shooting themselves in the foot when calling C APIs. */;
+    if(f.length!==args.length){
+      __argcMismatch(((f===fname) ? f.name : fname),f.length)
+      /* This is arguably over-pedantic but we want to help clients keep
+         from shooting themselves in the foot when calling C APIs. */;
+    }
     return (2===arguments.length && Array.isArray(arguments[1]))
       ? f.apply(null, arguments[1])
       : f.apply(null, args);
@@ -1418,14 +1420,15 @@ globalThis.WhWasmUtilInstaller = function(target){
   cache.xWrap.convert.arg = new Map;
   /** Map of type names to return result conversion functions. */
   cache.xWrap.convert.result = new Map;
+  /** Scope-local convenience aliases. */
   const xArg = cache.xWrap.convert.arg, xResult = cache.xWrap.convert.result;
 
   if(target.bigIntEnabled){
     xArg.set('i64', (i)=>BigInt(i));
   }
-  const __xArgPtr = 'i32' === ptrIR
+  const __xArgPtr = ('i32' === ptrIR)
         ? ((i)=>(i | 0)) : ((i)=>(BigInt(i) | BigInt(0)));
-  xArg.set('i32', __xArgPtr )
+  xArg.set('i32', (i)=>(i | 0) )
     .set('i16', (i)=>((i | 0) & 0xFFFF))
     .set('i8', (i)=>((i | 0) & 0xFF))
     .set('f32', (i)=>Number(i).valueOf())
@@ -1445,8 +1448,8 @@ globalThis.WhWasmUtilInstaller = function(target){
     .set(null, xResult.get('null'));
 
   { /* Copy xArg[...] handlers to xResult[...] for cases which have
-       identical semantics. Also add pointer-style variants of
-       them. */
+       identical semantics. Also add pointer-style variants of those
+       xArg entries to both xArg and xResult. */
     const copyToResult = ['i8', 'i16', 'i32', 'int',
                           'f32', 'float', 'f64', 'double'];
     if(target.bigIntEnabled) copyToResult.push('i64');
@@ -1905,11 +1908,11 @@ globalThis.WhWasmUtilInstaller = function(target){
        which convert their argument to an integer and truncate it to
        the given bit length.
 
-     - `*` and `pointer` (args): are assumed to be WASM pointer values
-       and are returned coerced to an appropriately-sized pointer
-       value (i32 or i64). Non-numeric values will coerce to 0 and
-       out-of-range values will have undefined results (just as with
-       any pointer misuse).
+     - `*`, `**`, and `pointer` (args): are assumed to be WASM pointer
+       values and are returned coerced to an appropriately-sized
+       pointer value (i32 or i64). Non-numeric values will coerce to 0
+       and out-of-range values will have undefined results (just as
+       with any pointer misuse).
 
      - `*` and `pointer` (results): aliases for the current
        WASM pointer numeric type.
@@ -1934,9 +1937,9 @@ globalThis.WhWasmUtilInstaller = function(target){
        distinguish between the two types of floating-point numbers.
 
      - `number` (results): converts the result to a JS Number using
-       Number(theValue).valueOf(). Note that this is for result
-       conversions only, as it's not possible to generically know
-       which type of number to convert arguments to.
+       Number(theValue). This is for result conversions only, as it's
+       not possible to generically know which type of number to
+       convert arguments to.
 
      Non-numeric conversions include:
 
@@ -1948,7 +1951,7 @@ globalThis.WhWasmUtilInstaller = function(target){
        to accommodate various uses of certain C APIs
        (e.g. output-style strings)...
 
-       - If the arg is a string, it creates a _temporary_
+       - If the arg is a JS string, it creates a _temporary_
          UTF-8-encoded C-string to pass to the exported function,
          cleaning it up before the wrapper returns. If a long-lived
          C-string pointer is required, that requires client-side code
@@ -1965,10 +1968,10 @@ globalThis.WhWasmUtilInstaller = function(target){
      - `string:dealloc` or `utf8:dealloc` (results): treats the result
        value as a non-const UTF-8 C-string, ownership of which has
        just been transfered to the caller. It copies the C-string to a
-       JS string, frees the C-string, and returns the JS string. If
-       such a result value is NULL, the JS result is `null`. Achtung:
-       when using an API which returns results from a specific
-       allocator, e.g. `my_malloc()`, this conversion _is not
+       JS string, frees the C-string using dealloc(), and returns the
+       JS string. If such a result value is NULL, the JS result is
+       `null`. Achtung: when using an API which returns results from a
+       specific allocator, e.g. `my_malloc()`, this conversion _is not
        legal_. Instead, an equivalent conversion which uses the
        appropriate deallocator is required. For example:
 
index fc6a024c4ef2f91213c57d2ac01d915d7cdf20a3..681619dfa0f2f37f8724d9e0787685d1bd1a24b8 100644 (file)
@@ -1261,7 +1261,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
           dw = sqlite3.oo1.DB.wrapHandle(pDb, true);
           pDb = 0;
           //sqlite3.config.debug("dw",dw);
-          T.assert( pTmp===dw.pointer, 'pDb===dw.pointer' );
+          T.assert( pTmp===dw.pointer, 'pTmp===dw.pointer' );
           T.assert( dw.filename === "", "dw.filename == "+dw.filename );
           let q = dw.prepare("select 1");
           try {
@@ -3567,9 +3567,12 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
       name: 'Delete via bound parameter in subquery',
       predicate: ()=>wasm.compileOptionUsed('ENABLE_FTS5') || "Missing FTS5",
       test: function(sqlite3){
-        // Testing https://sqlite.org/forum/forumpost/40ce55bdf5
-        // with the exception that that post uses "external content"
-        // for the FTS index.
+        /**
+           Testing https://sqlite.org/forum/forumpost/40ce55bdf5 with
+           the exception that that post uses "external content" for
+           the FTS index. This isn't testing a fix, just confirming
+           that the bug report is not really a bug.
+        */
         const db = new sqlite3.oo1.DB();//(':memory:','wt');
         db.exec([
           "create virtual table f using fts5 (path);",
@@ -3586,10 +3589,10 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
         //dump('Full fts table');
         let rc = fetchEm();
         T.assert(3===rc.length);
-        db.exec(`
-          delete from f where rowid in (
-          select rowid from f where path = :path
-           )`,
+        db.exec(
+          ["delete from f where rowid in (",
+           "select rowid from f where path = :path",
+           ")"],
           {bind: {":path": "def"}}
         );
         //dump('After deleting one entry via subquery');
index e79e5c8b1e0f2fa9c061d1565ed62d8ada84bdd4..93adce3fee9505d7995561ccf18db1e39c5b6e8f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Wasm:\s(A)\sdiverse\sinternal\sdoc\supdates.\s(B)\swhen\sgenerating\sautomated\sJS-to-WASM\sfunction\sproxies\sfor\sconverters\swhich\srequire\san\sadditional\smiddle-man\sproxy,\se.g.\ssqlite3_exec(),\suse\sthe\sclient-provided\sfunction,\snot\sthe\sproxy\sfunction,\sas\sthe\scache\skey,\sto\skeep\sfrom\sre-generating\sthe\sconversion\sin\ssome\scommon\suse\spatterns.
-D 2025-09-19T14:21:09.961
+C Diverse\scleanups\sand\sdocs\sin\sthe\sJS\sand\skvvfs\spieces.\sFunctional\schanges:\s(A)\sensure\sthat\sthe\s'i32'\sJS/WASM\sfunc\sarg/result\sconversion\sworks\sproperly\swith\sa\s64-bit-memory\sWASM\sbuild\s(which\swe\sneither\suse\snor\stest\sbut\s[https://webassembly.org/news/2025-09-17-wasm-3.0/\s|\sthe\snewly-ratified\sWASM\s3.0]\sbrings\swithin\spotential\sreach).\s(B)\sFix\ssqlite3_js_posix_create_file()\sto\snot\sdeallocate\sits\sinput\sarray\sif\sthe\sclient\spasses\sin\sraw\smemory\s(the\slibrary\shas\snever\sused\sit\sthat\sway\sbut\sthe\sAPI\spermits\sit).
+D 2025-09-19T17:24:47.155
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -597,9 +597,9 @@ F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90a
 F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701
 F ext/wasm/api/pre-js.c-pp.js 58f823de197e2c10d76179aa05410a593b7ae03e1ece983bb42ffd818e8857e1
 F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
-F ext/wasm/api/sqlite3-api-glue.c-pp.js 066c09125d12189863ec2b34e702b7b8a7ba25c00e73f77de0b727430ef65687
-F ext/wasm/api/sqlite3-api-oo1.c-pp.js 852f2cd6acddbae487fc4f1c3ec952e6c1e2033aa4e6c7091d330d983c87c032
-F ext/wasm/api/sqlite3-api-prologue.js 4272131346b102d6f1bfc07524331213ff89407b76cbbde4c0b48b19c692ba94
+F ext/wasm/api/sqlite3-api-glue.c-pp.js fab9a05257119d42f3d26cf4e437198a8c479d2c4751c5de4ac986969bd3dd4b
+F ext/wasm/api/sqlite3-api-oo1.c-pp.js dc8573267f0dd49ae314a295c0dbe86de921f6d6beabbb7a447029ca1ea4e1d9
+F ext/wasm/api/sqlite3-api-prologue.js 332bcf0c8a32af38c8b2f308b1cb37002e1db3ec27df9fe629116a591540e375
 F ext/wasm/api/sqlite3-api-worker1.c-pp.js 760191cd13416e6f5adfd9fcc8a97fed5645c9e0a5fbac213a2d4ce2d79a4334
 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
 F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
@@ -607,7 +607,7 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
 F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 0f68a64e508598910e7c01214ae27d603dfc8baec6a184506fafac603a901931
 F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4ab0704ee198de7d1059eccedc7703c931510b588d10af0ee36ea5b3ebbac284
 F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
-F ext/wasm/api/sqlite3-wasm.c 404cc1f0f5c307210a8d7c3a7dda57834e0e8b3d406ba51977a97a6d14a74734
+F ext/wasm/api/sqlite3-wasm.c c60f778e686a47279885b55345abefd3cf2a1da24c1921e530081444aec68a6e
 F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 4ad256b4ff7f839ad18931ed35d46cced544207bd2209665ec552e193f7f4544
 F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
 F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
@@ -618,7 +618,7 @@ F ext/wasm/c-pp.c cca55c5b55ebd8d29916adbedb0e40baa12caa9a2e8429f812683c308f9b0e
 F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
 F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
-F ext/wasm/common/whwasmutil.js 4ea5a413016d9a561a26976c699a2670f2385b93be04cd2d463dd6c1955bd175
+F ext/wasm/common/whwasmutil.js 000232b0a9527af5a73b3c0e46ef91a19517ae027ce73fd8902f06c490b9b97c
 F ext/wasm/config.make.in c424ae1cc3c89274520ad312509d36c4daa34a3fce5d0c688e5f8f4365e1049a
 F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
 F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
@@ -655,7 +655,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 aa694096feb5cfd9333f7029e933a4eae95bde5cc3edd29da4dc0f8dae452905
+F ext/wasm/tester1.c-pp.js de2736de2335a74a9ecbda9005af5c8b1c33fd8729591064ef4795650da65900
 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
@@ -725,7 +725,7 @@ F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
 F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
 F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
 F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
-F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
+F src/os_kv.c fb7ba8d6204197357f1eb7e1c7450d09c10043bf7e99aba602f4aa46b8fb11a3
 F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
 F src/os_unix.c b3da55bc4bb214b2bfb1e430b10e9d3ebcf6b11741921ab044c9b9539c8fcc4f
 F src/os_win.c f81a7cffdfe8c593a840895b3f64290714f0186b06302d2c397012252d830374
@@ -2175,8 +2175,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 468a11fd415710042b23880772f6c2c7771008208823fe3b554227a9244dbf92
-R 45b30de6d5f1d826a12d811876f55290
+P 5e5139c2a162562cee0071d03954ebc0b8938da0b045ec3f5eba32dc8e19604d
+R 39374a1a28932b274e07d195dbea9d94
 U stephan
-Z 31a53fb96f385e882a14f4d3fa47d2d3
+Z 8c740e2b096da4198cfd5683f58d6ede
 # Remove this line to create a well-formed Fossil manifest.
index 4dc27434ecf28bc7df4c01a94a8f80f9a4db9c7f..d078ee8e68ddb36c7568a8acda279d74fdcd080a 100644 (file)
@@ -1 +1 @@
-5e5139c2a162562cee0071d03954ebc0b8938da0b045ec3f5eba32dc8e19604d
+79af65a694fbbb3d501fb2ebd835c259ca644e0dafdd71eeb9f0a7c0e9128a1e
index 5e0ea49f1635e116aed1584a2bf63c6420655a35..c2d1f9b7addc56f1dca4f41db0fb2ce2e41a156f 100644 (file)
@@ -174,7 +174,7 @@ static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
 #define KVSTORAGE_KEY_SZ  32
 
 /* Expand the key name with an appropriate prefix and put the result
-** zKeyOut[].  The zKeyOut[] buffer is assumed to hold at least
+** in zKeyOut[].  The zKeyOut[] buffer is assumed to hold at least
 ** KVSTORAGE_KEY_SZ bytes.
 */
 static void kvstorageMakeKey(
@@ -233,10 +233,12 @@ static int kvstorageDelete(const char *zClass, const char *zKey){
 **
 ** Return the total number of bytes in the data, without truncation, and
 ** not counting the final zero terminator.   Return -1 if the key does
-** not exist.
+** not exist or its key cannot be read.
 **
-** If nBuf<=0 then this routine simply returns the size of the data without
-** actually reading it.
+** If nBuf<=0 then this routine simply returns the size of the data
+** without actually reading it.  Similarly, if nBuf==1 then it
+** zero-terminates zBuf at zBuf[0] and returns the size of the data
+** without reading it.
 */
 static int kvstorageRead(
   const char *zClass,
@@ -285,11 +287,9 @@ static int kvstorageRead(
 ** kvvfs i/o methods with JavaScript implementations in WASM builds.
 ** Maintenance reminder: if this struct changes in any way, the JSON
 ** rendering of its structure must be updated in
-** sqlite3_wasm_enum_json(). There are no binary compatibility
-** concerns, so it does not need an iVersion member. This file is
-** necessarily always compiled together with sqlite3_wasm_enum_json(),
-** and JS code dynamically creates the mapping of members based on
-** that JSON description.
+** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
+** compatibility concerns, so it does not need an iVersion
+** member.
 */
 typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
 struct sqlite3_kvvfs_methods {
@@ -306,8 +306,8 @@ struct sqlite3_kvvfs_methods {
 ** the compiler can hopefully optimize this level of indirection out.
 ** That said, kvvfs is intended primarily for use in WASM builds.
 **
-** Note that this is not explicitly flagged as static because the
-** amalgamation build will tag it with SQLITE_PRIVATE.
+** This is not explicitly flagged as static because the amalgamation
+** build will tag it with SQLITE_PRIVATE.
 */
 #ifndef SQLITE_WASM
 const