]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Strip progress handlers and window functions from the wasm bare-bones (formerly ...
authorstephan <stephan@noemail.net>
Thu, 25 Jul 2024 16:21:19 +0000 (16:21 +0000)
committerstephan <stephan@noemail.net>
Thu, 25 Jul 2024 16:21:19 +0000 (16:21 +0000)
FossilOrigin-Name: ec02e9237e1ef81c4196fa630822cb109eab926143ad09593a24273eb0668601

ext/wasm/GNUmakefile
ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core
ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras
ext/wasm/api/sqlite3-api-glue.c-pp.js
ext/wasm/api/sqlite3-wasm.c
ext/wasm/fiddle.make
ext/wasm/tester1.c-pp.js
manifest
manifest.uuid

index 785d501f39e6286082374896d9f86f688d3cb917..18f8ffc22de2589073e4ed51b7bc14f43860d9ce 100644 (file)
@@ -157,8 +157,9 @@ $(sqlite3.c): $(sqlite3.h)
 # of the makefile, some of which are relatively expensive to calculate
 # on each run (that is, they can take a human-visible amount of time).
 #
-# .gen.make is also home to make-side vars which are needed for
-# generating makefile code via shell code.
+# Sidebar: three attempts have been made to move much of the
+# $(eval)-generated makefile code into make-make.sh but the result is
+# even less legible/maintainable than make-side $(eval).
 ifeq (0,$(MAKING_CLEAN))
 .gen.make: $(MAKEFILE) $(sqlite3.c)
        rm -f $@
@@ -171,9 +172,39 @@ ifeq (,$(filter release snapshot,$(MAKECMDGOALS)))
   $(info Development build. Use 'release' or 'snapshot' target for a smaller release build.)
 endif
 
+########################################################################
+# minimal=1 disables all "extraneous" stuff from sqlite3-wasm.c, the
+# goal being to create a WASM file with only the core APIs.
+ifeq (1,$(minimal))
+  wasm-bare-bones := 1
+else
+  wasm-bare-bones := 0
+endif
+undefine minimal
+
 # Common options for building sqlite3-wasm.c and speedtest1.c.
 # Explicit ENABLEs...
-SQLITE_OPT = \
+SQLITE_OPT.common := \
+  -DSQLITE_THREADSAFE=0 \
+  -DSQLITE_TEMP_STORE=2 \
+  -DSQLITE_ENABLE_MATH_FUNCTIONS \
+  -DSQLITE_OS_KV_OPTIONAL=1 \
+  '-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \
+  -DSQLITE_USE_URI=1 \
+  -DSQLITE_C=$(sqlite3.c) \
+  -DSQLITE_OMIT_DEPRECATED \
+  -DSQLITE_OMIT_UTF16 \
+  -DSQLITE_OMIT_LOAD_EXTENSION \
+  -DSQLITE_OMIT_SHARED_CACHE
+# ^^^ These particular OMITs are hard-coded in sqlite3-wasm.c and
+# removing them from this list will serve only to break the speedtest1
+# builds.
+
+# Currently always needed but TODO is paring tester1.c-pp.js down
+# to be able to run without this:
+SQLITE_OPT.common += -DSQLITE_WASM_ENABLE_C_TESTS
+
+SQLITE_OPT.full-featured := \
   -DSQLITE_ENABLE_BYTECODE_VTAB \
   -DSQLITE_ENABLE_DBPAGE_VTAB \
   -DSQLITE_ENABLE_DBSTAT_VTAB \
@@ -186,22 +217,45 @@ SQLITE_OPT = \
   -DSQLITE_ENABLE_STMTVTAB \
   -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
 
-# Explicit OMITs...
-SQLITE_OPT += \
-  -DSQLITE_OMIT_LOAD_EXTENSION \
-  -DSQLITE_OMIT_DEPRECATED \
-  -DSQLITE_OMIT_UTF16 \
-  -DSQLITE_OMIT_SHARED_CACHE
-
-# Misc. build-time config options...
-SQLITE_OPT += \
-  -DSQLITE_THREADSAFE=0 \
-  -DSQLITE_TEMP_STORE=2 \
-  -DSQLITE_OS_KV_OPTIONAL=1 \
-  '-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \
-  -DSQLITE_USE_URI=1 \
-  -DSQLITE_WASM_ENABLE_C_TESTS \
-  -DSQLITE_C=$(sqlite3.c)
+ifeq (0,$(wasm-bare-bones))
+  # The so-called canonical build is full-featured:
+  SQLITE_OPT := \
+    $(SQLITE_OPT.common) \
+    $(SQLITE_OPT.full-featured)
+else
+  # The so-called bare-bones build is exactly that:
+  SQLITE_OPT := \
+    $(SQLITE_OPT.common) \
+    -DSQLITE_WASM_BARE_BONES
+  # SQLITE_WASM_BARE_BONES tells sqlite3-wasm.c to explicitly omit
+  # a bunch of stuff, in the interest of keeping the wasm file size
+  # down. As of this writing it equates to:
+  #
+  #  -USQLITE_ENABLE_DBPAGE_VTAB
+  #  -USQLITE_ENABLE_DBSTAT_VTAB
+  #  -USQLITE_ENABLE_EXPLAIN_COMMENTS
+  #  -USQLITE_ENABLE_FTS5
+  #  -USQLITE_ENABLE_OFFSET_SQL_FUNC
+  #  -USQLITE_ENABLE_PREUPDATE_HOOK
+  #  -USQLITE_ENABLE_RTREE
+  #  -USQLITE_ENABLE_SESSION
+  #  -USQLITE_ENABLE_STMTVTAB
+  #  -DSQLITE_OMIT_AUTHORIZATION
+  #  -DSQLITE_OMIT_GET_TABLE
+  #  -DSQLITE_OMIT_INCRBLOB
+  #  -DSQLITE_OMIT_INTROSPECTION_PRAGMAS
+  #  -DSQLITE_OMIT_JSON
+  #  -DSQLITE_OMIT_PROGRESS_CALLBACK
+  #  -DSQLITE_OMIT_WAL
+  #
+  # There are others we want here but which require explicit OMIT when
+  # creating their amalgamation, and that step is TODO:
+  #
+  #  -DSQLITE_OMIT_EXPLAIN
+  #  -DSQLITE_OMIT_TRIGGER
+  #  -DSQLITE_OMIT_VIRTUALTABLE
+  #  -DSQLITE_OMIT_WINDOWFUNC
+endif
 
 #SQLITE_OPT += -DSQLITE_DEBUG
 # Enabling SQLITE_DEBUG will break sqlite3_wasm_vfs_create_file()
@@ -211,18 +265,16 @@ SQLITE_OPT += \
 # in client code.
 
 ########################################################################
-# minimal=1 disables all "extraneous" stuff from sqlite3-wasm.c, the
-# goal being to create a WASM file with only the core APIs.
-ifeq (1,$(minimal))
-  SQLITE_OPT += -DSQLITE_WASM_MINIMAL
-  # SQLITE_WASM_MINIMAL tells sqlite3-wasm.c to explicitly omit
-  # a bunch of stuff, in the interest of keeping the wasm file size
-  # down.
-  wasm-minimal := 1
-else
-  wasm-minimal := 0
-endif
-undefine minimal
+# The following flags are hard-coded into sqlite3-wasm.c and cannot be
+# modified via the build process:
+#
+#  SQLITE_ENABLE_API_ARMOR
+#  SQLITE_OMIT_LOAD_EXTENSION
+#  SQLITE_OMIT_DEPRECATED
+#  SQLITE_OMIT_UTF16
+#  SQLITE_OMIT_SHARED_CACHE
+########################################################################
+
 
 ########################################################################
 # Adding custom C code via sqlite3_wasm_extra_init.c:
@@ -385,7 +437,7 @@ EXPORTED_FUNCTIONS.api.in := $(EXPORTED_FUNCTIONS.api.core)
 ifeq (1,$(SQLITE_C_IS_SEE))
   EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-see
 endif
-ifeq (0,$(wasm-minimal))
+ifeq (0,$(wasm-bare-bones))
   EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
 else
   $(info ========================================)
@@ -425,7 +477,7 @@ sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.c-pp.js
 sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.c-pp.js
 # sqlite3-vfs-helper = helper APIs for VFSes:
 sqlite3-api.jses += $(dir.api)/sqlite3-vfs-helper.c-pp.js
-ifeq (0,$(wasm-minimal))
+ifeq (0,$(wasm-bare-bones))
   # sqlite3-vtab-helper = helper APIs for VTABLEs:
   sqlite3-api.jses += $(dir.api)/sqlite3-vtab-helper.c-pp.js
 endif
@@ -1053,7 +1105,7 @@ $(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
         $(emcc.speedtest1.common) \
         $(emcc.flags.speedtest1-vanilla) $(pre-post-speedtest1-vanilla.flags) \
         $(SQLITE_OPT) \
-        -USQLITE_WASM_MINIMAL \
+        -USQLITE_WASM_BARE_BONES \
         -USQLITE_C -DSQLITE_C=$(sqlite3.canonical.c) \
         $(speedtest1.exit-runtime0) \
         -o $@ $(speedtest1.cfiles) -lm
index 263542bc94a7540ddf86aac58187bfd2fcfeaa95..2578002ce40015851e88938ee0cca6177a8e31bc 100644 (file)
@@ -41,7 +41,6 @@ _sqlite3_create_collation
 _sqlite3_create_collation_v2
 _sqlite3_create_function
 _sqlite3_create_function_v2
-_sqlite3_create_window_function
 _sqlite3_data_count
 _sqlite3_db_filename
 _sqlite3_db_handle
@@ -80,7 +79,6 @@ _sqlite3_open_v2
 _sqlite3_overload_function
 _sqlite3_prepare_v2
 _sqlite3_prepare_v3
-_sqlite3_progress_handler
 _sqlite3_randomness
 _sqlite3_realloc
 _sqlite3_realloc64
index 2e831447dd7f9db6c7b977aaeb789b425a372d91..e635d93b32ff696a77d924997b9c67d206fd1570 100644 (file)
@@ -1,3 +1,5 @@
+_sqlite3_create_window_function
+_sqlite3_progress_handler
 _sqlite3_set_authorizer
 _sqlite3_preupdate_blobwrite
 _sqlite3_preupdate_count
index 3c4bf582d1c24fd97e8ca0b55fc402cb57720bc5..680218370a850886675e832232660d68fdf02bad 100644 (file)
@@ -136,20 +136,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     ["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_create_collation() and sqlite3_create_collation_v2()
-       use hand-written bindings to simplify passing of the callback
-       function.
-      ["sqlite3_create_collation", "int",
-     "sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
-     "*", "*"],
-    ["sqlite3_create_collation_v2", "int",
-     "sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
-     "*", "*", "*"],
-    */
     ["sqlite3_data_count", "int", "sqlite3_stmt*"],
     ["sqlite3_db_filename", "string", "sqlite3*", "string"],
     ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
@@ -211,14 +203,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        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_progress_handler", undefined, [
-      "sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
-        name: 'xProgressHandler',
-        signature: 'i(p)',
-        bindScope: 'context',
-        contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
-      }), "*"
-    ]],
     ["sqlite3_realloc", "*","*","int"],
     ["sqlite3_reset", "int", "sqlite3_stmt*"],
     /* sqlite3_reset_auto_extension() has a hand-written binding. */
