Merge trunk changes into this branch.

FossilOrigin-Name: c4fb2f2ea0afe638fd7cffd89fbdb0a91589577c6f8299c7bbc17ac121be518b
This commit is contained in:
dan 2023-07-17 11:47:42 +00:00
commit 24433bea19
21 changed files with 533 additions and 608 deletions

View File

@ -68,13 +68,6 @@ ifeq (,$(emcc.version))
else
$(info using emcc version [$(emcc.version)])
endif
emcc.version := $(shell "$(emcc.bin)" --version | sed -n 1p \
| sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
ifeq (,$(emcc.version))
$(warning Cannot determine emcc version. This might unduly impact build flags.)
else
$(info using emcc version [$(emcc.version)])
endif
wasm-strip ?= $(shell which wasm-strip 2>/dev/null)
ifeq (,$(filter clean,$(MAKECMDGOALS)))
@ -159,6 +152,9 @@ endif
# bundle.
#
# A custom sqlite3.c must not have any spaces in its name.
# $(sqlite3.canonical.c) must point to the sqlite3.c in
# the sqlite3 canonical source tree, as that source file
# is required for certain utility and test code.
sqlite3.canonical.c := $(dir.top)/sqlite3.c
sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c))
sqlite3.h := $(dir.top)/sqlite3.h
@ -381,18 +377,14 @@ sqlite3-api.jses += $(dir.api)/sqlite3-v-helper.js
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
# "External" API files which are part of our distribution
# SOAP.js is an external API file which is part of our distribution
# but not part of the sqlite3-api.js amalgamation.
SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js
# COPY_XAPI = a $(call)able function to copy $1 to $(dir.dout), where
# $1 must be one of the "external" JS API files.
define COPY_XAPI
sqlite3-api.ext.jses += $$(dir.dout)/$$(notdir $(1))
$$(dir.dout)/$$(notdir $(1)): $(1) $$(MAKEFILE)
cp $$< $$@
endef
$(foreach X,$(SOAP.js),\
$(eval $(call COPY_XAPI,$(X))))
SOAP.js.bld := $(dir.dout)/$(notdir $(SOAP.js))
sqlite3-api.ext.jses += $(SOAP.js.bld)
$(SOAP.js.bld): $(SOAP.js)
cp $< $@
all quick: $(sqlite3-api.ext.jses)
q: quick
@ -615,26 +607,40 @@ $(post-js.js.in): $(post-jses.js) $(MAKEFILE)
########################################################################
# call-make-pre-post is a $(call)able which creates rules for
# pre-js-$(1).js. $1 = the base name of the JS file on whose behalf
# this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is the
# build mode: one of $(JS_BUILD_MODES). This
# sets up --[extern-][pre/post]-js flags in
# $(pre-post-$(1).flags.$(2)) and dependencies in
# $(pre-post-$(1).deps.$(2)).
# pre-js-$(1)-$(2).js. $1 = the base name of the JS file on whose
# behalf this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is
# the build mode: one of $(JS_BUILD_MODES). This sets up
# --[extern-][pre/post]-js flags in $(pre-post-$(1)-$(2).flags) and
# dependencies in $(pre-post-$(1)-$(2).deps). The resulting files get
# filtered using $(C-PP.FILTER). Any flags necessary for such
# filtering need to be set in $(c-pp.D.$(1)-$(2)) before $(call)ing
# this.
define call-make-pre-post
pre-post-$(1).flags.$(2) ?=
$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(2)) $$(MAKEFILE)
cp $$(pre-js.js.$(2)) $$@
pre-post-$(1)-$(2).flags ?=
pre-js.js.$(1)-$(2) := $$(dir.tmp)/pre-js.$(1)-$(2).intermediary.js
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
post-js.js.$(1)-$(2) := $$(dir.tmp)/post-js.$(1)-$(2).js
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
extern-post-js.js.$(1)-$(2) := $$(dir.tmp)/extern-post-js.$(1)-$(2).js
$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
pre-post-common.flags.$(1)-$(2) := \
$$(pre-post-common.flags) \
--post-js=$$(post-js.js.$(1)-$(2)) \
--extern-post-js=$$(extern-post-js.js.$(1)-$(2))
pre-post-jses.$(1)-$(2).deps := $$(pre-post-jses.deps.common) \
$$(post-js.js.$(1)-$(2)) $$(extern-post-js.js.$(1)-$(2))
$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(1)-$(2)) $$(MAKEFILE)
cp $$(pre-js.js.$(1)-$(2)) $$@
@if [ sqlite3-wasmfs = $(1) ]; then \
echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \
elif [ sqlite3 != $(1) ]; then \
echo "Module[xNameOfInstantiateWasm].uri = '$(1).wasm';"; \
fi >> $$@
pre-post-$(1).deps.$(2) := \
$$(pre-post-jses.deps.$(2)) \
pre-post-$(1)-$(2).deps := \
$$(pre-post-jses.$(1)-$(2).deps) \
$$(dir.tmp)/pre-js-$(1)-$(2).js
pre-post-$(1).flags.$(2) += \
$$(pre-post-common.flags.$(2)) \
pre-post-$(1)-$(2).flags += \
$$(pre-post-common.flags.$(1)-$(2)) \
--pre-js=$$(dir.tmp)/pre-js-$(1)-$(2).js
endef
# /post-js and pre-js
@ -645,7 +651,8 @@ endef
# https://github.com/emscripten-core/emscripten/issues/14383
sqlite3.wasm := $(dir.dout)/sqlite3.wasm
sqlite3-wasm.c := $(dir.api)/sqlite3-wasm.c
sqlite3-wasm.cses := $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
sqlite3-wasm.cfiles := $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
# sqlite3-wasm.o vs sqlite3-wasm.c: building against the latter
# (predictably) results in a slightly faster binary. We're close
# enough to the target speed requirements that the 500ms makes a
@ -655,7 +662,8 @@ sqlite3-wasm.cses := $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
# SQLITE3.xJS.EXPORT-DEFAULT is part of SQLITE3-WASMFS.xJS.RECIPE and
# SETUP_LIB_BUILD_MODE, factored into a separate piece to avoid code
# duplication. $1 is 1 if the build mode needs this workaround (esm,
# bundler-friendly) and 0 if not (vanilla).
# bundler-friendly, node) and 0 if not (vanilla). $2 must be empty for
# all builds except sqlite3-wasmfs.mjs, in which case it must be 1.
#
# Reminder for ESM builds: even if we use -sEXPORT_ES6=0, emcc _still_
# adds:
@ -671,11 +679,13 @@ sqlite3-wasm.cses := $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
# https://github.com/emscripten-core/emscripten/issues/18237
define SQLITE3.xJS.ESM-EXPORT-DEFAULT
if [ x1 = x$(1) ]; then \
echo "Fragile workaround for an Emscripten annoyance. See SQLITE3.xJS.RECIPE."; \
echo "Fragile workaround for emscripten/issues/18237. See SQLITE3.xJS.RECIPE."; \
sed -i -e '0,/^export default/{/^export default/d;}' $@ || exit $$?; \
if ! grep -q '^export default' $@; then \
echo "Cannot find export default." 1>&2; \
exit 1; \
if [ x != x$(2) ]; then \
if ! grep -q '^export default' $@; then \
echo "Cannot find export default." 1>&2; \
exit 1; \
fi; \
fi; \
fi
endef
@ -695,53 +705,57 @@ pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
# SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces
# for one of the build modes.
#
# $1 = build mode name: one of $(JS_BUILD_MODES)
# $2 = 1 for ESM build mode, else 0
# $3 = resulting sqlite-api JS/MJS file
# $4 = resulting JS/MJS file
# $5 = -D... flags for $(bin.c-pp)
# $6 = emcc -sXYZ flags (CURRENTLY UNUSED - was factored out)
# $1 = one of: sqlite3, sqlite3-wasmfs
# $2 = build mode name: one of $(JS_BUILD_MODES)
# $3 = 1 for ESM build mode, else 0
# $4 = resulting sqlite-api JS/MJS file
# $5 = resulting JS/MJS file
# $6 = -D... flags for $(bin.c-pp)
# $7 = emcc -sXYZ flags (CURRENTLY UNUSED - was factored out)
#
# emcc.environment.$(1) must be set to a value for the -sENVIRONMENT flag.
# Maintenance reminder: be careful not to introduce spaces around args
# ($1, $2), otherwise string concatenation will malfunction.
#
# emcc.environment.$(2) must be set to a value for the -sENVIRONMENT flag.
#
# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append
# CFLAGS to a given build mode.
#
# $(emcc.flags.$(1)) and $(emcc.flags.$(1).$(2)) may be defined to
# append emcc-specific flags to a given build mode.
define SETUP_LIB_BUILD_MODE
$(info Setting up build [$(1)]: $(4))
c-pp.D.$(1) := $(5)
pre-js.js.$(1) := $$(dir.tmp)/pre-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)),$$(c-pp.D.$(1))))
post-js.js.$(1) := $$(dir.tmp)/post-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)),$$(c-pp.D.$(1))))
extern-post-js.js.$(1) := $$(dir.tmp)/extern-post-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)),$$(c-pp.D.$(1))))
pre-post-common.flags.$(1) := \
$$(pre-post-common.flags) \
--post-js=$$(post-js.js.$(1)) \
--extern-post-js=$$(extern-post-js.js.$(1))
pre-post-jses.deps.$(1) := $$(pre-post-jses.deps.common) \
$$(post-js.js.$(1)) $$(extern-post-js.js.$(1))
$$(eval $$(call call-make-pre-post,sqlite3,$(1)))
emcc.flags.sqlite3.$(1) := $(6)
$$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(3), $(5)))
$(4): $(3) $$(MAKEFILE) $$(sqlite3-wasm.cses) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-sqlite3.deps.$(1))
$(info Setting up build [$(1)-$(2)]: $(5))
c-pp.D.$(1)-$(2) := $(6)
$$(eval $$(call call-make-pre-post,$(1),$(2)))
emcc.flags.$(1).$(2) ?=
emcc.flags.$(1).$(2) += $(7)
$$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(4), $(6)))
$(5): $(4) $$(MAKEFILE) $$(sqlite3-wasm.cfiles) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-$(1)-$(2).deps)
@echo "Building $$@ ..."
$$(emcc.bin) -o $$@ $$(emcc_opt_full) $$(emcc.flags) \
$$(emcc.jsflags) \
-sENVIRONMENT=$$(emcc.environment.$(1)) \
$$(pre-post-sqlite3.flags.$(1)) $$(emcc.flags.sqlite3.$(1)) \
$$(cflags.common) $$(SQLITE_OPT) $$(cflags.wasm_extra_init) $$(sqlite3-wasm.cses)
@$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(2))
@case $(1) in \
-sENVIRONMENT=$$(emcc.environment.$(2)) \
$$(pre-post-$(1)-$(2).flags) \
$$(emcc.flags.$(1)) $$(emcc.flags.$(1).$(2)) \
$$(cflags.common) $$(SQLITE_OPT) \
$$(cflags.$(1)) $$(cflags.$(1).$(2)) \
$$(cflags.wasm_extra_init) $$(sqlite3-wasm.cfiles)
@$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(3))
@dotwasm=$$(basename $$@).wasm; \
chmod -x $$$$dotwasm; \
$(maybe-wasm-strip) $$$$dotwasm; \
case $(2) in \
bundler-friendly|node) \
echo "Patching $(3) for sqlite3.wasm..."; \
rm -f $$(dir.dout)/sqlite3-$(1).wasm; \
sed -i -e 's/sqlite3-$(1).wasm/sqlite3.wasm/g' $$@ || exit $$$$?; \
echo "Patching $$@ for $(1).wasm..."; \
rm -f $$$$dotwasm; \
dotwasm=; \
sed -i -e 's/$(1)-$(2).wasm/$(1).wasm/g' $$@ || exit $$$$?; \
;; \
esac
chmod -x $$(sqlite3.wasm)
$$(maybe-wasm-strip) $$(sqlite3.wasm)
@ls -la $@ $$(sqlite3.wasm)
all: $(4)
quick: $(4)
CLEAN_FILES += $(3) $(4)
esac; \
ls -la $$$$dotwasm $$@
all: $(5)
quick: $(5)
CLEAN_FILES += $(4) $(5)
endef
# ^^^ /SETUP_LIB_BUILD_MODE
########################################################################
@ -753,21 +767,24 @@ sqlite3-api-bundler-friendly.mjs := $(dir.dout)/sqlite3-api-bundler-friendly.mjs
sqlite3-bundler-friendly.mjs := $(dir.dout)/sqlite3-bundler-friendly.mjs
sqlite3-api-node.mjs := $(dir.dout)/sqlite3-api-node.mjs
sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs
# Maintenance reminder: careful not to introduce spaces around args $1, $2
#$(info $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,esm,1, $(sqlite3-api.mjs), $(sqlite3.mjs), \
#$(info $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0,\
$(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,esm,1,\
$(sqlite3-api.mjs), $(sqlite3.mjs), \
-Dtarget=es6-module, -sEXPORT_ES6 -sUSE_ES6_IMPORT_META))
$(eval $(call SETUP_LIB_BUILD_MODE,bundler-friendly,1,\
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,bundler-friendly,1,\
$(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\
$(c-pp.D.esm) -Dtarget=es6-bundler-friendly))
$(eval $(call SETUP_LIB_BUILD_MODE,node,1,\
$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,node,1,\
$(sqlite3-api-node.mjs),$(sqlite3-node.mjs),\
$(c-pp.D.bundler-friendly) -Dtarget=node))
$(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node))
# The various -D... values used by *.c-pp.js include:
#
# -Dtarget=es6-module: for all ESM module builds
#
# -Dtarget=node: for node.js builds
#
# -Dtarget=es6-module -Dtarget=es6-bundler-friendly: intended for
# "bundler-friendly" ESM module build. These have some restrictions
# on how URL() objects are constructed in some contexts: URLs which
@ -849,7 +866,7 @@ all: batch
# emcc.speedtest1.common = emcc flags used by multiple builds of speedtest1
# emcc.speedtest1 = emcc flags used by main build of speedtest1
emcc.speedtest1.common := $(emcc_opt_full)
emcc.speedtest1 :=
emcc.speedtest1 := -I. -I$(dir $(sqlite3.canonical.c))
emcc.speedtest1 += -sENVIRONMENT=web
emcc.speedtest1 += -sALLOW_MEMORY_GROWTH
emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
@ -892,22 +909,24 @@ $(EXPORTED_FUNCTIONS.speedtest1): $(EXPORTED_FUNCTIONS.api.main)
@{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api.main); } > $@
speedtest1.js := $(dir.dout)/speedtest1.js
speedtest1.wasm := $(dir.dout)/speedtest1.wasm
cflags.speedtest1 := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
speedtest1.cses := $(speedtest1.c) $(sqlite3-wasm.c)
emcc.flags.speedtest1-vanilla := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
speedtest1.cfiles := $(speedtest1.c) $(sqlite3-wasm.c)
$(eval $(call call-make-pre-post,speedtest1,vanilla))
$(speedtest1.js): $(MAKEFILE) $(speedtest1.cses) \
$(pre-post-speedtest1.deps.vanilla) \
$(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
$(pre-post-speedtest1-vanilla.deps) \
$(EXPORTED_FUNCTIONS.speedtest1)
@echo "Building $@ ..."
$(emcc.bin) \
$(emcc.speedtest1) -I$(dir $(sqlite3.canonical.c)) \
$(emcc.speedtest1) \
$(emcc.speedtest1.common) \
$(cflags.speedtest1) $(pre-post-speedtest1.flags.vanilla) \
$(emcc.flags.speedtest1-vanilla) $(pre-post-speedtest1-vanilla.flags) \
$(SQLITE_OPT) \
-USQLITE_C -DSQLITE_C=$(sqlite3.canonical.c) \
$(speedtest1.exit-runtime0) \
-o $@ $(speedtest1.cses) -lm
-o $@ $(speedtest1.cfiles) -lm
$(maybe-wasm-strip) $(speedtest1.wasm)
chmod -x $(speedtest1.wasm)
ls -la $@ $(speedtest1.wasm)
speedtest1: $(speedtest1.js)
@ -933,9 +952,9 @@ CLEAN_FILES += $(speedtest1.js) $(speedtest1.wasm)
#
# To create those, we filter tester1.c-pp.js with $(bin.c-pp)...
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.js))
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.esm)))
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.sqlite3-esm)))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1.html))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.esm)))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.sqlite3-esm)))
tester1: tester1.js tester1.mjs tester1.html tester1-esm.html
# Note that we do not include $(sqlite3-bundler-friendly.mjs) in this
# because bundlers are client-specific.
@ -981,6 +1000,8 @@ include fiddle.make
ifneq (,$(filter wasmfs,$(MAKECMDGOALS)))
wasmfs.enable ?= 1
else
# Unconditionally enable wasmfs for [dist]clean so that the wasmfs
# sub-make can clean up.
wasmfs.enable ?= $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
endif
ifeq (1,$(wasmfs.enable))

