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

@@ -243,21 +243,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
purpose. For example:
const pAuxDtor = wasm.installFunction('v(p)', function(ptr){
//free ptr
//free ptr
});
myDb.onclose = {
after: ()=>{
wasm.uninstallFunction(pAuxDtor);
}
after: ()=>{
wasm.uninstallFunction(pAuxDtor);
}
};
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',