Adding the sqlite sourcecode
This commit is contained in:
1 parent
bdb54a1f8f
commit
406b584760
2208 files changed
+1172785
-1
No files matched your search
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
2022-05-22
|
||||
|
||||
The author disclaims copyright to this source code. In place of a
|
||||
legal notice, here is a blessing:
|
||||
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
|
||||
***********************************************************************
|
||||
|
||||
This file contains bootstrapping code used by various test scripts
|
||||
which live in this file's directory.
|
||||
*/
|
||||
'use strict';
|
||||
(function(self){
|
||||
/* querySelectorAll() proxy */
|
||||
const EAll = function(/*[element=document,] cssSelector*/){
|
||||
return (arguments.length>1 ? arguments[0] : document)
|
||||
.querySelectorAll(arguments[arguments.length-1]);
|
||||
};
|
||||
/* querySelector() proxy */
|
||||
const E = function(/*[element=document,] cssSelector*/){
|
||||
return (arguments.length>1 ? arguments[0] : document)
|
||||
.querySelector(arguments[arguments.length-1]);
|
||||
};
|
||||
|
||||
/**
|
||||
Helpers for writing sqlite3-specific tests.
|
||||
*/
|
||||
self.SqliteTestUtil = {
|
||||
/** Running total of the number of tests run via
|
||||
this API. */
|
||||
counter: 0,
|
||||
/**
|
||||
If expr is a function, it is called and its result
|
||||
is returned, coerced to a bool, else expr, coerced to
|
||||
a bool, is returned.
|
||||
*/
|
||||
toBool: function(expr){
|
||||
return (expr instanceof Function) ? !!expr() : !!expr;
|
||||
},
|
||||
/** abort() if expr is false. If expr is a function, it
|
||||
is called and its result is evaluated.
|
||||
*/
|
||||
assert: function f(expr, msg){
|
||||
if(!f._){
|
||||
f._ = ('undefined'===typeof abort
|
||||
? (msg)=>{throw new Error(msg)}
|
||||
: abort);
|
||||
}
|
||||
++this.counter;
|
||||
if(!this.toBool(expr)){
|
||||
f._(msg || "Assertion failed.");
|
||||
}
|
||||
return this;
|
||||
},
|
||||
/** Identical to assert() but throws instead of calling
|
||||
abort(). */
|
||||
affirm: function(expr, msg){
|
||||
++this.counter;
|
||||
if(!this.toBool(expr)) throw new Error(msg || "Affirmation failed.");
|
||||
return this;
|
||||
},
|
||||
/** Calls f() and squelches any exception it throws. If it
|
||||
does not throw, this function throws. */
|
||||
mustThrow: function(f, msg){
|
||||
++this.counter;
|
||||
let err;
|
||||
try{ f(); } catch(e){err=e;}
|
||||
if(!err) throw new Error(msg || "Expected exception.");
|
||||
return this;
|
||||
},
|
||||
/**
|
||||
Works like mustThrow() but expects filter to be a regex,
|
||||
function, or string to match/filter the resulting exception
|
||||
against. If f() does not throw, this test fails and an Error is
|
||||
thrown. If filter is a regex, the test passes if
|
||||
filter.test(error.message) passes. If it's a function, the test
|
||||
passes if filter(error) returns truthy. If it's a string, the
|
||||
test passes if the filter matches the exception message
|
||||
precisely. In all other cases the test fails, throwing an
|
||||
Error.
|
||||
|
||||
If it throws, msg is used as the error report unless it's falsy,
|
||||
in which case a default is used.
|
||||
*/
|
||||
mustThrowMatching: function(f, filter, msg){
|
||||
++this.counter;
|
||||
let err;
|
||||
try{ f(); } catch(e){err=e;}
|
||||
if(!err) throw new Error(msg || "Expected exception.");
|
||||
let pass = false;
|
||||
if(filter instanceof RegExp) pass = filter.test(err.message);
|
||||
else if(filter instanceof Function) pass = filter(err);
|
||||
else if('string' === typeof filter) pass = (err.message === filter);
|
||||
if(!pass){
|
||||
throw new Error(msg || ("Filter rejected this exception: "+err.message));
|
||||
}
|
||||
return this;
|
||||
},
|
||||
/** Throws if expr is truthy or expr is a function and expr()
|
||||
returns truthy. */
|
||||
throwIf: function(expr, msg){
|
||||
++this.counter;
|
||||
if(this.toBool(expr)) throw new Error(msg || "throwIf() failed");
|
||||
return this;
|
||||
},
|
||||
/** Throws if expr is falsy or expr is a function and expr()
|
||||
returns falsy. */
|
||||
throwUnless: function(expr, msg){
|
||||
++this.counter;
|
||||
if(!this.toBool(expr)) throw new Error(msg || "throwUnless() failed");
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
Parses window.location.search-style string into an object
|
||||
containing key/value pairs of URL arguments (already
|
||||
urldecoded). The object is created using Object.create(null),
|
||||
so contains only parsed-out properties and has no prototype
|
||||
(and thus no inherited properties).
|
||||
|
||||
If the str argument is not passed (arguments.length==0) then
|
||||
window.location.search.substring(1) is used by default. If
|
||||
neither str is passed in nor window exists then false is returned.
|
||||
|
||||
On success it returns an Object containing the key/value pairs
|
||||
parsed from the string. Keys which have no value are treated
|
||||
has having the boolean true value.
|
||||
|
||||
Pedantic licensing note: this code has appeared in other source
|
||||
trees, but was originally written by the same person who pasted
|
||||
it into those trees.
|
||||
*/
|
||||
processUrlArgs: function(str) {
|
||||
if( 0 === arguments.length ) {
|
||||
if( ('undefined' === typeof window) ||
|
||||
!window.location ||
|
||||
!window.location.search ) return false;
|
||||
else str = (''+window.location.search).substring(1);
|
||||
}
|
||||
if( ! str ) return false;
|
||||
str = (''+str).split(/#/,2)[0]; // remove #... to avoid it being added as part of the last value.
|
||||
const args = Object.create(null);
|
||||
const sp = str.split(/&+/);
|
||||
const rx = /^([^=]+)(=(.+))?/;
|
||||
var i, m;
|
||||
for( i in sp ) {
|
||||
m = rx.exec( sp[i] );
|
||||
if( ! m ) continue;
|
||||
args[decodeURIComponent(m[1])] = (m[3] ? decodeURIComponent(m[3]) : true);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
This is a module object for use with the emscripten-installed
|
||||
sqlite3InitModule() factory function.
|
||||
*/
|
||||
self.sqlite3TestModule = {
|
||||
/**
|
||||
Array of functions to call after Emscripten has initialized the
|
||||
wasm module. Each gets passed the Emscripten module object
|
||||
(which is _this_ object).
|
||||
*/
|
||||
postRun: [
|
||||
/* function(theModule){...} */
|
||||
],
|
||||
//onRuntimeInitialized: function(){},
|
||||
/* Proxy for C-side stdout output. */
|
||||
print: (...args)=>{console.log(...args)},
|
||||
/* Proxy for C-side stderr output. */
|
||||
printErr: (...args)=>{console.error(...args)},
|
||||
/**
|
||||
Called by the Emscripten module init bits to report loading
|
||||
progress. It gets passed an empty argument when loading is done
|
||||
(after onRuntimeInitialized() and any this.postRun callbacks
|
||||
have been run).
|
||||
*/
|
||||
setStatus: function f(text){
|
||||
if(!f.last){
|
||||
f.last = { text: '', step: 0 };
|
||||
f.ui = {
|
||||
status: E('#module-status'),
|
||||
progress: E('#module-progress'),
|
||||
spinner: E('#module-spinner')
|
||||
};
|
||||
}
|
||||
if(text === f.last.text) return;
|
||||
f.last.text = text;
|
||||
if(f.ui.progress){
|
||||
f.ui.progress.value = f.last.step;
|
||||
f.ui.progress.max = f.last.step + 1;
|
||||
}
|
||||
++f.last.step;
|
||||
if(text) {
|
||||
f.ui.status.classList.remove('hidden');
|
||||
f.ui.status.innerText = text;
|
||||
}else{
|
||||
if(f.ui.progress){
|
||||
f.ui.progress.remove();
|
||||
f.ui.spinner.remove();
|
||||
delete f.ui.progress;
|
||||
delete f.ui.spinner;
|
||||
}
|
||||
f.ui.status.classList.add('hidden');
|
||||
}
|
||||
},
|
||||
/**
|
||||
Config options used by the Emscripten-dependent initialization
|
||||
which happens via this.initSqlite3(). This object gets
|
||||
(indirectly) passed to sqlite3ApiBootstrap() to configure the
|
||||
sqlite3 API.
|
||||
*/
|
||||
sqlite3ApiConfig: {
|
||||
wasmfsOpfsDir: "/opfs"
|
||||
},
|
||||
/**
|
||||
Intended to be called by apps which need to call the
|
||||
Emscripten-installed sqlite3InitModule() routine. This function
|
||||
temporarily installs this.sqlite3ApiConfig into the self
|
||||
object, calls it sqlite3InitModule(), and removes
|
||||
self.sqlite3ApiConfig after initialization is done. Returns the
|
||||
promise from sqlite3InitModule(), and the next then() handler
|
||||
will get the sqlite3 API object as its argument.
|
||||
*/
|
||||
initSqlite3: function(){
|
||||
self.sqlite3ApiConfig = this.sqlite3ApiConfig;
|
||||
return self.sqlite3InitModule(this).finally(()=>delete self.sqlite3ApiConfig);
|
||||
}
|
||||
};
|
||||
})(self/*window or worker*/);
|
||||
@@ -0,0 +1,24 @@
|
||||
/* emscripten-related styling, used during the module load/intialization processes... */
|
||||
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
||||
div.emscripten { text-align: center; }
|
||||
div.emscripten_border { border: 1px solid black; }
|
||||
#module-spinner { overflow: visible; }
|
||||
#module-spinner > * {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.spinner {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
margin: 0px auto;
|
||||
animation: rotation 0.8s linear infinite;
|
||||
border-left: 10px solid rgb(0,150,240);
|
||||
border-right: 10px solid rgb(0,150,240);
|
||||
border-bottom: 10px solid rgb(0,150,240);
|
||||
border-top: 10px solid rgb(100,0,200);
|
||||
border-radius: 100%;
|
||||
background-color: rgb(200,100,250);
|
||||
}
|
||||
@keyframes rotation {
|
||||
from {transform: rotate(0deg);}
|
||||
to {transform: rotate(360deg);}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
textarea {
|
||||
font-family: monospace;
|
||||
}
|
||||
header {
|
||||
font-size: 130%;
|
||||
font-weight: bold;
|
||||
}
|
||||
.hidden, .initially-hidden {
|
||||
position: absolute !important;
|
||||
opacity: 0 !important;
|
||||
pointer-events: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
fieldset.options {
|
||||
font-size: 75%;
|
||||
}
|
||||
fieldset > legend {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
span.labeled-input {
|
||||
padding: 0.25em;
|
||||
margin: 0.25em 0.5em;
|
||||
border-radius: 0.25em;
|
||||
white-space: nowrap;
|
||||
background: #0002;
|
||||
}
|
||||
.center { text-align: center; }
|
||||
.error {
|
||||
color: red;
|
||||
background-color: yellow;
|
||||
}
|
||||
.strong { font-weight: 700 }
|
||||
.warning { color: firebrick; }
|
||||
.green { color: darkgreen; }
|
||||
.tests-pass { background-color: green; color: white }
|
||||
.tests-fail { background-color: red; color: yellow }
|
||||
.faded { opacity: 0.5; }
|
||||
.group-start {
|
||||
color: blue;
|
||||
background-color: skyblue;
|
||||
font-weight: bold;
|
||||
border-top: 1px dotted blue;
|
||||
padding: 0.5em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
.group-end {
|
||||
padding: 0.5em;
|
||||
margin-bottom: 0.25em;
|
||||
/*border-bottom: 1px dotted blue;*/
|
||||
}
|
||||
.group-end.green {
|
||||
background: lightgreen;
|
||||
border-bottom: 1px dotted green;
|
||||
}
|
||||
.one-test-line, .skipping-group {
|
||||
margin-left: 3em;
|
||||
}
|
||||
.skipping-test, .skipping-group {
|
||||
padding: 0.25em 0.5em;
|
||||
background-color: #ffff73;
|
||||
}
|
||||
.skipping-test {
|
||||
margin-left: 6em;
|
||||
}
|
||||
.one-test-summary {
|
||||
margin-left: 6em;
|
||||
}
|
||||
.full-test-summary {
|
||||
padding-bottom: 0.5em;
|
||||
padding-top: 0.5em;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
.input-wrapper {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
#test-output {
|
||||
border: 1px inset;
|
||||
border-radius: 0.25em;
|
||||
padding: 0.25em;
|
||||
/*max-height: 30em;*/
|
||||
overflow: auto;
|
||||
white-space: break-spaces;
|
||||
display: flex; flex-direction: column;
|
||||
font-family: monospace;
|
||||
}
|
||||
#test-output.reverse {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
label[for] { cursor: pointer }
|
||||
|
||||
h1 {
|
||||
border-radius: 0.25em;
|
||||
padding: 0.15em 0.25em;
|
||||
}
|
||||
h1:first-of-type {margin: 0 0 0.5em 0;}
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user