View File

@ -23,10 +23,7 @@ const toExportForESM =
impls which Emscripten installs at some point in the file above
this.
*/
const originalInit =
/* Maintenance reminder: DO NOT use `self.` here. It's correct
for non-ES6 Module cases but wrong for ES6 modules because those
resolve this symbol differently. */ sqlite3InitModule;
const originalInit = sqlite3InitModule;
if(!originalInit){
throw new Error("Expecting globalThis.sqlite3InitModule to be defined by the Emscripten build.");
}
@ -66,18 +63,16 @@ const toExportForESM =
//console.warn("Using replaced sqlite3InitModule()",globalThis.location);
return originalInit(...args).then((EmscriptenModule)=>{
if('undefined'!==typeof WorkerGlobalScope &&
(EmscriptenModule['ENVIRONMENT_IS_PTHREAD']
|| EmscriptenModule['_pthread_self']
|| 'function'===typeof threadAlert
|| globalThis?.location?.pathname?.endsWith?.('.worker.js')
)){
EmscriptenModule['ENVIRONMENT_IS_PTHREAD']){
/** Workaround for wasmfs-generated worker, which calls this
routine from each individual thread and requires that its
argument be returned. All of the criteria above are fragile,
based solely on inspection of the offending code, not public
Emscripten details. */
argument be returned. The conditional criteria above are
fragile, based solely on inspection of the offending code,
not public Emscripten details. */
//console.warn("sqlite3InitModule() returning E-module.",EmscriptenModule);
return EmscriptenModule;
}
//console.warn("sqlite3InitModule() returning sqlite3 object.");
const s = EmscriptenModule.sqlite3;
s.scriptInfo = initModuleState;
//console.warn("sqlite3.scriptInfo =",s.scriptInfo);
@ -124,5 +119,5 @@ const toExportForESM =
return globalThis.sqlite3InitModule /* required for ESM */;
})();
//#if target=es6-module
export default toExportForESM;
export { toExportForESM as default, toExportForESM as sqlite3InitModule }
//#endif

