1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-24 09:53:10 +03:00

Diverse cleanups and docs in the JS and kvvfs pieces. Functional changes: (A) ensure that the 'i32' JS/WASM func arg/result conversion works properly with a 64-bit-memory WASM build (which we neither use nor test but [https://webassembly.org/news/2025-09-17-wasm-3.0/ | the newly-ratified WASM 3.0] brings within potential reach). (B) Fix sqlite3_js_posix_create_file() to not deallocate its input array if the client passes in raw memory (the library has never used it that way but the API permits it).

FossilOrigin-Name: 79af65a694fbbb3d501fb2ebd835c259ca644e0dafdd71eeb9f0a7c0e9128a1e
This commit is contained in:
stephan
2025-09-19 17:24:47 +00:00
parent 194d6edeb6
commit d4cc844a2b
9 changed files with 171 additions and 141 deletions

View File

@@ -254,10 +254,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Then pass pAuxDtor as the final argument to appropriate
sqlite3_set_auxdata() calls.
Note that versions prior to 3.49.0 ostensibly had automatic
Prior to 3.49.0 this binding ostensibly had automatic
function conversion here but a typo prevented it from
working. Rather than fix it, it was removed because testing the
fix brought the huge potential for memory leaks to the
working. Rather than fix it, it was removed because testing
the fix brought the huge potential for memory leaks to the
forefront.
*/
["sqlite3_set_auxdata", undefined, [
@@ -323,7 +323,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
/* This list gets extended below */
/* This list gets extended with optional pieces below */
]/*.core*/,
/**
Functions which require BigInt (int64) support are separated
@@ -375,7 +375,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
]],
["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
["sqlite3_value_int64","i64", "sqlite3_value*"]
/* This list gets extended below */
/* This list gets extended with optional pieces below */
]/*.int64*/,
/**
Functions which are intended solely for API-internal use by the
@@ -435,12 +435,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
name: "sqlite3_set_authorizer::xAuth",
signature: "i(pi"+"ssss)",
contextKey: (argv, argIndex)=>argv[0/*(sqlite3*)*/],
/**
We use callProxy here to ensure (A) that exceptions
thrown from callback() have well-defined behavior and (B)
that its result is coerced to an integer.
*/
callProxy: (callback)=>{
return (pV, iCode, s0, s1, s2, s3)=>{
try{
s0 = s0 && wasm.cstrToJs(s0); s1 = s1 && wasm.cstrToJs(s1);
s2 = s2 && wasm.cstrToJs(s2); s3 = s3 && wasm.cstrToJs(s3);
return callback(pV, iCode, s0, s1, s2, s3) || 0;
return callback(pV, iCode, s0, s1, s2, s3) | 0;
}catch(e){
return e.resultCode || capi.SQLITE_ERROR;
}
@@ -470,12 +475,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
//#if enable-see
if( !!wasm.exports.sqlite3_key_v2 ){
/**
This code is capable of using an SEE build but note that an SEE
WASM build is generally incompatible with SEE's license
conditions. It is permitted for use internally in organizations
which have licensed SEE, but not for public sites because
exposing an SEE build of sqlite3.wasm effectively provides all
clients with a working copy of the commercial SEE code.
This code is capable of using an SEE build but an SEE WASM
build is generally incompatible with SEE's license conditions.
The project's official stance on WASM builds of SEE is: it is
permitted for use internally within organizations which have
licensed SEE, but not for public sites because exposing an SEE
build of sqlite3.wasm effectively provides all clients with a
working copy of SEE.
*/
bindingSignatures.core.push(
["sqlite3_key", "int", "sqlite3*", "string", "int"],
@@ -496,12 +502,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
/*["sqlite3_vtab_config" is variadic and requires a hand-written
proxy.] */
["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"],
["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"],
/*["sqlite3_vtab_config" is variadic and requires a hand-written
proxy.] */
["sqlite3_vtab_nochange","int", "sqlite3_context*"],
["sqlite3_vtab_on_conflict","int", "sqlite3*"],
["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
@@ -713,7 +719,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}/*session/changeset APIs*/
/**
Install JS<->C struct bindings for the non-opaque struct types we
Prepare JS<->C struct bindings for the non-opaque struct types we
need...
*/
sqlite3.StructBinder = globalThis.Jaccwabyt({
@@ -722,7 +728,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
dealloc: wasm.dealloc,
bigIntEnabled: wasm.bigIntEnabled,
memberPrefix: /* Never change this: this prefix is baked into any
amount of code and client-facing docs. */ '$'
amount of code and client-facing docs. (Much
later: it probably should have been '$$', but see
the previous sentence.) */ '$'
});
delete globalThis.Jaccwabyt;
@@ -745,16 +753,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
- Anything else: gets coerced to a JS string for use as a map
key. If a matching entry is found (as described next), it is
returned, else wasm.allocCString() is used to create a a new
string, map its pointer to (''+v) for the remainder of the
application's life, and returns that pointer value for this
call and all future calls which are passed a
string, map its pointer to a copy of (''+v) for the remainder
of the application's life, and returns that pointer value for
this call and all future calls which are passed a
string-equivalent argument.
Use case: sqlite3_bind_pointer() and sqlite3_result_pointer()
call for "a static string and preferably a string
literal." This converter is used to ensure that the string
value seen by those functions is long-lived and behaves as they
need it to.
Use case: sqlite3_bind_pointer(), sqlite3_result_pointer(), and
sqlite3_value_pointer() call for "a static string and
preferably a string literal". This converter is used to ensure
that the string value seen by those functions is long-lived and
behaves as they need it to, at the cost of a one-time leak of
each distinct key.
*/
wasm.xWrap.argAdapter(
'string:static',
@@ -822,6 +831,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
);
}
/**
Alias `T*` to `*` for return type conversions for common T
types, primarily to improve legibility of their binding
signatures.
*/
const __xRcPtr = wasm.xWrap.resultAdapter('*');
wasm.xWrap.resultAdapter('sqlite3*', __xRcPtr)
('sqlite3_context*', __xRcPtr)
@@ -834,15 +848,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Populate api object with sqlite3_...() by binding the "raw" wasm
exports into type-converting proxies using wasm.xWrap().
*/
if(0 === wasm.exports.sqlite3_step.length){
/* This environment wraps exports in nullary functions, which means
we must disable the arg-count validation we otherwise perform
on the wrappers. */
wasm.xWrap.doArgcCheck = false;
sqlite3.config.warn(
"Disabling sqlite3.wasm.xWrap.doArgcCheck due to environmental quirks."
);
}
for(const e of bindingSignatures.core){
capi[e[0]] = wasm.xWrap.apply(null, e);
}
@@ -854,18 +859,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
wasm.bigIntEnabled is true, install a bogus impl which throws
if called when bigIntEnabled is false. The alternative would be
to elide these functions altogether, which seems likely to
cause more confusion. */
const fI64Disabled = function(fname){
return ()=>toss(fname+"() is unavailable due to lack",
"of BigInt support in this build.");
};
cause more confusion, as documented APIs would resolve to the
undefined value in incompatible builds. */
for(const e of bindingSignatures.int64){
capi[e[0]] = wasm.bigIntEnabled
? wasm.xWrap.apply(null, e)
: fI64Disabled(e[0]);
: ()=>toss(e[0]+"() is unavailable due to lack",
"of BigInt support in this build.");
}
/* We don't need these anymore... */
/* We're done with bindingSignatures but it's const, so... */
delete bindingSignatures.core;
delete bindingSignatures.int64;
delete bindingSignatures.wasmInternal;
@@ -949,6 +952,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
string, or undefined if no such mapping is found.
*/
capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc];
/* Bind all registered C-side structs... */
const notThese = Object.assign(Object.create(null),{
// For each struct to NOT register, map its name to true:
@@ -968,7 +972,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
if(capi.sqlite3_index_info){
/* Move these inner structs into sqlite3_index_info. Binding
** them to WASM requires that we create global-scope structs to
** them to WASM requires that we create top-level structs to
** model them with, but those are no longer needed after we've
** passed them to StructBinder. */
for(const k of ['sqlite3_index_constraint',

View File

@@ -747,12 +747,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
closed when onclose.after is called. If this db is not opened
when close() is called, neither of the handlers are called. Any
exceptions the handlers throw are ignored because "destructors
must not throw."
must not throw".
Note that garbage collection of a db handle, if it happens at
all, will never trigger close(), so onclose handlers are not a
reliable way to implement close-time cleanup or maintenance of
a db.
Garbage collection of a db handle, if it happens at all, will
never trigger close(), so onclose handlers are not a reliable
way to implement close-time cleanup or maintenance of a db.
If this instance was created using DB.wrapHandle() and does not
own this.pointer then it does not close the db handle but it

View File

@@ -1046,10 +1046,16 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
}/*compileOptionUsed()*/;
/**
sqlite3.wasm.pstack (pseudo-stack) holds a special-case
stack-style allocator intended only for use with _small_ data of
not more than (in total) a few kb in size, managed as if it were
stack-based.
sqlite3.wasm.pstack (pseudo-stack) holds a special-case intended
solely for short-lived, small data. In practice, it's primarily
used to allocate output pointers. It mus not be used for any
memory which needs to outlive the scope in which it's obtained
from pstack.
The library guarantees only that a minimum of 2kb are available
in this allocator, and it may provide more (it's a build-time
value). pstack.quota and pstack.remaining can be used to get the
total resp. remaining amount of memory.
It has only a single intended usage:
@@ -1081,6 +1087,9 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
Sets the current pstack position to the given pointer. Results
are undefined if the passed-in value did not come from
this.pointer.
In debug builds this may trigger an assert() in the WASM
environment if passed an illegal value.
*/
restore: wasm.exports.sqlite3__wasm_pstack_restore,
/**
@@ -1186,7 +1195,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
configurable: false, iterable: true, writeable: false,
get: wasm.exports.sqlite3__wasm_pstack_ptr
//Whether or not a setter as an alternative to restore() is
//clearer or would just lead to confusion is unclear.
//clearer or would just lead to confusion or misuse is unclear.
//set: wasm.exports.sqlite3__wasm_pstack_restore
},
/**
@@ -1209,7 +1218,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
})/*wasm.pstack properties*/;
capi.sqlite3_randomness = (...args)=>{
if(1===args.length && util.isTypedArray(args[0])
if(1===args.length
&& util.isTypedArray(args[0])
&& 1===args[0].BYTES_PER_ELEMENT){
const ta = args[0];
if(0===ta.byteLength){
@@ -1231,7 +1241,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
offset += j;
} while(n > 0);
}catch(e){
console.error("Highly unexpected (and ignored!) "+
config.error("Highly unexpected (and ignored!) "+
"exception in sqlite3_randomness():",e);
}finally{
wasm.pstack.restore(stack);
@@ -1249,22 +1259,21 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
does not then it returns "" (noting that "" is a falsy value).
The first time this is called, this function inspects the current
environment to determine whether persistence support is available
and, if it is, enables it (if needed). After the first call it
always returns the cached result.
environment to determine whether WASMFS persistence support is
available and, if it is, enables it (if needed). After the first
call it always returns the cached result.
If the returned string is not empty, any files stored under the
given path (recursively) are housed in OPFS storage. If the
returned path (recursively) are housed in OPFS storage. If the
returned string is empty, this particular persistent storage
option is not available on the client.
Though the mount point name returned by this function is intended
to remain stable, clients should not hard-coded it
anywhere. Always call this function to get the path.
to remain stable, clients should not hard-coded it anywhere.
Always call this function to get the path.
Note that this function is a no-op in most builds of this
library, as the WASMFS capability requires a custom
build.
This function is a no-op in most builds of this library, as the
WASMFS capability requires a custom build.
*/
capi.sqlite3_wasmfs_opfs_dir = function(){
if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir;
@@ -1273,7 +1282,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
if(!pdir
|| !globalThis.FileSystemHandle
|| !globalThis.FileSystemDirectoryHandle
|| !globalThis.FileSystemFileHandle){
|| !globalThis.FileSystemFileHandle
|| !wasm.exports.sqlite3__wasm_init_wasmfs){
return __wasmfsOpfsDir = "";
}
try{
@@ -1305,11 +1315,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
(defaulting to "main"), returns a truthy value (see below) if
that db uses that VFS, else returns false. If pDb is falsy then
the 3rd argument is ignored and this function returns a truthy
value if the default VFS name matches that of the 2nd
argument. Results are undefined if pDb is truthy but refers to an
invalid pointer. The 3rd argument specifies the database name of
the given database connection to check, defaulting to the main
db.
value if the default VFS name matches that of the 2nd argument.
Results are undefined if pDb is truthy but refers to an invalid
pointer. The 3rd argument specifies the database name of the
given database connection to check, defaulting to the main db.
The 2nd and 3rd arguments may either be a JS string or a WASM
C-string. If the 2nd argument is a NULL WASM pointer, the default
@@ -1320,9 +1329,9 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
object.
To permit safe use of this function from APIs which may be called
via the C stack (like SQL UDFs), this function does not throw: if
bad arguments cause a conversion error when passing into
wasm-space, false is returned.
via C (like SQL UDFs), this function does not throw: if bad
arguments cause a conversion error when passing into wasm-space,
false is returned.
*/
capi.sqlite3_js_db_uses_vfs = function(pDb,vfsName,dbName=0){
try{
@@ -1437,8 +1446,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
It may behave differently in other environments.
The first argument must be either a JS string or WASM C-string
holding the filename. Note that this routine does _not_ create
intermediary directories if the filename has a directory part.
holding the filename. This routine does _not_ create intermediary
directories if the filename has a directory part.
The 2nd argument may either a valid WASM memory pointer, an
ArrayBuffer, or a Uint8Array. The 3rd must be the length, in
@@ -1475,7 +1484,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
capi.sqlite3_js_rc_str(rc));
}finally{
wasm.dealloc(pData);
if( pData && pData!==data ) wasm.dealloc(pData);
}
};
@@ -1484,12 +1493,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
debug builds of sqlite3 because its out-of-scope use of the
sqlite3_vfs API triggers assertions in the core library. That
was unfortunately not discovered until 2023-08-11. This function
is now deprecated and should not be used in new code.
is now deprecated. It should not be used in new code and should
be removed from existing code.
Alternative options:
- "unix" VFS and its variants can get equivalent functionality
with sqlite3_js_posix_create_file().
- The "unix" VFS and its variants can get equivalent
functionality with sqlite3_js_posix_create_file().
- OPFS: use either sqlite3.oo1.OpfsDb.importDb(), for the "opfs"
VFS, or the importDb() method of the PoolUtil object provided
@@ -1498,6 +1508,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
from here because the former is necessarily asynchronous and
the latter requires information not available to this function.
Historical (deprecated) behaviour:
Creates a file using the storage appropriate for the given
sqlite3_vfs. The first argument may be a VFS name (JS string
only, NOT a WASM C-string), WASM-managed `sqlite3_vfs*`, or
@@ -1540,7 +1552,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
- "unix" and related: will use the WASM build's equivalent of the
POSIX I/O APIs. This will work so long as neither a specific
VFS nor the WASM environment imposes requirements which break it.
VFS nor the WASM environment imposes requirements which break
it. (Much later: it turns out that debug builds of the library
impose such requirements, in that they assert() that dataLen is
an even multiple of a valid db page size.)
- "opfs": uses OPFS storage and creates directory parts of the
filename. It can only be used to import an SQLite3 database

View File

@@ -300,7 +300,10 @@ SQLITE_WASM_EXPORT void * sqlite3__wasm_stack_alloc(int n){
** enough for general-purpose string conversions because some of our
** tests use input files (strings) of 16MB+.
*/
static unsigned char PStack_mem[512 * 8] = {0};
static unsigned char PStack_mem[
1024 * 4 /* API docs guaranty at least 2kb and it's been set at 4kb
since it was introduced. */
] = {0};
static struct {
unsigned const char * const pBegin;/* Start (inclusive) of memory */
unsigned const char * const pEnd; /* One-after-the-end of memory */
@@ -401,7 +404,10 @@ void sqlite3__wasm_test_struct(WasmTestStruct * s){
*/
SQLITE_WASM_EXPORT
const char * sqlite3__wasm_enum_json(void){
static char aBuffer[1024 * 20] = {0} /* where the JSON goes */;
static char aBuffer[1024 * 20] =
{0} /* where the JSON goes. 2025-09-19: output size=19295, but
that can vary slightly from build to build, so a little
leeway is needed here. */;
int n = 0, nChildren = 0, nStruct = 0
/* output counters for figuring out where commas go */;
char * zPos = &aBuffer[1] /* skip first byte for now to help protect
@@ -971,8 +977,8 @@ const char * sqlite3__wasm_enum_json(void){
** }
** }
**
** Detailed documentation for those bits are in the docs for the
** Jaccwabyt JS-side component.
** Detailed documentation for those bits are in the Jaccwabyt
** JS-side component.
*/
/** Macros for emitting StructBinder description. */

View File

@@ -1352,7 +1352,7 @@ globalThis.WhWasmUtilInstaller = function(target){
The reason for the 2nd argument is...
When one of the returned pointers will refer to a 64-bit value,
e.g. a double or int64, an that value must be written or fetched,
e.g. a double or int64, and that value must be written or fetched,
e.g. using poke() or peek(), it is important that
the pointer in question be aligned to an 8-byte boundary or else
it will not be fetched or written properly and will corrupt or
@@ -1401,9 +1401,11 @@ globalThis.WhWasmUtilInstaller = function(target){
target.xCall = function(fname, ...args){
const f = (fname instanceof Function) ? fname : target.xGet(fname);
if(!(f instanceof Function)) toss("Exported symbol",fname,"is not a function.");
if(f.length!==args.length) __argcMismatch(((f===fname) ? f.name : fname),f.length)
if(f.length!==args.length){
__argcMismatch(((f===fname) ? f.name : fname),f.length)
/* This is arguably over-pedantic but we want to help clients keep
from shooting themselves in the foot when calling C APIs. */;
}
return (2===arguments.length && Array.isArray(arguments[1]))
? f.apply(null, arguments[1])
: f.apply(null, args);
@@ -1418,14 +1420,15 @@ globalThis.WhWasmUtilInstaller = function(target){
cache.xWrap.convert.arg = new Map;
/** Map of type names to return result conversion functions. */
cache.xWrap.convert.result = new Map;
/** Scope-local convenience aliases. */
const xArg = cache.xWrap.convert.arg, xResult = cache.xWrap.convert.result;
if(target.bigIntEnabled){
xArg.set('i64', (i)=>BigInt(i));
}
const __xArgPtr = 'i32' === ptrIR
const __xArgPtr = ('i32' === ptrIR)
? ((i)=>(i | 0)) : ((i)=>(BigInt(i) | BigInt(0)));
xArg.set('i32', __xArgPtr )
xArg.set('i32', (i)=>(i | 0) )
.set('i16', (i)=>((i | 0) & 0xFFFF))
.set('i8', (i)=>((i | 0) & 0xFF))
.set('f32', (i)=>Number(i).valueOf())
@@ -1445,8 +1448,8 @@ globalThis.WhWasmUtilInstaller = function(target){
.set(null, xResult.get('null'));
{ /* Copy xArg[...] handlers to xResult[...] for cases which have
identical semantics. Also add pointer-style variants of
them. */
identical semantics. Also add pointer-style variants of those
xArg entries to both xArg and xResult. */
const copyToResult = ['i8', 'i16', 'i32', 'int',
'f32', 'float', 'f64', 'double'];
if(target.bigIntEnabled) copyToResult.push('i64');
@@ -1905,11 +1908,11 @@ globalThis.WhWasmUtilInstaller = function(target){
which convert their argument to an integer and truncate it to
the given bit length.
- `*` and `pointer` (args): are assumed to be WASM pointer values
and are returned coerced to an appropriately-sized pointer
value (i32 or i64). Non-numeric values will coerce to 0 and
out-of-range values will have undefined results (just as with
any pointer misuse).
- `*`, `**`, and `pointer` (args): are assumed to be WASM pointer
values and are returned coerced to an appropriately-sized
pointer value (i32 or i64). Non-numeric values will coerce to 0
and out-of-range values will have undefined results (just as
with any pointer misuse).
- `*` and `pointer` (results): aliases for the current
WASM pointer numeric type.
@@ -1934,9 +1937,9 @@ globalThis.WhWasmUtilInstaller = function(target){
distinguish between the two types of floating-point numbers.
- `number` (results): converts the result to a JS Number using
Number(theValue).valueOf(). Note that this is for result
conversions only, as it's not possible to generically know
which type of number to convert arguments to.
Number(theValue). This is for result conversions only, as it's
not possible to generically know which type of number to
convert arguments to.
Non-numeric conversions include:
@@ -1948,7 +1951,7 @@ globalThis.WhWasmUtilInstaller = function(target){
to accommodate various uses of certain C APIs
(e.g. output-style strings)...
- If the arg is a string, it creates a _temporary_
- If the arg is a JS string, it creates a _temporary_
UTF-8-encoded C-string to pass to the exported function,
cleaning it up before the wrapper returns. If a long-lived
C-string pointer is required, that requires client-side code
@@ -1965,10 +1968,10 @@ globalThis.WhWasmUtilInstaller = function(target){
- `string:dealloc` or `utf8:dealloc` (results): treats the result
value as a non-const UTF-8 C-string, ownership of which has
just been transfered to the caller. It copies the C-string to a
JS string, frees the C-string, and returns the JS string. If
such a result value is NULL, the JS result is `null`. Achtung:
when using an API which returns results from a specific
allocator, e.g. `my_malloc()`, this conversion _is not
JS string, frees the C-string using dealloc(), and returns the
JS string. If such a result value is NULL, the JS result is
`null`. Achtung: when using an API which returns results from a
specific allocator, e.g. `my_malloc()`, this conversion _is not
legal_. Instead, an equivalent conversion which uses the
appropriate deallocator is required. For example:

View File

@@ -1261,7 +1261,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
dw = sqlite3.oo1.DB.wrapHandle(pDb, true);
pDb = 0;
//sqlite3.config.debug("dw",dw);
T.assert( pTmp===dw.pointer, 'pDb===dw.pointer' );
T.assert( pTmp===dw.pointer, 'pTmp===dw.pointer' );
T.assert( dw.filename === "", "dw.filename == "+dw.filename );
let q = dw.prepare("select 1");
try {
@@ -3567,9 +3567,12 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
name: 'Delete via bound parameter in subquery',
predicate: ()=>wasm.compileOptionUsed('ENABLE_FTS5') || "Missing FTS5",
test: function(sqlite3){
// Testing https://sqlite.org/forum/forumpost/40ce55bdf5
// with the exception that that post uses "external content"
// for the FTS index.
/**
Testing https://sqlite.org/forum/forumpost/40ce55bdf5 with
the exception that that post uses "external content" for
the FTS index. This isn't testing a fix, just confirming
that the bug report is not really a bug.
*/
const db = new sqlite3.oo1.DB();//(':memory:','wt');
db.exec([
"create virtual table f using fts5 (path);",
@@ -3586,10 +3589,10 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
//dump('Full fts table');
let rc = fetchEm();
T.assert(3===rc.length);
db.exec(`
delete from f where rowid in (
select rowid from f where path = :path
)`,
db.exec(
["delete from f where rowid in (",
"select rowid from f where path = :path",
")"],
{bind: {":path": "def"}}
);
//dump('After deleting one entry via subquery');

View File

@@ -1,5 +1,5 @@
C Wasm:\s(A)\sdiverse\sinternal\sdoc\supdates.\s(B)\swhen\sgenerating\sautomated\sJS-to-WASM\sfunction\sproxies\sfor\sconverters\swhich\srequire\san\sadditional\smiddle-man\sproxy,\se.g.\ssqlite3_exec(),\suse\sthe\sclient-provided\sfunction,\snot\sthe\sproxy\sfunction,\sas\sthe\scache\skey,\sto\skeep\sfrom\sre-generating\sthe\sconversion\sin\ssome\scommon\suse\spatterns.
D 2025-09-19T14:21:09.961
C Diverse\scleanups\sand\sdocs\sin\sthe\sJS\sand\skvvfs\spieces.\sFunctional\schanges:\s(A)\sensure\sthat\sthe\s'i32'\sJS/WASM\sfunc\sarg/result\sconversion\sworks\sproperly\swith\sa\s64-bit-memory\sWASM\sbuild\s(which\swe\sneither\suse\snor\stest\sbut\s[https://webassembly.org/news/2025-09-17-wasm-3.0/\s|\sthe\snewly-ratified\sWASM\s3.0]\sbrings\swithin\spotential\sreach).\s(B)\sFix\ssqlite3_js_posix_create_file()\sto\snot\sdeallocate\sits\sinput\sarray\sif\sthe\sclient\spasses\sin\sraw\smemory\s(the\slibrary\shas\snever\sused\sit\sthat\sway\sbut\sthe\sAPI\spermits\sit).
D 2025-09-19T17:24:47.155
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -597,9 +597,9 @@ F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90a
F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701
F ext/wasm/api/pre-js.c-pp.js 58f823de197e2c10d76179aa05410a593b7ae03e1ece983bb42ffd818e8857e1
F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
F ext/wasm/api/sqlite3-api-glue.c-pp.js 066c09125d12189863ec2b34e702b7b8a7ba25c00e73f77de0b727430ef65687
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 852f2cd6acddbae487fc4f1c3ec952e6c1e2033aa4e6c7091d330d983c87c032
F ext/wasm/api/sqlite3-api-prologue.js 4272131346b102d6f1bfc07524331213ff89407b76cbbde4c0b48b19c692ba94
F ext/wasm/api/sqlite3-api-glue.c-pp.js fab9a05257119d42f3d26cf4e437198a8c479d2c4751c5de4ac986969bd3dd4b
F ext/wasm/api/sqlite3-api-oo1.c-pp.js dc8573267f0dd49ae314a295c0dbe86de921f6d6beabbb7a447029ca1ea4e1d9
F ext/wasm/api/sqlite3-api-prologue.js 332bcf0c8a32af38c8b2f308b1cb37002e1db3ec27df9fe629116a591540e375
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 760191cd13416e6f5adfd9fcc8a97fed5645c9e0a5fbac213a2d4ce2d79a4334
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
@@ -607,7 +607,7 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 0f68a64e508598910e7c01214ae27d603dfc8baec6a184506fafac603a901931
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4ab0704ee198de7d1059eccedc7703c931510b588d10af0ee36ea5b3ebbac284
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
F ext/wasm/api/sqlite3-wasm.c 404cc1f0f5c307210a8d7c3a7dda57834e0e8b3d406ba51977a97a6d14a74734
F ext/wasm/api/sqlite3-wasm.c c60f778e686a47279885b55345abefd3cf2a1da24c1921e530081444aec68a6e
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 4ad256b4ff7f839ad18931ed35d46cced544207bd2209665ec552e193f7f4544
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
@@ -618,7 +618,7 @@ F ext/wasm/c-pp.c cca55c5b55ebd8d29916adbedb0e40baa12caa9a2e8429f812683c308f9b0e
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
F ext/wasm/common/whwasmutil.js 4ea5a413016d9a561a26976c699a2670f2385b93be04cd2d463dd6c1955bd175
F ext/wasm/common/whwasmutil.js 000232b0a9527af5a73b3c0e46ef91a19517ae027ce73fd8902f06c490b9b97c
F ext/wasm/config.make.in c424ae1cc3c89274520ad312509d36c4daa34a3fce5d0c688e5f8f4365e1049a
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
@@ -655,7 +655,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
F ext/wasm/tester1.c-pp.js aa694096feb5cfd9333f7029e933a4eae95bde5cc3edd29da4dc0f8dae452905
F ext/wasm/tester1.c-pp.js de2736de2335a74a9ecbda9005af5c8b1c33fd8729591064ef4795650da65900
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -725,7 +725,7 @@ F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_kv.c fb7ba8d6204197357f1eb7e1c7450d09c10043bf7e99aba602f4aa46b8fb11a3
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c b3da55bc4bb214b2bfb1e430b10e9d3ebcf6b11741921ab044c9b9539c8fcc4f
F src/os_win.c f81a7cffdfe8c593a840895b3f64290714f0186b06302d2c397012252d830374
@@ -2175,8 +2175,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 468a11fd415710042b23880772f6c2c7771008208823fe3b554227a9244dbf92
R 45b30de6d5f1d826a12d811876f55290
P 5e5139c2a162562cee0071d03954ebc0b8938da0b045ec3f5eba32dc8e19604d
R 39374a1a28932b274e07d195dbea9d94
U stephan
Z 31a53fb96f385e882a14f4d3fa47d2d3
Z 8c740e2b096da4198cfd5683f58d6ede
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
5e5139c2a162562cee0071d03954ebc0b8938da0b045ec3f5eba32dc8e19604d
79af65a694fbbb3d501fb2ebd835c259ca644e0dafdd71eeb9f0a7c0e9128a1e

View File

@@ -174,7 +174,7 @@ static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
#define KVSTORAGE_KEY_SZ 32
/* Expand the key name with an appropriate prefix and put the result
** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
** KVSTORAGE_KEY_SZ bytes.
*/
static void kvstorageMakeKey(
@@ -233,10 +233,12 @@ static int kvstorageDelete(const char *zClass, const char *zKey){
**
** Return the total number of bytes in the data, without truncation, and
** not counting the final zero terminator. Return -1 if the key does
** not exist.
** not exist or its key cannot be read.
**
** If nBuf<=0 then this routine simply returns the size of the data without
** actually reading it.
** If nBuf<=0 then this routine simply returns the size of the data
** without actually reading it. Similarly, if nBuf==1 then it
** zero-terminates zBuf at zBuf[0] and returns the size of the data
** without reading it.
*/
static int kvstorageRead(
const char *zClass,
@@ -285,11 +287,9 @@ static int kvstorageRead(
** kvvfs i/o methods with JavaScript implementations in WASM builds.
** Maintenance reminder: if this struct changes in any way, the JSON
** rendering of its structure must be updated in
** sqlite3_wasm_enum_json(). There are no binary compatibility
** concerns, so it does not need an iVersion member. This file is
** necessarily always compiled together with sqlite3_wasm_enum_json(),
** and JS code dynamically creates the mapping of members based on
** that JSON description.
** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
** compatibility concerns, so it does not need an iVersion
** member.
*/
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
struct sqlite3_kvvfs_methods {
@@ -306,8 +306,8 @@ struct sqlite3_kvvfs_methods {
** the compiler can hopefully optimize this level of indirection out.
** That said, kvvfs is intended primarily for use in WASM builds.
**
** Note that this is not explicitly flagged as static because the
** amalgamation build will tag it with SQLITE_PRIVATE.
** This is not explicitly flagged as static because the amalgamation
** build will tag it with SQLITE_PRIVATE.
*/
#ifndef SQLITE_WASM
const