layer. The data property is the string of the output, noting
that the emscripten binding emits these one line at a time. Thus,
if a C-side puts() emits multiple lines in a single call, the JS
- side will see that as multiple calls.
+ side will see that as multiple calls. Example:
+
+ {type:'stdout', data: 'Hi, world.'}
- module: Status text. This is intended to alert the main thread
about module loading status so that, e.g., the main thread can
update a progress widget and DTRT when the module is finished
- loading and available for work. The status text is mostly in some
- undocumented(?) format emited by the emscripten generated
- module-loading code, encoding progress info within it.
+ loading and available for work. Status messages come in the form
+
+ {type:'module', data:{
+ type:'status',
+ data: {text:string|null, step:1-based-integer}
+ }
+
+ with an incrementing step value for each subsequent message. When
+ the module loading is complete, a message with a text value of
+ null is posted.
- working: data='start'|'end'. Indicates that work is about to be
sent to the module or has just completed. This can be used, e.g.,
to disable UI elements which should not be activated while work
- is pending.
+ is pending. Example:
+
+ {type:'working', data:'start'}
Main-to-Worker types:
it starts and a 'working' event (data='end') when it finished. If
called while work is currently being executed it emits stderr
message instead of doing actual work, as the underlying db cannot
- handle concurrent tasks.
+ handle concurrent tasks. Example:
+
+ {type:'shellExec', data: 'select * from sqlite_master'}
- More TBD as the higher-level db layer develops.
*/
//onRuntimeInitialized: function(){},
print: function(text){wMsg('stdout', Array.prototype.slice.call(arguments));},
printErr: function(text){wMsg('stderr', Array.prototype.slice.call(arguments));},
- setStatus: function f(text){wMsg('module',{type:'status',data:text});},
+ /**
+ Intercepts status updates from the Module object and fires
+ worker events with a type of 'status' and a payload of:
+
+ {
+ text: string | null, // null at end of load process
+ step: integer // starts at 1, increments 1 per call
+ }
+
+ We have no way of knowing in advance how many steps will
+ be processed/posted, so creating a "percentage done" view is
+ not really practical. One can be approximated by giving it a
+ current value of message.step and max value of message.step+1,
+ though.
+
+ When work is finished, a message with a text value of null is
+ submitted.
+
+ After a message with text==null is posted, the module may later
+ post messages about fatal problems, e.g. an exit() being
+ triggered, so it is recommended that UI elements for posting
+ status messages not be outright removed from the DOM when
+ text==null, and that they instead be hidden until/unless
+ text!=null.
+ */
+ setStatus: function f(text){
+ if(!f.last) f.last = { step: 0, text: '' };
+ else if(text === f.last.text) return;
+ f.last.text = text;
+ wMsg('module',{
+ type:'status',
+ data:{step: ++f.last.step, text: text||null}
+ });
+ },
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
is called _before_ the final call to Module.setStatus(). */;
Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
- //console.log('onRuntimeInitialized');
- //wMsg('module','done');
+ wMsg('fiddle-ready');
};
(function(){
'use strict';
+ /* Recall that the 'self' symbol, except where locally
+ overwritten, refers to the global window or worker object. */
+
/**
The SqliteFiddle object is intended to be the primary
app-level object for the main-thread side of the sqlite
SF.addMsgHandler('module', function f(ev){
ev = ev.data;
- //console.log("Module status:",ev);
- if('status'!==ev.type) return;
- /* This weird handling of the ev.data is simply how
- emscripten's auto-generated code notifies the client of
- load progress. */
- let text = ev.data;
- if(!f.last) f.last = { time: Date.now(), text: '' };
- if(text === f.last.text) return;
- const m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
- const now = Date.now();
- if(m && now - f.last.time < 30) return; // if this is a progress update, skip it if too soon
- f.last.time = now;
- f.last.text = text;
- if(m) {
- text = m[1];
- progressElement.value = parseInt(m[2])*100;
- progressElement.max = parseInt(m[4])*100;
+ if('status'!==ev.type){
+ console.warn("Unexpected module-type message:",ev);
+ return;
+ }
+ const msg = ev.data;
+ progressElement.value = msg.step;
+ progressElement.max = msg.step + 1/*we don't know how many steps to expect*/;
+ if(1==msg.step){
progressElement.hidden = false;
spinnerElement.hidden = false;
- } else {
- progressElement.remove();
- if(!text) spinnerElement.remove();
}
- if(text){
- statusElement.innerText = text;
+ if(msg.text){
+ statusElement.classList.remove('hidden');
+ statusElement.innerText = msg.text;
}else{
- console.log("Finalizing status.");
- statusElement.remove();
- SF.clearMsgHandlers('module');
- self.onSFLoaded();
+ progressElement.remove();
+ spinnerElement.remove();
+ statusElement.classList.add('hidden');
+ /* The module can post messages about fatal problems,
+ e.g. an exit() being triggered or assertion failure,
+ after the last "load" message has arrived, so
+ leave the statusElement and message listener intact. */
}
});
+ /**
+ The 'fiddle-ready' event is fired (with no payload) when the
+ wasm module has finished loading. Interestingly, that happens
+ _before_ the final module:status event */
+ SF.addMsgHandler('fiddle-ready', function(){
+ SF.clearMsgHandlers('fiddle-ready');
+ self.onSFLoaded();
+ });
+
/**
Performs all app initialization which must wait until after the
worker module is loaded. This function removes itself when it's
-C wasm:\sadded\smissing\s'use\sstrict'\sand\sfixed\san\sundeclared\svar\suse\scaught\sby\sthat.
-D 2022-05-23T13:55:39.347
+C fiddle:\scleaned\sup\sand\sdocumented\sthe\sstatus-loading\sprogress\smechanism\sin\sprep\sfor\sreusing\sit\sin\sthe\ssqlite3-api\sworker.
+D 2022-05-23T16:54:18.777
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/fiddle/EXPORTED_RUNTIME_METHODS 91d5dcb0168ee056fa1a340cb8ab3c23d922622f8dad39d28919dd8af2b3ade0
F ext/fiddle/Makefile 9277c73e208b9c8093659256c9f07409c877e366480c7c22ec545ee345451d95
F ext/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
-F ext/fiddle/fiddle-worker.js c22557b641b47fa1473d3465a4e69fe06b8b09b924955805a4202c8201ddc429
+F ext/fiddle/fiddle-worker.js e87c17070b979bd057a6849332f2a86660a4255ff7f1b6671e3e6026182ffd5a
F ext/fiddle/fiddle.html 657c6c3f860c322fba3c69fa4f7a1209e2d2ce44b4bc65a3e154e3a97c047a7c
-F ext/fiddle/fiddle.js f9c79164428e96a5909532f18a8bc8f8c8ec4f738bfc09ad3d2a532c2400f9f0
+F ext/fiddle/fiddle.js 68f5bb45fc1ae7f8ae3f6b85f465257db514d12bf50ec492259685178c452a88
F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf
F ext/fiddle/sqlite3-api.js c684fc5ce6b6c3e70f33699de2fc4bf9eaf045a217a30125a9da31737a9ca9e7
F ext/fiddle/testing-common.js 53284264504821314f052017b54fa75ab065dcd9cbb754cc8060930498faeee8
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7e2d2e807272e98e9a3c9c9ba492b796a603f36b7cc12b16923cd8a9e6579851
-R 775bb58b424cc12ca6c6f62d38938ce2
+P c16a7f4950d47c2f5177db7dc5d83f0f11eb0cafdce1ec688d6f1bd740d92733
+R d12da4267c62c5adab320ccc656c0131
U stephan
-Z e5e8a91572b08fda7b97d6952202209e
+Z e5ea295f62c882bcf12e60eff235c6ea
# Remove this line to create a well-formed Fossil manifest.
-c16a7f4950d47c2f5177db7dc5d83f0f11eb0cafdce1ec688d6f1bd740d92733
\ No newline at end of file
+107e3497869d757265f2a4235082bf324ba1220075d1096c2a82021a5d348a6c
\ No newline at end of file