1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-27 20:41:58 +03:00

wasm/js: rename /persistent to /opfs to account for potential future persistent storage options. Minor flag-handling cleanups in the speedtest1 pages. Minor API tweaks in oo1.

FossilOrigin-Name: 4dc972a3656b2a9ec915bfb3f653136560c753ce4024c3f0d0d0c28f66db7a0a
This commit is contained in:
stephan
2022-09-27 09:17:37 +00:00
parent 278d3faf1f
commit 3d64548491
14 changed files with 372 additions and 359 deletions

View File

@ -495,24 +495,25 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
} }
}, },
/** /**
Similar to this.filename but will return a falsy value for Similar to the this.filename property but will return a falsy
special names like ":memory:". Throws if the DB has been value for special names like ":memory:". Throws if the DB has
closed. If passed an argument it then it will return the been closed. If passed an argument it then it will return the
filename of the ATTACHEd db with that name, else it assumes a filename of the ATTACHEd db with that name, else it assumes a
name of `main`. name of `main`. The argument may be either a JS string or
a pointer to a WASM-allocated C-string.
*/ */
getFilename: function(dbName='main'){ getFilename: function(dbName='main'){
return capi.sqlite3_db_filename(affirmDbOpen(this).pointer, dbName); return capi.sqlite3_db_filename(affirmDbOpen(this).pointer, dbName);
}, },
/** /**
Returns true if this db instance has a name which resolves to a Returns true if this db instance has a name which resolves to a
file. If the name is "" or ":memory:", it resolves to false. file. If the name is "" or starts with ":", it resolves to false.
Note that it is not aware of the peculiarities of URI-style Note that it is not aware of the peculiarities of URI-style
names and a URI-style name for a ":memory:" db will fool it. names and a URI-style name for a ":memory:" db will fool it.
Returns false if this db is closed. Returns false if this db is closed.
*/ */
hasFilename: function(){ hasFilename: function(){
return this.filename && ':memory'!==this.filename; return this.filename && ':'!==this.filename[0];
}, },
/** /**
Returns the name of the given 0-based db number, as documented Returns the name of the given 0-based db number, as documented
@ -525,9 +526,13 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Compiles the given SQL and returns a prepared Stmt. This is Compiles the given SQL and returns a prepared Stmt. This is
the only way to create new Stmt objects. Throws on error. the only way to create new Stmt objects. Throws on error.
The given SQL must be a string, a Uint8Array holding SQL, or a The given SQL must be a string, a Uint8Array holding SQL, a
WASM pointer to memory holding the NUL-terminated SQL string. WASM pointer to memory holding the NUL-terminated SQL string,
If the SQL contains no statements, an SQLite3Error is thrown. or an array of strings. In the latter case, the array is
concatenated together, with no separators, to form the SQL
string (arrays are often a convenient way to formulate long
statements). If the SQL contains no statements, an
SQLite3Error is thrown.
Design note: the C API permits empty SQL, reporting it as a 0 Design note: the C API permits empty SQL, reporting it as a 0
result code and a NULL stmt pointer. Supporting that case here result code and a NULL stmt pointer. Supporting that case here
@ -541,6 +546,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/ */
prepare: function(sql){ prepare: function(sql){
affirmDbOpen(this); affirmDbOpen(this);
if(Array.isArray(sql)) sql = sql.join('');
const stack = capi.wasm.scopedAllocPush(); const stack = capi.wasm.scopedAllocPush();
let ppStmt, pStmt; let ppStmt, pStmt;
try{ try{

View File

@ -883,12 +883,15 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
hook in to any C-side calls to sqlite3_initialize(), so we hook in to any C-side calls to sqlite3_initialize(), so we
cannot add an after-initialize callback mechanism. cannot add an after-initialize callback mechanism.
*/ */
opfsUtil.reregisterVfs = (asDefault=false)=>{ opfsUtil.registerVfs = (asDefault=false)=>{
return capi.wasm.exports.sqlite3_vfs_register( return capi.wasm.exports.sqlite3_vfs_register(
opfsVfs.pointer, asDefault ? 1 : 0 opfsVfs.pointer, asDefault ? 1 : 0
); );
}; };
//TODO to support fiddle db upload:
//opfsUtil.createFile = function(absName, content=undefined){...}
if(sqlite3.oo1){ if(sqlite3.oo1){
opfsUtil.OpfsDb = function(...args){ opfsUtil.OpfsDb = function(...args){
const opt = sqlite3.oo1.dbCtorHelper.normalizeArgs(...args); const opt = sqlite3.oo1.dbCtorHelper.normalizeArgs(...args);

View File

@ -120,7 +120,7 @@
the `free(3)`-compatible routine for the WASM the `free(3)`-compatible routine for the WASM
environment. Defaults to `"free"`. environment. Defaults to `"free"`.
- `persistentDirName`[^1]: if the environment supports persistent storage, this - `wasmfsOpfsDir`[^1]: if the environment supports persistent storage, this
directory names the "mount point" for that directory. It must be prefixed directory names the "mount point" for that directory. It must be prefixed
by `/` and may currently contain only a single directory-name part. Using by `/` and may currently contain only a single directory-name part. Using
the root directory name is not supported by any current persistent backend. the root directory name is not supported by any current persistent backend.
@ -157,7 +157,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
})(), })(),
allocExportName: 'malloc', allocExportName: 'malloc',
deallocExportName: 'free', deallocExportName: 'free',
persistentDirName: '/persistent' wasmfsOpfsDir: '/opfs'
}; };
Object.keys(configDefaults).forEach(function(k){ Object.keys(configDefaults).forEach(function(k){
config[k] = Object.getOwnPropertyDescriptor(apiConfig, k) config[k] = Object.getOwnPropertyDescriptor(apiConfig, k)
@ -174,7 +174,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
[ [
// If any of these config options are functions, replace them with // If any of these config options are functions, replace them with
// the result of calling that function... // the result of calling that function...
'Module', 'exports', 'memory', 'persistentDirName' 'Module', 'exports', 'memory', 'wasmfsOpfsDir'
].forEach((k)=>{ ].forEach((k)=>{
if('function' === typeof config[k]){ if('function' === typeof config[k]){
config[k] = config[k](); config[k] = config[k]();
@ -185,8 +185,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
all args with a space between each. */ all args with a space between each. */
const toss = (...args)=>{throw new Error(args.join(' '))}; const toss = (...args)=>{throw new Error(args.join(' '))};
if(config.persistentDirName && !/^\/[^/]+$/.test(config.persistentDirName)){ if(config.wasmfsOpfsDir && !/^\/[^/]+$/.test(config.wasmfsOpfsDir)){
toss("config.persistentDirName must be falsy or in the form '/dir-name'."); toss("config.wasmfsOpfsDir must be falsy or in the form '/dir-name'.");
} }
/** /**
@ -727,7 +727,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
capi.sqlite3_web_persistent_dir = function(){ capi.sqlite3_web_persistent_dir = function(){
if(undefined !== __persistentDir) return __persistentDir; if(undefined !== __persistentDir) return __persistentDir;
// If we have no OPFS, there is no persistent dir // If we have no OPFS, there is no persistent dir
const pdir = config.persistentDirName; const pdir = config.wasmfsOpfsDir;
if(!pdir if(!pdir
|| !self.FileSystemHandle || !self.FileSystemHandle
|| !self.FileSystemDirectoryHandle || !self.FileSystemDirectoryHandle
@ -748,7 +748,6 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
const pVfs = sqlite3.capi.sqlite3_vfs_find("unix-none"); const pVfs = sqlite3.capi.sqlite3_vfs_find("unix-none");
if(pVfs){ if(pVfs){
capi.sqlite3_vfs_register(pVfs,1); capi.sqlite3_vfs_register(pVfs,1);
console.warn("Installed 'unix-none' as the default sqlite3 VFS.");
} }
return __persistentDir = pdir; return __persistentDir = pdir;
}else{ }else{

View File

@ -571,7 +571,7 @@ int sqlite3_wasm_vfs_unlink(const char * zName){
WASM_KEEP WASM_KEEP
int sqlite3_wasm_init_wasmfs(const char *zMountPoint){ int sqlite3_wasm_init_wasmfs(const char *zMountPoint){
static backend_t pOpfs = 0; static backend_t pOpfs = 0;
if( !zMountPoint || !*zMountPoint ) zMountPoint = "/persistent"; if( !zMountPoint || !*zMountPoint ) zMountPoint = "/opfs";
if( !pOpfs ){ if( !pOpfs ){
pOpfs = wasmfs_create_opfs_backend(); pOpfs = wasmfs_create_opfs_backend();
if( pOpfs ){ if( pOpfs ){
@ -595,7 +595,8 @@ int sqlite3_wasm_init_wasmfs(const char *zMountPoint){
} }
#else #else
WASM_KEEP WASM_KEEP
int sqlite3_wasm_init_wasmfs(void){ int sqlite3_wasm_init_wasmfs(const char *zUnused){
if(zUnused){/*unused*/}
return SQLITE_NOTFOUND; return SQLITE_NOTFOUND;
} }
#endif /* __EMSCRIPTEN__ && SQLITE_WASM_WASMFS */ #endif /* __EMSCRIPTEN__ && SQLITE_WASM_WASMFS */

View File

@ -221,7 +221,7 @@
sqlite3 API. sqlite3 API.
*/ */
sqlite3ApiConfig: { sqlite3ApiConfig: {
persistentDirName: "/persistent" wasmfsOpfsDir: "/opfs"
}, },
/** /**
Intended to be called by apps which need to call the Intended to be called by apps which need to call the

View File

@ -44,7 +44,7 @@
oo = sqlite3.oo1/*high-level OO API*/; oo = sqlite3.oo1/*high-level OO API*/;
log("sqlite3 version",capi.sqlite3_libversion(), capi.sqlite3_sourceid()); log("sqlite3 version",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
const db = new oo.DB("/mydb.sqlite3"); const db = new oo.DB("/mydb.sqlite3");
log("transient b =",db.filename); log("transient db =",db.filename);
/** /**
Never(!) rely on garbage collection to clean up DBs and Never(!) rely on garbage collection to clean up DBs and
(especially) prepared statements. Always wrap their lifetimes (especially) prepared statements. Always wrap their lifetimes
@ -82,7 +82,12 @@
} }
log("Insert using a prepared statement..."); log("Insert using a prepared statement...");
let q = db.prepare("insert into t(a,b) values(?,?)"); let q = db.prepare([
// SQL may be a string or array of strings
// (concatenated w/o separators).
"insert into t(a,b) ",
"values(?,?)"
]);
try { try {
for( i = 100; i < 103; ++i ){ for( i = 100; i < 103; ++i ){
q.bind( [i, i*2] ).step(); q.bind( [i, i*2] ).step();

View File

@ -170,7 +170,7 @@
stdout("\nOPFS is available. To open a persistent db, use:\n\n", stdout("\nOPFS is available. To open a persistent db, use:\n\n",
" .open file:name?vfs=opfs\n\nbut note that some", " .open file:name?vfs=opfs\n\nbut note that some",
"features (e.g. upload) do not yet work with OPFS."); "features (e.g. upload) do not yet work with OPFS.");
S.opfs.reregisterVfs(); S.opfs.registerVfs();
} }
stdout('\nEnter ".help" for usage hints.'); stdout('\nEnter ".help" for usage hints.');
this.exec([ // initialization commands... this.exec([ // initialization commands...

View File

@ -14,7 +14,7 @@
builds. All of them require that this directory have been builds. All of them require that this directory have been
"make"d first. The intent is that <em>this</em> page be run "make"d first. The intent is that <em>this</em> page be run
using:</div> using:</div>
<blockquote><pre>althttpd -page index.html</pre></blockquote> <blockquote><pre>althttpd -enable-sab -page index.html</pre></blockquote>
<div>and the individual tests be started in their own tab. <div>and the individual tests be started in their own tab.
Warnings and Caveats: Warnings and Caveats:
<ul class='warning'> <ul class='warning'>
@ -23,9 +23,8 @@
<a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a> <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a>
and and
<a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy'>COEP</a> <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy'>COEP</a>
headers. The default build headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the
of <a href='https://sqlite.org/althttpd'>althttpd</a> <code>-enable-sab</code> flag for that.
<em>does not</em>.
</li> </li>
<li>Any OPFS-related pages require very recent version of <li>Any OPFS-related pages require very recent version of
Chrome or Chromium (v102 at least, possibly newer). OPFS Chrome or Chromium (v102 at least, possibly newer). OPFS
@ -37,9 +36,6 @@
page may depend on build-time options which are <em>off by page may depend on build-time options which are <em>off by
default</em> because they currently (as of 2022-09-08) break default</em> because they currently (as of 2022-09-08) break
with Worker-based pages. with Worker-based pages.
<!-- Similarly, WASMFS does not work on some platforms,
e.g. Raspberry Pi 4 (for which there is no Chrome
build, so it's currently a moot point). -->
</li> </li>
</ul> </ul>
</div> </div>
@ -63,9 +59,9 @@
<li>speedtest1 ports (sqlite3's primary benchmarking tool)... <li>speedtest1 ports (sqlite3's primary benchmarking tool)...
<ul> <ul>
<li><a href='speedtest1.html'>speedtest1</a>: a main-thread WASM build of speedtest1.</li> <li><a href='speedtest1.html'>speedtest1</a>: a main-thread WASM build of speedtest1.</li>
<li><a href='speedtest1-wasmfs.html'>speedtest1-wasmfs</a>: a variant of speedtest1 built solely for the wasmfs/opfs feature.</li> <li><a href='speedtest1-wasmfs.html?flags=--size,25'>speedtest1-wasmfs</a>: a variant of speedtest1 built solely for the wasmfs/opfs feature.</li>
<li><a href='speedtest1.html?vfs=kvvfs'>speedtest1-kvvfs</a>: speedtest1 with the kvvfs.</li> <li><a href='speedtest1.html?vfs=kvvfs'>speedtest1-kvvfs</a>: speedtest1 with the kvvfs.</li>
<li><a href='speedtest1-worker.html'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li> <li><a href='speedtest1-worker.html?size=25'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li>
<li><a href='speedtest1-worker.html?vfs=opfs&size=25'>speedtest1-worker-opfs</a>: speedtest1-worker with the <li><a href='speedtest1-worker.html?vfs=opfs&size=25'>speedtest1-worker-opfs</a>: speedtest1-worker with the
OPFS VFS preselected and configured for a moderate workload.</li> OPFS VFS preselected and configured for a moderate workload.</li>
</ul> </ul>

View File

@ -39,115 +39,113 @@
<script src="common/SqliteTestUtil.js"></script> <script src="common/SqliteTestUtil.js"></script>
<script src="speedtest1-wasmfs.js"></script> <script src="speedtest1-wasmfs.js"></script>
<script>(function(){ <script>(function(){
/** /**
If this environment contains OPFS, this function initializes it and If this environment contains OPFS, this function initializes it and
returns the name of the dir on which OPFS is mounted, else it returns returns the name of the dir on which OPFS is mounted, else it returns
an empty string. an empty string.
*/ */
const wasmfsDir = function f(wasmUtil){ const wasmfsDir = function f(wasmUtil,dirName="/opfs"){
if(undefined !== f._) return f._; if(undefined !== f._) return f._;
const pdir = '/persistent'; if( !self.FileSystemHandle
if( !self.FileSystemHandle || !self.FileSystemDirectoryHandle
|| !self.FileSystemDirectoryHandle || !self.FileSystemFileHandle){
|| !self.FileSystemFileHandle){
return f._ = ""; return f._ = "";
} }
try{ try{
if(0===wasmUtil.xCallWrapped( if(0===wasmUtil.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName
)){ )){
return f._ = pdir; return f._ = dirName;
}else{ }else{
return f._ = ""; return f._ = "";
} }
}catch(e){ }catch(e){
// sqlite3_wasm_init_wasmfs() is not available // sqlite3_wasm_init_wasmfs() is not available
return f._ = ""; return f._ = "";
} }
}; };
wasmfsDir._ = undefined; wasmfsDir._ = undefined;
const eOut = document.querySelector('#test-output'); const eOut = document.querySelector('#test-output');
const log2 = function(cssClass,...args){ const log2 = function(cssClass,...args){
const ln = document.createElement('div'); const ln = document.createElement('div');
if(cssClass) ln.classList.add(cssClass); if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' '))); ln.append(document.createTextNode(args.join(' ')));
eOut.append(ln); eOut.append(ln);
//this.e.output.lastElementChild.scrollIntoViewIfNeeded(); //this.e.output.lastElementChild.scrollIntoViewIfNeeded();
}; };
const logList = []; const logList = [];
const dumpLogList = function(){ const dumpLogList = function(){
logList.forEach((v)=>log2('',v)); logList.forEach((v)=>log2('',v));
logList.length = 0; logList.length = 0;
}; };
/* can't update DOM while speedtest is running unless we run /* can't update DOM while speedtest is running unless we run
speedtest in a worker thread. */; speedtest in a worker thread. */;
const log = (...args)=>{ const log = (...args)=>{
console.log(...args); console.log(...args);
logList.push(args.join(' ')); logList.push(args.join(' '));
}; };
const logErr = function(...args){ const logErr = function(...args){
console.error(...args); console.error(...args);
logList.push('ERROR: '+args.join(' ')); logList.push('ERROR: '+args.join(' '));
}; };
const runTests = function(sqlite3){ const runTests = function(sqlite3){
console.log("Module inited."); console.log("Module inited.");
const wasm = sqlite3.capi.wasm; const wasm = sqlite3.capi.wasm;
const unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]); const unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]);
const pDir = wasmfsDir(wasm); const pDir = wasmfsDir(wasm);
if(pDir) log2('',"Persistent storage:",pDir); if(pDir) log2('',"Persistent storage:",pDir);
else{ else{
log2('error',"Expecting persistent storage in this build."); log2('error',"Expecting persistent storage in this build.");
return; return;
} }
const scope = wasm.scopedAllocPush(); const scope = wasm.scopedAllocPush();
const dbFile = pDir+"/speedtest1.db"; const dbFile = pDir+"/speedtest1.db";
const urlParams = self.SqliteTestUtil.processUrlArgs(); const urlParams = new URL(self.location.href).searchParams;
const argv = ["speedtest1"]; const argv = ["speedtest1"];
if(urlParams.flags){ if(urlParams.has('flags')){
argv.push(...(urlParams.flags.split(','))); argv.push(...(urlParams.get('flags').split(',')));
let i = argv.indexOf('--vfs'); let i = argv.indexOf('--vfs');
if(i>=0) argv.splice(i,2); if(i>=0) argv.splice(i,2);
}else{ }else{
argv.push( argv.push(
"--singlethread", "--singlethread",
"--nomutex", "--nomutex",
"--nosync", "--nosync",
"--nomemstat" "--nomemstat"
); );
//"--memdb", // note that memdb trumps the filename arg //"--memdb", // note that memdb trumps the filename arg
} }
if(argv.indexOf('--memdb')>=0){ if(argv.indexOf('--memdb')>=0){
log2('error',"WARNING: --memdb flag trumps db filename."); log2('error',"WARNING: --memdb flag trumps db filename.");
} }
argv.push("--big-transactions"/*important for tests 410 and 510!*/, argv.push("--big-transactions"/*important for tests 410 and 510!*/,
dbFile); dbFile);
console.log("argv =",argv); console.log("argv =",argv);
// These log messages are not emitted to the UI until after main() returns. Fixing that // These log messages are not emitted to the UI until after main() returns. Fixing that
// requires moving the main() call and related cleanup into a timeout handler. // requires moving the main() call and related cleanup into a timeout handler.
if(pDir) unlink(dbFile); if(pDir) unlink(dbFile);
log2('',"Starting native app:\n ",argv.join(' ')); log2('',"Starting native app:\n ",argv.join(' '));
log2('',"This will take a while and the browser might warn about the runaway JS.", log2('',"This will take a while and the browser might warn about the runaway JS.",
"Give it time..."); "Give it time...");
logList.length = 0; logList.length = 0;
setTimeout(function(){ setTimeout(function(){
wasm.xCall('wasm_main', argv.length, wasm.xCall('wasm_main', argv.length,
wasm.scopedAllocMainArgv(argv)); wasm.scopedAllocMainArgv(argv));
wasm.scopedAllocPop(scope); wasm.scopedAllocPop(scope);
if(pDir) unlink(dbFile); if(pDir) unlink(dbFile);
logList.unshift("Done running native main(). Output:"); logList.unshift("Done running native main(). Output:");
dumpLogList(); dumpLogList();
}, 25); }, 25);
}/*runTests()*/; }/*runTests()*/;
self.sqlite3TestModule.print = log; self.sqlite3TestModule.print = log;
self.sqlite3TestModule.printErr = logErr; self.sqlite3TestModule.printErr = logErr;
sqlite3Speedtest1InitModule(self.sqlite3TestModule).then(function(M){ sqlite3Speedtest1InitModule(self.sqlite3TestModule).then(function(M){
runTests(M.sqlite3); runTests(M.sqlite3);
}); });
})(); })();</script>
</script>
</body> </body>
</html> </html>

