Throws if storage name n (JS string) is not valid for use as a
storage name. Much of this goes back to kvvfs having a fixed
buffer size for its keys, and the storage name needing to be
- encoded in the keys for local/session storage. We disallow
- non-ASCII to avoid problems with truncated multibyte characters
- at the end of the key buffer.
+ encoded in the keys for local/session storage.
The second argument must only be true when called from xOpen() -
it makes names with a "-journal" suffix legal.
*/
const validateStorageName = function(n,mayBeJournal=false){
if( kvvfsIsPersistentName(n) ) return;
- const len = n.length;
+ const len = (new Blob([n])).size/*byte length*/;
if( !len ) toss3(capi.SQLITE_RANGE, "Empty name is not permitted.");
let maxLen = cache.keySize - 1;
if( cache.rxJournalSuffix.test(n) ){
"Storage names may not have a '-journal' suffix.");
}
}else{
- maxLen -= 8 /* "-journal" */;
+ maxLen -= 8 /* so we have space for a matching "-journal" suffix */;
}
if( len > maxLen ){
toss3(capi.SQLITE_RANGE, "Storage name is too long. Limit =", maxLen);
let i;
for( i = 0; i < len; ++i ){
const ch = n.codePointAt(i);
- if( ch<43 || ch >126 ){
+ if( ch<32 ){
toss3(capi.SQLITE_RANGE,
"Illegal character ("+ch+"d) in storage name:",n);
}
'sync': true if it's from xSync(), false if it's from
xFileControl().
+
+ For efficiency's sake, all calls to this function should
+ be in the form:
+
+ store.listeners && notifyListeners(...);
+
+ Failing to do so will trigger an exceptin in this function (which
+ will be ignored but may produce a console warning).
*/
const notifyListeners = async function(eventName,store,...args){
try{
- if( store.listeners ){
- //cache.rxPageNoSuffix ??= /(\d+)$/;
- if( store.keyPrefix && args[0] ){
- args[0] = args[0].replace(store.keyPrefix,'');
- }
- let u8enc, z0, z1, wcache;
- for(const ear of store.listeners){
- const ev = Object.create(null);
- ev.storageName = store.jzClass;
- ev.type = eventName;
- const decodePages = ear.decodePages;
- const f = ear.events[eventName];
- if( f ){
- if( !ear.includeJournal && args[0]==='jrnl' ){
+ //cache.rxPageNoSuffix ??= /(\d+)$/;
+ if( store.keyPrefix && args[0] ){
+ args[0] = args[0].replace(store.keyPrefix,'');
+ }
+ let u8enc, z0, z1, wcache;
+ for(const ear of store.listeners){
+ const ev = Object.create(null);
+ ev.storageName = store.jzClass;
+ ev.type = eventName;
+ const decodePages = ear.decodePages;
+ const f = ear.events[eventName];
+ if( f ){
+ if( !ear.includeJournal && args[0]==='jrnl' ){
+ continue;
+ }
+ if( 'write'===eventName && ear.decodePages && +args[0]>0 ){
+ /* Decode pages to Uint8Array, caching the result in
+ wcache in case we have more listeners. */
+ ev.data = [args[0]];
+ if( wcache?.[args[0]] ){
+ ev.data[1] = wcache[args[0]];
continue;
}
- if( 'write'===eventName && ear.decodePages && +args[0]>0 ){
- /* Decode pages to Uint8Array, caching the result in
- wcache in case we have more listeners. */
- ev.data = [args[0]];
- if( wcache?.[args[0]] ){
- ev.data[1] = wcache[args[0]];
- continue;
- }
- u8enc ??= new TextEncoder('utf-8');
- z0 ??= cache.memBuffer(10);
- z1 ??= cache.memBuffer(11);
- const u = u8enc.encode(args[1]);
- const heap = wasm.heap8u();
- heap.set(u, Number(z0));
- heap[wasm.ptr.addn(z0, u.length)] = 0;
- const rc = kvvfsDecode(z0, z1, cache.buffer.n);
- if( rc>0 ){
- wcache ??= Object.create(null);
- wcache[args[0]]
- = ev.data[1]
- = heap.slice(Number(z1), wasm.ptr.addn(z1,rc));
- }else{
- continue;
- }
+ u8enc ??= new TextEncoder('utf-8');
+ z0 ??= cache.memBuffer(10);
+ z1 ??= cache.memBuffer(11);
+ const u = u8enc.encode(args[1]);
+ const heap = wasm.heap8u();
+ heap.set(u, Number(z0));
+ heap[wasm.ptr.addn(z0, u.length)] = 0;
+ const rc = kvvfsDecode(z0, z1, cache.buffer.n);
+ if( rc>0 ){
+ wcache ??= Object.create(null);
+ wcache[args[0]]
+ = ev.data[1]
+ = heap.slice(Number(z1), wasm.ptr.addn(z1,rc));
}else{
- ev.data = args.length
- ? ((args.length===1) ? args[0] : args)
- : undefined;
- }
- try{f(ev)?.catch?.(catchForNotify)}
- catch(e){
- warn("notifyListeners [",store.jzClass,"]",eventName,e);
+ continue;
}
+ }else{
+ ev.data = args.length
+ ? ((args.length===1) ? args[0] : args)
+ : undefined;
+ }
+ try{f(ev)?.catch?.(catchForNotify)}
+ catch(e){
+ warn("notifyListeners [",store.jzClass,"]",eventName,e);
}
}
}
const jzClass = wasm.cstrToJs(zName);
//debug("xOpen",jzClass);
validateStorageName(jzClass, true);
- util.assert( jzClass.length===wasm.cstrlen(zName),
- "ASCII-only validation failed" );
if( (flags & (capi.SQLITE_OPEN_MAIN_DB
| capi.SQLITE_OPEN_TEMP_DB
| capi.SQLITE_OPEN_TRANSIENT_DB))
const DB = sqlite3.oo1.DB;
T.mustThrowMatching(()=>{
- new JDb("this is an illegal name too long and spaces");
+ new JDb("this\ns an illegal - contains control characters");
/* We don't have a way to get error strings from xOpen()
to this point? xOpen() does not have a handle to the
db and SQLite is not calling xGetLastError() to fetch
the error string. */
}, capi.SQLITE_RANGE);
T.mustThrowMatching(()=>{
- new JDb("012345678901234567890123"/*too long*/);
+ new JDb("01234567890123456789"+
+ "01234567890123456789"+
+ "01234567890123456789"+
+ "01234567890123456789"+
+ "01234567890123456789"+
+ "01234567890123456789"+
+ "0"/*too long*/);
}, capi.SQLITE_RANGE);
T.mustThrowMatching(()=>new JDb(""), capi.SQLITE_RANGE);
{
name: 'concurrent transient kvvfs',
//predicate: ()=>false,
test: function(sqlite3){
- const filename = 'my';
+ const filename = '👷';
const kvvfs = sqlite3.kvvfs;
const DB = sqlite3.oo1.DB;
const JDb = sqlite3.oo1.JsStorageDb;
includeJournal: pglog.includeJournal,
decodePages: pglog.decodePages,
events: {
+ /**
+ These may be async but must not be in this case
+ because we can't test their result without a lot of
+ hoop-jumping if they are. Kvvfs calls these
+ asynchronously, though.
+ */
'open': (ev)=>{
//console.warn('open',ev);
incr(ev.type);
.assert('number'===typeof ev.data);
},
'close': (ev)=>{
- //^^^ if this is async, we can't time the test for
- // pglog.exception without far more hoop-jumping.
//console.warn('close',ev);
incr(ev.type);
T.assert('number'===typeof ev.data);
-C Reformulate\ssqlite3-wasm.c's\sexports\sso\sthat\sthey\sexport\sproperly\swith\sthe\swask-sdk\scompiler.
-D 2025-12-01T16:25:53.470
+C Relax\sthe\sname\slimits\son\skvvfs\sdbs.
+D 2025-12-01T16:28:55.133
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
-F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js 82e29781ab83805c7c82ddfe3b5c8fdbc65a914f1433bf966fd7f0f08c7c7c8b
+F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js 7b723b492460c1531334b0855f02556b45fc767f0276fe7110f5d651679a8a70
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js a2eea6442556867b589e04107796c6e1d04a472219529eeb45b7cd221d7d048b
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 88ce2078267a2d1af57525a32d896295f4a8db7664de0e17e82dc9ff006ed8d3
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 366596d8ff73d4cefb938bbe95bc839d503c3fab6c8335ce4bf52f0d8a7dee81
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.c-pp.html 0e432ec2c0d99cd470484337066e8d27e7aee4641d97115338f7d962bf7b081a
F ext/wasm/tester1.c-pp.html 52d88fe2c6f21a046030a36410b4839b632f4424028197a45a3d5669ea724ddb
-F ext/wasm/tester1.c-pp.js f248ff562b75ce1040c8d148d648afce7cad50683f532cac96dd82ccabcf282e
+F ext/wasm/tester1.c-pp.js 7506d33282dd3e02437a0e3f2eb477c7ae346099d28d482a74a5b4ee9d4028c5
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 104291469169bef0c2ec5aee9c1cc505447541801bc822e6d5fe5360aef6a2e4
-R 53cc160340c8953977c4053fb7d21394
+P d71849958aabdb05225be18d6bc46699cfda9de67c7105b11c3f79d1d01f47d4
+R fd9d654ea19b0109ad238cc31ff79cd0
U stephan
-Z 34eeecdc220cc86d4441f67333d1408a
+Z 7cd40f087bc8b7facc6511e6b1140591
# Remove this line to create a well-formed Fossil manifest.