]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Diverse internal cleanups in the JS/WASM pieces. A potential fix for a hypothetical...
authorstephan <stephan@noemail.net>
Mon, 15 Sep 2025 14:11:55 +0000 (14:11 +0000)
committerstephan <stephan@noemail.net>
Mon, 15 Sep 2025 14:11:55 +0000 (14:11 +0000)
FossilOrigin-Name: fabbc8b6d184d52a513e80fabd900f578424fc8a8055e3d64fac54b9e28ea18a

ext/wasm/api/sqlite3-api-glue.c-pp.js
ext/wasm/api/sqlite3-api-prologue.js
manifest
manifest.uuid

index 902b51622f4d060abd36e5da77fc14ea00530881..12c68c9d263569de221d22405e31770f4a7a3d6c 100644 (file)
@@ -79,252 +79,336 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        // elements instead: [x,y,z] is equivalent to x,y,z
      ]
 
-     Note that support for the API-specific data types in the
-     result/argument type strings gets plugged in at a later phase in
-     the API initialization process.
+     Support for the API-specific data types in the result/argument
+     type strings gets plugged in at a later phase in the API
+     initialization process.
   */
-  wasm.bindingSignatures = [
-    // Please keep these sorted by function name!
-    ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
-    /* sqlite3_auto_extension() has a hand-written binding. */
-    /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written
-       bindings to permit more flexible inputs. */
-    ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
-    ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
-    ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
-    ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
-    ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
-    ["sqlite3_bind_parameter_name", "string", "sqlite3_stmt*", "int"],
-    ["sqlite3_bind_pointer", "int",
-     "sqlite3_stmt*", "int", "*", "string:static", "*"],
-    ["sqlite3_busy_handler","int", [
-      "sqlite3*",
-      new wasm.xWrap.FuncPtrAdapter({
-        signature: 'i(pi)',
-        contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
-      }),
-      "*"
-    ]],
-    ["sqlite3_busy_timeout","int", "sqlite3*", "int"],
-    /* sqlite3_cancel_auto_extension() has a hand-written binding. */
-    /* sqlite3_close_v2() is implemented by hand to perform some
-       extra work. */
-    ["sqlite3_changes", "int", "sqlite3*"],
-    ["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
-    ["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
-    ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
-    ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
-    ["sqlite3_column_count", "int", "sqlite3_stmt*"],
-    ["sqlite3_column_decltype", "string", "sqlite3_stmt*", "int"],
-    ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
-    ["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
-    ["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
-    ["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
-    ["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
-    ["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
-    ["sqlite3_commit_hook", "void*", [
-      "sqlite3*",
-      new wasm.xWrap.FuncPtrAdapter({
-        name: 'sqlite3_commit_hook',
-        signature: 'i(p)',
-        contextKey: (argv)=>argv[0/* sqlite3* */]
-      }),
-      '*'
-    ]],
-    ["sqlite3_compileoption_get", "string", "int"],
-    ["sqlite3_compileoption_used", "int", "string"],
-    ["sqlite3_complete", "int", "string:flexible"],
-    ["sqlite3_context_db_handle", "sqlite3*", "sqlite3_context*"],
-    /* sqlite3_create_collation() and sqlite3_create_collation_v2()
-       use hand-written bindings to simplify passing of the callback
-       function. */
-    /* sqlite3_create_function(), sqlite3_create_function_v2(), and
-       sqlite3_create_window_function() use hand-written bindings to
-       simplify handling of their function-type arguments. */
-    ["sqlite3_data_count", "int", "sqlite3_stmt*"],
-    ["sqlite3_db_filename", "string", "sqlite3*", "string"],
-    ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
-    ["sqlite3_db_name", "string", "sqlite3*", "int"],
-    ["sqlite3_db_readonly", "int", "sqlite3*", "string"],
-    ["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"],
-    ["sqlite3_errcode", "int", "sqlite3*"],
-    ["sqlite3_errmsg", "string", "sqlite3*"],
-    ["sqlite3_error_offset", "int", "sqlite3*"],
-    ["sqlite3_errstr", "string", "int"],
-    ["sqlite3_exec", "int", [
-      "sqlite3*", "string:flexible",
-      new wasm.xWrap.FuncPtrAdapter({
-        signature: 'i(pipp)',
-        bindScope: 'transient',
-        callProxy: (callback)=>{
-          let aNames;
-          return (pVoid, nCols, pColVals, pColNames)=>{
-            try {
-              const aVals = wasm.cArgvToJs(nCols, pColVals);
-              if(!aNames) aNames = wasm.cArgvToJs(nCols, pColNames);
-              return callback(aVals, aNames) | 0;
-            }catch(e){
-              /* If we set the db error state here, the higher-level
-                 exec() call replaces it with its own, so we have no way
-                 of reporting the exception message except the console. We
-                 must not propagate exceptions through the C API. Though
-                 we make an effort to report OOM here, sqlite3_exec()
-                 translates that into SQLITE_ABORT as well. */
-              return e.resultCode || capi.SQLITE_ERROR;
+  const bindingSignatures = {
+    core: [
+      // Please keep these sorted by function name!
+      ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
+      /* sqlite3_auto_extension() has a hand-written binding. */
+      /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written
+         bindings to permit more flexible inputs. */
+      ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
+      ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
+      ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
+      ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
+      ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
+      ["sqlite3_bind_parameter_name", "string", "sqlite3_stmt*", "int"],
+      ["sqlite3_bind_pointer", "int",
+       "sqlite3_stmt*", "int", "*", "string:static", "*"],
+      ["sqlite3_busy_handler","int", [
+        "sqlite3*",
+        new wasm.xWrap.FuncPtrAdapter({
+          signature: 'i(pi)',
+          contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
+        }),
+        "*"
+      ]],
+      ["sqlite3_busy_timeout","int", "sqlite3*", "int"],
+      /* sqlite3_cancel_auto_extension() has a hand-written binding. */
+      /* sqlite3_close_v2() is implemented by hand to perform some
+         extra work. */
+      ["sqlite3_changes", "int", "sqlite3*"],
+      ["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
+      ["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
+      ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
+      ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
+      ["sqlite3_column_count", "int", "sqlite3_stmt*"],
+      ["sqlite3_column_decltype", "string", "sqlite3_stmt*", "int"],
+      ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
+      ["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
+      ["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
+      ["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
+      ["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
+      ["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
+      ["sqlite3_commit_hook", "void*", [
+        "sqlite3*",
+        new wasm.xWrap.FuncPtrAdapter({
+          name: 'sqlite3_commit_hook',
+          signature: 'i(p)',
+          contextKey: (argv)=>argv[0/* sqlite3* */]
+        }),
+        '*'
+      ]],
+      ["sqlite3_compileoption_get", "string", "int"],
+      ["sqlite3_compileoption_used", "int", "string"],
+      ["sqlite3_complete", "int", "string:flexible"],
+      ["sqlite3_context_db_handle", "sqlite3*", "sqlite3_context*"],
+      /* sqlite3_create_collation() and sqlite3_create_collation_v2()
+         use hand-written bindings to simplify passing of the callback
+         function. */
+      /* sqlite3_create_function(), sqlite3_create_function_v2(), and
+         sqlite3_create_window_function() use hand-written bindings to
+         simplify handling of their function-type arguments. */
+      ["sqlite3_data_count", "int", "sqlite3_stmt*"],
+      ["sqlite3_db_filename", "string", "sqlite3*", "string"],
+      ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
+      ["sqlite3_db_name", "string", "sqlite3*", "int"],
+      ["sqlite3_db_readonly", "int", "sqlite3*", "string"],
+      ["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"],
+      ["sqlite3_errcode", "int", "sqlite3*"],
+      ["sqlite3_errmsg", "string", "sqlite3*"],
+      ["sqlite3_error_offset", "int", "sqlite3*"],
+      ["sqlite3_errstr", "string", "int"],
+      ["sqlite3_exec", "int", [
+        "sqlite3*", "string:flexible",
+        new wasm.xWrap.FuncPtrAdapter({
+          signature: 'i(pipp)',
+          bindScope: 'transient',
+          callProxy: (callback)=>{
+            let aNames;
+            return (pVoid, nCols, pColVals, pColNames)=>{
+              try {
+                const aVals = wasm.cArgvToJs(nCols, pColVals);
+                if(!aNames) aNames = wasm.cArgvToJs(nCols, pColNames);
+                return callback(aVals, aNames) | 0;
+              }catch(e){
+                /* If we set the db error state here, the higher-level
+                   exec() call replaces it with its own, so we have no way
+                   of reporting the exception message except the console. We
+                   must not propagate exceptions through the C API. Though
+                   we make an effort to report OOM here, sqlite3_exec()
+                   translates that into SQLITE_ABORT as well. */
+                return e.resultCode || capi.SQLITE_ERROR;
+              }
             }
           }
-        }
-      }),
-      "*", "**"
-    ]],
-    ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
-    ["sqlite3_extended_errcode", "int", "sqlite3*"],
-    ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
-    ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
-    ["sqlite3_finalize", "int", "sqlite3_stmt*"],
-    ["sqlite3_free", undefined,"*"],
-    ["sqlite3_get_autocommit", "int", "sqlite3*"],
-    ["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
-    ["sqlite3_initialize", undefined],
-    ["sqlite3_interrupt", undefined, "sqlite3*"],
-    ["sqlite3_is_interrupted", "int", "sqlite3*"],
-    ["sqlite3_keyword_count", "int"],
-    ["sqlite3_keyword_name", "int", ["int", "**", "*"]],
-    ["sqlite3_keyword_check", "int", ["string", "int"]],
-    ["sqlite3_libversion", "string"],
-    ["sqlite3_libversion_number", "int"],
-    ["sqlite3_limit", "int", ["sqlite3*", "int", "int"]],
-    ["sqlite3_malloc", "*","int"],
-    ["sqlite3_open", "int", "string", "*"],
-    ["sqlite3_open_v2", "int", "string", "*", "int", "string"],
-    /* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
-       separately due to us requiring two different sets of semantics
-       for those, depending on how their SQL argument is provided. */
-    /* sqlite3_randomness() uses a hand-written wrapper to extend
-       the range of supported argument types. */
-    ["sqlite3_realloc", "*","*","int"],
-    ["sqlite3_reset", "int", "sqlite3_stmt*"],
-    /* sqlite3_reset_auto_extension() has a hand-written binding. */
-    ["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
-    ["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
-    ["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
-    ["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"],
-    ["sqlite3_result_error_nomem", undefined, "sqlite3_context*"],
-    ["sqlite3_result_error_toobig", undefined, "sqlite3_context*"],
-    ["sqlite3_result_int", undefined, "sqlite3_context*", "int"],
-    ["sqlite3_result_null", undefined, "sqlite3_context*"],
-    ["sqlite3_result_pointer", undefined,
-     "sqlite3_context*", "*", "string:static", "*"],
-    ["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
-    ["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
-    ["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
-    ["sqlite3_rollback_hook", "void*", [
-      "sqlite3*",
-      new wasm.xWrap.FuncPtrAdapter({
-        name: 'sqlite3_rollback_hook',
-        signature: 'v(p)',
-        contextKey: (argv)=>argv[0/* sqlite3* */]
-      }),
-      '*'
-    ]],
-    /**
-       We do not have a way to automatically clean up destructors
-       which are automatically converted from JS functions via the
-       final argument to sqlite3_set_auxdata(). Because of that,
-       automatic function conversion is not supported for this
-       function.  Clients should use wasm.installFunction() to create
-       such callbacks, then pass that pointer to
-       sqlite3_set_auxdata(). Relying on automated conversions here
-       would lead to leaks of JS/WASM proxy functions because
-       sqlite3_set_auxdata() is frequently called in UDFs.
-
-       The sqlite3.oo1.DB class's onclose handlers can be used for this
-       purpose. For example:
-
-       const pAuxDtor = wasm.installFunction('v(p)', function(ptr){
+        }),
+        "*", "**"
+      ]],
+      ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
+      ["sqlite3_extended_errcode", "int", "sqlite3*"],
+      ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
+      ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
+      ["sqlite3_finalize", "int", "sqlite3_stmt*"],
+      ["sqlite3_free", undefined,"*"],
+      ["sqlite3_get_autocommit", "int", "sqlite3*"],
+      ["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
+      ["sqlite3_initialize", undefined],
+      ["sqlite3_interrupt", undefined, "sqlite3*"],
+      ["sqlite3_is_interrupted", "int", "sqlite3*"],
+      ["sqlite3_keyword_count", "int"],
+      ["sqlite3_keyword_name", "int", ["int", "**", "*"]],
+      ["sqlite3_keyword_check", "int", ["string", "int"]],
+      ["sqlite3_libversion", "string"],
+      ["sqlite3_libversion_number", "int"],
+      ["sqlite3_limit", "int", ["sqlite3*", "int", "int"]],
+      ["sqlite3_malloc", "*","int"],
+      ["sqlite3_open", "int", "string", "*"],
+      ["sqlite3_open_v2", "int", "string", "*", "int", "string"],
+      /* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
+         separately due to us requiring two different sets of semantics
+         for those, depending on how their SQL argument is provided. */
+      /* sqlite3_randomness() uses a hand-written wrapper to extend
+         the range of supported argument types. */
+      ["sqlite3_realloc", "*","*","int"],
+      ["sqlite3_reset", "int", "sqlite3_stmt*"],
+      /* sqlite3_reset_auto_extension() has a hand-written binding. */
+      ["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
+      ["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
+      ["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
+      ["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"],
+      ["sqlite3_result_error_nomem", undefined, "sqlite3_context*"],
+      ["sqlite3_result_error_toobig", undefined, "sqlite3_context*"],
+      ["sqlite3_result_int", undefined, "sqlite3_context*", "int"],
+      ["sqlite3_result_null", undefined, "sqlite3_context*"],
+      ["sqlite3_result_pointer", undefined,
+       "sqlite3_context*", "*", "string:static", "*"],
+      ["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
+      ["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
+      ["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
+      ["sqlite3_rollback_hook", "void*", [
+        "sqlite3*",
+        new wasm.xWrap.FuncPtrAdapter({
+          name: 'sqlite3_rollback_hook',
+          signature: 'v(p)',
+          contextKey: (argv)=>argv[0/* sqlite3* */]
+        }),
+        '*'
+      ]],
+      /**
+         We do not have a way to automatically clean up destructors
+         which are automatically converted from JS functions via the
+         final argument to sqlite3_set_auxdata(). Because of that,
+         automatic function conversion is not supported for this
+         function.  Clients should use wasm.installFunction() to create
+         such callbacks, then pass that pointer to
+         sqlite3_set_auxdata(). Relying on automated conversions here
+         would lead to leaks of JS/WASM proxy functions because
+         sqlite3_set_auxdata() is frequently called in UDFs.
+
+         The sqlite3.oo1.DB class's onclose handlers can be used for this
+         purpose. For example:
+
+         const pAuxDtor = wasm.installFunction('v(p)', function(ptr){
          //free ptr
-       });
-       myDb.onclose = {
+         });
+         myDb.onclose = {
          after: ()=>{
-           wasm.uninstallFunction(pAuxDtor);
+         wasm.uninstallFunction(pAuxDtor);
          }
-       };
+         };
 
-       Then pass pAuxDtor as the final argument to appropriate
-       sqlite3_set_auxdata() calls.
+         Then pass pAuxDtor as the final argument to appropriate
+         sqlite3_set_auxdata() calls.
 
-       Note that versions prior to 3.49.0 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
-       forefront.
+         Note that versions prior to 3.49.0 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
+         forefront.
+      */
+      ["sqlite3_set_auxdata", undefined, [
+        "sqlite3_context*", "int", "*",
+        true
+          ? "*"
+          : new wasm.xWrap.FuncPtrAdapter({
+            /* If we can find a way to automate their cleanup, JS functions can
+               be auto-converted with this. */
+            name: 'xDestroyAuxData',
+            signature: 'v(p)',
+            contextKey: (argv, argIndex)=>argv[0/* sqlite3_context* */]
+          })
+      ]],
+      ['sqlite3_set_errmsg', 'int', 'sqlite3*', 'int', 'string'],
+      ["sqlite3_shutdown", undefined],
+      ["sqlite3_sourceid", "string"],
+      ["sqlite3_sql", "string", "sqlite3_stmt*"],
+      ["sqlite3_status", "int", "int", "*", "*", "int"],
+      ["sqlite3_step", "int", "sqlite3_stmt*"],
+      ["sqlite3_stmt_busy", "int", "sqlite3_stmt*"],
+      ["sqlite3_stmt_readonly", "int", "sqlite3_stmt*"],
+      ["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"],
+      ["sqlite3_strglob", "int", "string","string"],
+      ["sqlite3_stricmp", "int", "string", "string"],
+      ["sqlite3_strlike", "int", "string", "string","int"],
+      ["sqlite3_strnicmp", "int", "string", "string", "int"],
+      ["sqlite3_table_column_metadata", "int",
+       "sqlite3*", "string", "string", "string",
+       "**", "**", "*", "*", "*"],
+      ["sqlite3_total_changes", "int", "sqlite3*"],
+      ["sqlite3_trace_v2", "int", [
+        "sqlite3*", "int",
+        new wasm.xWrap.FuncPtrAdapter({
+          name: 'sqlite3_trace_v2::callback',
+          signature: 'i(ippp)',
+          contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
+        }),
+        "*"
+      ]],
+      ["sqlite3_txn_state", "int", ["sqlite3*","string"]],
+      /* sqlite3_uri_...() have very specific requirements for their
+         first C-string arguments, so we cannot perform any
+         string-type conversion on their first argument. */
+      ["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
+      ["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
+      ["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
+      ["sqlite3_user_data","void*", "sqlite3_context*"],
+      ["sqlite3_value_blob", "*", "sqlite3_value*"],
+      ["sqlite3_value_bytes","int", "sqlite3_value*"],
+      ["sqlite3_value_double","f64", "sqlite3_value*"],
+      ["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"],
+      ["sqlite3_value_free", undefined, "sqlite3_value*"],
+      ["sqlite3_value_frombind", "int", "sqlite3_value*"],
+      ["sqlite3_value_int","int", "sqlite3_value*"],
+      ["sqlite3_value_nochange", "int", "sqlite3_value*"],
+      ["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
+      ["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
+      ["sqlite3_value_subtype", "int", "sqlite3_value*"],
+      ["sqlite3_value_text", "string", "sqlite3_value*"],
+      ["sqlite3_value_type", "int", "sqlite3_value*"],
+      ["sqlite3_vfs_find", "*", "string"],
+      ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
+      ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
+
+      /* This list gets extended below */
+    ]/*.core*/,
+    /**
+       Functions which require BigInt (int64) support are separated
+       from the others because we need to conditionally bind them or
+       apply dummy impls, depending on the capabilities of the
+       environment.  (That said: we never actually build without
+       BigInt support, and such builds are untested.)
+
+       Not all of these functions directly require int64 but are only
+       for use with APIs which require int64. For example, the
+       vtab-related functions.
     */
-    ["sqlite3_set_auxdata", undefined, [
-      "sqlite3_context*", "int", "*",
-      true
-        ? "*"
-        : new wasm.xWrap.FuncPtrAdapter({
-          /* If we can find a way to automate their cleanup, JS functions can
-             be auto-converted with this. */
-          name: 'xDestroyAuxData',
-          signature: 'v(p)',
-          contextKey: (argv, argIndex)=>argv[0/* sqlite3_context* */]
-        })
-    ]],
-    ['sqlite3_set_errmsg', 'int', 'sqlite3*', 'int', 'string'],
-    ["sqlite3_shutdown", undefined],
-    ["sqlite3_sourceid", "string"],
-    ["sqlite3_sql", "string", "sqlite3_stmt*"],
-    ["sqlite3_status", "int", "int", "*", "*", "int"],
-    ["sqlite3_step", "int", "sqlite3_stmt*"],
-    ["sqlite3_stmt_busy", "int", "sqlite3_stmt*"],
-    ["sqlite3_stmt_readonly", "int", "sqlite3_stmt*"],
-    ["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"],
-    ["sqlite3_strglob", "int", "string","string"],
-    ["sqlite3_stricmp", "int", "string", "string"],
-    ["sqlite3_strlike", "int", "string", "string","int"],
-    ["sqlite3_strnicmp", "int", "string", "string", "int"],
-    ["sqlite3_table_column_metadata", "int",
-     "sqlite3*", "string", "string", "string",
-     "**", "**", "*", "*", "*"],
-    ["sqlite3_total_changes", "int", "sqlite3*"],
-    ["sqlite3_trace_v2", "int", [
-      "sqlite3*", "int",
-      new wasm.xWrap.FuncPtrAdapter({
-        name: 'sqlite3_trace_v2::callback',
-        signature: 'i(ippp)',
-        contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
-      }),
-      "*"
-    ]],
-    ["sqlite3_txn_state", "int", ["sqlite3*","string"]],
-    /* Note that sqlite3_uri_...() have very specific requirements for
-       their first C-string arguments, so we cannot perform any value
-       conversion on those. */
-    ["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
-    ["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
-    ["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
-    ["sqlite3_user_data","void*", "sqlite3_context*"],
-    ["sqlite3_value_blob", "*", "sqlite3_value*"],
-    ["sqlite3_value_bytes","int", "sqlite3_value*"],
-    ["sqlite3_value_double","f64", "sqlite3_value*"],
-    ["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"],
-    ["sqlite3_value_free", undefined, "sqlite3_value*"],
-    ["sqlite3_value_frombind", "int", "sqlite3_value*"],
-    ["sqlite3_value_int","int", "sqlite3_value*"],
-    ["sqlite3_value_nochange", "int", "sqlite3_value*"],
-    ["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
-    ["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
-    ["sqlite3_value_subtype", "int", "sqlite3_value*"],
-    ["sqlite3_value_text", "string", "sqlite3_value*"],
-    ["sqlite3_value_type", "int", "sqlite3_value*"],
-    ["sqlite3_vfs_find", "*", "string"],
-    ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
-    ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
-  ]/*wasm.bindingSignatures*/;
+    int64: [
+      ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
+      ["sqlite3_changes64","i64", ["sqlite3*"]],
+      ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
+      ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
+      /* Careful! Short version: de/serialize() are problematic because they
+         might use a different allocator than the user for managing the
+         deserialized block. de/serialize() are ONLY safe to use with
+         sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. Because
+         of this, the canonical builds of sqlite3.wasm/js guarantee that
+         sqlite3.wasm.alloc() and friends use those allocators. Custom builds
+         may not guarantee that, however. */,
+      ["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
+      ["sqlite3_malloc64", "*","i64"],
+      ["sqlite3_msize", "i64", "*"],
+      ["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
+      ["sqlite3_realloc64", "*","*", "i64"],
+      ["sqlite3_result_int64", undefined, "*", "i64"],
+      ["sqlite3_result_zeroblob64", "int", "*", "i64"],
+      ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
+      ["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
+      ["sqlite3_status64", "int", "int", "*", "*", "int"],
+      ["sqlite3_total_changes64", "i64", ["sqlite3*"]],
+      ["sqlite3_update_hook", "*", [
+        "sqlite3*",
+        new wasm.xWrap.FuncPtrAdapter({
+          name: 'sqlite3_update_hook',
+          signature: "v(iippj)",
+          contextKey: (argv)=>argv[0/* sqlite3* */],
+          callProxy: (callback)=>{
+            return (p,op,z0,z1,rowid)=>{
+              callback(p, op, wasm.cstrToJs(z0), wasm.cstrToJs(z1), rowid);
+            };
+          }
+        }),
+        "*"
+      ]],
+      ["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
+      ["sqlite3_value_int64","i64", "sqlite3_value*"]
+      /* This list gets extended below */
+    ]/*.int64*/,
+    /**
+       Functions which are intended solely for API-internal use by the
+       WASM components, not client code. These get installed into
+       sqlite3.util. Some of them get exposed to clients via variants
+       in sqlite3_js_...().
+
+       2024-01-11: these were renamed, with two underscores in the
+       prefix, to ensure that clients do not accidentally depend on
+       them.  They have always been documented as internal-use-only,
+       so no clients "should" be depending on the old names.
+    */
+    wasmInternal: [
+      ["sqlite3__wasm_db_reset", "int", "sqlite3*"],
+      ["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
+      [/* DO NOT USE. This is deprecated since 2023-08-11 because it
+          can trigger assert() in debug builds when used with file
+          sizes which are not an exact multiple of a valid db page
+          size.  This function is retained only so that
+          sqlite3_js_vfs_create_file() can continue to work (for a
+          given value of work), but that function emits a
+          config.warn() log message directing the reader to
+          alternatives. */
+        "sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"
+      ],
+      ["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
+      ["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
+      ["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
+    ]/*.wasmInternal*/
+  } /*bindingSignatures*/;
 
   if( !!wasm.exports.sqlite3_progress_handler ){
-    wasm.bindingSignatures.push(
+    bindingSignatures.core.push(
       ["sqlite3_progress_handler", undefined, [
         "sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
           name: 'xProgressHandler',
@@ -337,14 +421,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
   }
 
   if( !!wasm.exports.sqlite3_stmt_explain ){
-    wasm.bindingSignatures.push(
+    bindingSignatures.core.push(
       ["sqlite3_stmt_explain", "int", "sqlite3_stmt*", "int"],
       ["sqlite3_stmt_isexplain", "int", "sqlite3_stmt*"]
     );
   }
 
   if( !!wasm.exports.sqlite3_set_authorizer ){
-    wasm.bindingSignatures.push(
+    bindingSignatures.core.push(
       ["sqlite3_set_authorizer", "int", [
         "sqlite3*",
         new wasm.xWrap.FuncPtrAdapter({
@@ -369,7 +453,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
   }/* sqlite3_set_authorizer() */
 
   if( !!wasm.exports.sqlite3_column_origin_name ){
-    wasm.bindingSignatures.push(
+    bindingSignatures.core.push(
       ["sqlite3_column_database_name","string", "sqlite3_stmt*", "int"],
       ["sqlite3_column_origin_name","string", "sqlite3_stmt*", "int"],
       ["sqlite3_column_table_name","string", "sqlite3_stmt*", "int"]
@@ -380,11 +464,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     /* ^^^ "the problem" is that this is an optional feature and the
        build-time function-export list does not currently take
        optional features into account. */
-    wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
+    bindingSignatures.core.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
   }
 
 //#if enable-see
-  if(wasm.exports.sqlite3_key_v2 instanceof Function){
+  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
@@ -393,7 +477,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        exposing an SEE build of sqlite3.wasm effectively provides all
        clients with a working copy of the commercial SEE code.
     */
-    wasm.bindingSignatures.push(
+    bindingSignatures.core.push(
       ["sqlite3_key", "int", "sqlite3*", "string", "int"],
       ["sqlite3_key_v2","int","sqlite3*","string","*","int"],
       ["sqlite3_rekey", "int", "sqlite3*", "string", "int"],
@@ -403,60 +487,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
   }
 //#endif enable-see
 
-  /**
-     Functions which require BigInt (int64) support are separated from
-     the others because we need to conditionally bind them or apply
-     dummy impls, depending on the capabilities of the environment.
-     (That said: we never actually build without BigInt support,
-     and such builds are untested.)
-
-     Note that not all of these functions directly require int64
-     but are only for use with APIs which require int64. For example,
-     the vtab-related functions.
-  */
-  wasm.bindingSignatures.int64 = [
-    ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
-    ["sqlite3_changes64","i64", ["sqlite3*"]],
-    ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
-    ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
-    /* Careful! Short version: de/serialize() are problematic because they
-       might use a different allocator than the user for managing the
-       deserialized block. de/serialize() are ONLY safe to use with
-       sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. Because
-       of this, the canonical builds of sqlite3.wasm/js guarantee that
-       sqlite3.wasm.alloc() and friends use those allocators. Custom builds
-       may not guarantee that, however. */,
-    ["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
-    ["sqlite3_malloc64", "*","i64"],
-    ["sqlite3_msize", "i64", "*"],
-    ["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
-    ["sqlite3_realloc64", "*","*", "i64"],
-    ["sqlite3_result_int64", undefined, "*", "i64"],
-    ["sqlite3_result_zeroblob64", "int", "*", "i64"],
-    ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
-    ["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
-    ["sqlite3_status64", "int", "int", "*", "*", "int"],
-    ["sqlite3_total_changes64", "i64", ["sqlite3*"]],
-    ["sqlite3_update_hook", "*", [
-      "sqlite3*",
-      new wasm.xWrap.FuncPtrAdapter({
-        name: 'sqlite3_update_hook',
-        signature: "v(iippj)",
-        contextKey: (argv)=>argv[0/* sqlite3* */],
-        callProxy: (callback)=>{
-          return (p,op,z0,z1,rowid)=>{
-            callback(p, op, wasm.cstrToJs(z0), wasm.cstrToJs(z1), rowid);
-          };
-        }
-      }),
-      "*"
-    ]],
-    ["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
-    ["sqlite3_value_int64","i64", "sqlite3_value*"]
-  ];
-
   if( wasm.bigIntEnabled && !!wasm.exports.sqlite3_declare_vtab ){
-    wasm.bindingSignatures.int64.push(
+    bindingSignatures.int64.push(
       ["sqlite3_create_module", "int",
        ["sqlite3*","string","sqlite3_module*","*"]],
       ["sqlite3_create_module_v2", "int",
@@ -477,7 +509,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
   }/* virtual table APIs */
 
   if(wasm.bigIntEnabled && !!wasm.exports.sqlite3_preupdate_hook){
-    wasm.bindingSignatures.int64.push(
+    bindingSignatures.int64.push(
       ["sqlite3_preupdate_blobwrite", "int", "sqlite3*"],
       ["sqlite3_preupdate_count", "int", "sqlite3*"],
       ["sqlite3_preupdate_depth", "int", "sqlite3*"],
@@ -522,7 +554,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       }
     };
 
-    wasm.bindingSignatures.int64.push(...[
+    bindingSignatures.int64.push(
       ['sqlite3changegroup_add', 'int', ['sqlite3_changegroup*', 'int', 'void*']],
       ['sqlite3changegroup_add_strm', 'int', [
         'sqlite3_changegroup*',
@@ -677,36 +709,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
         }),
         '*'
       ]]
-    ]);
+    );
   }/*session/changeset APIs*/
 
-  /**
-     Functions which are intended solely for API-internal use by the
-     WASM components, not client code. These get installed into
-     sqlite3.util. Some of them get exposed to clients via variants
-     in sqlite3_js_...().
-
-     2024-01-11: these were renamed, with two underscores in the
-     prefix, to ensure that clients do not accidentally depend on
-     them.  They have always been documented as internal-use-only, so
-     no clients "should" be depending on the old names.
-  */
-  wasm.bindingSignatures.wasmInternal = [
-    ["sqlite3__wasm_db_reset", "int", "sqlite3*"],
-    ["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
-    [/* DO NOT USE. This is deprecated since 2023-08-11 because it can
-        trigger assert() in debug builds when used with file sizes
-        which are not sizes to a multiple of a valid db page size. */
-      "sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"
-    ],
-    ["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
-    ["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
-    ["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
-  ];
-
   /**
      Install JS<->C struct bindings for the non-opaque struct types we
-     need... */
+     need...
+  */
   sqlite3.StructBinder = globalThis.Jaccwabyt({
     heap: 0 ? wasm.memory : wasm.heap8u,
     alloc: wasm.alloc,
@@ -759,10 +768,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
 
     /**
        Add some descriptive xWrap() aliases for '*' intended to (A)
-       initially improve readability/correctness of
-       wasm.bindingSignatures and (B) provide automatic conversion
-       from higher-level representations, e.g. capi.sqlite3_vfs to
-       `sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
+       improve readability/correctness of bindingSignatures and (B)
+       provide automatic conversion from higher-level representations,
+       e.g. capi.sqlite3_vfs to `sqlite3_vfs*` via (capi.sqlite3_vfs
+       instance).pointer.
     */
     const __xArgPtr = wasm.xWrap.argAdapter('*');
     const nilType = function(){
@@ -834,10 +843,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
         "Disabling sqlite3.wasm.xWrap.doArgcCheck due to environmental quirks."
       );
     }
-    for(const e of wasm.bindingSignatures){
+    for(const e of bindingSignatures.core){
       capi[e[0]] = wasm.xWrap.apply(null, e);
     }
-    for(const e of wasm.bindingSignatures.wasmInternal){
+    for(const e of bindingSignatures.wasmInternal){
       util[e[0]] = wasm.xWrap.apply(null, e);
     }
 
@@ -850,15 +859,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       return ()=>toss(fname+"() is unavailable due to lack",
                       "of BigInt support in this build.");
     };
-    for(const e of wasm.bindingSignatures.int64){
+    for(const e of bindingSignatures.int64){
       capi[e[0]] = wasm.bigIntEnabled
         ? wasm.xWrap.apply(null, e)
         : fI64Disabled(e[0]);
     }
 
-    /* There's no need to expose bindingSignatures to clients,
-       implicitly making it part of the public interface. */
-    delete wasm.bindingSignatures;
+    /* We don't need these anymore... */
+    delete bindingSignatures.core;
+    delete bindingSignatures.int64;
+    delete bindingSignatures.wasmInternal;
 
     /**
        Sets the given db's error state. Accepts:
@@ -913,7 +923,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
                           'sqlite3Status',
                           'stmtStatus', 'syncFlags',
                           'trace', 'txnState', 'udfFlags',
-                          'version' ];
+                          'version'];
     if(wasm.bigIntEnabled){
       defineGroups.push('serialize', 'session', 'vtab');
     }
@@ -1098,10 +1108,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
         continue;
       }
       closeArgs.length = x.length/*==argument count*/
-      /* recall that undefined entries translate to 0 when passed to
-         WASM. */;
+        || 1 /* Recall that: (A) undefined entries translate to 0 when
+                passed to WASM and (B) Safari wraps wasm.exports.* in
+                nullary functions so x.length is 0 there. */;
       try{ capi[name](...closeArgs) }
       catch(e){
+        /* This "cannot happen" unless something is well and truly sideways. */
         sqlite3.config.warn("close-time call of",name+"(",closeArgs,") threw:",e);
       }
     }
@@ -1203,10 +1215,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
 
        2) It accepts JS functions for its function-pointer arguments,
           for which it will install WASM-bound proxies. The bindings
-          are "permanent," in that they will stay in the WASM environment
-          until it shuts down unless the client calls this again with the
-          same collation name and a value of 0 or null for the
-          the function pointer(s).
+          are "permanent," in that they will stay in the WASM
+          environment until it shuts down unless the client calls this
+          again with the same collation name and a value of 0 or null
+          for the the function pointer(s). sqlite3_close_v2() will
+          also clean up such automatically-installed WASM functions.
 
        For consistency with the C API, it requires the same number of
        arguments. It returns capi.SQLITE_MISUSE if passed any other
@@ -1447,11 +1460,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       sqlite3_prepare_v3() */
 
     /**
-       Helper for string:flexible conversions which require a
+       Helper for string:flexible conversions which requires a
        byte-length counterpart argument. Passed a value and its
        ostensible length, this function returns [V,N], where V is
-       either v or a transformed copy of v and N is either n, -1, or
-       the byte length of v (if it's a byte array or ArrayBuffer).
+       either v or a transformed copy of v and N is either n (if v is
+       a WASM pointer), -1 (if v is a string or Array), or the byte
+       length of v (if it's a byte array or ArrayBuffer).
     */
     const __flexiString = (v,n)=>{
       if('string'===typeof v){
@@ -1484,15 +1498,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
                                 "int", "**",
                                 "**"/*MUST be 0 or null or undefined!*/]),
       /**
-         Impl which requires that the 2nd argument be a pointer
-         to the SQL string, instead of being converted to a
-         string. This variant is necessary for cases where we
-         require a non-NULL value for the final argument
-         (exec()'ing multiple statements from one input
-         string). For simpler cases, where only the first
-         statement in the SQL string is required, the wrapper
-         named sqlite3_prepare_v2() is sufficient and easier to
-         use because it doesn't require dealing with pointers.
+         Impl which requires that the 2nd argument be a pointer to the
+         SQL string, instead of being converted to a JS string. This
+         variant is necessary for cases where we require a non-NULL
+         value for the final argument (prepare/step of multiple
+         statements from one input string). For simpler cases, where
+         only the first statement in the SQL string is required, the
+         wrapper named sqlite3_prepare_v2() is sufficient and easier
+         to use because it doesn't require dealing with pointers.
       */
       full: wasm.xWrap('sqlite3_prepare_v3',
                        "int", ["sqlite3*", "*", "int", "int",
index e3807a314ca8eefd81b15b3934321f3066953d26..636e893d1fc17a13d98611c244dc3f147df78a57 100644 (file)
@@ -542,8 +542,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        4th-argument value, taking care not to pass a value which
        truncates a multi-byte UTF-8 character. When passing
        WASM-format strings, it is important that the final argument be
-       valid or unexpected content can result can result, or even a
-       crash if the application reads past the WASM heap bounds.
+       valid or unexpected content can result, or WASM may crash if
+       the application reads past the WASM heap bounds.
     */
     sqlite3_bind_text: undefined/*installed later*/,
 
@@ -614,10 +614,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
          functions passed in to this routine, and thus wrapped by this
          routine, get automatic conversions of arguments and result
          values. The routines which perform those conversions are
-         exposed for client-side use as
-         sqlite3_create_function_v2.convertUdfArgs() and
-         sqlite3_create_function_v2.setUdfResult(). sqlite3_create_function()
-         and sqlite3_create_window_function() have those same methods.
+         exposed for client-side use as sqlite3_values_to_js(),
+         sqlite3_result_js(), and sqlite3_result_error_js().
 
        For xFunc(), xStep(), and xFinal():
 
@@ -635,18 +633,14 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        possibly generating a console.error() message.  Destructors
        must not throw.
 
-       Once installed, there is currently no way to uninstall the
-       automatically-converted WASM-bound JS functions from WASM. They
-       can be uninstalled from the database as documented in the C
-       API, but this wrapper currently has no infrastructure in place
-       to also free the WASM-bound JS wrappers, effectively resulting
-       in a memory leak if the client uninstalls the UDF. Improving that
-       is a potential TODO, but removing client-installed UDFs is rare
-       in practice. If this factor is relevant for a given client,
-       they can create WASM-bound JS functions themselves, hold on to their
-       pointers, and pass the pointers in to here. Later on, they can
-       free those pointers (using `wasm.uninstallFunction()` or
-       equivalent).
+       Automatically-converted JS-to-WASM functions will be cleaned up
+       either when (A) this function is called again with the same
+       name, arity, and encoding, but null/0 values for the functions,
+       or (B) when pDb is passed to sqlite3_close_v2(). If this factor
+       is relevant for a given client, they can create WASM-bound JS
+       functions themselves, hold on to their pointers, and pass the
+       pointers in to here. Later on, they can free those pointers
+       (using `wasm.uninstallFunction()` or equivalent).
 
        C reference: https://sqlite.org/c3ref/create_function.html
 
@@ -686,10 +680,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
 
        2) sqlite3_prepare_v3(pDb, sqlPointer, sqlByteLen, prepFlags, ppStmt, sqlPointerToPointer)
 
-       Note that the SQL length argument (the 3rd argument) must, for
-       usage (1), always be negative because it must be a byte length
-       and that value is expensive to calculate from JS (where only
-       the character length of strings is readily available). It is
+       The SQL length argument (the 3rd argument) must, for usage (1),
+       always be negative because it must be a byte length and that
+       value is expensive to calculate from JS (where only the
+       character length of strings is readily available). It is
        retained in this API's interface for code/documentation
        compatibility reasons but is currently _always_ ignored. With
        usage (2), the 3rd argument is used as-is but is is still
@@ -715,8 +709,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        (e.g. using capi.wasm.alloc() or equivalent). In that case,
        the final argument may be 0/null/undefined or must be a pointer
        to which the "tail" of the compiled SQL is written, as
-       documented for the C-side sqlite3_prepare_v3(). In case (2),
-       the underlying C function is called with the equivalent of:
+       documented for the C-side sqlite3_prepare_v3().
+
+       In case (2), the underlying C function is called with the
+       equivalent of:
 
        (pDb, sqlAsPointer, sqlByteLen, prepFlags, ppStmt, pzTail)
 
@@ -1553,27 +1549,29 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
   capi.sqlite3_js_vfs_create_file = function(vfs, filename, data, dataLen){
     config.warn("sqlite3_js_vfs_create_file() is deprecated and",
                 "should be avoided because it can lead to C-level crashes.",
-                "See its documentation for alternative options.");
+                "See its documentation for alternatives.");
     let pData;
     if(data){
-      if(wasm.isPtr(data)){
+      if( wasm.isPtr(data) ){
         pData = data;
-      }else if(data instanceof ArrayBuffer){
-        data = new Uint8Array(data);
-      }
-      if(data instanceof Uint8Array){
-        pData = wasm.allocFromTypedArray(data);
-        if(arguments.length<4 || !util.isInt32(dataLen) || dataLen<0){
-          dataLen = data.byteLength;
-        }
       }else{
-        SQLite3Error.toss("Invalid 3rd argument type for sqlite3_js_vfs_create_file().");
+        if( data instanceof ArrayBuffer ){
+          data = new Uint8Array(data);
+        }
+        if( data instanceof Uint8Array ){
+          pData = wasm.allocFromTypedArray(data);
+          if(arguments.length<4 || !util.isInt32(dataLen) || dataLen<0){
+            dataLen = data.byteLength;
+          }
+        }else{
+          SQLite3Error.toss("Invalid 3rd argument type for sqlite3_js_vfs_create_file().");
+        }
       }
     }else{
        pData = 0;
     }
     if(!util.isInt32(dataLen) || dataLen<0){
-      wasm.dealloc(pData);
+      if( pData && pData!==data ) wasm.dealloc(pData);
       SQLite3Error.toss("Invalid 4th argument for sqlite3_js_vfs_create_file().");
     }
     try{
@@ -1581,7 +1579,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);
     }
   };
 
index 49c04cbbfef8f06286e0d1773f6f8593f8b6cea0..6b9e94a1e52360e1c38c62606ee9c2bb65b8d7ca 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Expose\ssqlite3_set_errmsg()\sto\sthe\sJNI\sbindings.
-D 2025-09-14T12:55:57.217
+C Diverse\sinternal\scleanups\sin\sthe\sJS/WASM\spieces.\sA\spotential\sfix\sfor\sa\shypothetical\sdb-close-time\sresource\sleak\sof\sa\ssubset\sof\sautomated\sJS-to-WASM\sfunction\sconversions\sin\sSafari.\sThat\sbrowser\sexposes\sWASM-exported\sfunctions\svia\snullary\swrappers,\swhich\scauses\sa\shandful\sof\sthem\sto\smisbehave\s(not\sclean\sup)\sat\ssqlite3_close_v2()-time.
+D 2025-09-15T14:11:55.851
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -596,9 +596,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 0c60e7b54259b061b6ed0d96c747b9c77d1c2186c5785a7d638f8afc6d3829d6
+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 4f1c2a9dc9caf631907766e9872c27d11b255ccae779e8af01c7f8b932817214
+F ext/wasm/api/sqlite3-api-prologue.js 4272131346b102d6f1bfc07524331213ff89407b76cbbde4c0b48b19c692ba94
 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
@@ -2174,8 +2174,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 e447a50f3a3791c264a68000948daa64edb1857d51d256fbd1ff0f2c2b330d5e
-R 914e412c108c33985260767ddbccf671
+P 292866a46948e8d707bd14864fd1b40eec1bd2e22dcd249ec94711b646c8a70b
+R 3d648bd2f0581cd393c02110c0b966eb
 U stephan
-Z fb5496b4e64823b519fcbc93dbe57147
+Z cb971779c9e9efb3d18793a17a591051
 # Remove this line to create a well-formed Fossil manifest.
index bb2b1509bf66df65f1e8d0507f276a11627ac91c..76e48d8148ad93f52c960057598b5b30b9daae51 100644 (file)
@@ -1 +1 @@
-292866a46948e8d707bd14864fd1b40eec1bd2e22dcd249ec94711b646c8a70b
+fabbc8b6d184d52a513e80fabd900f578424fc8a8055e3d64fac54b9e28ea18a