View File

@ -127,75 +127,75 @@
} }
</style> </style>
<script>(function(){ <script>(function(){
'use strict'; 'use strict';
const E = (sel)=>document.querySelector(sel); const E = (sel)=>document.querySelector(sel);
const eOut = E('#test-output'); const eOut = E('#test-output');
const log2 = function(cssClass,...args){ const log2 = function(cssClass,...args){
let ln; let ln;
if(1 || cssClass){ if(1 || cssClass){
ln = document.createElement('div'); ln = document.createElement('div');
if(cssClass) ln.classList.add(cssClass); if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' '))); ln.append(document.createTextNode(args.join(' ')));
}else{ }else{
// This doesn't work with the "reverse order" option! // This doesn't work with the "reverse order" option!
ln = document.createTextNode(args.join(' ')+'\n'); ln = document.createTextNode(args.join(' ')+'\n');
} }
eOut.append(ln); eOut.append(ln);
}; };
const log = (...args)=>{ const log = (...args)=>{
//console.log(...args); //console.log(...args);
log2('', ...args); log2('', ...args);
}; };
const logErr = function(...args){ const logErr = function(...args){
console.error(...args); console.error(...args);
log2('error', ...args); log2('error', ...args);
}; };
const logWarn = function(...args){ const logWarn = function(...args){
console.warn(...args); console.warn(...args);
log2('warning', ...args); log2('warning', ...args);
}; };
const spacePad = function(str,len=21){ const spacePad = function(str,len=21){
if(str.length===len) return str; if(str.length===len) return str;
else if(str.length>len) return str.substr(0,len); else if(str.length>len) return str.substr(0,len);
const a = []; a.length = len - str.length; const a = []; a.length = len - str.length;
return str+a.join(' '); return str+a.join(' ');
}; };
// OPTION elements seem to ignore white-space:pre, so do this the hard way... // OPTION elements seem to ignore white-space:pre, so do this the hard way...
const nbspPad = function(str,len=21){ const nbspPad = function(str,len=21){
if(str.length===len) return str; if(str.length===len) return str;
else if(str.length>len) return str.substr(0,len); else if(str.length>len) return str.substr(0,len);
const a = []; a.length = len - str.length; const a = []; a.length = len - str.length;
return str+a.join('&nbsp;'); return str+a.join('&nbsp;');
}; };
const W = new Worker("speedtest1-worker.js"+self.location.search); const W = new Worker("speedtest1-worker.js"+self.location.search);
const mPost = function(msgType,payload){ const mPost = function(msgType,payload){
W.postMessage({type: msgType, data: payload}); W.postMessage({type: msgType, data: payload});
}; };
const eFlags = E('#select-flags'); const eFlags = E('#select-flags');
const eSelectedFlags = E('#toolbar-selected-flags'); const eSelectedFlags = E('#toolbar-selected-flags');
const eLinkMainThread = E('#link-main-thread'); const eLinkMainThread = E('#link-main-thread');
const eLinkWasmfs = E('#link-wasmfs'); const eLinkWasmfs = E('#link-wasmfs');
const eLinkKvvfs = E('#link-kvvfs'); const eLinkKvvfs = E('#link-kvvfs');
const urlParams = new URL(self.location.href).searchParams; const urlParams = new URL(self.location.href).searchParams;
const getSelectedFlags = ()=>{ const getSelectedFlags = ()=>{
const f = Array.prototype.map.call(eFlags.selectedOptions, (v)=>v.value); const f = Array.prototype.map.call(eFlags.selectedOptions, (v)=>v.value);
[ [
'size', 'vfs' 'size', 'vfs'
].forEach(function(k){ ].forEach(function(k){
if(urlParams.has(k)) f.push('--'+k, urlParams.get(k)); if(urlParams.has(k)) f.push('--'+k, urlParams.get(k));
}); });
return f; return f;
}; };
const updateSelectedFlags = function(){ const updateSelectedFlags = function(){
eSelectedFlags.innerText = ''; eSelectedFlags.innerText = '';
const flags = getSelectedFlags(); const flags = getSelectedFlags();
flags.forEach(function(f){ flags.forEach(function(f){
const e = document.createElement('span'); const e = document.createElement('span');
e.innerText = f; e.innerText = f;
eSelectedFlags.appendChild(e); eSelectedFlags.appendChild(e);
}); });
const rxStripDash = /^(-+)?/; const rxStripDash = /^(-+)?/;
const comma = flags.join(','); const comma = flags.join(',');
@ -205,9 +205,9 @@
eLinkWasmfs.href = 'speedtest1-wasmfs.html?flags='+comma; eLinkWasmfs.href = 'speedtest1-wasmfs.html?flags='+comma;
eLinkKvvfs.setAttribute('target', 'speedtest1-kvvfs-'+comma); eLinkKvvfs.setAttribute('target', 'speedtest1-kvvfs-'+comma);
eLinkKvvfs.href = 'speedtest1-kvvfs.html?flags='+comma; eLinkKvvfs.href = 'speedtest1-kvvfs.html?flags='+comma;
}; };
eFlags.addEventListener('change', updateSelectedFlags ); eFlags.addEventListener('change', updateSelectedFlags );
{ {
const flags = Object.create(null); const flags = Object.create(null);
/* TODO? Flags which require values need custom UI /* TODO? Flags which require values need custom UI
controls and some of them make little sense here controls and some of them make little sense here
@ -259,111 +259,111 @@
flags["--verify"] = "Run additional verification steps."; flags["--verify"] = "Run additional verification steps.";
flags["--without"] = "rowid Use WITHOUT ROWID where appropriate"; flags["--without"] = "rowid Use WITHOUT ROWID where appropriate";
const preselectedFlags = [ const preselectedFlags = [
'--big-transactions', '--big-transactions',
'--singlethread' '--singlethread'
]; ];
if(urlParams.has('flags')){ if(urlParams.has('flags')){
preselectedFlags.push(...urlParams.get('flags').split(',')); preselectedFlags.push(...urlParams.get('flags').split(','));
} }
if('opfs'!==urlParams.get('vfs')){ if('opfs'!==urlParams.get('vfs')){
preselectedFlags.push('--memdb'); preselectedFlags.push('--memdb');
} }
Object.keys(flags).sort().forEach(function(f){ Object.keys(flags).sort().forEach(function(f){
const opt = document.createElement('option'); const opt = document.createElement('option');
eFlags.appendChild(opt); eFlags.appendChild(opt);
const lbl = nbspPad(f)+flags[f]; const lbl = nbspPad(f)+flags[f];
//opt.innerText = lbl; //opt.innerText = lbl;
opt.innerHTML = lbl; opt.innerHTML = lbl;
opt.value = f; opt.value = f;
if(preselectedFlags.indexOf(f) >= 0) opt.selected = true; if(preselectedFlags.indexOf(f) >= 0) opt.selected = true;
}); });
const cbReverseLog = E('#cb-reverse-log-order'); const cbReverseLog = E('#cb-reverse-log-order');
const lblReverseLog = E('#lbl-reverse-log-order'); const lblReverseLog = E('#lbl-reverse-log-order');
if(cbReverseLog.checked){ if(cbReverseLog.checked){
lblReverseLog.classList.add('warning'); lblReverseLog.classList.add('warning');
eOut.classList.add('reverse'); eOut.classList.add('reverse');
} }
cbReverseLog.addEventListener('change', function(){ cbReverseLog.addEventListener('change', function(){
if(this.checked){ if(this.checked){
eOut.classList.add('reverse'); eOut.classList.add('reverse');
lblReverseLog.classList.add('warning'); lblReverseLog.classList.add('warning');
}else{ }else{
eOut.classList.remove('reverse'); eOut.classList.remove('reverse');
lblReverseLog.classList.remove('warning'); lblReverseLog.classList.remove('warning');
} }
}, false); }, false);
updateSelectedFlags(); updateSelectedFlags();
} }
E('#btn-output-clear').addEventListener('click', ()=>{ E('#btn-output-clear').addEventListener('click', ()=>{
eOut.innerText = ''; eOut.innerText = '';
}); });
E('#btn-reset-flags').addEventListener('click',()=>{ E('#btn-reset-flags').addEventListener('click',()=>{
eFlags.value = ''; eFlags.value = '';
updateSelectedFlags(); updateSelectedFlags();
}); });
E('#btn-run').addEventListener('click',function(){ E('#btn-run').addEventListener('click',function(){
log("Running speedtest1. UI controls will be disabled until it completes."); log("Running speedtest1. UI controls will be disabled until it completes.");
mPost('run', getSelectedFlags()); mPost('run', getSelectedFlags());
}); });
const eControls = E('#ui-controls'); const eControls = E('#ui-controls');
/** Update Emscripten-related UI elements while loading the module. */ /** Update Emscripten-related UI elements while loading the module. */
const updateLoadStatus = function f(text){ const updateLoadStatus = function f(text){
if(!f.last){ if(!f.last){
f.last = { text: '', step: 0 }; f.last = { text: '', step: 0 };
const E = (cssSelector)=>document.querySelector(cssSelector); const E = (cssSelector)=>document.querySelector(cssSelector);
f.ui = { f.ui = {
status: E('#module-status'), status: E('#module-status'),
progress: E('#module-progress'), progress: E('#module-progress'),
spinner: E('#module-spinner') spinner: E('#module-spinner')
}; };
} }
if(text === f.last.text) return; if(text === f.last.text) return;
f.last.text = text; f.last.text = text;
if(f.ui.progress){ if(f.ui.progress){
f.ui.progress.value = f.last.step; f.ui.progress.value = f.last.step;
f.ui.progress.max = f.last.step + 1; f.ui.progress.max = f.last.step + 1;
} }
++f.last.step; ++f.last.step;
if(text) { if(text) {
f.ui.status.classList.remove('hidden'); f.ui.status.classList.remove('hidden');
f.ui.status.innerText = text; f.ui.status.innerText = text;
}else{ }else{
if(f.ui.progress){ if(f.ui.progress){
f.ui.progress.remove(); f.ui.progress.remove();
f.ui.spinner.remove(); f.ui.spinner.remove();
delete f.ui.progress; delete f.ui.progress;
delete f.ui.spinner; delete f.ui.spinner;
} }
f.ui.status.classList.add('hidden'); f.ui.status.classList.add('hidden');
} }
}; };
W.onmessage = function(msg){ W.onmessage = function(msg){
msg = msg.data; msg = msg.data;
switch(msg.type){ switch(msg.type){
case 'ready': case 'ready':
log("Worker is ready."); log("Worker is ready.");
eControls.classList.remove('hidden'); eControls.classList.remove('hidden');
break; break;
case 'stdout': log(msg.data); break; case 'stdout': log(msg.data); break;
case 'stdout': logErr(msg.data); break; case 'stdout': logErr(msg.data); break;
case 'run-start': case 'run-start':
eControls.disabled = true; eControls.disabled = true;
log("Running speedtest1 with argv =",msg.data.join(' ')); log("Running speedtest1 with argv =",msg.data.join(' '));
break; break;
case 'run-end': case 'run-end':
log("speedtest1 finished."); log("speedtest1 finished.");
eControls.disabled = false; eControls.disabled = false;
// app output is in msg.data // app output is in msg.data
break; break;
case 'error': logErr(msg.data); break; case 'error': logErr(msg.data); break;
case 'load-status': updateLoadStatus(msg.data); break; case 'load-status': updateLoadStatus(msg.data); break;
default: default:
logErr("Unhandled worker message type:",msg); logErr("Unhandled worker message type:",msg);
break; break;
} }
}; };
})();</script> })();</script>
</body> </body>
</html> </html>

