Strip progress handlers and window functions from the wasm bare-bones (formerly 'minimal') JS bits, noting that we can't yet use OMIT_WINDOWFUNC (for the C parts) without a custom amalgamation. Currently at 604kb.

FossilOrigin-Name: ec02e9237e1ef81c4196fa630822cb109eab926143ad09593a24273eb0668601
This commit is contained in:
stephan 2024-07-25 16:21:19 +00:00
parent 520d1a8486
commit e7840ce681
9 changed files with 496 additions and 403 deletions

View 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

View 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

View File

@ -1,3 +1,5 @@
_sqlite3_create_window_function
_sqlite3_progress_handler
_sqlite3_set_authorizer
_sqlite3_preupdate_blobwrite
_sqlite3_preupdate_count

View 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*/;

View File

@ -95,21 +95,16 @@
/**********************************************************************/
/* 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... */
@ -137,48 +132,61 @@
#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
@ -234,10 +242,6 @@
#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

View 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) > $@

View 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"}
}
};
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);
}
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;
}
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.");
.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;
}
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();
}
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(!W.bigIntEnabled){
log("Skipping WasmTestStruct tests: BigInt not enabled.");
return;
}
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.");
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.");
}
}
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.");
}
}
}/*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;
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.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('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);

View File

@ -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.

View File

@ -1 +1 @@
b029c4067943e366a9b25b8303136fab10822bd771ea4658ac4cd716ff4a0d8f
ec02e9237e1ef81c4196fa630822cb109eab926143ad09593a24273eb0668601