self.WhWasmUtilInstaller(wasm);
delete self.WhWasmUtilInstaller;
+ {
+ /**
+ Find a mapping for SQLITE_WASM_DEALLOC, which the API
+ guarantees is a WASM pointer to the same underlying function as
+ wasm.dealloc() (noting that wasm.dealloc() is permitted to be a
+ JS wrapper around the WASM function). There is unfortunately no
+ O(1) algorithm for finding this pointer: we have to walk the
+ WASM indirect function table to find it. However, experience
+ indicates that that particular function is always very close to
+ the front of the table (it's been entry #3 in all relevant
+ tests).
+ */
+ const dealloc = wasm.exports[sqlite3.config.deallocExportName];
+ const nFunc = wasm.functionTable().length;
+ let i;
+ for(i = 0; i < nFunc; ++i){
+ const e = wasm.functionEntry(i);
+ if(dealloc === e){
+ capi.SQLITE_WASM_DEALLOC = i;
+ break;
+ }
+ }
+ if(dealloc !== wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){
+ toss("Internal error: cannot find function pointer for SQLITE_WASM_DEALLOC.");
+ }
+ }
+
/**
Signatures for the WASM-exported C-side functions. Each entry
is an array with 2+ elements:
text = pMem.join('');
}
let p, n;
- try {
+ try{
if(util.isSQLableTypedArray(text)){
p = wasm.allocFromTypedArray(text);
n = text.byteLength;
"Invalid 3rd argument type for sqlite3_bind_text()."
);
}
- return __bindText(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
- }finally{
+ return __bindText(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
+ }catch(e){
wasm.dealloc(p);
+ return util.sqlite3_wasm_db_error(
+ capi.sqlite3_db_handle(pStmt), e
+ );
}
}/*sqlite3_bind_text()*/;
"Invalid 3rd argument type for sqlite3_bind_blob()."
);
}
- return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
- }finally{
+ return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
+ }catch(e){
wasm.dealloc(p);
+ return util.sqlite3_wasm_db_error(
+ capi.sqlite3_db_handle(pStmt), e
+ );
}
}/*sqlite3_bind_blob()*/;
success.
*/
const bindOne = function f(stmt,ndx,bindType,val){
- affirmUnlocked(stmt, 'bind()');
+ affirmUnlocked(affirmStmtOpen(stmt), 'bind()');
if(!f._){
f._tooBigInt = (v)=>toss3(
"BigInt value is too big to store without precision loss:", v
so we have no range checking. */
f._ = {
string: function(stmt, ndx, val, asBlob){
- const stack = wasm.scopedAllocPush();
- try{
- const [pStr, n] = wasm.scopedAllocCString(val, true);
- const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
- return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_TRANSIENT);
- }finally{
- wasm.scopedAllocPop(stack);
- }
+ const [pStr, n] = wasm.allocCString(val, true);
+ const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
+ return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_WASM_DEALLOC);
}
};
}/* static init */
toss3("Binding a value as a blob requires",
"that it be a string, Uint8Array, Int8Array, or ArrayBuffer.");
}
- const stack = wasm.scopedAllocPush();
- try{
- const pBlob = wasm.scopedAlloc(val.byteLength || 1);
- wasm.heap8().set(val.byteLength ? val : [0], pBlob)
- rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
- capi.SQLITE_TRANSIENT);
- }finally{
- wasm.scopedAllocPop(stack);
- }
+ const pBlob = wasm.alloc(val.byteLength || 1);
+ wasm.heap8().set(val.byteLength ? val : [0], pBlob)
+ rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
+ capi.SQLITE_WASM_DEALLOC);
break;
}
default:
};
/**
- Returns true if v appears to be one of our bind()-able TypedArray
- types: Uint8Array or Int8Array. Support for TypedArrays with
- element sizes >1 is a potential TODO just waiting on a use case
- to justify them.
+ Returns v if v appears to be one of our bind()-able TypedArray
+ types: Uint8Array or Int8Array or ArrayBuffer. Support for
+ TypedArrays with element sizes >1 is a potential TODO just
+ waiting on a use case to justify them. Until then, their `buffer`
+ property can be used to pass them as an ArrayBuffer. If it's not
+ a bindable array type, a falsy value is returned.
*/
const isBindableTypedArray = (v)=>{
- return v && (v instanceof Uint8Array || v instanceof Int8Array);
- //v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
+ return v && (v instanceof Uint8Array
+ || v instanceof Int8Array
+ || v instanceof ArrayBuffer);
};
/**
isSQLableTypedArray() list.
*/
const isSQLableTypedArray = (v)=>{
- return v && (v instanceof Uint8Array || v instanceof Int8Array);
- //v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
+ return v && (v instanceof Uint8Array
+ || v instanceof Int8Array
+ || v instanceof ArrayBuffer);
};
/** Returns true if isBindableTypedArray(v) does, else throws with a message
- 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.
+ In all of those cases, the final argument (destructor) is
+ ignored and capi.SQLITE_WASM_DEALLOC is assumed.
A 3rd argument of `null` is treated as if it were a WASM pointer
of 0.
treated as that type.
In each of those cases, the final argument (text destructor) is
- ignored and capi.SQLITE_TRANSIENT is assumed.
+ ignored and capi.SQLITE_WASM_DEALLOC is assumed.
A 3rd argument of `null` is treated as if it were a WASM pointer
of 0.
capi.sqlite3_result_error(pCtx, ''+e, -1);
}
};
-
+
/**
This function passes its 2nd argument to one of the
sqlite3_result_xyz() routines, depending on the type of that
- `bigint`: similar to `number` but will trigger an error if the
value is too big to store in an int64.
- `string`: `sqlite3_result_text()`
- - Uint8Array or Int8Array: `sqlite3_result_blob()`
+ - Uint8Array or Int8Array or ArrayBuffer: `sqlite3_result_blob()`
- `undefined`: is a no-op provided to simplify certain use cases.
Anything else triggers `sqlite3_result_error()` with a
f(pCtx, val);
break;
}
- case 'string':
- capi.sqlite3_result_text(pCtx, val, -1, capi.SQLITE_TRANSIENT);
+ case 'string': {
+ const [p, n] = wasm.allocCString(val,true);
+ capi.sqlite3_result_text(pCtx, p, n, capi.SQLITE_WASM_DEALLOC);
break;
+ }
case 'object':
if(null===val/*yes, typeof null === 'object'*/) {
capi.sqlite3_result_null(pCtx);
const pBlob = wasm.allocFromTypedArray(val);
capi.sqlite3_result_blob(
pCtx, pBlob, val.byteLength,
- wasm.exports[sqlite3.config.deallocExportName]
+ capi.SQLITE_WASM_DEALLOC
);
break;
}
return *p = *p * 2;
}
+SQLITE_WASM_KEEP
+void * sqlite3_wasm_test_voidptr(void * p){
+ return p;
+}
+
SQLITE_WASM_KEEP
int64_t sqlite3_wasm_test_int64_max(void){
return (int64_t)0x7fffffffffffffff;
name: 'virtual table #1: eponymous w/ manual exception handling',
predicate: ()=>!!capi.sqlite3_index_info,
test: function(sqlite3){
- warn("The vtab/module JS bindings are experimental and subject to change.");
const VT = sqlite3.vtab;
const tmplCols = Object.assign(Object.create(null),{
A: 0, B: 1
name: 'virtual table #2: non-eponymous w/ automated exception wrapping',
predicate: ()=>!!capi.sqlite3_index_info,
test: function(sqlite3){
- warn("The vtab/module JS bindings are experimental and subject to change.");
const VT = sqlite3.vtab;
const tmplCols = Object.assign(Object.create(null),{
A: 0, B: 1
-C Extend\soo1.Stmt.bind()\sto\saccept\sArrayBuffer\sinstances\sto\sbind\sas\sblobs.
-D 2022-12-24T14:16:02.217
+C Replace\sJS-side\suse\sof\sSQLITE_TRANSIENT\swith\sthe\snew\sSQLITE_WASM_DEALLOC,\sreducing\sthe\samount\sallocation/copying\srequired\sby\ssqlite3_bind_blob/text()\sand\ssqlite3_result_blob/text().\sRemove\sthe\s'experimental'\slog\smessage\sfrom\sthe\svirtual\stable\stests.
+D 2022-12-24T15:28:45.647
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 f0651048a2601bf79f7f39c2c855f6417e65548417f5019ac9ac2ffb2463f2b9
-F ext/wasm/api/sqlite3-api-oo1.js 1312eaf2776c957e41a6fd63c31e7487502bf71745805c41f72429e0925802a5
-F ext/wasm/api/sqlite3-api-prologue.js 683956ea6ab5e0132db48bb693a6bb9dd92f36c8c0902af36572e9b29006ac6d
+F ext/wasm/api/sqlite3-api-glue.js ba532798e577497da9221bf9ac7d286619eec4d16736c927f1d10f3c8d21ada3
+F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b
+F ext/wasm/api/sqlite3-api-prologue.js b0302c61abf21966c8cf9788453fea29c790633f7a14a92e05e6db994b590d11
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/api/sqlite3-v-helper.js 6f6c3e390a72e08b0a5b16a0d567d7af3c04d172831853a29d72a6f1dd40ff24
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 66daf6fb6843bea615fe193109e1542efbeca24f560ee9da63375a910bb48115
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
-F ext/wasm/api/sqlite3-wasm.c b114bb85cdf8be7b2939ddcc2bbc2f30c190c44b993c34a77b017c978345efb1
+F ext/wasm/api/sqlite3-wasm.c 313489816e1733a10ece74a92cbea65d3ee241eb07d98088e96258cc211c9719
F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
-F ext/wasm/tester1.c-pp.js 145c493221727eb40194280bb2852da49f857e850d8394c31b7bd4caeb5d7bed
+F ext/wasm/tester1.c-pp.js dec750b65ec33ff267b35370ab746899859beb0a7c695cb9b087663d5b144512
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6a37874db04f3b4842994ad17fc74cb6222f8ea0fa1315a23aff1ffa69bcd12a
-R b07f6a4d9e30a3f649f5decc82bdf7ef
+P f76bd30137fbff981625ffcb28cddd5e8651803dfc3f2d8d7801ead33496311d
+R 244f04d134cc6151e3968d82d6c44161
U stephan
-Z 934cef85bd1b053ac09da3261d128afb
+Z 5d490510463cd36c1f126d30ea32761d
# Remove this line to create a well-formed Fossil manifest.
-f76bd30137fbff981625ffcb28cddd5e8651803dfc3f2d8d7801ead33496311d
\ No newline at end of file
+ffe2999a91a7dec129a38afb675fe9e539d7c347886bfea85cba55f6367d54d1
\ No newline at end of file