View File

@ -23,7 +23,7 @@ if('undefined' !== typeof Module){ // presumably an Emscripten build
const SABC = Object.assign(
Object.create(null), {
exports: Module['asm'],
memory: Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */
memory: Module.wasmMemory /* gets set if built with -sIMPORTED_MEMORY */
},
globalThis.sqlite3ApiConfig || {}
);

View File

@ -53,7 +53,7 @@
- `memory`[^1]: optional WebAssembly.Memory object, defaulting to
`exports.memory`. In Emscripten environments this should be set
to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be
to `Module.wasmMemory` if the build uses `-sIMPORTED_MEMORY`, or be
left undefined/falsy to default to `exports.memory` when using
WASM-exported memory.
@ -92,8 +92,8 @@
currently work due to incompatible Emscripten-side changes made
in the WASMFS+OPFS combination. This option is currently ignored.
[^1] = This property may optionally be a function, in which case this
function re-assigns calls that function to fetch the value,
[^1] = This property may optionally be a function, in which case
this function calls that function to fetch the value,
enabling delayed evaluation.
The returned object is the top-level sqlite3 namespace object.
@ -149,11 +149,6 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
config[k] = config[k]();
}
});
config.wasmOpfsDir =
/* 2022-12-17: WASMFS+OPFS can no longer be activated from the
main thread (aborts via a failed assert() if it's attempted),
which eliminates any(?) benefit to supporting it. */ false;
/**
The main sqlite3 binding API gets installed into this object,
mimicking the C API as closely as we can. The numerous members
@ -809,7 +804,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|| toss3("Missing API config.exports (WASM module exports)."),
/**
When Emscripten compiles with `-sIMPORT_MEMORY`, it
When Emscripten compiles with `-sIMPORTED_MEMORY`, it
initalizes the heap and imports it into wasm, as opposed to
the other way around. In this case, the memory is not
available via this.exports.memory.
@ -1177,31 +1172,31 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
/** State for sqlite3_wasmfs_opfs_dir(). */
let __wasmfsOpfsDir = undefined;
/**
2022-12-17: incompatible WASMFS changes have made WASMFS+OPFS
unavailable from the main thread, which eliminates the most
significant benefit of supporting WASMFS. This function is now a
no-op which always returns a falsy value. Before that change,
this function behaved as documented below (and how it will again
if we can find a compelling reason to support it).
If the wasm environment has a WASMFS/OPFS-backed persistent
storage directory, its path is returned by this function. If it
does not then it returns "" (noting that "" is a falsy value).
The first time this is called, this function inspects the current
environment to determine whether persistence support is available
and, if it is, enables it (if needed).
and, if it is, enables it (if needed). After the first call it
always returns the cached result.
This function currently only recognizes the WASMFS/OPFS storage
combination and its path refers to storage rooted in the
Emscripten-managed virtual filesystem.
If the returned string is not empty, any files stored under the
given path (recursively) are housed in OPFS storage. If the
returned string is empty, this particular persistent storage
option is not available on the client.
Though the mount point name returned by this function is intended
to remain stable, clients should not hard-coded it anywhere. Always call this function to get the path.
Note that this function is a no-op in must builds of this
library, as the WASMFS capability requires a custom
build.
*/
capi.sqlite3_wasmfs_opfs_dir = function(){
if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir;
// If we have no OPFS, there is no persistent dir
const pdir = config.wasmfsOpfsDir;
console.error("sqlite3_wasmfs_opfs_dir() can no longer work due "+
"to incompatible WASMFS changes. It will be removed.");
if(!pdir
|| !globalThis.FileSystemHandle
|| !globalThis.FileSystemDirectoryHandle
@ -1223,8 +1218,6 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
};
/**
Experimental and subject to change or removal.
Returns true if sqlite3.capi.sqlite3_wasmfs_opfs_dir() is a
non-empty string and the given name starts with (that string +
'/'), else returns false.
@ -1234,13 +1227,6 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
return (p && name) ? name.startsWith(p+'/') : false;
};
// This bit is highly arguable and is incompatible with the fiddle shell.
if(false && 0===wasm.exports.sqlite3_vfs_find(0)){
/* Assume that sqlite3_initialize() has not yet been called.
This will be the case in an SQLITE_OS_KV build. */
wasm.exports.sqlite3_initialize();
}
/**
Given an `sqlite3*`, an sqlite3_vfs name, and an optional db name
(defaulting to "main"), returns a truthy value (see below) if

View File

@ -118,11 +118,11 @@ const installOpfsVfs = function callee(options){
options.proxyUri = options.proxyUri();
}
const thePromise = new Promise(function(promiseResolve_, promiseReject_){
const loggers = {
0:sqlite3.config.error,
1:sqlite3.config.warn,
2:sqlite3.config.log
};
const loggers = [
sqlite3.config.error,
sqlite3.config.warn,
sqlite3.config.log
];
const logImpl = (level,...args)=>{
if(options.verbose>level) loggers[level]("OPFS syncer:",...args);
};
@ -191,8 +191,9 @@ const installOpfsVfs = function callee(options){
s.count = s.time = 0;
}
}/*metrics*/;
const opfsVfs = new sqlite3_vfs();
const opfsIoMethods = new sqlite3_io_methods();
const opfsVfs = new sqlite3_vfs()
.addOnDispose( ()=>opfsIoMethods.dispose());
let promiseWasRejected = undefined;
const promiseReject = (err)=>{
promiseWasRejected = true;
@ -241,11 +242,10 @@ const installOpfsVfs = function callee(options){
opfsVfs.$zName = wasm.allocCString("opfs");
// All C-side memory of opfsVfs is zeroed out, but just to be explicit:
opfsVfs.$xDlOpen = opfsVfs.$xDlError = opfsVfs.$xDlSym = opfsVfs.$xDlClose = null;
opfsVfs.ondispose = [
opfsVfs.addOnDispose(
'$zName', opfsVfs.$zName,
'cleanup default VFS wrapper', ()=>(dVfs ? dVfs.dispose() : null),
'cleanup opfsIoMethods', ()=>opfsIoMethods.dispose()
];
'cleanup default VFS wrapper', ()=>(dVfs ? dVfs.dispose() : null)
);
/**
Pedantic sidebar about opfsVfs.ondispose: the entries in that array
are items to clean up when opfsVfs.dispose() is called, but in this
@ -298,6 +298,7 @@ const installOpfsVfs = function callee(options){
lock contention to free up.
*/
state.asyncIdleWaitTime = 150;
/**
Whether the async counterpart should log exceptions to
the serialization channel. That produces a great deal of
@ -832,22 +833,19 @@ const installOpfsVfs = function callee(options){
/* If it turns out that we need to adjust for timezone, see:
https://stackoverflow.com/a/11760121/1458521 */
wasm.poke(pOut, 2440587.5 + (new Date().getTime()/86400000),
'double');
'double');
return 0;
},
xCurrentTimeInt64: function(pVfs,pOut){
// TODO: confirm that this calculation is correct
wasm.poke(pOut, (2440587.5 * 86400000) + new Date().getTime(),
'i64');
'i64');
return 0;
},
xDelete: function(pVfs, zName, doSyncDir){
mTimeStart('xDelete');
opRun('xDelete', wasm.cstrToJs(zName), doSyncDir, false);
/* We're ignoring errors because we cannot yet differentiate
between harmless and non-harmless failures. */
const rc = opRun('xDelete', wasm.cstrToJs(zName), doSyncDir, false);
mTimeEnd();
return 0;
return rc;
},
xFullPathname: function(pVfs,zName,nOut,pOut){
/* Until/unless we have some notion of "current dir"
@ -1089,7 +1087,7 @@ const installOpfsVfs = function callee(options){
propagate any exception on error, rather than returning false.
*/
opfsUtil.unlink = async function(fsEntryName, recursive = false,
throwOnError = false){
throwOnError = false){
try {
const [hDir, filenamePart] =
await opfsUtil.getDirForFilename(fsEntryName, false);
@ -1186,19 +1184,23 @@ const installOpfsVfs = function callee(options){
contention. */
sqlite3.capi.sqlite3_busy_timeout(oo1Db, 10000);
sqlite3.capi.sqlite3_exec(oo1Db, [
/* Truncate journal mode is faster than delete for
this vfs, per speedtest1. That gap seems to have closed with
Chrome version 108 or 109, but "persist" is very roughly 5-6%
faster than truncate in initial tests.
/* As of July 2023, the PERSIST journal mode on OPFS is
somewhat slower than DELETE or TRUNCATE (it was faster
before Chrome version 108 or 109). TRUNCATE and DELETE
have very similar performance on OPFS.
For later analysis: Roy Hashimoto notes that TRUNCATE
and PERSIST modes may decrease OPFS concurrency because
multiple connections can open the journal file in those
modes:
Roy Hashimoto notes that TRUNCATE and PERSIST modes may
decrease OPFS concurrency because multiple connections
can open the journal file in those modes:
https://github.com/rhashimoto/wa-sqlite/issues/68
Given that, and the fact that testing has not revealed
any appreciable difference between performance of
TRUNCATE and DELETE modes on OPFS, we currently (as of
2023-07-13) default to DELETE mode.
*/
"pragma journal_mode=persist;",
"pragma journal_mode=DELETE;",
/*
This vfs benefits hugely from cache on moderate/large
speedtest1 --size 50 and --size 100 workloads. We

View File

@ -1,69 +0,0 @@
/**
Dummy function stubs to get sqlite3.c compiling with
wasi-sdk. This requires, in addition:
-D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID
-lwasi-emulated-getpid
*/
typedef unsigned mode_t;
int fchmod(int fd, mode_t mode);
int fchmod(int fd, mode_t mode){
return (fd && mode) ? 0 : 0;
}
typedef unsigned uid_t;
typedef uid_t gid_t;
int fchown(int fd, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group){
return (fd && owner && group) ? 0 : 0;
}
uid_t geteuid(void);
uid_t geteuid(void){return 0;}
#if !defined(F_WRLCK)
enum {
F_WRLCK,
F_RDLCK,
F_GETLK,
F_SETLK,
F_UNLCK
};
#endif
#undef HAVE_PREAD
#include <wasi/api.h>
#define WASM__KEEP __attribute__((used))
#if 0
/**
wasi-sdk cannot build sqlite3's default VFS without at least the following
functions. They are apparently syscalls which clients have to implement or
otherwise obtain.
https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md
*/
environ_get
environ_sizes_get
clock_time_get
fd_close
fd_fdstat_get
fd_fdstat_set_flags
fd_filestat_get
fd_filestat_set_size
fd_pread
fd_prestat_get
fd_prestat_dir_name
fd_read
fd_seek
fd_sync
fd_write
path_create_directory
path_filestat_get
path_filestat_set_times
path_open
path_readlink
path_remove_directory
path_unlink_file
poll_oneoff
proc_exit
#endif

View File

@ -1656,25 +1656,11 @@ globalThis.WhWasmUtilInstaller = function(target){
? opt.callProxy : undefined;
}
/** If true, the constructor emits a warning. The intent is that
this be set to true after bootstrapping of the higher-level
client library is complete, to warn downstream clients that
they shouldn't be relying on this implemenation detail which
does not have a stable interface. */
static warnOnUse = false;
/** If true, convertArg() will FuncPtrAdapter.debugOut() when it
(un)installs a function binding to/from WASM. Note that
deinstallation of bindScope=transient bindings happens
via scopedAllocPop() so will not be output. */
static debugFuncInstall = false;
/** Function used for debug output. */
static debugOut = console.debug.bind(console);
static bindScopes = [
'transient', 'context', 'singleton', 'permanent'
];
/**
Note that static class members are defined outside of the class
to work around an emcc toolchain build problem: one of the
tools in emsdk v3.1.42 does not support the static keyword.
*/
/* Dummy impl. Overwritten per-instance as needed. */
contextKey(argv,argIndex){
@ -1761,6 +1747,26 @@ globalThis.WhWasmUtilInstaller = function(target){
}/*convertArg()*/
}/*FuncPtrAdapter*/;
/** If true, the constructor emits a warning. The intent is that
this be set to true after bootstrapping of the higher-level
client library is complete, to warn downstream clients that
they shouldn't be relying on this implemenation detail which
does not have a stable interface. */
xArg.FuncPtrAdapter.warnOnUse = false;
/** If true, convertArg() will FuncPtrAdapter.debugOut() when it
(un)installs a function binding to/from WASM. Note that
deinstallation of bindScope=transient bindings happens
via scopedAllocPop() so will not be output. */
xArg.FuncPtrAdapter.debugFuncInstall = false;
/** Function used for debug output. */
xArg.FuncPtrAdapter.debugOut = console.debug.bind(console);
xArg.FuncPtrAdapter.bindScopes = [
'transient', 'context', 'singleton', 'permanent'
];
const __xArgAdapterCheck =
(t)=>xArg.get(t) || toss("Argument adapter not found:",t);

View File

@ -93,8 +93,8 @@
<ul>
<li><a href='speedtest1.html'>speedtest1</a>: a main-thread WASM build of speedtest1.</li>
<li><a href='speedtest1.html?vfs=kvvfs'>speedtest1?vfs=kvvfs</a>: speedtest1 with the kvvfs.</li>
<li><a href='speedtest1-worker.html?size=25'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li>
<li><a href='speedtest1-worker.html?vfs=opfs&size=25'>speedtest1-worker?vfs=opfs</a>: speedtest1-worker with the
<li><a href='speedtest1-worker.html?size=15'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li>
<li><a href='speedtest1-worker.html?vfs=opfs&size=10'>speedtest1-worker?vfs=opfs</a>: speedtest1-worker with the
OPFS VFS preselected and configured for a moderate workload.</li>
</ul>
</li>
@ -117,18 +117,19 @@
</li>
</ul>
</li>
<!--li>WASMFS-specific tests which currently do not work due to incompatible changes
made to the WASMFS+OPFS combination.
<li><strong>WASMFS</strong>-specific tests which require that
the WASMFS build is available on this server (it is not by
default) and that this server emits the COOP/COEP headers.
<ul>
<li><a href='speedtest1-wasmfs.html?flags=--size,25'>speedtest1-wasmfs</a>:
<li><a href='scratchpad-wasmfs.html'>scratchpad-wasmfs</a>:
experimenting with WASMFS/OPFS-based persistence.
</li>
<li><a href='speedtest1-wasmfs.html?flags=--size,15'>speedtest1-wasmfs</a>:
a variant of speedtest1 built solely for the wasmfs/opfs
feature.</li>
<li><a href='scratchpad-wasmfs-main.html'>scratchpad-wasmfs-main</a>:
experimenting with WASMFS/OPFS-based persistence. Maintenance
reminder: we cannot currently (2022-09-15) load WASMFS in a
worker due to an Emscripten wasm loader limitation.</li>
feature.
</li>
</ul>
</li-->
</li>
<!--li><a href='x.html'></a></li-->
</ul>
</div>

View File

@ -1,70 +0,0 @@
/*
2022-05-22
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A basic test script for sqlite3-api.js. This file must be run in
main JS thread and sqlite3.js must have been loaded before it.
*/
'use strict';
(function(){
const toss = function(...args){throw new Error(args.join(' '))};
const log = console.log.bind(console),
warn = console.warn.bind(console),
error = console.error.bind(console);
const stdout = log;
const stderr = error;
const test1 = function(db){
db.exec("create table if not exists t(a);")
.transaction(function(db){
db.prepare("insert into t(a) values(?)")
.bind(new Date().getTime())
.stepFinalize();
stdout("Number of values in table t:",
db.selectValue("select count(*) from t"));
});
};
const runTests = function(sqlite3){
const capi = sqlite3.capi,
oo = sqlite3.oo1,
wasm = sqlite3.wasm;
stdout("Loaded sqlite3:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
const persistentDir = capi.sqlite3_wasmfs_opfs_dir();
if(persistentDir){
stdout("Persistent storage dir:",persistentDir);
}else{
stderr("No persistent storage available.");
}
const startTime = performance.now();
let db;
try {
db = new oo.DB(persistentDir+'/foo.db');
stdout("DB filename:",db.filename);
const banner1 = '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>',
banner2 = '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<';
[
test1
].forEach((f)=>{
const n = performance.now();
stdout(banner1,"Running",f.name+"()...");
f(db, sqlite3);
stdout(banner2,f.name+"() took ",(performance.now() - n),"ms");
});
}finally{
if(db) db.close();
}
stdout("Total test time:",(performance.now() - startTime),"ms");
};
sqlite3InitModule(self.sqlite3TestModule).then(runTests);
})();

View File

@ -10,20 +10,6 @@
</head>
<body>
<header id='titlebar'><span>sqlite3 WASMFS/OPFS Main-thread Scratchpad</span></header>
<!-- emscripten bits -->
<figure id="module-spinner">
<div class="spinner"></div>
<div class='center'><strong>Initializing app...</strong></div>
<div class='center'>
On a slow internet connection this may take a moment. If this
message displays for "a long time", intialization may have
failed and the JavaScript console may contain clues as to why.
</div>
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<p>Scratchpad/test app for the WASMF/OPFS integration in the
main window thread. This page requires that the sqlite3 API have
been built with WASMFS support. If OPFS support is available then
@ -33,8 +19,12 @@
<p>All stuff on this page happens in the dev console.</p>
<hr>
<div id='test-output'></div>
<script src="sqlite3-wasmfs.js"></script>
<script src="common/SqliteTestUtil.js"></script>
<script src="scratchpad-wasmfs-main.js"></script>
<script>
(function(){
const W = new Worker('scratchpad-wasmfs.mjs',{
type: 'module'
});
})();
</script>
</body>
</html>

View File

@ -0,0 +1,70 @@
/*
2022-05-22
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A basic test script for sqlite3-api.js. This file must be run in
main JS thread and sqlite3.js must have been loaded before it.
*/
import sqlite3InitModule from './jswasm/sqlite3-wasmfs.mjs';
//console.log('sqlite3InitModule =',sqlite3InitModule);
const toss = function(...args){throw new Error(args.join(' '))};
const log = console.log.bind(console),
warn = console.warn.bind(console),
error = console.error.bind(console);
const stdout = log;
const stderr = error;
const test1 = function(db){
db.exec("create table if not exists t(a);")
.transaction(function(db){
db.prepare("insert into t(a) values(?)")
.bind(new Date().getTime())
.stepFinalize();
stdout("Number of values in table t:",
db.selectValue("select count(*) from t"));
});
};
const runTests = function(sqlite3){
const capi = sqlite3.capi,
oo = sqlite3.oo1,
wasm = sqlite3.wasm;
stdout("Loaded module:",sqlite3);
stdout("Loaded sqlite3:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
const persistentDir = capi.sqlite3_wasmfs_opfs_dir();
if(persistentDir){
stdout("Persistent storage dir:",persistentDir);
}else{
stderr("No persistent storage available.");
}
const startTime = performance.now();
let db;
try {
db = new oo.DB(persistentDir+'/foo.db');
stdout("DB filename:",db.filename);
const banner1 = '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>',
banner2 = '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<';
[
test1
].forEach((f)=>{
const n = performance.now();
stdout(banner1,"Running",f.name+"()...");
f(db, sqlite3);
stdout(banner2,f.name+"() took ",(performance.now() - n),"ms");
});
}finally{
if(db) db.close();
}
stdout("Total test time:",(performance.now() - startTime),"ms");
};
sqlite3InitModule().then(runTests);

View File

@ -10,141 +10,46 @@
</head>
<body>
<header id='titlebar'><span>speedtest1-wasmfs.wasm</span></header>
<div>See also: <a href='speedtest1-worker.html'>A Worker-thread variant of this page.</a></div>
<!-- emscripten bits -->
<figure id="module-spinner">
<div class="spinner"></div>
<div class='center'><strong>Initializing app...</strong></div>
<div class='center'>
On a slow internet connection this may take a moment. If this
message displays for "a long time", intialization may have
failed and the JavaScript console may contain clues as to why.
</div>
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<div class='warning'>This page starts running the main exe when it loads, which will
block the UI until it finishes! Adding UI controls to manually configure and start it
are TODO.</div>
</div>
<div>See also: <a href='speedtest1-worker.html'>speedtest1-worker</a></div>
<div class='warning'>Achtung: running it with the dev tools open may
<em>drastically</em> slow it down. For faster results, keep the dev
tools closed when running it!
</div>
<div>Output is delayed/buffered because we cannot update the UI while the
speedtest is running. Output will appear below when ready...
<div id='test-output'></div>
<script src="common/SqliteTestUtil.js"></script>
<script src="speedtest1-wasmfs.js"></script>
<script>(function(){
/**
If this environment contains OPFS, this function initializes it and
returns the name of the dir on which OPFS is mounted, else it returns
an empty string.
*/
const wasmfsDir = function f(wasmUtil,dirName="/opfs"){
if(undefined !== f._) return f._;
if( !self.FileSystemHandle
|| !self.FileSystemDirectoryHandle
|| !self.FileSystemFileHandle){
return f._ = "";
}
try{
if(0===wasmUtil.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName
)){
return f._ = dirName;
}else{
return f._ = "";
}
}catch(e){
// sqlite3_wasm_init_wasmfs() is not available
return f._ = "";
}
};
wasmfsDir._ = undefined;
const eOut = document.querySelector('#test-output');
const log2 = function(cssClass,...args){
const ln = document.createElement('div');
if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' ')));
eOut.append(ln);
//this.e.output.lastElementChild.scrollIntoViewIfNeeded();
};
const logList = [];
const dumpLogList = function(){
logList.forEach((v)=>log2('',v));
logList.length = 0;
};
/* can't update DOM while speedtest is running unless we run
speedtest in a worker thread. */;
const log = (...args)=>{
console.log(...args);
logList.push(args.join(' '));
};
const logErr = function(...args){
console.error(...args);
logList.push('ERROR: '+args.join(' '));
};
const runTests = function(sqlite3){
console.log("Module inited.");
const wasm = sqlite3.wasm;
const __unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["*","string"]);
const unlink = (fn)=>__unlink(0,fn);
const pDir = wasmfsDir(wasm);
if(pDir) log2('',"Persistent storage:",pDir);
else{
log2('error',"Expecting persistent storage in this build.");
return;
}
const scope = wasm.scopedAllocPush();
const dbFile = pDir+"/speedtest1.db";
const urlParams = new URL(self.location.href).searchParams;
const argv = ["speedtest1"];
if(urlParams.has('flags')){
argv.push(...(urlParams.get('flags').split(',')));
let i = argv.indexOf('--vfs');
if(i>=0) argv.splice(i,2);
}else{
argv.push(
"--singlethread",
"--nomutex",
"--nosync",
"--nomemstat"
);
//"--memdb", // note that memdb trumps the filename arg
}
if(argv.indexOf('--memdb')>=0){
log2('error',"WARNING: --memdb flag trumps db filename.");
}
argv.push("--big-transactions"/*important for tests 410 and 510!*/,
dbFile);
console.log("argv =",argv);
// These log messages are not emitted to the UI until after main() returns. Fixing that
// requires moving the main() call and related cleanup into a timeout handler.
if(pDir) unlink(dbFile);
log2('',"Starting native app:\n ",argv.join(' '));
log2('',"This will take a while and the browser might warn about the runaway JS.",
"Give it time...");
logList.length = 0;
setTimeout(function(){
wasm.xCall('wasm_main', argv.length,
wasm.scopedAllocMainArgv(argv));
wasm.scopedAllocPop(scope);
if(pDir) unlink(dbFile);
logList.unshift("Done running native main(). Output:");
dumpLogList();
}, 25);
}/*runTests()*/;
self.sqlite3TestModule.print = log;
self.sqlite3TestModule.printErr = logErr;
sqlite3InitModule(self.sqlite3TestModule).then(runTests);
})();</script>
<script>
(function(){
const eOut = document.querySelector('#test-output');
const log2 = function(cssClass,...args){
const ln = document.createElement('div');
if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' ')));
eOut.append(ln);
//this.e.output.lastElementChild.scrollIntoViewIfNeeded();
};
/* can't update DOM while speedtest is running unless we run
speedtest in a worker thread. */;
const log = (...args)=>{
console.log(...args);
log2('',...args);
};
const logErr = function(...args){
console.error(...args);
log2('error',...args);
};
const W = new Worker(
'speedtest1-wasmfs.mjs'+globalThis.location.search,{
type: 'module'
});
log("Starting up...");
W.onmessage = function({data}){
switch(data.type){
case 'log': log(...data.args); break;
case 'logErr': logErr(...data.args); break;
default:
break;
}
};
})();
</script>
</body>
</html>