@@ -303,6 +287,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
   ]/*wasm.bindingSignatures*/;
 
+  if( !!wasm.exports.sqlite3_progress_handler ){
+    wasm.bindingSignatures.push(
+      ["sqlite3_progress_handler", undefined, [
+        "sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
+          name: 'xProgressHandler',
+          signature: 'i(p)',
+          bindScope: 'context',
+          contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
+        }), "*"
+      ]]
+    );
+  }
+
   if( !!wasm.exports.sqlite3_stmt_explain ){
     wasm.bindingSignatures.push(
       ["sqlite3_stmt_explain", "int", "sqlite3_stmt*", "int"],
@@ -950,7 +947,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
 
   /** Code duplication reducer for functions which take an encoding
       argument and require SQLITE_UTF8.  Sets the db error code to
-      SQLITE_FORMAT and returns that code. */
+      SQLITE_FORMAT, installs a descriptive error message,
+      and returns SQLITE_FORMAT. */
   const __errEncoding = (pDb)=>{
     return util.sqlite3__wasm_db_error(
       pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding."
@@ -1000,11 +998,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     this._addUDF(pDb, name, arity, m.udf);
   };
 
-  __dbCleanupMap.addWindowFunc = function(pDb, name, arity){
-    const m = __dbCleanupMap(pDb, 1);
-    if(!m.wudf) m.wudf = new Map;
-    this._addUDF(pDb, name, arity, m.wudf);
-  };
+  if( wasm.exports.sqlite3_create_window_function ){
+    __dbCleanupMap.addWindowFunc = function(pDb, name, arity){
+      const m = __dbCleanupMap(pDb, 1);
+      if(!m.wudf) m.wudf = new Map;
+      this._addUDF(pDb, name, arity, m.wudf);
+    };
+  }
 
   /**
      Intended to be called _only_ from sqlite3_close_v2(),
@@ -1273,17 +1273,20 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       ]
     );
 
-    const __sqlite3CreateWindowFunction = wasm.xWrap(
-      "sqlite3_create_window_function", "int", [
-        "sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
-        "int"/*eTextRep*/, "*"/*pApp*/,
-        new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
-        new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
-        new wasm.xWrap.FuncPtrAdapter({name: 'xValue', ...__cfProxy.xFinalAndValue}),
-        new wasm.xWrap.FuncPtrAdapter({name: 'xInverse', ...__cfProxy.xInverseAndStep}),
-        new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
-      ]
-    );
+    const __sqlite3CreateWindowFunction =
+          wasm.exports.sqlite3_create_window_function
+          ? wasm.xWrap(
+            "sqlite3_create_window_function", "int", [
+              "sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
+              "int"/*eTextRep*/, "*"/*pApp*/,
+              new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
+              new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
+              new wasm.xWrap.FuncPtrAdapter({name: 'xValue', ...__cfProxy.xFinalAndValue}),
+              new wasm.xWrap.FuncPtrAdapter({name: 'xInverse', ...__cfProxy.xInverseAndStep}),
+              new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
+            ]
+          )
+          : undefined;
 
     /* Documented in the api object's initializer. */
     capi.sqlite3_create_function_v2 = function f(
@@ -1328,61 +1331,71 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     };
 
     /* Documented in the api object's initializer. */
-    capi.sqlite3_create_window_function = function f(
-      pDb, funcName, nArg, eTextRep, pApp,
-      xStep,   //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
-      xFinal,  //void (*xFinal)(sqlite3_context*)
-      xValue,  //void (*xValue)(sqlite3_context*)
-      xInverse,//void (*xInverse)(sqlite3_context*,int,sqlite3_value**)
-      xDestroy //void (*xDestroy)(void*)
-    ){
-      if( f.length!==arguments.length ){
-        return __dbArgcMismatch(pDb,"sqlite3_create_window_function",f.length);
-      }else if( 0 === (eTextRep & 0xf) ){
-        eTextRep |= capi.SQLITE_UTF8;
-      }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
-        return __errEncoding(pDb);
-      }
-      try{
-        const rc = __sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
-                                                 pApp, xStep, xFinal, xValue,
-                                                 xInverse, xDestroy);
-        if(0===rc && (xStep instanceof Function
-                      || xFinal instanceof Function
-                      || xValue instanceof Function
-                      || xInverse instanceof Function
-                      || xDestroy instanceof Function)){
-          __dbCleanupMap.addWindowFunc(pDb, funcName, nArg);
+    if( __sqlite3CreateWindowFunction ){
+      capi.sqlite3_create_window_function = function f(
+        pDb, funcName, nArg, eTextRep, pApp,
+        xStep,   //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
+        xFinal,  //void (*xFinal)(sqlite3_context*)
+        xValue,  //void (*xValue)(sqlite3_context*)
+        xInverse,//void (*xInverse)(sqlite3_context*,int,sqlite3_value**)
+        xDestroy //void (*xDestroy)(void*)
+      ){
+        if( f.length!==arguments.length ){
+          return __dbArgcMismatch(pDb,"sqlite3_create_window_function",f.length);
+        }else if( 0 === (eTextRep & 0xf) ){
+          eTextRep |= capi.SQLITE_UTF8;
+        }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
+          return __errEncoding(pDb);
         }
-        return rc;
-      }catch(e){
-        console.error("sqlite3_create_window_function() setup threw:",e);
-        return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
-      }
-    };
+        try{
+          const rc = __sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
+                                                   pApp, xStep, xFinal, xValue,
+                                                   xInverse, xDestroy);
+          if(0===rc && (xStep instanceof Function
+                        || xFinal instanceof Function
+                        || xValue instanceof Function
+                        || xInverse instanceof Function
+                        || xDestroy instanceof Function)){
+            __dbCleanupMap.addWindowFunc(pDb, funcName, nArg);
+          }
+          return rc;
+        }catch(e){
+          console.error("sqlite3_create_window_function() setup threw:",e);
+          return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
+        }
+      };
+    }else{
+      delete capi.sqlite3_create_window_function;
+    }
     /**
        A _deprecated_ alias for capi.sqlite3_result_js() which
        predates the addition of that function in the public API.
     */
     capi.sqlite3_create_function_v2.udfSetResult =
