-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split the fiddle JS code into separate pre-/post-init files to simpli…
…fy editing. emcc will combine these into the final fiddle.js, so the number of output deliverables does not change. FossilOrigin-Name: d3d8ea011868bcfa11bb3fe2db78eea6e77ac1005534d9c091f9a81e03f0a7e6
- Loading branch information
stephan
committed
May 19, 2022
1 parent
b8a2b20
commit 0fb074a
Showing
6 changed files
with
211 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* This is the --post-js file for emcc. It gets appended to the | ||
generated fiddle.js. It should contain all app-level code. | ||
Maintenance achtung: do not call any wasm-bound functions from | ||
outside of the onRuntimeInitialized() function. They are not | ||
permitted to be called until after the module init is complete, | ||
which does not happen until after this file is processed. Once that | ||
init is finished, Module.onRuntimeInitialized() will be | ||
triggered. All app-level init code should go into that callback or | ||
be triggered via it. Calling wasm-bound functions before that | ||
callback is run will trigger an assertion in the wasm environment. | ||
*/ | ||
window.Module.onRuntimeInitialized = function(){ | ||
'use strict'; | ||
const Module = window.Module /* wasm module as set up by emscripten */; | ||
delete Module.onRuntimeInitialized; | ||
const taInput = document.querySelector('#input'); | ||
const btnClearIn = document.querySelector('#btn-clear'); | ||
document.querySelectorAll('button').forEach(function(e){ | ||
e.removeAttribute('disabled'); | ||
}); | ||
btnClearIn.addEventListener('click',function(){ | ||
taInput.value = ''; | ||
},false); | ||
// Ctrl-enter and shift-enter both run the current SQL. | ||
taInput.addEventListener('keydown',function(ev){ | ||
if((ev.ctrlKey || ev.shiftKey) && 13 === ev.keyCode){ | ||
ev.preventDefault(); | ||
ev.stopPropagation(); | ||
btnRun.click(); | ||
} | ||
}, false); | ||
const taOutput = document.querySelector('#output'); | ||
const btnClearOut = document.querySelector('#btn-clear-output'); | ||
btnClearOut.addEventListener('click',function(){ | ||
taOutput.value = ''; | ||
},false); | ||
/* Sends the given text to the shell. If it's null or empty, this | ||
is a no-op except that the very first call will initialize the | ||
db and output an informational header. */ | ||
const doExec = function f(sql){ | ||
if(!f._) f._ = Module.cwrap('fiddle_exec', null, ['string']); | ||
if(Module._isDead){ | ||
Module.printErr("shell module has exit()ed. Cannot run SQL."); | ||
return; | ||
} | ||
if(Module.config.autoClearOutput) taOutput.value=''; | ||
f._(sql); | ||
}; | ||
const btnRun = document.querySelector('#btn-run'); | ||
btnRun.addEventListener('click',function(){ | ||
const sql = taInput.value.trim(); | ||
if(sql){ | ||
doExec(sql); | ||
} | ||
},false); | ||
|
||
document.querySelector('#opt-cb-sbs') | ||
.addEventListener('change', function(){ | ||
document.querySelector('#main-wrapper').classList[ | ||
this.checked ? 'add' : 'remove' | ||
]('side-by-side'); | ||
}, false); | ||
document.querySelector('#btn-notes-caveats') | ||
.addEventListener('click', function(){ | ||
document.querySelector('#notes-caveats').remove(); | ||
}, false); | ||
|
||
/* For each checkbox with data-config=X, set up a binding to | ||
Module.config[X]. */ | ||
document.querySelectorAll('input[type=checkbox][data-config]') | ||
.forEach(function(e){ | ||
e.checked = !!Module.config[e.dataset.config]; | ||
e.addEventListener('change', function(){ | ||
Module.config[this.dataset.config] = this.checked; | ||
}, false); | ||
}); | ||
|
||
/* For each button with data-cmd=X, map a click handler which | ||
calls doExec(X). */ | ||
const cmdClick = function(){doExec(this.dataset.cmd);}; | ||
document.querySelectorAll('button[data-cmd]').forEach( | ||
e => e.addEventListener('click', cmdClick, false) | ||
); | ||
|
||
doExec(null)/*sets up the db and outputs the header*/; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* This is the --pre-js file for emcc. It gets prepended to the | ||
generated fiddle.js. It should contain only code which is relevant | ||
to the setup and initialization of the wasm module. */ | ||
(function(){ | ||
'use strict'; | ||
|
||
/** | ||
What follows is part of the emscripten core setup. Do not | ||
modify it without understanding what it's doing. | ||
*/ | ||
const statusElement = document.getElementById('status'); | ||
const progressElement = document.getElementById('progress'); | ||
const spinnerElement = document.getElementById('spinner'); | ||
const Module = window.Module = { | ||
/* Config object. Referenced by certain Module methods and | ||
app-level code. */ | ||
config: { | ||
/* If true, the Module.print() impl will auto-scroll | ||
the output widget to the bottom when it receives output, | ||
else it won't. */ | ||
autoScrollOutput: true, | ||
/* If true, the output area will be cleared before each | ||
command is run, else it will not. */ | ||
autoClearOutput: false, | ||
/* If true, Module.print() will echo its output to | ||
the console, in addition to its normal output widget. */ | ||
printToConsole: false, | ||
}, | ||
preRun: [], | ||
postRun: [], | ||
//onRuntimeInitialized: function(){}, | ||
print: (function f() { | ||
if(!f._){ | ||
f._ = document.getElementById('output'); | ||
} | ||
f._.value = ''; // clear browser cache | ||
return function(text) { | ||
if(arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' '); | ||
// These replacements are necessary if you render to raw HTML | ||
//text = text.replace(/&/g, "&"); | ||
//text = text.replace(/</g, "<"); | ||
//text = text.replace(/>/g, ">"); | ||
//text = text.replace('\n', '<br>', 'g'); | ||
//console.log("arguments",arguments); | ||
if(window.Module.config.printToConsole) console.log(text); | ||
f._.value += text + "\n"; | ||
if(window.Module.config.autoScrollOutput){ | ||
f._.scrollTop = f._.scrollHeight; | ||
} | ||
}; | ||
})(), | ||
setStatus: function f(text) { | ||
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; | ||
progressElement.hidden = false; | ||
spinnerElement.hidden = false; | ||
} else { | ||
progressElement.value = null; | ||
progressElement.max = null; | ||
progressElement.hidden = true; | ||
if(!text) spinnerElement.hidden = true; | ||
} | ||
statusElement.innerHTML = text; | ||
}, | ||
totalDependencies: 0, | ||
monitorRunDependencies: function(left) { | ||
this.totalDependencies = Math.max(this.totalDependencies, left); | ||
this.setStatus(left | ||
? ('Preparing... (' + (this.totalDependencies-left) | ||
+ '/' + this.totalDependencies + ')') | ||
: 'All downloads complete.'); | ||
} | ||
}; | ||
Module.printErr = Module.print/*capture stderr output*/; | ||
Module.setStatus('Downloading...'); | ||
window.onerror = function(/*message, source, lineno, colno, error*/) { | ||
const err = arguments[4]; | ||
if(err && 'ExitStatus'==err.name){ | ||
Module._isDead = true; | ||
Module.printErr("FATAL ERROR:", err.message); | ||
Module.printErr("Restarting the app requires reloading the page."); | ||
const taOutput = document.querySelector('#output'); | ||
if(taOutput) taOutput.classList.add('error'); | ||
} | ||
Module.setStatus('Exception thrown, see JavaScript console'); | ||
spinnerElement.style.display = 'none'; | ||
Module.setStatus = function(text) { | ||
if(text) console.error('[post-exception status] ' + text); | ||
}; | ||
}; | ||
})(); |
Oops, something went wrong.