mirror of
https://github.com/sqlite/sqlite.git
synced 2025-10-24 09:53:10 +03:00
Diverse internal cleanups in the JS/WASM pieces. A potential fix for a hypothetical db-close-time resource leak of a subset of automated JS-to-WASM function conversions in Safari. That browser exposes WASM-exported functions via nullary wrappers, which causes a handful of them to misbehave (not clean up) at sqlite3_close_v2()-time.
FossilOrigin-Name: fabbc8b6d184d52a513e80fabd900f578424fc8a8055e3d64fac54b9e28ea18a
This commit is contained in:
@@ -79,11 +79,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
// elements instead: [x,y,z] is equivalent to x,y,z
|
||||
]
|
||||
|
||||
Note that support for the API-specific data types in the
|
||||
result/argument type strings gets plugged in at a later phase in
|
||||
the API initialization process.
|
||||
Support for the API-specific data types in the result/argument
|
||||
type strings gets plugged in at a later phase in the API
|
||||
initialization process.
|
||||
*/
|
||||
wasm.bindingSignatures = [
|
||||
const bindingSignatures = {
|
||||
core: [
|
||||
// Please keep these sorted by function name!
|
||||
["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
|
||||
/* sqlite3_auto_extension() has a hand-written binding. */
|
||||
@@ -298,9 +299,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
"*"
|
||||
]],
|
||||
["sqlite3_txn_state", "int", ["sqlite3*","string"]],
|
||||
/* Note that sqlite3_uri_...() have very specific requirements for
|
||||
their first C-string arguments, so we cannot perform any value
|
||||
conversion on those. */
|
||||
/* sqlite3_uri_...() have very specific requirements for their
|
||||
first C-string arguments, so we cannot perform any
|
||||
string-type conversion on their first argument. */
|
||||
["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
|
||||
["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
|
||||
["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
|
||||
@@ -321,100 +322,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
["sqlite3_vfs_find", "*", "string"],
|
||||
["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
|
||||
["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
|
||||
]/*wasm.bindingSignatures*/;
|
||||
|
||||
if( !!wasm.exports.sqlite3_progress_handler ){
|
||||
wasm.bindingSignatures.push(
|
||||
["sqlite3_progress_handler", undefined, [
|
||||
"sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
|
||||
name: 'xProgressHandler',
|
||||
signature: 'i(p)',
|
||||
bindScope: 'context',
|
||||
contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
|
||||
}), "*"
|
||||
]]
|
||||
);
|
||||
}
|
||||
|
||||
if( !!wasm.exports.sqlite3_stmt_explain ){
|
||||
wasm.bindingSignatures.push(
|
||||
["sqlite3_stmt_explain", "int", "sqlite3_stmt*", "int"],
|
||||
["sqlite3_stmt_isexplain", "int", "sqlite3_stmt*"]
|
||||
);
|
||||
}
|
||||
|
||||
if( !!wasm.exports.sqlite3_set_authorizer ){
|
||||
wasm.bindingSignatures.push(
|
||||
["sqlite3_set_authorizer", "int", [
|
||||
"sqlite3*",
|
||||
new wasm.xWrap.FuncPtrAdapter({
|
||||
name: "sqlite3_set_authorizer::xAuth",
|
||||
signature: "i(pi"+"ssss)",
|
||||
contextKey: (argv, argIndex)=>argv[0/*(sqlite3*)*/],
|
||||
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;
|
||||
}catch(e){
|
||||
return e.resultCode || capi.SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
"*"/*pUserData*/
|
||||
]]
|
||||
);
|
||||
}/* sqlite3_set_authorizer() */
|
||||
|
||||
if( !!wasm.exports.sqlite3_column_origin_name ){
|
||||
wasm.bindingSignatures.push(
|
||||
["sqlite3_column_database_name","string", "sqlite3_stmt*", "int"],
|
||||
["sqlite3_column_origin_name","string", "sqlite3_stmt*", "int"],
|
||||
["sqlite3_column_table_name","string", "sqlite3_stmt*", "int"]
|
||||
);
|
||||
}
|
||||
|
||||
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
|
||||
/* ^^^ "the problem" is that this is an optional feature and the
|
||||
build-time function-export list does not currently take
|
||||
optional features into account. */
|
||||
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
|
||||
}
|
||||
|
||||
//#if enable-see
|
||||
if(wasm.exports.sqlite3_key_v2 instanceof Function){
|
||||
/* This list gets extended below */
|
||||
]/*.core*/,
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
wasm.bindingSignatures.push(
|
||||
["sqlite3_key", "int", "sqlite3*", "string", "int"],
|
||||
["sqlite3_key_v2","int","sqlite3*","string","*","int"],
|
||||
["sqlite3_rekey", "int", "sqlite3*", "string", "int"],
|
||||
["sqlite3_rekey_v2", "int", "sqlite3*", "string", "*", "int"],
|
||||
["sqlite3_activate_see", undefined, "string"]
|
||||
);
|
||||
}
|
||||
//#endif enable-see
|
||||
Functions which require BigInt (int64) support are separated
|
||||
from the others because we need to conditionally bind them or
|
||||
apply dummy impls, depending on the capabilities of the
|
||||
environment. (That said: we never actually build without
|
||||
BigInt support, and such builds are untested.)
|
||||
|
||||
/**
|
||||
Functions which require BigInt (int64) support are separated from
|
||||
the others because we need to conditionally bind them or apply
|
||||
dummy impls, depending on the capabilities of the environment.
|
||||
(That said: we never actually build without BigInt support,
|
||||
and such builds are untested.)
|
||||
|
||||
Note that not all of these functions directly require int64
|
||||
but are only for use with APIs which require int64. For example,
|
||||
the vtab-related functions.
|
||||
Not all of these functions directly require int64 but are only
|
||||
for use with APIs which require int64. For example, the
|
||||
vtab-related functions.
|
||||
*/
|
||||
wasm.bindingSignatures.int64 = [
|
||||
int64: [
|
||||
["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
|
||||
["sqlite3_changes64","i64", ["sqlite3*"]],
|
||||
["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
|
||||
@@ -453,10 +375,120 @@ 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 */
|
||||
]/*.int64*/,
|
||||
/**
|
||||
Functions which are intended solely for API-internal use by the
|
||||
WASM components, not client code. These get installed into
|
||||
sqlite3.util. Some of them get exposed to clients via variants
|
||||
in sqlite3_js_...().
|
||||
|
||||
2024-01-11: these were renamed, with two underscores in the
|
||||
prefix, to ensure that clients do not accidentally depend on
|
||||
them. They have always been documented as internal-use-only,
|
||||
so no clients "should" be depending on the old names.
|
||||
*/
|
||||
wasmInternal: [
|
||||
["sqlite3__wasm_db_reset", "int", "sqlite3*"],
|
||||
["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
|
||||
[/* DO NOT USE. This is deprecated since 2023-08-11 because it
|
||||
can trigger assert() in debug builds when used with file
|
||||
sizes which are not an exact multiple of a valid db page
|
||||
size. This function is retained only so that
|
||||
sqlite3_js_vfs_create_file() can continue to work (for a
|
||||
given value of work), but that function emits a
|
||||
config.warn() log message directing the reader to
|
||||
alternatives. */
|
||||
"sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"
|
||||
],
|
||||
["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
|
||||
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
|
||||
["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
|
||||
]/*.wasmInternal*/
|
||||
} /*bindingSignatures*/;
|
||||
|
||||
if( !!wasm.exports.sqlite3_progress_handler ){
|
||||
bindingSignatures.core.push(
|
||||
["sqlite3_progress_handler", undefined, [
|
||||
"sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
|
||||
name: 'xProgressHandler',
|
||||
signature: 'i(p)',
|
||||
bindScope: 'context',
|
||||
contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
|
||||
}), "*"
|
||||
]]
|
||||
);
|
||||
}
|
||||
|
||||
if( !!wasm.exports.sqlite3_stmt_explain ){
|
||||
bindingSignatures.core.push(
|
||||
["sqlite3_stmt_explain", "int", "sqlite3_stmt*", "int"],
|
||||
["sqlite3_stmt_isexplain", "int", "sqlite3_stmt*"]
|
||||
);
|
||||
}
|
||||
|
||||
if( !!wasm.exports.sqlite3_set_authorizer ){
|
||||
bindingSignatures.core.push(
|
||||
["sqlite3_set_authorizer", "int", [
|
||||
"sqlite3*",
|
||||
new wasm.xWrap.FuncPtrAdapter({
|
||||
name: "sqlite3_set_authorizer::xAuth",
|
||||
signature: "i(pi"+"ssss)",
|
||||
contextKey: (argv, argIndex)=>argv[0/*(sqlite3*)*/],
|
||||
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;
|
||||
}catch(e){
|
||||
return e.resultCode || capi.SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
"*"/*pUserData*/
|
||||
]]
|
||||
);
|
||||
}/* sqlite3_set_authorizer() */
|
||||
|
||||
if( !!wasm.exports.sqlite3_column_origin_name ){
|
||||
bindingSignatures.core.push(
|
||||
["sqlite3_column_database_name","string", "sqlite3_stmt*", "int"],
|
||||
["sqlite3_column_origin_name","string", "sqlite3_stmt*", "int"],
|
||||
["sqlite3_column_table_name","string", "sqlite3_stmt*", "int"]
|
||||
);
|
||||
}
|
||||
|
||||
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
|
||||
/* ^^^ "the problem" is that this is an optional feature and the
|
||||
build-time function-export list does not currently take
|
||||
optional features into account. */
|
||||
bindingSignatures.core.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
|
||||
}
|
||||
|
||||
//#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.
|
||||
*/
|
||||
bindingSignatures.core.push(
|
||||
["sqlite3_key", "int", "sqlite3*", "string", "int"],
|
||||
["sqlite3_key_v2","int","sqlite3*","string","*","int"],
|
||||
["sqlite3_rekey", "int", "sqlite3*", "string", "int"],
|
||||
["sqlite3_rekey_v2", "int", "sqlite3*", "string", "*", "int"],
|
||||
["sqlite3_activate_see", undefined, "string"]
|
||||
);
|
||||
}
|
||||
//#endif enable-see
|
||||
|
||||
if( wasm.bigIntEnabled && !!wasm.exports.sqlite3_declare_vtab ){
|
||||
wasm.bindingSignatures.int64.push(
|
||||
bindingSignatures.int64.push(
|
||||
["sqlite3_create_module", "int",
|
||||
["sqlite3*","string","sqlite3_module*","*"]],
|
||||
["sqlite3_create_module_v2", "int",
|
||||
@@ -477,7 +509,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}/* virtual table APIs */
|
||||
|
||||
if(wasm.bigIntEnabled && !!wasm.exports.sqlite3_preupdate_hook){
|
||||
wasm.bindingSignatures.int64.push(
|
||||
bindingSignatures.int64.push(
|
||||
["sqlite3_preupdate_blobwrite", "int", "sqlite3*"],
|
||||
["sqlite3_preupdate_count", "int", "sqlite3*"],
|
||||
["sqlite3_preupdate_depth", "int", "sqlite3*"],
|
||||
@@ -522,7 +554,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}
|
||||
};
|
||||
|
||||
wasm.bindingSignatures.int64.push(...[
|
||||
bindingSignatures.int64.push(
|
||||
['sqlite3changegroup_add', 'int', ['sqlite3_changegroup*', 'int', 'void*']],
|
||||
['sqlite3changegroup_add_strm', 'int', [
|
||||
'sqlite3_changegroup*',
|
||||
@@ -677,36 +709,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}),
|
||||
'*'
|
||||
]]
|
||||
]);
|
||||
);
|
||||
}/*session/changeset APIs*/
|
||||
|
||||
/**
|
||||
Functions which are intended solely for API-internal use by the
|
||||
WASM components, not client code. These get installed into
|
||||
sqlite3.util. Some of them get exposed to clients via variants
|
||||
in sqlite3_js_...().
|
||||
|
||||
2024-01-11: these were renamed, with two underscores in the
|
||||
prefix, to ensure that clients do not accidentally depend on
|
||||
them. They have always been documented as internal-use-only, so
|
||||
no clients "should" be depending on the old names.
|
||||
*/
|
||||
wasm.bindingSignatures.wasmInternal = [
|
||||
["sqlite3__wasm_db_reset", "int", "sqlite3*"],
|
||||
["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
|
||||
[/* DO NOT USE. This is deprecated since 2023-08-11 because it can
|
||||
trigger assert() in debug builds when used with file sizes
|
||||
which are not sizes to a multiple of a valid db page size. */
|
||||
"sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"
|
||||
],
|
||||
["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
|
||||
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
|
||||
["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
|
||||
];
|
||||
|
||||
/**
|
||||
Install JS<->C struct bindings for the non-opaque struct types we
|
||||
need... */
|
||||
need...
|
||||
*/
|
||||
sqlite3.StructBinder = globalThis.Jaccwabyt({
|
||||
heap: 0 ? wasm.memory : wasm.heap8u,
|
||||
alloc: wasm.alloc,
|
||||
@@ -759,10 +768,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
/**
|
||||
Add some descriptive xWrap() aliases for '*' intended to (A)
|
||||
initially improve readability/correctness of
|
||||
wasm.bindingSignatures and (B) provide automatic conversion
|
||||
from higher-level representations, e.g. capi.sqlite3_vfs to
|
||||
`sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
|
||||
improve readability/correctness of bindingSignatures and (B)
|
||||
provide automatic conversion from higher-level representations,
|
||||
e.g. capi.sqlite3_vfs to `sqlite3_vfs*` via (capi.sqlite3_vfs
|
||||
instance).pointer.
|
||||
*/
|
||||
const __xArgPtr = wasm.xWrap.argAdapter('*');
|
||||
const nilType = function(){
|
||||
@@ -834,10 +843,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
"Disabling sqlite3.wasm.xWrap.doArgcCheck due to environmental quirks."
|
||||
);
|
||||
}
|
||||
for(const e of wasm.bindingSignatures){
|
||||
for(const e of bindingSignatures.core){
|
||||
capi[e[0]] = wasm.xWrap.apply(null, e);
|
||||
}
|
||||
for(const e of wasm.bindingSignatures.wasmInternal){
|
||||
for(const e of bindingSignatures.wasmInternal){
|
||||
util[e[0]] = wasm.xWrap.apply(null, e);
|
||||
}
|
||||
|
||||
@@ -850,15 +859,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
return ()=>toss(fname+"() is unavailable due to lack",
|
||||
"of BigInt support in this build.");
|
||||
};
|
||||
for(const e of wasm.bindingSignatures.int64){
|
||||
for(const e of bindingSignatures.int64){
|
||||
capi[e[0]] = wasm.bigIntEnabled
|
||||
? wasm.xWrap.apply(null, e)
|
||||
: fI64Disabled(e[0]);
|
||||
}
|
||||
|
||||
/* There's no need to expose bindingSignatures to clients,
|
||||
implicitly making it part of the public interface. */
|
||||
delete wasm.bindingSignatures;
|
||||
/* We don't need these anymore... */
|
||||
delete bindingSignatures.core;
|
||||
delete bindingSignatures.int64;
|
||||
delete bindingSignatures.wasmInternal;
|
||||
|
||||
/**
|
||||
Sets the given db's error state. Accepts:
|
||||
@@ -1098,10 +1108,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
continue;
|
||||
}
|
||||
closeArgs.length = x.length/*==argument count*/
|
||||
/* recall that undefined entries translate to 0 when passed to
|
||||
WASM. */;
|
||||
|| 1 /* Recall that: (A) undefined entries translate to 0 when
|
||||
passed to WASM and (B) Safari wraps wasm.exports.* in
|
||||
nullary functions so x.length is 0 there. */;
|
||||
try{ capi[name](...closeArgs) }
|
||||
catch(e){
|
||||
/* This "cannot happen" unless something is well and truly sideways. */
|
||||
sqlite3.config.warn("close-time call of",name+"(",closeArgs,") threw:",e);
|
||||
}
|
||||
}
|
||||
@@ -1203,10 +1215,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
2) It accepts JS functions for its function-pointer arguments,
|
||||
for which it will install WASM-bound proxies. The bindings
|
||||
are "permanent," in that they will stay in the WASM environment
|
||||
until it shuts down unless the client calls this again with the
|
||||
same collation name and a value of 0 or null for the
|
||||
the function pointer(s).
|
||||
are "permanent," in that they will stay in the WASM
|
||||
environment until it shuts down unless the client calls this
|
||||
again with the same collation name and a value of 0 or null
|
||||
for the the function pointer(s). sqlite3_close_v2() will
|
||||
also clean up such automatically-installed WASM functions.
|
||||
|
||||
For consistency with the C API, it requires the same number of
|
||||
arguments. It returns capi.SQLITE_MISUSE if passed any other
|
||||
@@ -1447,11 +1460,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
sqlite3_prepare_v3() */
|
||||
|
||||
/**
|
||||
Helper for string:flexible conversions which require a
|
||||
Helper for string:flexible conversions which requires a
|
||||
byte-length counterpart argument. Passed a value and its
|
||||
ostensible length, this function returns [V,N], where V is
|
||||
either v or a transformed copy of v and N is either n, -1, or
|
||||
the byte length of v (if it's a byte array or ArrayBuffer).
|
||||
either v or a transformed copy of v and N is either n (if v is
|
||||
a WASM pointer), -1 (if v is a string or Array), or the byte
|
||||
length of v (if it's a byte array or ArrayBuffer).
|
||||
*/
|
||||
const __flexiString = (v,n)=>{
|
||||
if('string'===typeof v){
|
||||
@@ -1484,15 +1498,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
"int", "**",
|
||||
"**"/*MUST be 0 or null or undefined!*/]),
|
||||
/**
|
||||
Impl which requires that the 2nd argument be a pointer
|
||||
to the SQL string, instead of being converted to a
|
||||
string. This variant is necessary for cases where we
|
||||
require a non-NULL value for the final argument
|
||||
(exec()'ing multiple statements from one input
|
||||
string). For simpler cases, where only the first
|
||||
statement in the SQL string is required, the wrapper
|
||||
named sqlite3_prepare_v2() is sufficient and easier to
|
||||
use because it doesn't require dealing with pointers.
|
||||
Impl which requires that the 2nd argument be a pointer to the
|
||||
SQL string, instead of being converted to a JS string. This
|
||||
variant is necessary for cases where we require a non-NULL
|
||||
value for the final argument (prepare/step of multiple
|
||||
statements from one input string). For simpler cases, where
|
||||
only the first statement in the SQL string is required, the
|
||||
wrapper named sqlite3_prepare_v2() is sufficient and easier
|
||||
to use because it doesn't require dealing with pointers.
|
||||
*/
|
||||
full: wasm.xWrap('sqlite3_prepare_v3',
|
||||
"int", ["sqlite3*", "*", "int", "int",
|
||||
|
||||
@@ -542,8 +542,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
4th-argument value, taking care not to pass a value which
|
||||
truncates a multi-byte UTF-8 character. When passing
|
||||
WASM-format strings, it is important that the final argument be
|
||||
valid or unexpected content can result can result, or even a
|
||||
crash if the application reads past the WASM heap bounds.
|
||||
valid or unexpected content can result, or WASM may crash if
|
||||
the application reads past the WASM heap bounds.
|
||||
*/
|
||||
sqlite3_bind_text: undefined/*installed later*/,
|
||||
|
||||
@@ -614,10 +614,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
functions passed in to this routine, and thus wrapped by this
|
||||
routine, get automatic conversions of arguments and result
|
||||
values. The routines which perform those conversions are
|
||||
exposed for client-side use as
|
||||
sqlite3_create_function_v2.convertUdfArgs() and
|
||||
sqlite3_create_function_v2.setUdfResult(). sqlite3_create_function()
|
||||
and sqlite3_create_window_function() have those same methods.
|
||||
exposed for client-side use as sqlite3_values_to_js(),
|
||||
sqlite3_result_js(), and sqlite3_result_error_js().
|
||||
|
||||
For xFunc(), xStep(), and xFinal():
|
||||
|
||||
@@ -635,18 +633,14 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
possibly generating a console.error() message. Destructors
|
||||
must not throw.
|
||||
|
||||
Once installed, there is currently no way to uninstall the
|
||||
automatically-converted WASM-bound JS functions from WASM. They
|
||||
can be uninstalled from the database as documented in the C
|
||||
API, but this wrapper currently has no infrastructure in place
|
||||
to also free the WASM-bound JS wrappers, effectively resulting
|
||||
in a memory leak if the client uninstalls the UDF. Improving that
|
||||
is a potential TODO, but removing client-installed UDFs is rare
|
||||
in practice. If this factor is relevant for a given client,
|
||||
they can create WASM-bound JS functions themselves, hold on to their
|
||||
pointers, and pass the pointers in to here. Later on, they can
|
||||
free those pointers (using `wasm.uninstallFunction()` or
|
||||
equivalent).
|
||||
Automatically-converted JS-to-WASM functions will be cleaned up
|
||||
either when (A) this function is called again with the same
|
||||
name, arity, and encoding, but null/0 values for the functions,
|
||||
or (B) when pDb is passed to sqlite3_close_v2(). If this factor
|
||||
is relevant for a given client, they can create WASM-bound JS
|
||||
functions themselves, hold on to their pointers, and pass the
|
||||
pointers in to here. Later on, they can free those pointers
|
||||
(using `wasm.uninstallFunction()` or equivalent).
|
||||
|
||||
C reference: https://sqlite.org/c3ref/create_function.html
|
||||
|
||||
@@ -686,10 +680,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
|
||||
2) sqlite3_prepare_v3(pDb, sqlPointer, sqlByteLen, prepFlags, ppStmt, sqlPointerToPointer)
|
||||
|
||||
Note that the SQL length argument (the 3rd argument) must, for
|
||||
usage (1), always be negative because it must be a byte length
|
||||
and that value is expensive to calculate from JS (where only
|
||||
the character length of strings is readily available). It is
|
||||
The SQL length argument (the 3rd argument) must, for usage (1),
|
||||
always be negative because it must be a byte length and that
|
||||
value is expensive to calculate from JS (where only the
|
||||
character length of strings is readily available). It is
|
||||
retained in this API's interface for code/documentation
|
||||
compatibility reasons but is currently _always_ ignored. With
|
||||
usage (2), the 3rd argument is used as-is but is is still
|
||||
@@ -715,8 +709,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
(e.g. using capi.wasm.alloc() or equivalent). In that case,
|
||||
the final argument may be 0/null/undefined or must be a pointer
|
||||
to which the "tail" of the compiled SQL is written, as
|
||||
documented for the C-side sqlite3_prepare_v3(). In case (2),
|
||||
the underlying C function is called with the equivalent of:
|
||||
documented for the C-side sqlite3_prepare_v3().
|
||||
|
||||
In case (2), the underlying C function is called with the
|
||||
equivalent of:
|
||||
|
||||
(pDb, sqlAsPointer, sqlByteLen, prepFlags, ppStmt, pzTail)
|
||||
|
||||
@@ -1553,12 +1549,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
capi.sqlite3_js_vfs_create_file = function(vfs, filename, data, dataLen){
|
||||
config.warn("sqlite3_js_vfs_create_file() is deprecated and",
|
||||
"should be avoided because it can lead to C-level crashes.",
|
||||
"See its documentation for alternative options.");
|
||||
"See its documentation for alternatives.");
|
||||
let pData;
|
||||
if(data){
|
||||
if( wasm.isPtr(data) ){
|
||||
pData = data;
|
||||
}else if(data instanceof ArrayBuffer){
|
||||
}else{
|
||||
if( data instanceof ArrayBuffer ){
|
||||
data = new Uint8Array(data);
|
||||
}
|
||||
if( data instanceof Uint8Array ){
|
||||
@@ -1569,11 +1566,12 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
}else{
|
||||
SQLite3Error.toss("Invalid 3rd argument type for sqlite3_js_vfs_create_file().");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
pData = 0;
|
||||
}
|
||||
if(!util.isInt32(dataLen) || dataLen<0){
|
||||
wasm.dealloc(pData);
|
||||
if( pData && pData!==data ) wasm.dealloc(pData);
|
||||
SQLite3Error.toss("Invalid 4th argument for sqlite3_js_vfs_create_file().");
|
||||
}
|
||||
try{
|
||||
@@ -1581,7 +1579,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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
||||
C Expose\ssqlite3_set_errmsg()\sto\sthe\sJNI\sbindings.
|
||||
D 2025-09-14T12:55:57.217
|
||||
C Diverse\sinternal\scleanups\sin\sthe\sJS/WASM\spieces.\sA\spotential\sfix\sfor\sa\shypothetical\sdb-close-time\sresource\sleak\sof\sa\ssubset\sof\sautomated\sJS-to-WASM\sfunction\sconversions\sin\sSafari.\sThat\sbrowser\sexposes\sWASM-exported\sfunctions\svia\snullary\swrappers,\swhich\scauses\sa\shandful\sof\sthem\sto\smisbehave\s(not\sclean\sup)\sat\ssqlite3_close_v2()-time.
|
||||
D 2025-09-15T14:11:55.851
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -596,9 +596,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 0c60e7b54259b061b6ed0d96c747b9c77d1c2186c5785a7d638f8afc6d3829d6
|
||||
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 4f1c2a9dc9caf631907766e9872c27d11b255ccae779e8af01c7f8b932817214
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 4272131346b102d6f1bfc07524331213ff89407b76cbbde4c0b48b19c692ba94
|
||||
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
|
||||
@@ -2174,8 +2174,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 e447a50f3a3791c264a68000948daa64edb1857d51d256fbd1ff0f2c2b330d5e
|
||||
R 914e412c108c33985260767ddbccf671
|
||||
P 292866a46948e8d707bd14864fd1b40eec1bd2e22dcd249ec94711b646c8a70b
|
||||
R 3d648bd2f0581cd393c02110c0b966eb
|
||||
U stephan
|
||||
Z fb5496b4e64823b519fcbc93dbe57147
|
||||
Z cb971779c9e9efb3d18793a17a591051
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
@@ -1 +1 @@
|
||||
292866a46948e8d707bd14864fd1b40eec1bd2e22dcd249ec94711b646c8a70b
|
||||
fabbc8b6d184d52a513e80fabd900f578424fc8a8055e3d64fac54b9e28ea18a
|
||||
|
||||
Reference in New Issue
Block a user