View File

@ -0,0 +1,90 @@
import sqlite3InitModule from './jswasm/speedtest1-wasmfs.mjs';
const wMsg = (type,...args)=>{
postMessage({type, args});
};
wMsg('log',"speedtest1-wasmfs starting...");
/**
If this environment contains OPFS, this function initializes it and
returns the name of the dir on which OPFS is mounted, else it returns
an empty string.
*/
const wasmfsDir = function f(wasmUtil,dirName="/opfs"){
if(undefined !== f._) return f._;
if( !self.FileSystemHandle
|| !self.FileSystemDirectoryHandle
|| !self.FileSystemFileHandle){
return f._ = "";
}
try{
if(0===wasmUtil.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName
)){
return f._ = dirName;
}else{
return f._ = "";
}
}catch(e){
// sqlite3_wasm_init_wasmfs() is not available
return f._ = "";
}
};
wasmfsDir._ = undefined;
const log = (...args)=>wMsg('log',...args);
const logErr = (...args)=>wMsg('logErr',...args);
const runTests = function(sqlite3){
console.log("Module inited.",sqlite3);
const wasm = sqlite3.wasm;
const __unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["*","string"]);
const unlink = (fn)=>__unlink(0,fn);
const pDir = wasmfsDir(wasm);
if(pDir) log("Persistent storage:",pDir);
else{
logErr("Expecting persistent storage in this build.");
return;
}
const scope = wasm.scopedAllocPush();
const dbFile = pDir+"/speedtest1.db";
const urlParams = new URL(self.location.href).searchParams;
const argv = ["speedtest1"];
if(urlParams.has('flags')){
argv.push(...(urlParams.get('flags').split(',')));
let i = argv.indexOf('--vfs');
if(i>=0) argv.splice(i,2);
}else{
argv.push(
"--singlethread",
"--nomutex",
//"--nosync",
"--nomemstat",
"--size", "10"
);
}
if(argv.indexOf('--memdb')>=0){
logErr("WARNING: --memdb flag trumps db filename.");
}
argv.push("--big-transactions"/*important for tests 410 and 510!*/,
dbFile);
//log("argv =",argv);
// These log messages are not emitted to the UI until after main() returns. Fixing that
// requires moving the main() call and related cleanup into a timeout handler.
if(pDir) unlink(dbFile);
log("Starting native app:\n ",argv.join(' '));
log("This will take a while and the browser might warn about the runaway JS.",
"Give it time...");
setTimeout(function(){
if(pDir) unlink(dbFile);
wasm.xCall('wasm_main', argv.length,
wasm.scopedAllocMainArgv(argv));
wasm.scopedAllocPop(scope);
if(pDir) unlink(dbFile);
log("Done running native main()");
}, 25);
}/*runTests()*/;
sqlite3InitModule({
print: log,
printErr: logErr
}).then(runTests);

