('sqlite3_stmt*', aPtr)
('sqlite3_context*', aPtr)
('sqlite3_value*', aPtr)
- ('sqlite3_vfs*', aPtr)
- ('void*', aPtr);
+ ('void*', aPtr)
+ /**
+ `sqlite3_vfs*`:
+
+ - v is-a string: use the result of sqlite3_vfs_find(v) but
+ throw if it returns 0.
+ - v is-a capi.sqlite3_vfs: use v.pointer.
+ - Else return the same as the `'*'` argument conversion.
+ */
+ ('sqlite3_vfs*', (v)=>{
+ if('string'===typeof v){
+ const x = capi.sqlite3_vfs_find(v);
+ /* A NULL sqlite3_vfs pointer will be treated as the default
+ VFS in many contexts. We specifically do not want that
+ behavior here. */
+ if(!x) sqlite3.SQLite3Error.toss("Unknown sqlite3_vfs name:",v);
+ return x;
+ }else if(v instanceof sqlite3.capi.sqlite3_vfs) v = v.pointer;
+ return aPtr(v);
+ });
+
wasm.xWrap.resultAdapter('sqlite3*', aPtr)
('sqlite3_context*', aPtr)
('sqlite3_stmt*', aPtr)
'version'
]){
for(const e of Object.entries(wasm.ctype[t])){
- // ^^^ [k,v] there triggers a buggy code transormation via one
- // of the Emscripten-driven optimizers.
+ // ^^^ [k,v] there triggers a buggy code transformation via
+ // one of the Emscripten-driven optimizers.
capi[e[0]] = e[1];
}
}
constructor(...args){
if(1===args.length && __isInt(args[0])){
super(__rcStr(args[0]));
- }else if(2===args.length && 'object'===typeof args){
+ }else if(2===args.length && 'object'===typeof args[1]){
if(__isInt(args[0])) super(__rcStr(args[0]), args[1]);
else super(...args);
}else{
message.
*/
constructor(...args){
- if(2===args.length && 'object'===typeof args){
+ if(2===args.length && 'object'===typeof args[1]){
super(...args);
}else if(args.length){
super(args.join(' '));
/**
Reports info about compile-time options using
- sqlite_compileoption_get() and sqlite3_compileoption_used(). It
+ sqlite3_compileoption_get() and sqlite3_compileoption_used(). It
has several distinct uses:
If optName is an array then it is expected to be a list of
["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
];
-
/**
sqlite3.wasm.pstack (pseudo-stack) holds a special-case
stack-style allocator intended only for use with _small_ data of
"bytes for sqlite3_aggregate_context()")
: 0);
};
+
+ /**
+ 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
+ a capi.sqlite3_vfs instance. Pass 0 (a NULL pointer) to use the
+ default VFS. If passed a string which does not resolve using
+ sqlite3_vfs_find(), an exception is thrown. (Note that a WASM
+ C-string is not accepted because it is impossible to
+ distinguish from a C-level `sqlite3_vfs*`.)
+
+ The second argument, the filename, must be a JS or WASM C-string.
+
+ The 3rd may either be falsy, a valid WASM memory pointer, or a
+ Uint8Array. The 4th must be the length, in bytes, of the data
+ array to copy. If the 3rd argument is a Uint8Array and the 4th is
+ not a positive integer then the 4th defaults to the array's
+ byteLength value.
+
+ If data is falsy then a file is created with dataLen bytes filled
+ with uninitialized data (whatever truncate() leaves there). If
+ data is not falsy then a file is created or truncated and it is
+ filled with the first dataLen bytes of the data source.
+
+ Throws if any arguments are invalid or if creating or writing to
+ the file fails.
+
+ Note that most VFSes do _not_ automatically create directory
+ parts of filenames, nor do all VFSes have a concept of
+ directories. If the given filename is not valid for the given
+ VFS, an exception will be thrown. This function exists primarily
+ to assist in implementing file-upload capability, with the caveat
+ that clients must have some idea of the VFS into which they want
+ to upload and that VFS must support the operation.
+
+ VFS-specific notes:
+
+ - "memdb" and "kvvfs": results are undefined.
+
+ - "unix" and related: will use the WASM build's equivalent of the
+ POSIX I/O APIs.
+
+ - "opfs": if available, uses OPFS storage and _does_ create
+ directory parts of the filename.
+ */
+ capi.sqlite3_js_vfs_create_file = function(vfs, filename, data, dataLen){
+ let pData;
+ if(!data) pData = 0;
+ else if(wasm.isPtr(data)){
+ pData = data;
+ }else if(data instanceof Uint8Array){
+ pData = wasm.allocFromTypedArray(data);
+ if(arguments.length<4 || !util.isInt32(dataLen) || dataLen<0){
+ dataLen = data.byteLength;
+ }
+ }else{
+ SQLite3Error.toss("Invalid 3rd argument type for sqlite3_js_vfs_create_file().");
+ }
+ if(!util.isInt32(dataLen) || dataLen<0){
+ wasm.dealloc(pData);
+ SQLite3Error.toss("Invalid 4th argument for sqlite3_js_vfs_create_file().");
+ }
+ try{
+ const rc = wasm.sqlite3_wasm_vfs_create_file(vfs, filename, pData, dataLen);
+ if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
+ capi.sqlite3_js_rc_str(rc));
+ }finally{
+ wasm.dealloc(pData);
+ }
+ };
if( util.isUIThread() ){
/* Features specific to the main window thread... */
const __xResultAdapterCheck =
(t)=>xcv.result[t] || toss("Result adapter not found:",t);
-
+
cache.xWrap.convertArg = (t,v)=>__xArgAdapterCheck(t)(v);
cache.xWrap.convertResult =
(t,v)=>(null===t ? v : (t ? __xResultAdapterCheck(t)(v) : undefined));
exception.
Clients may map their own result and argument adapters using
- xWrap.resultAdapter() and xWrap.argAdaptor(), noting that not all
+ xWrap.resultAdapter() and xWrap.argAdapter(), noting that not all
type conversions are valid for both arguments _and_ result types
as they often have different memory ownership requirements.
};
}/*xWrap()*/;
- /** Internal impl for xWrap.resultAdapter() and argAdaptor(). */
+ /** Internal impl for xWrap.resultAdapter() and argAdapter(). */
const __xAdapter = function(func, argc, typeName, adapter, modeName, xcvPart){
if('string'===typeof typeName){
if(1===argc) return xcvPart[typeName];
*/
target.xWrap.argAdapter = function f(typeName, adapter){
return __xAdapter(f, arguments.length, typeName, adapter,
- 'argAdaptor()', xcv.arg);
+ 'argAdapter()', xcv.arg);
};
/**
return target.xWrap(fname, resultType, argTypes||[]).apply(null, args||[]);
};
+ /**
+ This function is ONLY exposed in the public API to facilitate
+ testing. It should not be used in application-level code, only
+ in test code.
+
+ Expects to be given (typeName, value) and returns a conversion
+ of that value as has been registered using argAdapter().
+ It throws if no adapter is found.
+
+ ACHTUNG: the adapter may require that a scopedAllocPush() is
+ active and it may allocate memory within that scope.
+ */
+ target.xWrap.testConvertArg = cache.xWrap.convertArg;
+ /**
+ This function is ONLY exposed in the public API to facilitate
+ testing. It should not be used in application-level code, only
+ in test code.
+
+ Expects to be given (typeName, value) and returns a conversion
+ of that value as has been registered using resultAdapter().
+ It throws if no adapter is found.
+
+ ACHTUNG: the adapter may allocate memory which the caller may need
+ to know how to free.
+ */
+ target.xWrap.testConvertResult = cache.xWrap.convertResult;
+
return target;
};
//log("vfsList =",vfsList);
for(const v of vfsList){
T.assert('string' === typeof v)
- .assert(capi.sqlite3_vfs_find(v) > 0);
+ .assert(wasm.isPtr(
+ capi.sqlite3_vfs_find(v)
+ ));
}
+ // While we have vfsList handy, let's verify...
+ wasm.scopedAllocCall(()=>{
+ const vfsArg = (v)=>wasm.xWrap.testConvertArg('sqlite3_vfs*',v);
+ T.assert(wasm.isPtr(vfsArg(vfsList[0])));
+ const pVfs = capi.sqlite3_vfs_find(vfsList[0]);
+ const vfs = new capi.sqlite3_vfs(pVfs);
+ T.assert(wasm.isPtr(vfsArg(vfs)));
+ vfs.dispose();
+ });
}
/**
Trivia: the magic db name ":memory:" does not actually use the
////////////////////////////////////////////////////////////////////////
T.g('OPFS (Worker thread only and only in supported browsers)',
- (sqlite3)=>{return !!sqlite3.opfs})
+ (sqlite3)=>!!sqlite3.opfs)
.t({
- name: 'OPFS sanity checks',
+ name: 'OPFS db sanity checks',
test: async function(sqlite3){
- const filename = 'sqlite3-tester1.db';
- const pVfs = capi.sqlite3_vfs_find('opfs');
+ const filename = this.opfsDbFile = 'sqlite3-tester1.db';
+ const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs');
T.assert(pVfs);
- const unlink = (fn=filename)=>wasm.sqlite3_wasm_vfs_unlink(pVfs,fn);
+ const unlink = this.opfsUnlink =
+ (fn=filename)=>{wasm.sqlite3_wasm_vfs_unlink(pVfs,fn)};
unlink();
let db = new sqlite3.oo1.OpfsDb(filename);
try {
db.close();
unlink();
}
+ }
+ }/*OPFS db sanity checks*/)
+ .t({
+ name: 'OPFS utility APIs and sqlite3_js_vfs_create_file()',
+ test: async function(sqlite3){
+ const filename = this.opfsDbFile;
+ const pVfs = this.opfsVfs;
+ const unlink = this.opfsUnlink;
+ T.assert(filename && pVfs && !!unlink);
+ unlink();
+ // Sanity-test sqlite3_js_vfs_create_file()...
+ /**************************************************************
+ ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended
+ for client-side use. It is only for this project's own
+ internal use. Its APIs are subject to change or removal at
+ any time.
+ ***************************************************************/
+ const opfs = sqlite3.opfs;
+ const fSize = 1379;
+ let sh;
+ try{
+ T.assert(!(await opfs.entryExists(filename)));
+ capi.sqlite3_js_vfs_create_file(
+ pVfs, filename, null, fSize
+ );
+ T.assert(await opfs.entryExists(filename));
+ let fh = await opfs.rootDirectory.getFileHandle(filename);
+ sh = await fh.createSyncAccessHandle();
+ T.assert(fSize === await sh.getSize());
+ await sh.close();
+ sh = undefined;
+ unlink();
+ T.assert(!(await opfs.entryExists(filename)));
+
+ const ba = new Uint8Array([1,2,3,4,5]);
+ capi.sqlite3_js_vfs_create_file(
+ "opfs", filename, ba
+ );
+ T.assert(await opfs.entryExists(filename));
+ fh = await opfs.rootDirectory.getFileHandle(filename);
+ sh = await fh.createSyncAccessHandle();
+ T.assert(ba.byteLength === await sh.getSize());
+ await sh.close();
+ sh = undefined;
+ unlink();
- if(sqlite3.opfs){
- // Sanity-test sqlite3_wasm_vfs_create_file()...
- const opfs = sqlite3.opfs;
- const fSize = 1379;
- let sh;
- try{
- T.assert(!(await opfs.entryExists(filename)));
- let rc = wasm.sqlite3_wasm_vfs_create_file(
- pVfs, filename, null, fSize
+ T.mustThrowMatching(()=>{
+ capi.sqlite3_js_vfs_create_file(
+ "no-such-vfs", filename, ba
);
- T.assert(0===rc)
- .assert(await opfs.entryExists(filename));
- const fh = await opfs.rootDirectory.getFileHandle(filename);
- sh = await fh.createSyncAccessHandle();
- T.assert(fSize === await sh.getSize());
- }finally{
- if(sh) await sh.close();
- unlink();
- }
-
- // Some sanity checks of the opfs utility functions...
- const testDir = '/sqlite3-opfs-'+opfs.randomFilename(12);
- const aDir = testDir+'/test/dir';
- T.assert(await opfs.mkdir(aDir), "mkdir failed")
- .assert(await opfs.mkdir(aDir), "mkdir must pass if the dir exists")
- .assert(!(await opfs.unlink(testDir+'/test')), "delete 1 should have failed (dir not empty)")
- .assert((await opfs.unlink(testDir+'/test/dir')), "delete 2 failed")
- .assert(!(await opfs.unlink(testDir+'/test/dir')),
- "delete 2b should have failed (dir already deleted)")
- .assert((await opfs.unlink(testDir, true)), "delete 3 failed")
- .assert(!(await opfs.entryExists(testDir)),
- "entryExists(",testDir,") should have failed");
+ }, "Unknown sqlite3_vfs name: no-such-vfs");
+ }finally{
+ if(sh) await sh.close();
+ unlink();
}
+
+ // Some sanity checks of the opfs utility functions...
+ const testDir = '/sqlite3-opfs-'+opfs.randomFilename(12);
+ const aDir = testDir+'/test/dir';
+ T.assert(await opfs.mkdir(aDir), "mkdir failed")
+ .assert(await opfs.mkdir(aDir), "mkdir must pass if the dir exists")
+ .assert(!(await opfs.unlink(testDir+'/test')), "delete 1 should have failed (dir not empty)")
+ .assert((await opfs.unlink(testDir+'/test/dir')), "delete 2 failed")
+ .assert(!(await opfs.unlink(testDir+'/test/dir')),
+ "delete 2b should have failed (dir already deleted)")
+ .assert((await opfs.unlink(testDir, true)), "delete 3 failed")
+ .assert(!(await opfs.entryExists(testDir)),
+ "entryExists(",testDir,") should have failed");
}
- }/*OPFS sanity checks*/)
+ }/*OPFS util sanity checks*/)
;/* end OPFS tests */
////////////////////////////////////////////////////////////////////////
-C Add\sa\stestcase()\smacro\sto\sverify\sthat\sthe\scase\sof\sa\sNOT\sNULL\serror\smessage\nhitting\sthe\sstring\slength\slimit.
-D 2022-11-30T21:18:23.655
+C Expand\s"sqlite3_vfs*"\sJS-to-WASM\sfunction\sargument\sconversions\sto\saccept\sVFS\snames\s(JS\sstrings)\sand\scapi.sqlite3_vfs\sinstances.\sImplement\ssqlite3_js_vfs_create_file()\sto\sfacilitate\screation\sof\sfile-upload\sfeatures\swhich\sstore\sthe\sfile\sin\sVFS-specific\sstorage\s(where\spossible,\se.g.\s"unix"\sand\s"opfs"\sVFSes).\sCorrect\san\sargument\stype\scheck\sin\sthe\sSQLite3Error\sand\sWasmAllocError\sconstructors.
+D 2022-12-01T03:55:28.175
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 03c40b65530d67bb2748b7380aea5fd1534500f812b76a6b401066dcd7fc4116
+F ext/wasm/api/sqlite3-api-glue.js 5468ba750e081c55ff3c572e3ae47dd415be73907ce40117fb121f37f4d0649e
F ext/wasm/api/sqlite3-api-oo1.js 06ad2079368e16cb9f182c18cd37bdc3932536856dff4f60582d0ca5f6c491a8
-F ext/wasm/api/sqlite3-api-prologue.js e63bcd1d1942d3313bd11e76ac1fccdd3e34ba54a48b8c8296db8dd892705dbc
+F ext/wasm/api/sqlite3-api-prologue.js 04f789bab878ea67be8b18dd4292011bbfeb78ebad79eb79c591136332bd469a
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 9963c78bf6e5ccb5ba28e8597851bd9d980e86803b6d341cc985e586aef10c82
F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/common/testing.css 35889709547d89a6109ff83b25c11bbc91d8dd43aab8722e428655ca98880a06
-F ext/wasm/common/whwasmutil.js 16a592d5c304a2d268ca1c28e08a5b029a2f3cbe10af78dbc3456cfc9e3559d1
+F ext/wasm/common/whwasmutil.js dbe625a22bf0962cde1f958f2be604d27d2f97ee1b4e6ee0f19c6480aa36aeed
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
F ext/wasm/tester1-worker.html 5ef353348c37cf2e4fd0b23da562d3275523e036260b510734e9a3239ba8c987
F ext/wasm/tester1.c-pp.html 74aa9b31c75f12490653f814b53c3dd39f40cd3f70d6a53a716f4e8587107399
-F ext/wasm/tester1.c-pp.js c39594bb1a0272a08a1544277a29c1ed920b4c4877611591e7c3185744ae2431
+F ext/wasm/tester1.c-pp.js b6a8b9d8e8b070d40c140a68072bf0aa41819fe37fb5bbb9391966a3cbc154fa
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
F ext/wasm/tests/opfs/concurrency/test.js bfc3d7e27b207f0827f12568986b8d516a744529550b449314f5c21c9e9faf4a
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 6ee61f8cede4998f0c838d6506b058c6b09f34b3d7f30ed296100785c93f8d00
-R ca2f65a200c7997e977e891739f47e7d
-U drh
-Z 02ee85efaa582407b1d21e8a02ad86a6
+P 91f50964c10fb12d889bda7d597d8edf475d97d2d8b534b4400e0fed1d753c6a
+R e4bc31bd87c945bd19fac07fc1661145
+U stephan
+Z a323b013b8116acefa1b2ce6dcb45815
# Remove this line to create a well-formed Fossil manifest.
-91f50964c10fb12d889bda7d597d8edf475d97d2d8b534b4400e0fed1d753c6a
\ No newline at end of file
+e1009b16d351b23676ad7bffab0c91b373a92132eb855c9af61991b50cd237ed
\ No newline at end of file