diff --git a/ext/fiddle/fiddle.js b/ext/fiddle/fiddle.js index c03a09af11..51bfcc146d 100644 --- a/ext/fiddle/fiddle.js +++ b/ext/fiddle/fiddle.js @@ -525,19 +525,33 @@ /** Initiate a download of the db. */ const btnExport = E('#btn-export'); - const eDisableDuringExport = [ - /* UI elements to disable while export is running. Normally - the export is fast enough that this won't matter, but we - really don't want to be reading (from outside of sqlite) - the db when the user taps btnShellExec. */ - btnShellExec, btnExport - ]; + const eLoadDb = E('#load-db'); + /** + Enables (if passed true) or disables all UI elements which + "might," if timed "just right," interfere with an + in-progress db import/export/exec operation. + */ + const enableMutatingElements = function f(enable){ + if(!f._elems){ + f._elems = [ + /* UI elements to disable while import/export are + running. Normally the export is fast enough + that this won't matter, but we really don't + want to be reading (from outside of sqlite) the + db when the user taps btnShellExec. */ + btnShellExec, btnExport, eLoadDb + ]; + } + f._elems.forEach( enable + ? (e)=>e.removeAttribute('disabled') + : (e)=>e.setAttribute('disabled','disabled') ); + }; btnExport.addEventListener('click',function(){ - eDisableDuringExport.forEach(e=>e.setAttribute('disabled','disabled')); + enableMutatingElements(false); SF.wMsg('db-export'); }); SF.addMsgHandler('db-export', function(ev){ - eDisableDuringExport.forEach(e=>e.removeAttribute('disabled')); + enableMutatingElements(true); ev = ev.data; if(ev.error){ SF.echo("Export failed:",ev.error); @@ -560,11 +574,11 @@ /** Handle load/import of an external db file. */ - E('#load-db').addEventListener('change',function(){ + eLoadDb.addEventListener('change',function(){ const f = this.files[0]; const r = new FileReader(); const status = {loaded: 0, total: 0}; - this.setAttribute('disabled','disabled'); + enableMutatingElements(false); r.addEventListener('loadstart', function(){ SF.echo("Loading",f.name,"..."); }); @@ -573,7 +587,7 @@ }); const that = this; r.addEventListener('load', function(){ - that.removeAttribute('disabled'); + enableMutatingElements(true); SF.echo("Loaded",f.name+". Opening db..."); SF.wMsg('open',{ filename: f.name, @@ -581,11 +595,11 @@ }); }); r.addEventListener('error',function(){ - that.removeAttribute('disabled'); + enableMutatingElements(true); SF.echo("Loading",f.name,"failed for unknown reasons."); }); r.addEventListener('abort',function(){ - that.removeAttribute('disabled'); + enableMutatingElements(true); SF.echo("Cancelled loading of",f.name+"."); }); r.readAsArrayBuffer(f); diff --git a/ext/fiddle/sqlite3-api.js b/ext/fiddle/sqlite3-api.js index 943f1bc8e0..1be4d9c775 100644 --- a/ext/fiddle/sqlite3-api.js +++ b/ext/fiddle/sqlite3-api.js @@ -461,7 +461,7 @@ Module.postRun.push(function(namespace/*the module object, the target for delete this._pDb; if(this.filename){ if(alsoUnlink){ - try{SQM.FS.unlink(this.filename);} + try{SQM.FS.unlink('/'+this.filename);} catch(e){/*ignored*/} } delete this.filename; @@ -1530,9 +1530,9 @@ Module.postRun.push(function(namespace/*the module object, the target for else if(this.db) this.db.close(); return this.db = (Array.isArray(arg) ? new DB(...arg) : new DB(arg)); }, - close: function(){ + close: function(alsoUnlink){ if(this.db){ - this.db.close(); + this.db.close(alsoUnlink); this.db = undefined; } }, @@ -1679,9 +1679,30 @@ Module.postRun.push(function(namespace/*the module object, the target for } const db = wState.open(args); return {filename: db.filename}; + }, + /** + Proxy for DB.close(). If ev.data may either be a boolean or + an object with an `unlink` property. If that value is + truthy then the db file (if the db is currently open) will + be unlinked from the virtual filesystem, else it will be + kept intact. The response object is: + + {filename: db filename _if_ the db is is opened when this + is called, else the undefined value + } + */ + close: function(ev){ + const response = { + filename: wState.db && wState.db.filename + }; + if(wState.db){ + wState.close(!!(ev.data && 'object'===typeof ev.data) + ? ev.data.unlink : ev.data); + } + return response; } }/*wMsgHandler*/; - + /** UNDER CONSTRUCTION! diff --git a/ext/fiddle/testing2.js b/ext/fiddle/testing2.js index 4ec9faae6a..4bb21b95f0 100644 --- a/ext/fiddle/testing2.js +++ b/ext/fiddle/testing2.js @@ -25,14 +25,23 @@ const error = console.error.bind(console); SW.onerror = function(event){ - warn("onerror",event); + error("onerror",event); }; + /** + A queue for callbacks which are to be run in response to async + DB commands. See the notes in runTests() for why we need + this. The event-handling plumbing of this file requires that + any DB command which includes a `messageId` property also have + a queued callback entry, as the existence of that property in + response payloads is how it knows whether or not to shift an + entry off of the queue. + */ const MsgHandlerQueue = { queue: [], id: 0, - push: function(type,f){ - this.queue.push(f); + push: function(type,callback){ + this.queue.push(callback); return type + '-' + (++this.id); }, shift: function(){ @@ -57,7 +66,7 @@ }; /** Methods which map directly to onmessage() event.type keys. - They get passed the inbound event. */ + They get passed the inbound event.data. */ const dbMsgHandler = { open: function(ev){ log("open result",ev.data); @@ -78,8 +87,11 @@ T.assert(null===ev.data || 'number' === typeof ev.data.b); } }; - + const runTests = function(){ + const mustNotReach = ()=>{ + throw new Error("This is not supposed to be reached."); + }; /** "The problem" now is that the test results are async. We know, however, that the messages posted to the worker will @@ -127,9 +139,7 @@ .assert(1===ev.resultRows[0].a) .assert(6===ev.resultRows[2].b) }); - runOneTest('exec',{sql:'intentional_error'}, function(){ - throw new Error("This is not supposed to be reached."); - }); + runOneTest('exec',{sql:'intentional_error'}, mustNotReach); // Ensure that the message-handler queue survives ^^^ that error... runOneTest('exec',{ sql:'select 1', @@ -164,6 +174,16 @@ .assert(ev.buffer.length > 1024) .assert('application/x-sqlite3' === ev.mimetype); }); + + /***** close() tests must come last. *****/ + runOneTest('close',{unlink:true},function(ev){ + ev = ev.data; + T.assert('string' === typeof ev.filename); + }); + runOneTest('close',{unlink:true},function(ev){ + ev = ev.data; + T.assert(undefined === ev.filename); + }); }; SW.onmessage = function(ev){ diff --git a/manifest b/manifest index bceb19de1f..2da13f7e78 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\stweaks\sto,\sand\sconsolidation\sof,\sthe\swasm-related\sbuild\sflags. -D 2022-06-01T14:52:23.135 +C fiddle:\sadded\sanother\sUI\selement\sto\sthe\slist\sof\sthose\swhich\sare\sdisabled\sduring\slong-running\sactivities.\sAdded\sDB.close()\sbinding\sto\sthe\sWorker-based\swasm\sbinding. +D 2022-06-01T16:04:29.637 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -63,15 +63,15 @@ F ext/fiddle/SqliteTestUtil.js 559731c3e8e0de330ec7d292e6c1846566408caee6637acc8 F ext/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/fiddle/fiddle-worker.js 88bc2193a6cb6a3f04d8911bed50a4401fe6f277de7a71ba833865ab64a1b4ae F ext/fiddle/fiddle.html 724f1cd4126616bc87f5871f78d3f7aaaf41e45c9728724627baab87e6af35f0 -F ext/fiddle/fiddle.js 5b456ed7085830cda2fc75a0801476174a978521949335f24bc4154d076dcd4d +F ext/fiddle/fiddle.js 2ce9a93aad55cbf64a16b607149847a64cc4dc4e13df8b6d2a0e964b4269dc6c F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf -F ext/fiddle/sqlite3-api.js 2d7b0e63affa1dcad97de6c5bfef2eb1fb2ecdde44b8991299cd01b988ce9994 +F ext/fiddle/sqlite3-api.js b32d23349cf32c54265d132387b5711a29d61c1fcf6159fbef72d1f04dda5e3c F ext/fiddle/sqlite3-worker.js a9c2b614beca187dbdd8c053ec2770cc61ec1ac9c0ec6398ceb49a79f705a421 F ext/fiddle/testing.css 750572dded671d2cf142bbcb27af5542522ac08db128245d0b9fe410aa1d7f2a F ext/fiddle/testing1.html ea1f3be727f78e420007f823912c1a03b337ecbb8e79449abc2244ad4fe15d9a F ext/fiddle/testing1.js b5bf7e33b35f02f4208e4d68eaa41e5ed42eaefd57e0a1131e87cba96d4808dc F ext/fiddle/testing2.html 9063b2430ade2fe9da4e711addd1b51a2741cf0c7ebf6926472a5e5dd63c0bc4 -F ext/fiddle/testing2.js afb3f79c5731b50148201797150a64e210a16730a34a72965599f6985a4f83c6 +F ext/fiddle/testing2.js 7b45b4e7fddbd51dbaf89b6722c02758051b34bac5a98c11b569a7e7572f88ee F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b F ext/fts1/ft_hash.h 06df7bba40dadd19597aa400a875dbc2fed705ea @@ -1974,8 +1974,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e96feccc21d9b858f076960e029b615809243d0cc3f95db75180feb01887451f -R 471b902d8001c2396cd771e4411b6c73 +P f0ad6b1b324f9c0f4340f6cf9584884d1206b56fe1010db43bcbef324e713ea3 +R 8aa54d35311465583fa9edb90a82d403 U stephan -Z 12097a5aaa82e69db2d6ce001a3738eb +Z f4b934a70d4d19bc08d2e676d68f616b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index aca23f850e..841901757f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f0ad6b1b324f9c0f4340f6cf9584884d1206b56fe1010db43bcbef324e713ea3 \ No newline at end of file +5933163ed1a8f996e81023c7c5822655dc6411d30016f37fe8863f760530dc5b \ No newline at end of file