-      capi.sqlite3_create_function.udfSetResult =
+      capi.sqlite3_create_function.udfSetResult = capi.sqlite3_result_js;
+    if(capi.sqlite3_create_window_function){
       capi.sqlite3_create_window_function.udfSetResult = capi.sqlite3_result_js;
+    }
 
     /**
        A _deprecated_ alias for capi.sqlite3_values_to_js() which
        predates the addition of that function in the public API.
     */
     capi.sqlite3_create_function_v2.udfConvertArgs =
-      capi.sqlite3_create_function.udfConvertArgs =
+      capi.sqlite3_create_function.udfConvertArgs = capi.sqlite3_values_to_js;
+    if(capi.sqlite3_create_window_function){
       capi.sqlite3_create_window_function.udfConvertArgs = capi.sqlite3_values_to_js;
+    }
 
     /**
        A _deprecated_ alias for capi.sqlite3_result_error_js() which
        predates the addition of that function in the public API.
     */
     capi.sqlite3_create_function_v2.udfSetError =
-      capi.sqlite3_create_function.udfSetError =
+      capi.sqlite3_create_function.udfSetError = capi.sqlite3_result_error_js;
+    if(capi.sqlite3_create_window_function){
       capi.sqlite3_create_window_function.udfSetError = capi.sqlite3_result_error_js;
+    }
 
   }/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/;
 
index c0da2c623db7c3fdd301e1d92d6c80bddd7bea77..c5dd495e54a66ca189d409dfb90172654df8a170 100644 (file)
 
 /**********************************************************************/
 /* SQLITE_O... */
-#ifndef SQLITE_OMIT_DEPRECATED
-# define SQLITE_OMIT_DEPRECATED 1
-#endif
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-# define SQLITE_OMIT_LOAD_EXTENSION 1
-#endif
-#ifndef SQLITE_OMIT_SHARED_CACHE
-# define SQLITE_OMIT_SHARED_CACHE 1
-#endif
-#ifndef SQLITE_OMIT_UTF16
-# define SQLITE_OMIT_UTF16 1
-#endif
-#ifndef SQLITE_OS_KV_OPTIONAL
-# define SQLITE_OS_KV_OPTIONAL 1
-#endif
+#undef SQLITE_OMIT_DEPRECATED
+#define SQLITE_OMIT_DEPRECATED 1
+#undef SQLITE_OMIT_LOAD_EXTENSION
+#define SQLITE_OMIT_LOAD_EXTENSION 1
+#undef SQLITE_OMIT_SHARED_CACHE
+#define SQLITE_OMIT_SHARED_CACHE 1
+#undef SQLITE_OMIT_UTF16
+#define SQLITE_OMIT_UTF16 1
+#undef SQLITE_OS_KV_OPTIONAL
+#define SQLITE_OS_KV_OPTIONAL 1
 
 /**********************************************************************/
 /* SQLITE_S... */
 #endif
 
 /*
-** If SQLITE_WASM_MINIMAL is defined, undefine most of the ENABLE
+** If SQLITE_WASM_BARE_BONES is defined, undefine most of the ENABLE
 ** macros.
 */
-#ifdef SQLITE_WASM_MINIMAL
-#  undef SQLITE_ENABLE_DBPAGE_VTAB
-#  undef SQLITE_ENABLE_DBSTAT_VTAB
-#  undef SQLITE_ENABLE_EXPLAIN_COMMENTS
-#  undef SQLITE_ENABLE_FTS5
-#  undef SQLITE_ENABLE_OFFSET_SQL_FUNC
-#  undef SQLITE_ENABLE_PREUPDATE_HOOK
-#  undef SQLITE_ENABLE_RTREE
-#  undef SQLITE_ENABLE_SESSION
-#  undef SQLITE_ENABLE_STMTVTAB
-#  undef SQLITE_OMIT_AUTHORIZATION
+#ifdef SQLITE_WASM_BARE_BONES
+#  undef  SQLITE_ENABLE_DBPAGE_VTAB
+#  undef  SQLITE_ENABLE_DBSTAT_VTAB
+#  undef  SQLITE_ENABLE_EXPLAIN_COMMENTS
+#  undef  SQLITE_ENABLE_FTS5
+#  undef  SQLITE_ENABLE_OFFSET_SQL_FUNC
+#  undef  SQLITE_ENABLE_PREUPDATE_HOOK
+#  undef  SQLITE_ENABLE_RTREE
+#  undef  SQLITE_ENABLE_SESSION
+#  undef  SQLITE_ENABLE_STMTVTAB
+#  undef  SQLITE_OMIT_AUTHORIZATION
 #  define SQLITE_OMIT_AUTHORIZATION