View File

@ -259,7 +259,7 @@
flags["--utf16be"] = "Set text encoding to UTF-16BE";
flags["--utf16le"] = "Set text encoding to UTF-16LE";
flags["--verify"] = "Run additional verification steps.";
flags["--without"] = "rowid Use WITHOUT ROWID where appropriate";
flags["--without-rowid"] = "Use WITHOUT ROWID where appropriate";
const preselectedFlags = [
'--big-transactions',
'--singlethread'

View File

@ -45,7 +45,7 @@
*/
//#if target=es6-module
import {default as sqlite3InitModule} from './jswasm/sqlite3.mjs';
self.sqlite3InitModule = sqlite3InitModule;
globalThis.sqlite3InitModule = sqlite3InitModule;
//#else
'use strict';
//#endif
@ -57,7 +57,7 @@ self.sqlite3InitModule = sqlite3InitModule;
*/
let logClass;
/* Predicate for tests/groups. */
const isUIThread = ()=>(self.window===self && self.document);
const isUIThread = ()=>(globalThis.window===self && globalThis.document);
/* Predicate for tests/groups. */
const isWorker = ()=>!isUIThread();
/* Predicate for tests/groups. */
@ -3050,14 +3050,15 @@ self.sqlite3InitModule = sqlite3InitModule;
////////////////////////////////////////////////////////////////////////
log("Loading and initializing sqlite3 WASM module...");
if(0){
self.sqlite3ApiConfig = {
globalThis.sqlite3ApiConfig = {
debug: ()=>{},
log: ()=>{},
warn: ()=>{},
error: ()=>{}
}
}
if(!self.sqlite3InitModule && !isUIThread()){
//#ifnot target=es6-module
if(!globalThis.sqlite3InitModule && !isUIThread()){
/* Vanilla worker, as opposed to an ES6 module worker */
/*
If sqlite3.js is in a directory other than this script, in order
@ -3070,27 +3071,28 @@ self.sqlite3InitModule = sqlite3InitModule;
that's not needed.
URL arguments passed as part of the filename via importScripts()
are simply lost, and such scripts see the self.location of
are simply lost, and such scripts see the globalThis.location of
_this_ script.
*/
let sqlite3Js = 'sqlite3.js';
const urlParams = new URL(self.location.href).searchParams;
const urlParams = new URL(globalThis.location.href).searchParams;
if(urlParams.has('sqlite3.dir')){
sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
}
importScripts(sqlite3Js);
}
self.sqlite3InitModule.__isUnderTest =
//#endif
globalThis.sqlite3InitModule.__isUnderTest =
true /* disables certain API-internal cleanup so that we can
test internal APIs from here */;
self.sqlite3InitModule({
globalThis.sqlite3InitModule({
print: log,
printErr: error
}).then(function(sqlite3){
//console.log('sqlite3 =',sqlite3);
log("Done initializing WASM/JS bits. Running tests...");
sqlite3.config.warn("Installing sqlite3 bits as global S for local dev/test purposes.");
self.S = sqlite3;
globalThis.S = sqlite3;
capi = sqlite3.capi;
wasm = sqlite3.wasm;
log("sqlite3 version:",capi.sqlite3_libversion(),

View File

@ -6,14 +6,10 @@
# GNUMakefile.
########################################################################
MAKEFILE.wasmfs := $(lastword $(MAKEFILE_LIST))
$(warning The WASMFS build is currently incomplete.)
# Maintenance reminder: these particular files cannot be built into a
# subdirectory because loading of the auxiliary
# sqlite3-wasmfs.worker.js file it creates fails if sqlite3-wasmfs.js
# is loaded from any directory other than the one in which the
# containing HTML lives. Similarly, they cannot be loaded from a
# Worker to an Emscripten quirk regarding loading nested Workers.
dir.wasmfs := $(dir.wasm)
#dir.wasmfs := $(dir.wasm)
dir.wasmfs := $(dir.dout)
sqlite3-wasmfs.js := $(dir.wasmfs)/sqlite3-wasmfs.js
sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs
sqlite3-wasmfs.wasm := $(dir.wasmfs)/sqlite3-wasmfs.wasm
@ -28,105 +24,92 @@ CLEAN_FILES += $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.wasm) \
cflags.sqlite3-wasmfs :=
cflags.sqlite3-wasmfs += -std=c99 -fPIC
cflags.sqlite3-wasmfs += -pthread
cflags.sqlite3-wasmfs += $(cflags.speedtest1)
cflags.sqlite3-wasmfs += $(SQLITE_OPT) -DSQLITE_ENABLE_WASMFS
cflags.sqlite3-wasmfs += -DSQLITE_ENABLE_WASMFS
########################################################################
# emcc flags specific to building the final .js/.wasm file...
emcc.flags.sqlite3-wasmfs := -fPIC
emcc.flags.sqlite3-wasmfs += --no-entry
emcc.flags.sqlite3-wasmfs += --minify 0
emcc.flags.sqlite3-wasmfs += -sMODULARIZE
emcc.flags.sqlite3-wasmfs += -sEXPORT_NAME=$(sqlite3.js.init-func)
emcc.flags.sqlite3-wasmfs += -sSTRICT_JS
emcc.flags.sqlite3-wasmfs += -sDYNAMIC_EXECUTION=0
emcc.flags.sqlite3-wasmfs += -sNO_POLYFILL
emcc.flags.sqlite3-wasmfs += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
emcc.flags.sqlite3-wasmfs += -sEXPORTED_FUNCTIONS=@$(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api)
emcc.flags.sqlite3-wasmfs += -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory,allocateUTF8OnStack
emcc.flags.sqlite3-wasmfs :=
emcc.flags.sqlite3-wasmfs += \
-sEXPORTED_RUNTIME_METHODS=wasmMemory,allocateUTF8OnStack,stringToUTF8OnStack
# wasmMemory ==> for -sIMPORTED_MEMORY
# allocateUTF8OnStack ==> wasmfs internals
# *OnStack ==> wasmfs internals (leaky abstraction)
emcc.flags.sqlite3-wasmfs += -sUSE_CLOSURE_COMPILER=0
emcc.flags.sqlite3-wasmfs += -Wno-limited-postlink-optimizations
# ^^^^^ it likes to warn when we have "limited optimizations" via the -g3 flag.
emcc.flags.sqlite3-wasmfs += -sALLOW_TABLE_GROWTH
emcc.flags.sqlite3-wasmfs += -sSTACK_SIZE=512KB
emcc.flags.sqlite3-wasmfs += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
emcc.flags.sqlite3-wasmfs += -sMEMORY64=0
emcc.flags.sqlite3-wasmfs += -sIMPORTED_MEMORY
emcc.flags.sqlite3-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
# ^^^^ 64MB is not enough for WASMFS/OPFS test runs using batch-runner.js
sqlite3-wasmfs.fsflags := -pthread -sWASMFS \
-sPTHREAD_POOL_SIZE=2 -sENVIRONMENT=web,worker \
-sERROR_ON_UNDEFINED_SYMBOLS=0 -sLLD_REPORT_UNDEFINED
-sPTHREAD_POOL_SIZE=1 \
-sERROR_ON_UNDEFINED_SYMBOLS=0 -sLLD_REPORT_UNDEFINED
# ^^^^^ why undefined symbols are necessary for the wasmfs build is anyone's guess.
emcc.flags.sqlite3-wasmfs += $(sqlite3-wasmfs.fsflags)
#emcc.flags.sqlite3-wasmfs += -sALLOW_MEMORY_GROWTH
emcc.flags.sqlite3-wasmfs += -sALLOW_MEMORY_GROWTH=0
#^^^ using ALLOW_MEMORY_GROWTH produces a warning from emcc:
# USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code slowly,
# see https://github.com/WebAssembly/design/issues/1271 [-Wpthreads-mem-growth]
# And, indeed, it runs slowly if memory is permitted to grow.
emcc.flags.sqlite3-wasmfs.vanilla :=
emcc.flags.sqlite3-wasmfs.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
$(eval $(call call-make-pre-js,sqlite3-wasmfs,vanilla))
$(eval $(call call-make-pre-js,sqlite3-wasmfs,esm))
Xemcc.flags.sqlite3-wasmfs.vanilla += \
$(pre-post-common.flags.vanilla) \
$(pre-post-sqlite3-wasmfs.flags.vanilla)
Xemcc.flags.sqlite3-wasmfs.esm += \
$(pre-post-common.flags.esm) \
$(pre-post-sqlite3-wasmfs.flags.esm)
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(sqlite3-wasm.c) \
$(EXPORTED_FUNCTIONS.api) $(MAKEFILE) $(MAKEFILE.wasmfs)
$(sqlite3-wasmfs.js): $(pre-post-sqlite3-wasmfs.deps.vanilla)
$(sqlite3-wasmfs.mjs): $(pre-post-sqlite3-wasmfs.deps.esm)
# SQLITE3-WASMFS.xJS.RECIPE is the wasmfs-specific counterpart
# of SQLITE3.xJS.RECIPE from the main makefile.
define SQLITE3-WASMFS.xJS.RECIPE
@echo "Building $@ ..."
$(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \
$(cflags.sqlite3-wasmfs) \
$(emcc.flags.sqlite3-wasmfs) $(emcc.flags.sqlite3-wasmfs.$(1)) \
$(pre-post-sqlite3-wasmfs.flags.$(1)) \
$(sqlite3-wasm.c)
@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(1))
chmod -x $(sqlite3-wasmfs.wasm)
$(maybe-wasm-strip) $(sqlite3-wasmfs.wasm)
@ls -la $(sqlite3-wasmfs.wasm) sqlite3-wasmfs*js
endef
$(sqlite3-wasmfs.js):
$(call SQLITE3-WASMFS.xJS.RECIPE,vanilla)
$(sqlite3-wasmfs.mjs): $(sqlite3-wasmfs.js)
$(call SQLITE3-WASMFS.xJS.RECIPE,esm)
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.js)
wasmfs: $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs)
#emcc.flags.sqlite3-wasmfs.vanilla :=
#emcc.flags.sqlite3-wasmfs.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
sqlite3-api.mjs.wasmfs := $(dir.tmp)/sqlite3-api-wasmfs.mjs
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3-wasmfs,esm,1,\
$(sqlite3-api.mjs.wasmfs), $(sqlite3-wasmfs.mjs),\
$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs,\
-sEXPORT_ES6 -sUSE_ES6_IMPORT_META\
))
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(MAKEFILE.wasmfs)
########################################################################
# Build quirk: we cannot build BOTH .js and .mjs with our current
# build infrastructure because the supplemental *.worker.js files get
# generated with the name of the main module file
# ($(sqlite3-wasmfs.{js,mjs})) hard-coded in them. Thus the last one
# to get built gets the *.worker.js files mapped to it. In order to
# build both modes they would need to have distinct base names or
# output directories. "The problem" with giving them distinct base
# names is that it means that the corresponding .wasm file is also
# built/saved multiple times.
#
wasmfs.build.ext := mjs
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(SOAP.js.bld)
ifeq (js,$(wasmfs.build.ext))
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.js)
wasmfs: $(sqlite3-wasmfs.js)
else
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.mjs)
wasmfs: $(sqlite3-wasmfs.mjs)
endif
#all: wasmfs
########################################################################
# speedtest1 for wasmfs.
speedtest1-wasmfs.js := $(dir.wasmfs)/speedtest1-wasmfs.js
speedtest1-wasmfs.wasm := $(subst .js,.wasm,$(speedtest1-wasmfs.js))
speedtest1-wasmfs.mjs := $(dir.wasmfs)/speedtest1-wasmfs.mjs
speedtest1-wasmfs.wasm := $(subst .mjs,.wasm,$(speedtest1-wasmfs.mjs))
emcc.flags.speedtest1-wasmfs := $(sqlite3-wasmfs.fsflags)
emcc.flags.speedtest1-wasmfs += $(SQLITE_OPT) -DSQLITE_ENABLE_WASMFS
emcc.flags.speedtest1-wasmfs += $(SQLITE_OPT)
emcc.flags.speedtest1-wasmfs += -sALLOW_MEMORY_GROWTH=0
emcc.flags.speedtest1-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
#$(eval $(call call-make-pre-js,speedtest1-wasmfs,vanilla))
$(speedtest1-wasmfs.js): $(speedtest1.cses) $(sqlite3-wasmfs.js) \
#$(eval $(call call-make-pre-js,speedtest1-wasmfs,ems))
$(speedtest1-wasmfs.mjs): $(speedtest1.cfiles) $(sqlite3-wasmfs.js) \
$(MAKEFILE) $(MAKEFILE.wasmfs) \
$(pre-post-sqlite3-wasmfs.deps) \
$(pre-post-sqlite3-wasmfs-esm.deps) \
$(EXPORTED_FUNCTIONS.speedtest1)
@echo "Building $@ ..."
$(emcc.bin) \
$(emcc.speedtest1.common) $(emcc.flags.speedtest1-wasmfs) \
$(pre-post-sqlite3-wasmfs.flags.vanilla) \
$(pre-post-sqlite3-wasmfs-esm.flags) \
$(cflags.common) \
$(cflags.sqlite3-wasmfs) \
-o $@ $(speedtest1.cses) -lm
$(emcc.speedtest1.common) \
$(emcc.flags.speedtest1-vanilla) \
$(emcc.flags.sqlite3-wasmfs) \
$(emcc.flags.speedtest1-wasmfs) \
-o $@ $(speedtest1.cfiles) -lm
@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1)
$(maybe-wasm-strip) $(speedtest1-wasmfs.wasm)
chmod -x $(speedtest1-wasmfs.wasm)
ls -la $@ $(speedtest1-wasmfs.wasm)
#speedtest1: $(speedtest1-wasmfs.js)
wasmfs: $(speedtest1-wasmfs.js)
CLEAN_FILES += $(speedtest1-wasmfs.js) $(speedtest1-wasmfs.wasm) \
$(subst .js,.worker.js,$(speedtest1-wasmfs.js))
wasmfs: $(speedtest1-wasmfs.mjs)
CLEAN_FILES += $(speedtest1-wasmfs.mjs) $(speedtest1-wasmfs.wasm) \
$(subst .js,.worker.js,$(speedtest1-wasmfs.mjs))
# end speedtest1.js
########################################################################