View File

@ -8,7 +8,7 @@
*/ */
const wasmfsDir = function f(wasmUtil){ const wasmfsDir = function f(wasmUtil){
if(undefined !== f._) return f._; if(undefined !== f._) return f._;
const pdir = '/persistent'; const pdir = '/opfs';
if( !self.FileSystemHandle if( !self.FileSystemHandle
|| !self.FileSystemDirectoryHandle || !self.FileSystemDirectoryHandle
|| !self.FileSystemFileHandle){ || !self.FileSystemFileHandle){

View File

@ -39,131 +39,136 @@
<script src="common/SqliteTestUtil.js"></script> <script src="common/SqliteTestUtil.js"></script>
<script src="speedtest1.js"></script> <script src="speedtest1.js"></script>
<script>(function(){ <script>(function(){
/** /**
If this environment contains OPFS, this function initializes it and If this environment contains OPFS, this function initializes it and
returns the name of the dir on which OPFS is mounted, else it returns returns the name of the dir on which OPFS is mounted, else it returns
an empty string. an empty string.
*/ */
const wasmfsDir = function f(wasmUtil){ const wasmfsDir = function f(wasmUtil){
if(undefined !== f._) return f._; if(undefined !== f._) return f._;
const pdir = '/persistent'; const pdir = '/persistent';
if( !self.FileSystemHandle if( !self.FileSystemHandle
|| !self.FileSystemDirectoryHandle || !self.FileSystemDirectoryHandle
|| !self.FileSystemFileHandle){ || !self.FileSystemFileHandle){
return f._ = ""; return f._ = "";
} }
try{ try{
if(0===wasmUtil.xCallWrapped( if(0===wasmUtil.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
)){ )){
return f._ = pdir; return f._ = pdir;
}else{ }else{
return f._ = ""; return f._ = "";
} }
}catch(e){ }catch(e){
// sqlite3_wasm_init_wasmfs() is not available // sqlite3_wasm_init_wasmfs() is not available
return f._ = ""; return f._ = "";
} }
}; };
wasmfsDir._ = undefined; wasmfsDir._ = undefined;
const eOut = document.querySelector('#test-output'); const eOut = document.querySelector('#test-output');
const log2 = function(cssClass,...args){ const log2 = function(cssClass,...args){
const ln = document.createElement('div'); const ln = document.createElement('div');
if(cssClass) ln.classList.add(cssClass); if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' '))); ln.append(document.createTextNode(args.join(' ')));
eOut.append(ln); eOut.append(ln);
//this.e.output.lastElementChild.scrollIntoViewIfNeeded(); //this.e.output.lastElementChild.scrollIntoViewIfNeeded();
}; };
const logList = []; const logList = [];
const dumpLogList = function(){ const dumpLogList = function(){
logList.forEach((v)=>log2('',v)); logList.forEach((v)=>log2('',v));
logList.length = 0; logList.length = 0;
}; };
/* can't update DOM while speedtest is running unless we run /* can't update DOM while speedtest is running unless we run
speedtest in a worker thread. */; speedtest in a worker thread. */;
const log = (...args)=>{ const log = (...args)=>{
console.log(...args); console.log(...args);
logList.push(args.join(' ')); logList.push(args.join(' '));
}; };
const logErr = function(...args){ const logErr = function(...args){
console.error(...args); console.error(...args);
logList.push('ERROR: '+args.join(' ')); logList.push('ERROR: '+args.join(' '));
}; };
const runTests = function(sqlite3){ const runTests = function(sqlite3){
const capi = sqlite3.capi, wasm = capi.wasm; const capi = sqlite3.capi, wasm = capi.wasm;
//console.debug('sqlite3 =',sqlite3); //console.debug('sqlite3 =',sqlite3);
const unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]); const unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]);
const pDir = wasmfsDir(wasm); const pDir = wasmfsDir(wasm);
if(pDir){ if(pDir){
console.warn("Persistent storage:",pDir); console.warn("Persistent storage:",pDir);
} }
const scope = wasm.scopedAllocPush(); const scope = wasm.scopedAllocPush();
let dbFile = pDir+"/speedtest1.db"; let dbFile = pDir+"/speedtest1.db";
const urlParams = self.SqliteTestUtil.processUrlArgs(); const urlParams = new URL(self.location.href).searchParams;
const argv = ["speedtest1"]; const argv = ["speedtest1"];
if('string'===typeof urlParams.vfs){ if(urlParams.has('flags')){
if(!capi.sqlite3_vfs_find(urlParams.vfs)){ argv.push(...(urlParams.get('flags').split(',')));
log2('error',"Unknown VFS:",urlParams.vfs); }
return;
}
argv.push("--vfs", urlParams.vfs);
log2('',"Using VFS:",urlParams.vfs);
if('kvvfs' === urlParams.vfs){
urlParams.size = 2;
dbFile = 'session';
log2('warning',"kvvfs VFS: forcing --size",urlParams.size,
"and filename '"+dbFile+"'.");
capi.sqlite3_web_kvvfs_clear('session');
}
}
[
'size'
].forEach(function(k){
const v = urlParams[k];
if(v) argv.push('--'+k, urlParams[k]);
});
if(urlParams.flags){
argv.push(...(urlParams.flags.split(',')));
}else{
argv.push(
"--singlethread",
//"--nomutex",
//"--nosync",
"--nomemstat"
);
//"--memdb", // note that memdb trumps the filename arg
}
argv.push("--big-transactions"/*important for tests 410 and 510!*/,
dbFile);
console.log("argv =",argv);
// These log messages are not emitted to the UI until after main() returns. Fixing that
// requires moving the main() call and related cleanup into a timeout handler.
if(pDir) unlink(dbFile);
log2('',"Starting native app:\n ",argv.join(' '));
log2('',"This will take a while and the browser might warn about the runaway JS.",
"Give it time...");
logList.length = 0;
setTimeout(function(){
wasm.xCall('wasm_main', argv.length,
wasm.scopedAllocMainArgv(argv));
wasm.scopedAllocPop(scope);
if(pDir) unlink(dbFile);
logList.unshift("Done running native main(). Output:");
dumpLogList();
}, 50);
}/*runTests()*/;
self.sqlite3TestModule.print = log; let forceSize = 0;
self.sqlite3TestModule.printErr = logErr; if(urlParams.has('vfs')){
sqlite3Speedtest1InitModule(self.sqlite3TestModule) const vfs = urlParams.get('vfs');
if(!capi.sqlite3_vfs_find(vfs)){
log2('error',"Unknown VFS:",vfs);
return;
}
argv.push("--vfs", vfs);
log2('',"Using VFS:",vfs);
if('kvvfs' === vfs){
forceSize = 2;
dbFile = 'session';
log2('warning',"kvvfs VFS: forcing --size",forceSize,
"and filename '"+dbFile+"'.");
capi.sqlite3_web_kvvfs_clear(dbFile);
}
}
if(forceSize){
argv.push('--size',forceSize);
}else{
[
'size'
].forEach(function(k){
const v = urlParams.get(k);
if(v) argv.push('--'+k, urlParams[k]);
});
}
argv.push(
"--singlethread",
//"--nomutex",
//"--nosync",
//"--memdb", // note that memdb trumps the filename arg
"--nomemstat"
);
argv.push("--big-transactions"/*important for tests 410 and 510!*/,
dbFile);
console.log("argv =",argv);
// These log messages are not emitted to the UI until after main() returns. Fixing that
// requires moving the main() call and related cleanup into a timeout handler.
if(pDir) unlink(dbFile);
log2('',"Starting native app:\n ",argv.join(' '));
log2('',"This will take a while and the browser might warn about the runaway JS.",
"Give it time...");
logList.length = 0;
setTimeout(function(){
wasm.xCall('wasm_main', argv.length,
wasm.scopedAllocMainArgv(argv));
wasm.scopedAllocPop(scope);
if(pDir) unlink(dbFile);
logList.unshift("Done running native main(). Output:");
dumpLogList();
}, 50);
}/*runTests()*/;
self.sqlite3TestModule.print = log;
self.sqlite3TestModule.printErr = logErr;
sqlite3Speedtest1InitModule(self.sqlite3TestModule)
.then((EmscriptenModule)=>{ .then((EmscriptenModule)=>{
return EmscriptenModule.sqlite3.installOpfsVfs() return EmscriptenModule.sqlite3.installOpfsVfs()
.catch((e)=>{console.warn(e.message)}) .catch((e)=>{console.warn(e.message)})
.then(()=>runTests(EmscriptenModule.sqlite3)); .then(()=>runTests(EmscriptenModule.sqlite3));
}); });
})(); })();</script>
</script> </body>
</body>
</html> </html>

