wasm.bindingSignatures = [
// Please keep these sorted by function name!
["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
- ["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*"
- /* TODO: we should arguably write a custom wrapper which knows
- how to handle Blob, TypedArrays, and JS strings. */
- ],
+ /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written
+ bindings to permit more flexible inputs. */
["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
["sqlite3_bind_pointer", "int",
"sqlite3_stmt*", "int", "*", "string:static", "*"],
- ["sqlite3_bind_text","int", "sqlite3_stmt*", "int", "string", "int", "*"
- /* We should arguably create a hand-written binding of
- bind_text() which does more flexible text conversion, along
- the lines of sqlite3_prepare_v3(). The slightly problematic
- part is the final argument (text destructor). */
- ],
- //["sqlite3_busy_handler","int", "sqlite3*", "*", "*"],
- // ^^^^ TODO: custom binding which auto-converts JS function arg
- // to a WASM function, noting that calling it multiple times
- // would introduce a leak.
+ ["sqlite3_busy_handler","int", [
+ "sqlite3*",
+ new wasm.xWrap.FuncPtrAdapter({
+ signature: 'i(pi)',
+ contextKey: (argIndex,argv)=>'sqlite3@'+argv[0]
+ }),
+ "*"
+ ]],
["sqlite3_busy_timeout","int", "sqlite3*", "int"],
["sqlite3_close_v2", "int", "sqlite3*"],
["sqlite3_changes", "int", "sqlite3*"],
if(1){/* Special-case handling of sqlite3_prepare_v2() and
sqlite3_prepare_v3() */
+
/**
Helper for string:flexible conversions which require a
byte-length counterpart argument. Passed a value and its
/**
Scope-local holder of the two impls of sqlite3_prepare_v2/v3().
*/
- const __prepare = Object.create(null);
- /**
- This binding expects a JS string as its 2nd argument and
- null as its final argument. In order to compile multiple
- statements from a single string, the "full" impl (see
- below) must be used.
- */
- __prepare.basic = wasm.xWrap('sqlite3_prepare_v3',
- "int", ["sqlite3*", "string",
- "int"/*ignored for this impl!*/,
- "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.
- */
- __prepare.full = wasm.xWrap('sqlite3_prepare_v3',
- "int", ["sqlite3*", "*", "int", "int",
- "**", "**"]);
+ const __prepare = {
+ /**
+ This binding expects a JS string as its 2nd argument and
+ null as its final argument. In order to compile multiple
+ statements from a single string, the "full" impl (see
+ below) must be used.
+ */
+ basic: wasm.xWrap('sqlite3_prepare_v3',
+ "int", ["sqlite3*", "string",
+ "int"/*ignored for this impl!*/,
+ "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.
+ */
+ full: wasm.xWrap('sqlite3_prepare_v3',
+ "int", ["sqlite3*", "*", "int", "int",
+ "**", "**"])
+ };
/* Documented in the capi object's initializer. */
capi.sqlite3_prepare_v3 = function f(pDb, sql, sqlLen, prepFlags, ppStmt, pzTail){
? capi.sqlite3_prepare_v3(pDb, sql, sqlLen, 0, ppStmt, pzTail)
: __dbArgcMismatch(pDb,"sqlite3_prepare_v2",f.length);
};
- }/*sqlite3_prepare_v2/v3()*/;
+
+ }/*sqlite3_prepare_v2/v3()*/
+
+ {/*sqlite3_bind_text/blob()*/
+ const __bindText = wasm.xWrap("sqlite3_bind_text", "int", [
+ "sqlite3_stmt*", "int", "string", "int", "*"
+ ]);
+ const __bindBlob = wasm.xWrap("sqlite3_bind_blob", "int", [
+ "sqlite3_stmt*", "int", "*", "int", "*"
+ ]);
+
+ /** Documented in the capi object's initializer. */
+ capi.sqlite3_bind_text = function f(pStmt, iCol, text, nText, xDestroy){
+ if(f.length!==arguments.length){
+ return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt),
+ "sqlite3_bind_text", f.length);
+ }else if(wasm.isPtr(text) || null===text){
+ return __bindText(pStmt, iCol, text, nText, xDestroy);
+ }else if(text instanceof ArrayBuffer){
+ text = new Uint8Array(text);
+ }else if(Array.isArray(pMem)){
+ text = pMem.join('');
+ }
+ let p, n;
+ try {
+ if(util.isSQLableTypedArray(text)){
+ p = wasm.allocFromTypedArray(text);
+ n = text.byteLength;
+ }else if('string'===typeof text){
+ [p, n] = wasm.allocCString(text);
+ }else{
+ return util.sqlite3_wasm_db_error(
+ capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
+ "Invalid 3rd argument type for sqlite3_bind_text()."
+ );
+ }
+ return __bindText(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
+ }finally{
+ wasm.dealloc(p);
+ }
+ }/*sqlite3_bind_text()*/;
+
+ /** Documented in the capi object's initializer. */
+ capi.sqlite3_bind_blob = function f(pStmt, iCol, pMem, nMem, xDestroy){
+ if(f.length!==arguments.length){
+ return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt),
+ "sqlite3_bind_blob", f.length);
+ }else if(wasm.isPtr(pMem) || null===pMem){
+ return __bindBlob(pStmt, iCol, pMem, nMem, xDestroy);
+ }else if(pMem instanceof ArrayBuffer){
+ pMem = new Uint8Array(pMem);
+ }else if(Array.isArray(pMem)){
+ pMem = pMem.join('');
+ }
+ let p, n;
+ try{
+ if(util.isBindableTypedArray(pMem)){
+ p = wasm.allocFromTypedArray(pMem);
+ n = nMem>=0 ? nMem : pMem.byteLength;
+ }else if('string'===typeof pMem){
+ [p, n] = wasm.allocCString(pMem);
+ }else{
+ return util.sqlite3_wasm_db_error(
+ capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
+ "Invalid 3rd argument type for sqlite3_bind_blob()."
+ );
+ }
+ return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
+ }finally{
+ wasm.dealloc(p);
+ }
+ }/*sqlite3_bind_blob()*/;
+
+ }/*sqlite3_bind_text/blob()*/
{/* sqlite3_set_authorizer() */
const __ssa = wasm.xWrap("sqlite3_set_authorizer", 'int', [
}else if(!util.isBindableTypedArray(val)){
toss3("Binding a value as a blob requires",
"that it be a string, Uint8Array, or Int8Array.");
- }else if(1){
- /* _Hypothetically_ more efficient than the impl in the 'else' block. */
+ }else{
const stack = wasm.scopedAllocPush();
try{
const pBlob = wasm.scopedAlloc(val.byteLength || 1);
}finally{
wasm.scopedAllocPop(stack);
}
- }else{
- const pBlob = wasm.allocFromTypedArray(val);
- try{
- rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
- capi.SQLITE_TRANSIENT);
- }finally{
- wasm.dealloc(pBlob);
- }
}
break;
}
};
Object.assign(capi, {
+ /**
+ sqlite3_bind_blob() works exactly like its C counterpart unless
+ its 3rd argument is one of:
+
+ - JS string: the 3rd argument is converted to a C string, the
+ 4th argument is ignored, and the C-string's length is used
+ in its place.
+
+ - Array: converted to a string as defined for "flexible
+ strings" and then it's treated as a JS string.
+
+ - Int8Array or Uint8Array: wasm.allocFromTypedArray() is used to
+ conver the memory to the WASM heap. If the 4th argument is
+ 0 or greater, it is used as-is, otherwise the array's byteLength
+ value is used. This is an exception to the C API's undefined
+ behavior for a negative 4th argument, but results are undefined
+ if the given 4th argument value is greater than the byteLength
+ of the input array.
+
+ - If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
+ treated as that type.
+
+ In all of those cases, the final argument (text destructor) is
+ ignored and capi.SQLITE_TRANSIENT is assumed.
+
+ A 3rd argument of `null` is treated as if it were a WASM pointer
+ of 0.
+
+ If the 3rd argument is neither a WASM pointer nor one of the
+ above-described types, capi.SQLITE_MISUSE is returned.
+
+ The first argument may be either an `sqlite3_stmt*` WASM
+ pointer or an sqlite3.oo1.Stmt instance.
+
+ For consistency with the C API, it requires the same number of
+ arguments. It returns capi.SQLITE_MISUSE if passed any other
+ argument count.
+ */
+ sqlite3_bind_blob: undefined/*installed later*/,
+
+ /**
+ sqlite3_bind_text() works exactly like its C counterpart unless
+ its 3rd argument is one of:
+
+ - JS string: the 3rd argument is converted to a C string, the
+ 4th argument is ignored, and the C-string's length is used
+ in its place.
+
+ - Array: converted to a string as defined for "flexible
+ strings". The 4th argument is ignored and a value of -1
+ is assumed.
+
+ - Int8Array or Uint8Array: is assumed to contain UTF-8 text, is
+ converted to a string. The 4th argument is ignored, replaced
+ by the array's byteLength value.
+
+ - If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
+ treated as that type.
+
+ In each of those cases, the final argument (text destructor) is
+ ignored and capi.SQLITE_TRANSIENT is assumed.
+
+ A 3rd argument of `null` is treated as if it were a WASM pointer
+ of 0.
+
+ If the 3rd argument is neither a WASM pointer nor one of the
+ above-described types, capi.SQLITE_MISUSE is returned.
+
+ The first argument may be either an `sqlite3_stmt*` WASM
+ pointer or an sqlite3.oo1.Stmt instance.
+
+ For consistency with the C API, it requires the same number of
+ arguments. It returns capi.SQLITE_MISUSE if passed any other
+ argument count.
+
+ If client code needs to bind partial strings, it needs to
+ either parcel the string up before passing it in here or it
+ must pass in a WASM pointer for the 3rd argument and a valid
+ 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.
+ */
+ sqlite3_bind_text: undefined/*installed later*/,
+
/**
sqlite3_create_function_v2() differs from its native
counterpart only in the following ways:
WASM build is compiled with emcc's `-sALLOW_TABLE_GROWTH`
flag.
*/
- sqlite3_create_function_v2: function(
+ sqlite3_create_function_v2: (
pDb, funcName, nArg, eTextRep, pApp,
xFunc, xStep, xFinal, xDestroy
- ){/*installed later*/},
+ )=>{/*installed later*/},
/**
Equivalent to passing the same arguments to
sqlite3_create_function_v2(), with 0 as the final argument.
*/
- sqlite3_create_function:function(
+ sqlite3_create_function: (
pDb, funcName, nArg, eTextRep, pApp,
xFunc, xStep, xFinal
- ){/*installed later*/},
+ )=>{/*installed later*/},
/**
The sqlite3_create_window_function() JS wrapper differs from
its native implementation in the exact same way that
xInverse(), is treated identically to xStep() by the wrapping
layer.
*/
- sqlite3_create_window_function: function(
+ sqlite3_create_window_function: (
pDb, funcName, nArg, eTextRep, pApp,
xStep, xFinal, xValue, xInverse, xDestroy
- ){/*installed later*/},
+ )=>{/*installed later*/},
/**
The sqlite3_prepare_v3() binding handles two different uses
with differing JS/WASM semantics:
toss3,
typedArrayPart
};
-
+
Object.assign(wasm, {
/**
Emscripten APIs have a deep-seated assumption that all pointers
.set('int', xArg.get('i32'))
.set('null', (i)=>i)
.set(null, xArg.get('null'))
- .set('**', __xArgPtr);
+ .set('**', __xArgPtr)
+ .set('*', __xArgPtr);
xResult.set('*', __xArgPtr)
.set('pointer', __xArgPtr)
.set('number', (v)=>Number(v))
if('string'===typeof v) return target.scopedAllocCString(v);
return v ? __xArgPtr(v) : null;
};
- xArg.set('string', __xArgString);
- xArg.set('utf8', __xArgString);
- xArg.set('pointer', __xArgString);
- xArg.set('*', __xArgString);
-
- xResult.set('string', (i)=>target.cstrToJs(i));
- xResult.set('utf8', xResult.get('string'));
- xResult.set('string:dealloc', (i)=>{
- try { return i ? target.cstrToJs(i) : null }
- finally{ target.dealloc(i) }
- });
- xResult.set('utf8:dealloc', xResult.get('string:dealloc'));
- xResult.set('json', (i)=>JSON.parse(target.cstrToJs(i)));
- xResult.set('json:dealloc', (i)=>{
- try{ return i ? JSON.parse(target.cstrToJs(i)) : null }
- finally{ target.dealloc(i) }
- });
+ xArg.set('string', __xArgString)
+ .set('utf8', __xArgString)
+ .set('pointer', __xArgString);
+ //xArg.set('*', __xArgString);
+
+ xResult.set('string', (i)=>target.cstrToJs(i))
+ .set('utf8', xResult.get('string'))
+ .set('string:dealloc', (i)=>{
+ try { return i ? target.cstrToJs(i) : null }
+ finally{ target.dealloc(i) }
+ })
+ .set('utf8:dealloc', xResult.get('string:dealloc'))
+ .set('json', (i)=>JSON.parse(target.cstrToJs(i)))
+ .set('json:dealloc', (i)=>{
+ try{ return i ? JSON.parse(target.cstrToJs(i)) : null }
+ finally{ target.dealloc(i) }
+ });
/**
Internal-use-only base class for FuncPtrAdapter and potentially
- `N*` (args): a type name in the form `N*`, where N is a numeric
type name, is treated the same as WASM pointer.
- - `*` and `pointer` (args): have multple semantics. They
- behave exactly as described below for `string` args.
+ - `*` 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): are aliases for the current
+ - `*` and `pointer` (results): aliases for the current
WASM pointer numeric type.
- `**` (args): is simply a descriptive alias for the WASM pointer
-C Internal\sJS\scleanups.\sCorrect\spart\sof\s[ac136925a645]\sto\saccount\sfor\sthe\seTextRep\sflag\sbeing\sable\sto\shold\sflags\sother\sthan\sthe\sencoding.
-D 2022-12-23T21:10:49.493
+C Reimplement\sJS's\ssqlite3_bind_text/blob()\swith\shand-written\sbindings\sto\spermit\smore\sflexible\sinputs.\sAdd\sautomated\sJS-to-C\sfunction\sconversion\sto\ssqlite3_busy_handler().\ssqlite3.wasm.xWrap()'s\s'*'\sargument\sconversion\sno\slonger\streats\sJS\sstrings\sas\sC-strings:\sthose\sconversions\srequire\sexplicit\sopt-in\svia\sthe\s'string'\sconverter\s(or\sequivalent).
+D 2022-12-23T23:46:33.608
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
-F ext/wasm/api/sqlite3-api-glue.js f50211dc11f1debf972cdaea87cb4df9772022828072e7100cf5025d1dca2a78
-F ext/wasm/api/sqlite3-api-oo1.js 4cce9671e8a31ac9b76bd8559e7827ccc2b121734e460fa9c7d243735a771ec8
-F ext/wasm/api/sqlite3-api-prologue.js 789639d256e3134563c5c9be25ade28b40e06e783885d26cccc01cd1ed4b820d
+F ext/wasm/api/sqlite3-api-glue.js f0651048a2601bf79f7f39c2c855f6417e65548417f5019ac9ac2ffb2463f2b9
+F ext/wasm/api/sqlite3-api-oo1.js c2a3e310f993a632b6c5da0c49b0635863a73df60c4f9fc0a30648f25e4ec32a
+F ext/wasm/api/sqlite3-api-prologue.js 683956ea6ab5e0132db48bb693a6bb9dd92f36c8c0902af36572e9b29006ac6d
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
-F ext/wasm/common/whwasmutil.js 97807770ec452fdcaa48509c5decd3a2c1e3001164a62a3223a347f66967533e
+F ext/wasm/common/whwasmutil.js 700fb1b702986522d2177fe8247bfbab3040e82cb4f6c35e929c4c85fbd7ffc5
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P deffe6fb211410fa1a1fbca824a52b4e09b54d4b4f4a4e12d71c9e4b7e8606fb
-R 537077e8e7a576993086a957d5c52d05
+P 1dfc03ab1e0269807beef27bf884ab9ead7553d4a5f6ed213f812d7fa052045f
+R 0557f08bf576b7be78ec588d2742348d
U stephan
-Z 379d99233453fc912eb71dcbaf16b8ce
+Z 4e12d5aedea06f895991428eb871a6d7
# Remove this line to create a well-formed Fossil manifest.
-1dfc03ab1e0269807beef27bf884ab9ead7553d4a5f6ed213f812d7fa052045f
\ No newline at end of file
+96ba44946b3e88b6aa305c4363cbbfeab0d9120b3d8c4d2587d68b9293ea7cc6
\ No newline at end of file