View File

@ -1,5 +1,5 @@
C Store\slarge\stombstone\shash\stables\sin\smultiple\sdatabase\srecords.\sEnsure\sthe\ssame\shash\stables\shandle\srowid\s0.
D 2023-07-15T18:57:57.087
C Merge\strunk\schanges\sinto\sthis\sbranch.
D 2023-07-17T11:47:42.362
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -483,28 +483,27 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile 38700d5074af690f004e4e5f3533164ab49693b9d0832929c4ecf97a0bc09494
F ext/wasm/GNUmakefile 74e351ff45b4061cfed8df237d301819a04182ae304a99118883b064baa25fc2
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
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 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54
F ext/wasm/api/extern-post-js.c-pp.js 393ab78b807da94096eae1a68bfddb999a2299936a185d910162fe87a57a9a3a
F ext/wasm/api/extern-post-js.c-pp.js 116749b7e55b7519129de06d3d353e19df68cfb24b12204aa4dc30c9a83023fe
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08902f15c34720ee4a1
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
F ext/wasm/api/sqlite3-api-cleanup.js cc21e3486da748463e02bbe51e2464c6ac136587cdfd5aa00cd0b5385f6ca808
F ext/wasm/api/sqlite3-api-cleanup.js 23ceec5ef74a0e649b19694ca985fd89e335771e21f24f50df352a626a8c81bf
F ext/wasm/api/sqlite3-api-glue.js f1b2dcb944de5138bb5bd9a1559d2e76a4f3ec25260963d709e8237476688803
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
F ext/wasm/api/sqlite3-api-prologue.js 17f4ec398ba34c5c666fea8e8c4eb82064a35b302f2f2eb355283cd8d3f68ed5
F ext/wasm/api/sqlite3-api-prologue.js 7d1c1ef59b9dcc42ad3a9cec9da972c42e29316a270cd126e7f660509b09027b
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 961bbc3ccc1fa4e91d6519a96e8811ad7ae60173bd969fee7775dacb6eee1da2
F ext/wasm/api/sqlite3-v-helper.js e5c202a9ecde9ef818536d3f5faf26c03a1a9f5192b1ddea8bdabf30d75ef487
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 05f2563ddebfdc7a0f0ac0eb7cb381bb72043299aae1600ba9367c12f52b3fcc
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 891f3a18d9ac9b0422b32fd975319dfcd0af5a8ca392f0cce850524e51b49c87
F ext/wasm/api/sqlite3-wasm.c 12a096d8e58a0af0589142bae5a3c27a0c7e19846755a1a37d2c206352fbedda
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
@ -514,7 +513,7 @@ F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
F ext/wasm/common/whwasmutil.js 03407d7b61b817fd135c82401987e56688a45ee4d6b9c0eced160c0000d6e4c2
F ext/wasm/common/whwasmutil.js ae263dec9d7384f4c530f324b99d00516a4d6f26424372daee65031e00eb49b3
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
@ -532,14 +531,15 @@ F ext/wasm/fiddle/fiddle-worker.js 163d6139a93fab4bcb72064923df050d4e7c0ff0d8aa0
F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/index-dist.html 22379774f0ad4edcaaa8cf9c674c82e794cc557719a8addabed74eb8069d412e
F ext/wasm/index.html dd900891844caebd9cadbddd704f66bd841d7c12fd69ce5af490e2c10fb49f45
F ext/wasm/index.html b768e8659b4fe311912e54d42906449d51c0f84b7f036cca47ec1f93bf3f91de
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
F ext/wasm/scratchpad-wasmfs-main.js 4c140457f4d6da9d646a49addd91edb6e9ad1643c6c48e3258b5bce24725dc18
F ext/wasm/speedtest1-wasmfs.html 7a301f4f5b6ad4f5d37fd6e7ca03a2f5d5547fd289da60a39075a93d7646d354
F ext/wasm/speedtest1-worker.html 82869822e641c1bef3ec0cd2d7d2b6a42d0b4f68a7b160fb2e1dd0b523940a9b
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 w ext/wasm/scratchpad-wasmfs-main.html
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 w ext/wasm/scratchpad-wasmfs-main.js
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe
F ext/wasm/speedtest1-worker.html 97c2bf5f8534091ce718de05801090d5a80c3f13575996f095ba23638e1bdca0
F ext/wasm/speedtest1-worker.js 13b57c4a41729678a1194014afec2bd5b94435dcfc8d1039dfa9a533ac819ee1
F ext/wasm/speedtest1.html ff048b4a623aa192e83e143e48f1ce2a899846dd42c023fdedc8772b6e3f07da
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
@ -549,12 +549,12 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
F ext/wasm/tester1.c-pp.js 1a05497ae2b2fcca008d43b37072f9b841e1c970c06c01eb0faf675db567bfc8
F ext/wasm/tester1.c-pp.js 4420eb97b6b4fc79e4e156b4b8010dd9f373365f4230dd76d823fb04ce28ffde
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
F ext/wasm/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5
F ext/wasm/wasmfs.make cf9a68162d92ca2bcb0b9528b244cb36d5cc2d84ccc9c2d398461927d6e75aea
F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966f1bc16a
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
@ -577,7 +577,7 @@ F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
F src/btree.c c9400cc1509116a29120dc06feb00ca7e26b5a4a6dba80758b1ba109d8fce5a4
F src/btree.c 2281facb0531d53fb42c03d1f32bc1b5903564d782ec5ff4ffc63171d960e2aa
F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
F src/btreeInt.h 3b4eff7155c0cea6971dc51f62e3529934a15a6640ec607dd42a767e379cb3a9
F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4
@ -643,7 +643,7 @@ F src/shell.c.in d320d8a13636de06d777cc1eab981caca304e175464e98183cf4ea68d93db81
F src/sqlite.h.in f999ef3642f381d69679b2516b430dbcb6c5a2a951b7f5e43dc4751b474a5774
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
F src/sqliteInt.h 002a6c3e24752d123468c5d948a80e2cd4acf01badce268f9dd98b581cd7bb96
F src/sqliteInt.h dcb1a885e8b6cb78df618944b89d44361a99d0fe33e1bba2c150a855f7dc5599
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@ -720,7 +720,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac
F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c cbfeeb7415baa545efa244dd34bb5af4ae953a206fed720c6fa7f1ef763ec122
F src/wal.c dd843f619ac60d5dadab7109cf402432ba74dde0c301505fd1c202add07659e3
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c 2dc708cf8b6a691fb79f16bbc46567497ee6f991043318d421e294b2da114d93
@ -2044,8 +2044,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 0e801f11cd2d50fc710a80c2b3b805c7801e660cff1bcc87be89133d43796524
R 681d2015e734a53885da51bd1dfb0cfa
P 4410e60d0c76e057ee962124f9239c6e17fd5ccafdbb4d9b703448eabd7781e3 984d491eb3fe06f714bf07d6873321f3992a072812b46508e599bfefd39dff3e
R 3a33d523b0a231ecfa8d84bbc59989ba
U dan
Z bb27d80790c5d5605515450ca29c8287
Z cf32871cae7a0d476c03b4d509e36da6
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
4410e60d0c76e057ee962124f9239c6e17fd5ccafdbb4d9b703448eabd7781e3
c4fb2f2ea0afe638fd7cffd89fbdb0a91589577c6f8299c7bbc17ac121be518b