-/*Reminder re. custom sqlite3.c:
+#  undef  SQLITE_OMIT_GET_TABLE
+#  define SQLITE_OMIT_GET_TABLE
+#  undef  SQLITE_OMIT_INCRBLOB
+#  define SQLITE_OMIT_INCRBLOB
+#  undef  SQLITE_OMIT_INTROSPECTION_PRAGMAS
+#  define SQLITE_OMIT_INTROSPECTION_PRAGMAS
+#  undef  SQLITE_OMIT_JSON
+#  define SQLITE_OMIT_JSON
+#  undef  SQLITE_OMIT_PROGRESS_CALLBACK
+#  define SQLITE_OMIT_PROGRESS_CALLBACK
+#  undef  SQLITE_OMIT_WAL
+#  define SQLITE_OMIT_WAL
+/*
+  The following OMITs do not work with the standard amalgamation, so
+  require a custom build:
 
   fossil clean -x
   ./configure
-  OPTS='-DSQLITE_OMIT_VIRTUALTABLE -DSQLITE_OMIT_EXPLAIN -DSQLITE_OMIT_TRIGGER' make -e sqlite3
-*/
-/*Requires a custom sqlite3.c
-#  undef SQLITE_OMIT_TRIGGER
-#  define SQLITE_OMIT_TRIGGER
-*/
-/*TODO (requires build tweaks)
-#  undef SQLITE_OMIT_WINDOWFUNC
-#  define SQLITE_OMIT_WINDOWFUNC
-*/
-/*Requires a custom sqlite3.c
+  OPTS='...' make -e sqlite3
+
+  where ... has a -D... for each of the following OMIT flags:
+
 #  undef SQLITE_OMIT_EXPLAIN
 #  define SQLITE_OMIT_EXPLAIN
-*/
-/*Requires a custom sqlite3.c
+
+#  undef SQLITE_OMIT_TRIGGER
+#  define SQLITE_OMIT_TRIGGER
+
 #  undef SQLITE_OMIT_VIRTUALTABLE
 #  define SQLITE_OMIT_VIRTUALTABLE
+
+#  undef SQLITE_OMIT_WINDOWFUNC
+#  define SQLITE_OMIT_WINDOWFUNC
+
+  As of this writing (2024-07-25), such a build fails in various ways
+  for as-yet-unknown reasons.
 */
-#  undef SQLITE_OMIT_JSON
-#  define SQLITE_OMIT_JSON
 #endif
 
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_WASM_MINIMAL)
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_WASM_BARE_BONES)
 #  define SQLITE_WASM_HAS_VTAB 1
 #else
 #  define SQLITE_WASM_HAS_VTAB 0
 #undef INC__STRINGIFY
 #undef SQLITE_C
 
-#if defined(__EMSCRIPTEN__)
-#  include <emscripten/console.h>
-#endif
-
 #if 0
 /*
 ** An EXPERIMENT in implementing a stack-based allocator analog to
@@ -1720,6 +1724,7 @@ char * sqlite3__wasm_qfmt_token(char *z, int addQuotes){
 }
 
 #if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS)
+#include <emscripten/console.h>
 #include <emscripten/wasmfs.h>
 
 /*
@@ -1941,5 +1946,5 @@ int sqlite3__wasm_SQLTester_strglob(const char *zGlob, const char *z){
 
 #undef SQLITE_WASM_EXPORT
 #undef SQLITE_WASM_HAS_VTAB
-#undef SQLITE_WASM_MINIMAL
+#undef SQLITE_WASM_BARE_BONES
 #undef SQLITE_WASM_ENABLE_C_TESTS
index 1f0d9e2ad0c8a8314fe92d291461f69b2effc3ea..b081d251552ddc4dd770d6ed2ee59dca2f850402 100644 (file)
@@ -41,10 +41,11 @@ fiddle.emcc-flags = \
   $(emcc.exportedRuntimeMethods) \
   -sEXPORTED_FUNCTIONS=@$(abspath $(EXPORTED_FUNCTIONS.fiddle)) \
   -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory \
-  $(SQLITE_OPT) $(SHELL_OPT) \
-  -USQLITE_WASM_MINIMAL \
+  $(SQLITE_OPT.full-featured) \
+  $(SQLITE_OPT.common) \
+  $(SHELL_OPT) \
+  -USQLITE_WASM_BARE_BONES \
   -DSQLITE_SHELL_FIDDLE
-# -D_POSIX_C_SOURCE is needed for strdup() with emcc
 
 # Flags specifically for debug builds of fiddle. Performance suffers
 # greatly in debug builds.
@@ -55,7 +56,8 @@ fiddle.emcc-flags.debug := $(fiddle.emcc-flags) \
 
 fiddle.EXPORTED_FUNCTIONS.in := \
     EXPORTED_FUNCTIONS.fiddle.in \
-    $(EXPORTED_FUNCTIONS.api)
+    $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core \
+    $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
 
 $(EXPORTED_FUNCTIONS.fiddle): $(fiddle.EXPORTED_FUNCTIONS.in) $(MAKEFILE.fiddle)
        sort -u $(fiddle.EXPORTED_FUNCTIONS.in) > $@
index b8db1a59b2fed4309071861b762e75e9d991078d..6023069bc45fbf785b858af5e25d4b0c496f2ec9 100644 (file)
@@ -848,171 +848,176 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
     }/*WhWasmUtil*/)
 
   ////////////////////////////////////////////////////////////////////