View File

@ -1,5 +1,5 @@
C Fiddle:\sreplace\sdb\sexport\sroutine\swith\sa\sC-side\sone\swhich\sworks\sfor\sboth\sEmscripten\sFS-hosted\sand\sOPFS-hosted\sdb\sfiles.\sMinor\scode-adjacent\scleanups. C wasm/js:\srename\s/persistent\sto\s/opfs\sto\saccount\sfor\spotential\sfuture\spersistent\sstorage\soptions.\sMinor\sflag-handling\scleanups\sin\sthe\sspeedtest1\spages.\sMinor\sAPI\stweaks\sin\soo1.
D 2022-09-26T13:55:10.137 D 2022-09-27T09:17:37.806
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -483,39 +483,39 @@ F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba814
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77 F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77
F ext/wasm/api/sqlite3-api-glue.js fe5ca21ac519e6411f5e7a6403d06fe92c51ef81cca8e07ea8895df8ec9c2e4e F ext/wasm/api/sqlite3-api-glue.js fe5ca21ac519e6411f5e7a6403d06fe92c51ef81cca8e07ea8895df8ec9c2e4e
F ext/wasm/api/sqlite3-api-oo1.js 455fcb28dd77b9781e087aac77392fb78f8ee8e5b125a99c1488604de27a5bb1 F ext/wasm/api/sqlite3-api-oo1.js 97a786b366fcac442e1557c3eedef3afa96877411bd6239094d4db5fd5b3c353
F ext/wasm/api/sqlite3-api-opfs.js e0dfae09aedc6fe414d8d350e7228a6a88de030a0cb19a748ac8269aef9b11db F ext/wasm/api/sqlite3-api-opfs.js 1128b3cbfbecbe66324d334f4561ccf61f2b08f73075e6c77a053f7ecb71090f
F ext/wasm/api/sqlite3-api-prologue.js d39bda7d83aaeb8e15574afe8308221ed11c6f24865ccff06cf0424b665e681e F ext/wasm/api/sqlite3-api-prologue.js 0ba5ae19021524e02d977668c6b16e951b4ebe0d5f0ff0577e85f4209284a11a
F ext/wasm/api/sqlite3-api-worker1.js 2eeb2a24e1a90322d84a9b88a99919b806623de62792436446099c0988f2030b F ext/wasm/api/sqlite3-api-worker1.js 2eeb2a24e1a90322d84a9b88a99919b806623de62792436446099c0988f2030b
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 7010405f1981cd5929568403a618f80398f7acbf76b3eb11c4f23789206eb164 F ext/wasm/api/sqlite3-wasm.c 1409d76529537c2d21a06678df81a3cb5050e212a5ae4cdd9fb42ca5716c65e9
F ext/wasm/batch-runner.html 2857a6db7292ac83d1581af865d643fd34235db2df830d10b43b01388c599e04 F ext/wasm/batch-runner.html 2857a6db7292ac83d1581af865d643fd34235db2df830d10b43b01388c599e04
F ext/wasm/batch-runner.js 6f5b86e0b5519a9a941d9f17ee9c5ecdc63f452f157602fe7fdf87f6275a2b49 F ext/wasm/batch-runner.js 6f5b86e0b5519a9a941d9f17ee9c5ecdc63f452f157602fe7fdf87f6275a2b49
F ext/wasm/common/SqliteTestUtil.js 529161a624265ba84271a52db58da022649832fa1c71309fb1e02cc037327a2b F ext/wasm/common/SqliteTestUtil.js c997c12188c97109f344701a58dd627b9c0f98f32cc6a88413f6171f2191531c
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962 F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962
F ext/wasm/common/whwasmutil.js 20291bbf4955358d0b5ead58db4c575be269b4976e39c43a93331547e3b86363 F ext/wasm/common/whwasmutil.js 20291bbf4955358d0b5ead58db4c575be269b4976e39c43a93331547e3b86363
F ext/wasm/demo-123-worker.html e419b66495d209b5211ec64903b4cfb3ca7df20d652b41fcd28bf018a773234f F ext/wasm/demo-123-worker.html e419b66495d209b5211ec64903b4cfb3ca7df20d652b41fcd28bf018a773234f
F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4 F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4
F ext/wasm/demo-123.js 234655683e35a4543a23de7b10800d76b0369947b33e089e5613171fa7795afb F ext/wasm/demo-123.js 9a64c4e535c9d7c8d9a8dd67ca40b42b95baad85049deb84cd447b859e59cc68
F ext/wasm/demo-kvvfs1.html 7d4f28873de67f51ac18c584b7d920825139866a96049a49c424d6f5a0ea5e7f F ext/wasm/demo-kvvfs1.html 7d4f28873de67f51ac18c584b7d920825139866a96049a49c424d6f5a0ea5e7f
F ext/wasm/demo-kvvfs1.js e884ea35022d772c0d1dd884b40011413696438394f605c6cd4808cfb1642a4a F ext/wasm/demo-kvvfs1.js e884ea35022d772c0d1dd884b40011413696438394f605c6cd4808cfb1642a4a
F ext/wasm/fiddle.make fd56fa21bada6ecbf860686a9a789ebda7cc3d9b60835927000fcb00246ea50f F ext/wasm/fiddle.make fd56fa21bada6ecbf860686a9a789ebda7cc3d9b60835927000fcb00246ea50f
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/fiddle/fiddle-worker.js 1fe173ba963314df99df9eb8f0f45f1c3a72c056f16510e47787eb1790cb5531 F ext/wasm/fiddle/fiddle-worker.js 425b75b1debe1108c10f1373fdd75994a18adbdc0a593e7ff0ecd91cc6498e89
F ext/wasm/fiddle/fiddle.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2 F ext/wasm/fiddle/fiddle.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/fiddle/fiddle.js aa44051be6e48c53fd23c829177d43f557dcc6f0998ccfcbae7c473ff405f0c6 F ext/wasm/fiddle/fiddle.js aa44051be6e48c53fd23c829177d43f557dcc6f0998ccfcbae7c473ff405f0c6
F ext/wasm/index.html a39d14f6de6bd1294d39522fcf40eca3c9f0b6da44bb8df6948378e9f30468f5 F ext/wasm/index.html 63b370619e4f849ac76f1baed435c05edc29dbb6795bc7c1c935561ff667dd27
F ext/wasm/jaccwabyt/jaccwabyt.js 0d7f32817456a0f3937fcfd934afeb32154ca33580ab264dab6c285e6dbbd215 F ext/wasm/jaccwabyt/jaccwabyt.js 0d7f32817456a0f3937fcfd934afeb32154ca33580ab264dab6c285e6dbbd215
F ext/wasm/jaccwabyt/jaccwabyt.md 9aa6951b529a8b29f578ec8f0355713c39584c92cf1708f63ba0cf917cb5b68e F ext/wasm/jaccwabyt/jaccwabyt.md 9aa6951b529a8b29f578ec8f0355713c39584c92cf1708f63ba0cf917cb5b68e
F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5300668e9960fff30d0d36f F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5300668e9960fff30d0d36f
F ext/wasm/jaccwabyt/jaccwabyt_test.exports 5ff001ef975c426ffe88d7d8a6e96ec725e568d2c2307c416902059339c06f19 F ext/wasm/jaccwabyt/jaccwabyt_test.exports 5ff001ef975c426ffe88d7d8a6e96ec725e568d2c2307c416902059339c06f19
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06 F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
F ext/wasm/scratchpad-wasmfs-main.js f0836e3576df7a89390d777bb53e142e559e8a79becfb2a5a976490b05a1c4fa F ext/wasm/scratchpad-wasmfs-main.js f0836e3576df7a89390d777bb53e142e559e8a79becfb2a5a976490b05a1c4fa
F ext/wasm/speedtest1-wasmfs.html 9d8cd19eab8854d17f7129aa11607cae6f6d9857c505a4aef13000588583d93e F ext/wasm/speedtest1-wasmfs.html 852504ccf9d095c8f57d4f4f9cc2f912b3b432e300c6b5ed8d6234a37eeb86a6
F ext/wasm/speedtest1-worker.html 802cbd09a14b5a7abb4b66bff243d5fd89fd476ffe083554bdfd4c177fb6474c F ext/wasm/speedtest1-worker.html 3780a29a6d0467dde34b61bf50a1b2e1a12a4e8498f4835b1293e79a3edcd675
F ext/wasm/speedtest1-worker.js 11e7f68cedd2a83b0e638f94c1d2f58406ba672a7e88b66bff5d4f4284e8ba16 F ext/wasm/speedtest1-worker.js 08f9e9ffe0082098b2566a56c1b2655a70917b17edcdec9a28cdcc01c097d4df
F ext/wasm/speedtest1.html 8ae6ece128151d01f90579de69cfa06f021acdb760735250ef745eba7ed05d49 F ext/wasm/speedtest1.html 4f4e26b634bb3288f2cad8cf4d458076b33d8bd0f3fd56e089a17bed32df6287
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0 F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5 F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
@ -2026,8 +2026,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 9b2244e1c8a40efe6547094a1b57acc8f2173145a8731abb0e36268ce0a8ef41 P 3579a8d6f1f6cd3cd8aad9949536870c5fe7bae8c1778f700dd85d763e266b94
R ee45c68d4b4cfbf2a729d26cea95ac0e R 786e465dc63fbf42c76f34e46e9a73e9
U stephan U stephan
Z a7778a8aaef90b52f5b829e56bd6cae3 Z 0e6490797de722dba8eac0d97289515b
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
3579a8d6f1f6cd3cd8aad9949536870c5fe7bae8c1778f700dd85d763e266b94 4dc972a3656b2a9ec915bfb3f653136560c753ce4024c3f0d0d0c28f66db7a0a