mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
In wasm builds, ifdef out shell commands which require file I/O, pipes, or which trigger an exit() (.quit and .exit). Documented some of the quirks and limitations of the C/WASM crossover. Keep the JS code from calling into the C code after an exit() has been triggered.
FossilOrigin-Name: bee436e62a956e49b0df4a92abff2c89f2b44e21d8f593716df0331f8fc49814
This commit is contained in:
@ -53,13 +53,22 @@
|
||||
.button-bar button {
|
||||
margin: 0.25em 1em;
|
||||
}
|
||||
label {
|
||||
label[for] {
|
||||
cursor: pointer;
|
||||
}
|
||||
fieldset {
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
background-color: yellow;
|
||||
}
|
||||
.hidden {
|
||||
position: absolute !important;
|
||||
opacity: 0 !important;
|
||||
pointer-events: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -97,6 +106,34 @@ select * from t;</textarea>
|
||||
<label for='opt-cb-sbs'>Side-by-side</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
<hr>
|
||||
<header>
|
||||
Notes and Caveats
|
||||
(<input id='cb-notes-caveats' type='checkbox'>
|
||||
<label for='cb-notes-caveats'>hide</label>)
|
||||
</header>
|
||||
<div id='notes-caveats'>
|
||||
<p>
|
||||
This JavaScript application runs a C application which has been
|
||||
compiled into WASM (Web Assembly). As such, it has certain
|
||||
limitations. Those include, but are not limited to:
|
||||
</p>
|
||||
<ul>
|
||||
<li>It <strong>cannot recover after a call to
|
||||
<code>exit()</code></strong>. If the native code triggers
|
||||
an exit, reloading the page is the only way to restart
|
||||
the application. (Making the app restartable without reloading
|
||||
the page would require significant surgery in the C code.)
|
||||
</li>
|
||||
<li>It <strong>cannot perform any file I/O</strong>, and running
|
||||
any command which attempts to do so might trigger an
|
||||
<code>exit()</code>.
|
||||
</li>
|
||||
<li>A number of dot-commands available in the CLI shell are
|
||||
explicitly removed from this version of the shell.
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- #notes-caveats -->
|
||||
<script type='text/javascript'>
|
||||
(function(){
|
||||
/**
|
||||
@ -126,7 +163,14 @@ select * from t;</textarea>
|
||||
btnClearOut.addEventListener('click',function(){
|
||||
taOutput.value = '';
|
||||
},false);
|
||||
const doExec = Module.cwrap('fiddle_exec', null, ['string']);
|
||||
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.");
|
||||
}else{
|
||||
f._(sql);
|
||||
}
|
||||
};
|
||||
const btnRun = document.querySelector('#btn-run');
|
||||
btnRun.addEventListener('click',function(){
|
||||
const sql = taInput.value.trim();
|
||||
@ -136,11 +180,18 @@ select * from t;</textarea>
|
||||
},false);
|
||||
doExec(null)/*sets up the db and outputs the header*/;
|
||||
|
||||
let e = document.querySelector('#opt-cb-sbs');
|
||||
const mainWrapper = document.querySelector('#main-wrapper');
|
||||
e.addEventListener('change', function(){
|
||||
mainWrapper.classList[this.checked ? 'add' : 'remove']('side-by-side');
|
||||
}, false);
|
||||
document.querySelector('#opt-cb-sbs')
|
||||
.addEventListener('change', function(){
|
||||
document.querySelector('#main-wrapper').classList[
|
||||
this.checked ? 'add' : 'remove'
|
||||
]('side-by-side');
|
||||
}, false);
|
||||
document.querySelector('#cb-notes-caveats')
|
||||
.addEventListener('change', function(){
|
||||
document.querySelector('#notes-caveats').classList[
|
||||
this.checked ? 'add' : 'remove'
|
||||
]('hidden');
|
||||
}, false);
|
||||
|
||||
/* For all buttons with data-cmd=X, map a click handler which
|
||||
calls doExec(X). */
|
||||
@ -217,6 +268,7 @@ select * from t;</textarea>
|
||||
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');
|
||||
|
@ -64,7 +64,30 @@ Then browse to `http://localhost:9090/fiddle.html`.
|
||||
Note that when serving this app via [althttpd][], it must be a version
|
||||
from 2022-05-17 or newer so that it recognizes the `.wasm` file
|
||||
extension and responds with the mimetype `application/wasm`, as the
|
||||
wasm loader is pedantic about that detail.
|
||||
WASM loader is pedantic about that detail.
|
||||
|
||||
# Known Quirks and Limitations
|
||||
|
||||
Some "impedence mismatch" between C and WASM/JavaScript is to be
|
||||
expected.
|
||||
|
||||
## No I/O
|
||||
|
||||
sqlite3 shell commands which require file I/O or pipes are disabled in
|
||||
the WASM build.
|
||||
|
||||
## `exit()` Triggered from C
|
||||
|
||||
When C code calls `exit()`, as happens (for example) when running an
|
||||
"unsafe" command when safe mode is active, WASM's connection to the
|
||||
sqlite3 shell environment has no sensible choice but to shut down
|
||||
because `exit()` leaves it in a state we can no longer recover
|
||||
from. The JavaScript-side application attempts to recognize this and
|
||||
warn the user that restarting the application is necessary. Currently
|
||||
the only way to restart it is to reload the page. Restructuring the
|
||||
shell code such that it could be "rebooted" without restarting the
|
||||
JS app would require some invasive changes which are not currently
|
||||
on any TODO list but have not been entirely ruled out long-term.
|
||||
|
||||
|
||||
[emscripten]: https://emscripten.org
|
||||
|
Reference in New Issue
Block a user