-    .t('sqlite3.StructBinder (jaccwabyt🐇)', function(sqlite3){
-      const S = sqlite3, W = S.wasm;
-      const MyStructDef = {
-        sizeof: 16,
-        members: {
-          p4: {offset: 0, sizeof: 4, signature: "i"},
-          pP: {offset: 4, sizeof: 4, signature: "P"},
-          ro: {offset: 8, sizeof: 4, signature: "i", readOnly: true},
-          cstr: {offset: 12, sizeof: 4, signature: "s"}
+    .t({
+      name: 'sqlite3.StructBinder (jaccwabyt🐇)',
+      predicate: (sqlite3)=>!!sqlite3.wasm.exports.sqlite3__wasm_test_struct
+        || "Built without SQLITE_WASM_ENABLE_C_TESTS",
+      test: function(sqlite3){
+        const S = sqlite3, W = S.wasm;
+        const MyStructDef = {
+          sizeof: 16,
+          members: {
+            p4: {offset: 0, sizeof: 4, signature: "i"},
+            pP: {offset: 4, sizeof: 4, signature: "P"},
+            ro: {offset: 8, sizeof: 4, signature: "i", readOnly: true},
+            cstr: {offset: 12, sizeof: 4, signature: "s"}
+          }
+        };
+        if(W.bigIntEnabled){
+          const m = MyStructDef;
+          m.members.p8 = {offset: m.sizeof, sizeof: 8, signature: "j"};
+          m.sizeof += m.members.p8.sizeof;
         }
-      };
-      if(W.bigIntEnabled){
-        const m = MyStructDef;
-        m.members.p8 = {offset: m.sizeof, sizeof: 8, signature: "j"};
-        m.sizeof += m.members.p8.sizeof;
-      }
-      const StructType = S.StructBinder.StructType;
-      const K = S.StructBinder('my_struct',MyStructDef);
-      T.mustThrowMatching(()=>K(), /via 'new'/).
-        mustThrowMatching(()=>new K('hi'), /^Invalid pointer/);
-      const k1 = new K(), k2 = new K();
-      try {
-        T.assert(k1.constructor === K).
-          assert(K.isA(k1)).
-          assert(k1 instanceof K).
-          assert(K.prototype.lookupMember('p4').key === '$p4').
-          assert(K.prototype.lookupMember('$p4').name === 'p4').
-          mustThrowMatching(()=>K.prototype.lookupMember('nope'), /not a mapped/).
-          assert(undefined === K.prototype.lookupMember('nope',false)).
-          assert(k1 instanceof StructType).
-          assert(StructType.isA(k1)).
-          mustThrowMatching(()=>k1.$ro = 1, /read-only/);
-        Object.keys(MyStructDef.members).forEach(function(key){
-          key = K.memberKey(key);
-          T.assert(0 == k1[key],
-                   "Expecting allocation to zero the memory "+
-                   "for "+key+" but got: "+k1[key]+
-                   " from "+k1.memoryDump());
-        });
-        T.assert('number' === typeof k1.pointer).
-          mustThrowMatching(()=>k1.pointer = 1, /pointer/);
-        k1.$p4 = 1; k1.$pP = 2;
-        T.assert(1 === k1.$p4).assert(2 === k1.$pP);
-        if(MyStructDef.members.$p8){
-          k1.$p8 = 1/*must not throw despite not being a BigInt*/;
-          k1.$p8 = BigInt(Number.MAX_SAFE_INTEGER * 2);
-          T.assert(BigInt(2 * Number.MAX_SAFE_INTEGER) === k1.$p8);
+        const StructType = S.StructBinder.StructType;
+        const K = S.StructBinder('my_struct',MyStructDef);
+        T.mustThrowMatching(()=>K(), /via 'new'/).
+          mustThrowMatching(()=>new K('hi'), /^Invalid pointer/);
+        const k1 = new K(), k2 = new K();
+        try {
+          T.assert(k1.constructor === K).
+            assert(K.isA(k1)).
+            assert(k1 instanceof K).
+            assert(K.prototype.lookupMember('p4').key === '$p4').
+            assert(K.prototype.lookupMember('$p4').name === 'p4').
+            mustThrowMatching(()=>K.prototype.lookupMember('nope'), /not a mapped/).
+            assert(undefined === K.prototype.lookupMember('nope',false)).
+            assert(k1 instanceof StructType).
+            assert(StructType.isA(k1)).
+            mustThrowMatching(()=>k1.$ro = 1, /read-only/);
+          Object.keys(MyStructDef.members).forEach(function(key){
+            key = K.memberKey(key);
+            T.assert(0 == k1[key],
+                     "Expecting allocation to zero the memory "+
+                     "for "+key+" but got: "+k1[key]+
+                     " from "+k1.memoryDump());
+          });
+          T.assert('number' === typeof k1.pointer).
+            mustThrowMatching(()=>k1.pointer = 1, /pointer/);
+          k1.$p4 = 1; k1.$pP = 2;
+          T.assert(1 === k1.$p4).assert(2 === k1.$pP);
+          if(MyStructDef.members.$p8){
+            k1.$p8 = 1/*must not throw despite not being a BigInt*/;
+            k1.$p8 = BigInt(Number.MAX_SAFE_INTEGER * 2);
+            T.assert(BigInt(2 * Number.MAX_SAFE_INTEGER) === k1.$p8);
+          }
+          T.assert(!k1.ondispose);
+          k1.setMemberCString('cstr', "A C-string.");
+          T.assert(Array.isArray(k1.ondispose)).
+            assert(k1.ondispose[0] === k1.$cstr).
+            assert('number' === typeof k1.$cstr).
+            assert('A C-string.' === k1.memberToJsString('cstr'));
+          k1.$pP = k2;
+          T.assert(k1.$pP === k2.pointer);
+          k1.$pP = null/*null is special-cased to 0.*/;
+          T.assert(0===k1.$pP);
+          let ptr = k1.pointer;
+          k1.dispose();
+          T.assert(undefined === k1.pointer).
+            mustThrowMatching(()=>{k1.$pP=1}, /disposed instance/);
+        }finally{
+          k1.dispose();
+          k2.dispose();
         }
-        T.assert(!k1.ondispose);
-        k1.setMemberCString('cstr', "A C-string.");
-        T.assert(Array.isArray(k1.ondispose)).
-          assert(k1.ondispose[0] === k1.$cstr).
-          assert('number' === typeof k1.$cstr).
-          assert('A C-string.' === k1.memberToJsString('cstr'));
-        k1.$pP = k2;
-        T.assert(k1.$pP === k2.pointer);
-        k1.$pP = null/*null is special-cased to 0.*/;
-        T.assert(0===k1.$pP);
-        let ptr = k1.pointer;
-        k1.dispose();
-        T.assert(undefined === k1.pointer).
-          mustThrowMatching(()=>{k1.$pP=1}, /disposed instance/);
-      }finally{
-        k1.dispose();
-        k2.dispose();
-      }
 
-      if(!W.bigIntEnabled){
-        log("Skipping WasmTestStruct tests: BigInt not enabled.");
-        return;
-      }
+        if(!W.bigIntEnabled){
+          log("Skipping WasmTestStruct tests: BigInt not enabled.");
+          return;
+        }
 
-      const WTStructDesc =
-            W.ctype.structs.filter((e)=>'WasmTestStruct'===e.name)[0];
-      const autoResolvePtr = true /* EXPERIMENTAL */;
-      if(autoResolvePtr){
-        WTStructDesc.members.ppV.signature = 'P';
-      }
-      const WTStruct = S.StructBinder(WTStructDesc);
-      //log(WTStruct.structName, WTStruct.structInfo);
-      const wts = new WTStruct();
-      //log("WTStruct.prototype keys:",Object.keys(WTStruct.prototype));
-      try{
-        T.assert(wts.constructor === WTStruct).
-          assert(WTStruct.memberKeys().indexOf('$ppV')>=0).
-          assert(wts.memberKeys().indexOf('$v8')>=0).
-          assert(!K.isA(wts)).
-          assert(WTStruct.isA(wts)).
-          assert(wts instanceof WTStruct).
-          assert(wts instanceof StructType).
-          assert(StructType.isA(wts)).
-          assert(wts.pointer>0).assert(0===wts.$v4).assert(0n===wts.$v8).
-          assert(0===wts.$ppV).assert(0===wts.$xFunc);
-        const testFunc =
-              W.xGet('sqlite3__wasm_test_struct'/*name gets mangled in -O3 builds!*/);
-        let counter = 0;
-        //log("wts.pointer =",wts.pointer);
-        const wtsFunc = function(arg){
-          /*log("This from a JS function called from C, "+
+        const WTStructDesc =
+              W.ctype.structs.filter((e)=>'WasmTestStruct'===e.name)[0];
+        const autoResolvePtr = true /* EXPERIMENTAL */;
+        if(autoResolvePtr){
+          WTStructDesc.members.ppV.signature = 'P';
+        }
+        const WTStruct = S.StructBinder(WTStructDesc);
+        //log(WTStruct.structName, WTStruct.structInfo);
+        const wts = new WTStruct();
+        //log("WTStruct.prototype keys:",Object.keys(WTStruct.prototype));
+        try{
+          T.assert(wts.constructor === WTStruct).
+            assert(WTStruct.memberKeys().indexOf('$ppV')>=0).
+            assert(wts.memberKeys().indexOf('$v8')>=0).
+            assert(!K.isA(wts)).
+            assert(WTStruct.isA(wts)).
+            assert(wts instanceof WTStruct).
+            assert(wts instanceof StructType).
+            assert(StructType.isA(wts)).
+            assert(wts.pointer>0).assert(0===wts.$v4).assert(0n===wts.$v8).
+            assert(0===wts.$ppV).assert(0===wts.$xFunc);
+          const testFunc =
+                W.xGet('sqlite3__wasm_test_struct'/*name gets mangled in -O3 builds!*/);
+          let counter = 0;
+          //log("wts.pointer =",wts.pointer);
+          const wtsFunc = function(arg){
+            /*log("This from a JS function called from C, "+
               "which itself was called from JS. arg =",arg);*/
-          ++counter;
-          if(3===counter){
-            tossQuietly("Testing exception propagation.");
+            ++counter;
+            if(3===counter){
+              tossQuietly("Testing exception propagation.");
+            }
           }
+          wts.$v4 = 10; wts.$v8 = 20;
+          wts.$xFunc = W.installFunction(wtsFunc, wts.memberSignature('xFunc'))
+          T.assert(0===counter).assert(10 === wts.$v4).assert(20n === wts.$v8)
+            .assert(0 === wts.$ppV).assert('number' === typeof wts.$xFunc)
+            .assert(0 === wts.$cstr)
+            .assert(wts.memberIsString('$cstr'))
+            .assert(!wts.memberIsString('$v4'))
+            .assert(null === wts.memberToJsString('$cstr'))
+            .assert(W.functionEntry(wts.$xFunc) instanceof Function);
+          /* It might seem silly to assert that the values match
+             what we just set, but recall that all of those property
+             reads and writes are, via property interceptors,
+             actually marshaling their data to/from a raw memory
+             buffer, so merely reading them back is actually part of
+             testing the struct-wrapping API. */
+
+          testFunc(wts.pointer);
+          //log("wts.pointer, wts.$ppV",wts.pointer, wts.$ppV);
+          T.assert(1===counter).assert(20 === wts.$v4).assert(40n === wts.$v8)
+            .assert(wts.$ppV === wts.pointer)
+            .assert('string' === typeof wts.memberToJsString('cstr'))
+            .assert(wts.memberToJsString('cstr') === wts.memberToJsString('$cstr'))
+            .mustThrowMatching(()=>wts.memberToJsString('xFunc'),
+                               /Invalid member type signature for C-string/)
+          ;
+          testFunc(wts.pointer);
+          T.assert(2===counter).assert(40 === wts.$v4).assert(80n === wts.$v8)
+            .assert(wts.$ppV === wts.pointer);
+          /** The 3rd call to wtsFunc throw from JS, which is called
+              from C, which is called from JS. Let's ensure that
+              that exception propagates back here... */
+          T.mustThrowMatching(()=>testFunc(wts.pointer),/^Testing/);
+          W.uninstallFunction(wts.$xFunc);
+          wts.$xFunc = 0;
+          wts.$ppV = 0;
+          T.assert(!wts.$ppV);
+          //WTStruct.debugFlags(0x03);
+          wts.$ppV = wts;
+          T.assert(wts.pointer === wts.$ppV)
+          wts.setMemberCString('cstr', "A C-string.");
+          T.assert(Array.isArray(wts.ondispose)).
+            assert(wts.ondispose[0] === wts.$cstr).
+            assert('A C-string.' === wts.memberToJsString('cstr'));
+          const ptr = wts.pointer;
+          wts.dispose();
+          T.assert(ptr).assert(undefined === wts.pointer);
+        }finally{
+          wts.dispose();
         }
-        wts.$v4 = 10; wts.$v8 = 20;
-        wts.$xFunc = W.installFunction(wtsFunc, wts.memberSignature('xFunc'))
-        T.assert(0===counter).assert(10 === wts.$v4).assert(20n === wts.$v8)
-          .assert(0 === wts.$ppV).assert('number' === typeof wts.$xFunc)
-          .assert(0 === wts.$cstr)
-          .assert(wts.memberIsString('$cstr'))
-          .assert(!wts.memberIsString('$v4'))
-          .assert(null === wts.memberToJsString('$cstr'))
-          .assert(W.functionEntry(wts.$xFunc) instanceof Function);
-        /* It might seem silly to assert that the values match
-           what we just set, but recall that all of those property
-           reads and writes are, via property interceptors,
-           actually marshaling their data to/from a raw memory
-           buffer, so merely reading them back is actually part of
-           testing the struct-wrapping API. */
-
-        testFunc(wts.pointer);
-        //log("wts.pointer, wts.$ppV",wts.pointer, wts.$ppV);
-        T.assert(1===counter).assert(20 === wts.$v4).assert(40n === wts.$v8)
-          .assert(wts.$ppV === wts.pointer)
-          .assert('string' === typeof wts.memberToJsString('cstr'))
-          .assert(wts.memberToJsString('cstr') === wts.memberToJsString('$cstr'))
-          .mustThrowMatching(()=>wts.memberToJsString('xFunc'),
-                             /Invalid member type signature for C-string/)
-        ;
-        testFunc(wts.pointer);
-        T.assert(2===counter).assert(40 === wts.$v4).assert(80n === wts.$v8)
-          .assert(wts.$ppV === wts.pointer);
-        /** The 3rd call to wtsFunc throw from JS, which is called
-            from C, which is called from JS. Let's ensure that
-            that exception propagates back here... */
-        T.mustThrowMatching(()=>testFunc(wts.pointer),/^Testing/);
-        W.uninstallFunction(wts.$xFunc);
-        wts.$xFunc = 0;
-        wts.$ppV = 0;
-        T.assert(!wts.$ppV);
-        //WTStruct.debugFlags(0x03);
-        wts.$ppV = wts;
-        T.assert(wts.pointer === wts.$ppV)
-        wts.setMemberCString('cstr', "A C-string.");
-        T.assert(Array.isArray(wts.ondispose)).
-          assert(wts.ondispose[0] === wts.$cstr).
-          assert('A C-string.' === wts.memberToJsString('cstr'));
-        const ptr = wts.pointer;
-        wts.dispose();
-        T.assert(ptr).assert(undefined === wts.pointer);
-      }finally{
-        wts.dispose();
-      }
 
-      if(1){ // ondispose of other struct instances
-        const s1 = new WTStruct, s2 = new WTStruct, s3 = new WTStruct;
-        T.assert(s1.lookupMember instanceof Function)
-          .assert(s1.addOnDispose instanceof Function);
-        s1.addOnDispose(s2,"testing variadic args");
-        T.assert(2===s1.ondispose.length);
-        s2.addOnDispose(s3);
-        s1.dispose();
-        T.assert(!s2.pointer,"Expecting s2 to be ondispose'd by s1.");
-        T.assert(!s3.pointer,"Expecting s3 to be ondispose'd by s2.");
+        if(1){ // ondispose of other struct instances
+          const s1 = new WTStruct, s2 = new WTStruct, s3 = new WTStruct;
+          T.assert(s1.lookupMember instanceof Function)
+            .assert(s1.addOnDispose instanceof Function);
+          s1.addOnDispose(s2,"testing variadic args");
+          T.assert(2===s1.ondispose.length);
+          s2.addOnDispose(s3);
+          s1.dispose();
+          T.assert(!s2.pointer,"Expecting s2 to be ondispose'd by s1.");
+          T.assert(!s3.pointer,"Expecting s3 to be ondispose'd by s2.");
+        }
       }
     }/*StructBinder*/)
 
@@ -1126,75 +1131,84 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
 
   ////////////////////////////////////////////////////////////////////////
   T.g('sqlite3.oo1')
-    .t('Create db', function(sqlite3){
-      const dbFile = '/tester1.db';
-      sqlite3.util.sqlite3__wasm_vfs_unlink(0, dbFile);
-      const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c');
-      db.onclose = {
-        disposeAfter: [],
-        disposeBefore: [
-          (db)=>{
-            //console.debug("db.onclose.before dropping modules");
-            //sqlite3.capi.sqlite3_drop_modules(db.pointer, 0);
-          }
-        ],
-        before: function(db){
-          while(this.disposeBefore.length){
-            const v = this.disposeBefore.shift();
-            console.debug("db.onclose.before cleaning up:",v);
-            if(wasm.isPtr(v)) wasm.dealloc(v);
-            else if(v instanceof sqlite3.StructBinder.StructType){
-              v.dispose();
-            }else if(v instanceof Function){
-              try{ v(db) } catch(e){
-                console.warn("beforeDispose() callback threw:",e);
+    .t({
+      name:'Create db',
+      //predicate: (sqlite3)=>
+      test: function(sqlite3){
+        const dbFile = '/tester1.db';
+        sqlite3.util.sqlite3__wasm_vfs_unlink(0, dbFile);
+        const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c');
+        db.onclose = {
+          disposeAfter: [],
+          disposeBefore: [
+            (db)=>{
+              //console.debug("db.onclose.before dropping modules");
+              //sqlite3.capi.sqlite3_drop_modules(db.pointer, 0);
+            }
+          ],
+          before: function(db){
+            while(this.disposeBefore.length){
+              const v = this.disposeBefore.shift();
+              console.debug("db.onclose.before cleaning up:",v);
+              if(wasm.isPtr(v)) wasm.dealloc(v);
+              else if(v instanceof sqlite3.StructBinder.StructType){
+                v.dispose();
+              }else if(v instanceof Function){
+                try{ v(db) } catch(e){
+                  console.warn("beforeDispose() callback threw:",e);
+                }
               }
             }
-          }
-        },
-        after: function(){
-          while(this.disposeAfter.length){
-            const v = this.disposeAfter.shift();
-            console.debug("db.onclose.after cleaning up:",v);
-            if(wasm.isPtr(v)) wasm.dealloc(v);
-            else if(v instanceof sqlite3.StructBinder.StructType){
-              v.dispose();
-            }else if(v instanceof Function){
-              try{v()} catch(e){/*ignored*/}
+          },
+          after: function(){
+            while(this.disposeAfter.length){
+              const v = this.disposeAfter.shift();
+              console.debug("db.onclose.after cleaning up:",v);
+              if(wasm.isPtr(v)) wasm.dealloc(v);
+              else if(v instanceof sqlite3.StructBinder.StructType){
+                v.dispose();
+              }else if(v instanceof Function){
+                try{v()} catch(e){/*ignored*/}
+              }
             }
           }
-        }
-      };
-
-      T.assert(wasm.isPtr(db.pointer))
-        .mustThrowMatching(()=>db.pointer=1, /read-only/)
-        .assert(0===sqlite3.capi.sqlite3_extended_result_codes(db.pointer,1))
-        .assert('main'===db.dbName(0))
-        .assert('string' === typeof db.dbVfsName())
-        .assert(db.pointer === wasm.xWrap.testConvertArg('sqlite3*',db));
-      // Custom db error message handling via sqlite3_prepare_v2/v3()
-      let rc = capi.sqlite3_prepare_v3(db.pointer, {/*invalid*/}, -1, 0, null, null);
-      T.assert(capi.SQLITE_MISUSE === rc)
-        .assert(0 === capi.sqlite3_errmsg(db.pointer).indexOf("Invalid SQL"))
-        .assert(dbFile === db.dbFilename())
-        .assert(!db.dbFilename('nope'));
-      //Sanity check DB.checkRc()...
-      let ex;
-      try{db.checkRc(rc)}
-      catch(e){ex = e}
-      T.assert(ex instanceof sqlite3.SQLite3Error)
-        .assert(capi.SQLITE_MISUSE===ex.resultCode)
-        .assert(0===ex.message.indexOf("SQLITE_MISUSE: sqlite3 result code"))
-        .assert(ex.message.indexOf("Invalid SQL")>0);
-      T.assert(db === db.checkRc(0))
-        .assert(db === sqlite3.oo1.DB.checkRc(db,0))
-        .assert(null === sqlite3.oo1.DB.checkRc(null,0));
+        };
 
-      this.progressHandlerCount = 0;
-      capi.sqlite3_progress_handler(db, 5, (p)=>{
-        ++this.progressHandlerCount;
-        return 0;
-      }, 0);
+        T.assert(wasm.isPtr(db.pointer))
+          .mustThrowMatching(()=>db.pointer=1, /read-only/)
+          .assert(0===sqlite3.capi.sqlite3_extended_result_codes(db.pointer,1))
+          .assert('main'===db.dbName(0))
+          .assert('string' === typeof db.dbVfsName())
+          .assert(db.pointer === wasm.xWrap.testConvertArg('sqlite3*',db));
+        // Custom db error message handling via sqlite3_prepare_v2/v3()
+        let rc = capi.sqlite3_prepare_v3(db.pointer, {/*invalid*/}, -1, 0, null, null);
+        T.assert(capi.SQLITE_MISUSE === rc)
+          .assert(0 === capi.sqlite3_errmsg(db.pointer).indexOf("Invalid SQL"))
+          .assert(dbFile === db.dbFilename())
+          .assert(!db.dbFilename('nope'));
+        //Sanity check DB.checkRc()...
+        let ex;
+        try{db.checkRc(rc)}
+        catch(e){ex = e}
+        T.assert(ex instanceof sqlite3.SQLite3Error)
+          .assert(capi.SQLITE_MISUSE===ex.resultCode)
+          .assert(0===ex.message.indexOf("SQLITE_MISUSE: sqlite3 result code"))
+          .assert(ex.message.indexOf("Invalid SQL")>0);
+        T.assert(db === db.checkRc(0))
+          .assert(db === sqlite3.oo1.DB.checkRc(db,0))
+          .assert(null === sqlite3.oo1.DB.checkRc(null,0));
+
+        this.progressHandlerCount = 0;
+        if( wasm.compileOptionUsed('OMIT_PROGRESS_CALLBACK') ){
+          T.assert( !capi.sqlite3_progress_handler );
+        }else{
+          T.assert( capi.sqlite3_progress_handler );
+          capi.sqlite3_progress_handler(db, 5, (p)=>{
+            ++this.progressHandlerCount;
+            return 0;
+          }, 0);
+        }
+      }
     })
   ////////////////////////////////////////////////////////////////////
     .t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){
@@ -1236,7 +1250,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
         new TextEncoder('utf-8').encode("select 3 as a")
       );
       //debug("statement =",st);
-      this.progressHandlerCount = 0;
+      T.assert( !this.progressHandlerCount );
       let rc;
       try {
         T.assert(wasm.isPtr(st.pointer))
@@ -1278,7 +1292,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
               st, capi.SQLITE_STMTSTATUS_RUN, 0
             ) > 0);
 
-        T.assert(this.progressHandlerCount > 0,
+        T.assert(this.progressHandlerCount>0
+                 || wasm.compileOptionUsed('OMIT_PROGRESS_CALLBACK'),
                  "Expecting progress callback.").
           assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
           assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
@@ -1363,7 +1378,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
         .assert(2 === list.length)
         .assert('string'===typeof list[1])
         .assert(3===db.changes())
-        .assert(this.progressHandlerCount > 0,
+        .assert(this.progressHandlerCount > 0
+                || wasm.compileOptionUsed('OMIT_PROGRESS_CALLBACK'),
                 "Expecting progress callback.")
       if(wasm.bigIntEnabled){
         T.assert(3n===db.changes(false,true));
@@ -1904,7 +1920,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
   ////////////////////////////////////////////////////////////////////
     .t({
       name: 'Window UDFs',
-      //predicate: ()=>false,
+      predicate: (sqlite3)=>!!sqlite3.wasm.exports.sqlite3_create_window_function
+      /*!sqlite3.wasm.compileOptionUsed('OMIT_WINDOWFUNC')*/
+        || "Missing window functions",
       test: function(){
         /* Example window function, table, and results taken from:
            https://sqlite.org/windowfunctions.html#udfwinfunc */
@@ -3132,7 +3150,10 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
         ]);
         T.assert(2 === u1.getFileCount() /* one is the journal file */)
           .assert(3 === db.selectValue('select count(*) from t'))
-          .assert('wal'===db.selectValue('pragma journal_mode'));
+          .assert(
+            'wal'===db.selectValue('pragma journal_mode')
+              || wasm.compileOptionUsed('OMIT_WAL')
+          );
         db.close();
         T.assert(1 === u1.getFileCount());
         db = new u2.OpfsSAHPoolDb(dbName);
index 6b6d0243f4dfe4c2964679986af86369f57caedc..1df2fad795f7b3a29b6f1cec051f2b0c6b49fc75 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C More\swork\son\sthe\sminimal-mode\swasm\sbuild\s(now\s603kb\suncompressed).\sRemove\sthe\shard-coded\sfeature-enable\sflags\sfrom\ssqlite3-wasm.c\sand\srely\son\sthe\sbuild\sto\sprovide\sthem.\sSome\swasm\sbuild\scleanup,\sbut\sattempts\sto\scompletely\soverhaul\sit\shave\sbeen\sthwarted\sby\smy\sinability\sto\smake\sscript-generated\smakefile\scode\smore\slegible/maintainable\sthan\sthe\scurrent\seval\sspaghetti.
-D 2024-07-25T14:00:26.899
+C Strip\sprogress\shandlers\sand\swindow\sfunctions\sfrom\sthe\swasm\sbare-bones\s(formerly\s'minimal')\sJS\sbits,\snoting\sthat\swe\scan't\syet\suse\sOMIT_WINDOWFUNC\s(for\sthe\sC\sparts)\swithout\sa\scustom\samalgamation.\sCurrently\sat\s604kb.
+D 2024-07-25T16:21:19.087
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -593,7 +593,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
 F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
 F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
-F ext/wasm/GNUmakefile c89b6d0e7f969de03cfcbd5d5f64985ee9ba823a7be6b150fb9c2976c7adb0d6
+F ext/wasm/GNUmakefile 1857ad71bfdc780019639f49dc054fee491b4ddba2669898b8acfd4ffba50030
 F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
 F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
 F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -601,8 +601,8 @@ F ext/wasm/SQLTester/SQLTester.mjs ce765c0ad7d57f93553d12ef4dca574deb00300134a26
 F ext/wasm/SQLTester/SQLTester.run.mjs c72b7fe2072d05992f7a3d8c6a1d34e95712513ceabe40849784e24e41c84638
 F ext/wasm/SQLTester/index.html 3f8a016df0776be76605abf20e815ecaafbe055abac0e1fe5ea080e7846b760d
 F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
-F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core 38f85e6ec5f9c776087bc38aef9ef35eeb7e54942ddb1dd04e9ac0122958b741
-F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras 2a8c9f7d865cc6e5661b2cd40a45e963a1f8070a88def6ead4c40d4fa0c91998
+F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core 2bcbbfe3b95c043ed6037e2708a2ee078d212dd1612c364f93588d8dc97300fe
+F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras fe40d6d758646e38f8b15f709044951e10884214f5453d35502100179c388c13
 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
 F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
 F ext/wasm/api/README.md 34fe11466f9c1d81b10a0469e1114e5f1c5a6365c73d80a1a6ca639a1a358b73
@@ -612,7 +612,7 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
 F ext/wasm/api/post-js-header.js 04dc12c3edd666b64a1b4ef3b6690c88dcc653f26451fd4734472d8e29c1c122
 F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
 F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
-F ext/wasm/api/sqlite3-api-glue.c-pp.js 12f6f3840afdf8ff7a4374dc1a96a26bcc369e17853e0fe917c38f4d66c6e2d8
+F ext/wasm/api/sqlite3-api-glue.c-pp.js fb6dbfe692cc23000a65a4cd95a1a47ed5eb592dc9d8b55363b3c2952a787244
 F ext/wasm/api/sqlite3-api-oo1.c-pp.js f3a8e2004c6625d17946c11f2fb32008be78bc5207bf746fc77d59848813225f
 F ext/wasm/api/sqlite3-api-prologue.js 6f1257e04885632ed9f44d43aba200b86e0bc16709ffdba29abbbeb1bc8e8b76
 F ext/wasm/api/sqlite3-api-worker1.c-pp.js 5cc22a3c0d52828cb32aad8691488719f47d27567e63e8bc8b832d74371c352d
@@ -622,7 +622,7 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
 F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js e529a99b7d5a088284821e2902b20d3404b561126969876997d5a73a656c9199
 F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js e99e3d99f736937914527070f00ab13e9391d3f1cef884ab99a64cbcbee8d675
 F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
-F ext/wasm/api/sqlite3-wasm.c 79335b70d4d404b33fb485a4f65422a1ded0977c38e3b1a0cd8e26b49d3c9fba
+F ext/wasm/api/sqlite3-wasm.c 83f5e9f998e9fa4261eb84e9f092210e3ffe03895119f5ded0429eb34ab9d2be
 F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 46f303ba8ddd1b2f0a391798837beddfa72e8c897038c8047eda49ce7d5ed46b
 F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
 F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
@@ -645,7 +645,7 @@ F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2
 F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef
 F ext/wasm/dist.make 653e212c1e84aa3be168d62a10616ccea45ee9585b0192745d2706707a5248ce
 F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
-F ext/wasm/fiddle.make 2406b02473878a99fb6a2eaff0923277017adc45eb041b2afb2d7707bf7b375c
+F ext/wasm/fiddle.make b3b118516ed581cdf2c16de8eb1672427320e67ff19d710a09c891e895883644
 F ext/wasm/fiddle/fiddle-worker.js 850e66fce39b89d59e161d1abac43a181a4caa89ddeea162765d660277cd84ce
 F ext/wasm/fiddle/fiddle.js b444a5646a9aac9f3fc06c53d78af5e1912eb235d69a8e6010723e4eb0e9d4a1
 F ext/wasm/fiddle/index.html 739e0b75bc592679665d25e2f7649d2b8b2db678f3b41a772a8720b609b8482d
@@ -669,7 +669,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 7d0eba1496286338770133356488b4415de7970f4ee2c08f7f587bb18d8b6b0b
+F ext/wasm/tester1.c-pp.js eb56110cd1959fc72c4001decc066ac7978912304e08aa402ca76527007cea5a
 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
@@ -2197,8 +2197,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P ed746b3dd3248b68cb91de50ac5ba5fd3a7c2fcbde76324e86b88edbfecd896b
-R acaefae7f2493e8276236de40774aafc
+P b029c4067943e366a9b25b8303136fab10822bd771ea4658ac4cd716ff4a0d8f
+R 4aba6600c1b56bb40f0e32cfcacb9fbe
 U stephan
-Z 2f4bcd240a0ced338bed244e56f0f58c
+Z c6f1d9cf14c3543f4f2774a34de2bf76
 # Remove this line to create a well-formed Fossil manifest.
index 930c8e1a5102d7d522c3e764b6e98680954f12cd..6de85ff0e9e7610e3f9cc6cc6ce4b4d7eb8c5691 100644 (file)
@@ -1 +1 @@
-b029c4067943e366a9b25b8303136fab10822bd771ea4658ac4cd716ff4a0d8f
+ec02e9237e1ef81c4196fa630822cb109eab926143ad09593a24273eb0668601