View File

@ -1534,7 +1534,7 @@ static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload ){
Pgno ovfl;
if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
if( SQLITE_OVERFLOW(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
testcase( pSrc!=pPage );
*pRC = SQLITE_CORRUPT_BKPT;
return;
@ -8695,7 +8695,7 @@ static int balance_nonroot(
assert( iOvflSpace <= (int)pBt->pageSize );
for(k=0; ALWAYS(k<NB*2) && b.ixNx[k]<=j; k++){}
pSrcEnd = b.apEnd[k];
if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}

View File

@ -889,8 +889,31 @@ typedef INT16_TYPE LogEst;
** the end of buffer S. This macro returns true if P points to something
** contained within the buffer S.
*/
#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
/*
** P is one byte past the end of a large buffer. Return true if a span of bytes
** between S..E crosses the end of that buffer. In other words, return true
** if the sub-buffer S..E-1 overflows the buffer show last byte is P-1.
**
** S is the start of the span. E is one byte past the end of end of span.
**
** P
** |-----------------| FALSE
** |-------|
** S E
**
** P
** |-----------------|
** |-------| TRUE
** S E
**
** P
** |-----------------|
** |-------| FALSE
** S E
*/
#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P)))
/*
** Macros to determine whether the machine is big or little endian,

View File

@ -1818,23 +1818,15 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
nByte = sizeof(WalIterator)
+ (nSegment-1)*sizeof(struct WalSegment)
+ iLast*sizeof(ht_slot);
p = (WalIterator *)sqlite3_malloc64(nByte);
p = (WalIterator *)sqlite3_malloc64(nByte
+ sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
);
if( !p ){
return SQLITE_NOMEM_BKPT;
}
memset(p, 0, nByte);
p->nSegment = nSegment;
/* Allocate temporary space used by the merge-sort routine. This block
** of memory will be freed before this function returns.
*/
aTmp = (ht_slot *)sqlite3_malloc64(
sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
);
if( !aTmp ){
rc = SQLITE_NOMEM_BKPT;
}
aTmp = (ht_slot*)&(((u8*)p)[nByte]);
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
WalHashLoc sLoc;
@ -1862,8 +1854,6 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
}
}
sqlite3_free(aTmp);
if( rc!=SQLITE_OK ){
walIteratorFree(p);
p = 0;