aboutsummaryrefslogtreecommitdiff
path: root/ext/fiddle/sqlite3-api.js
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2022-05-25 08:51:07 +0000
committerstephan <stephan@noemail.net>2022-05-25 08:51:07 +0000
commit26542e722bcdd9511b75cbc8cbf4720c01780632 (patch)
tree83cdd0a9c13528e8161b4cfb44cb45b2bbb0c4ae /ext/fiddle/sqlite3-api.js
parente599cc427f72c117d08e56387f7cd556a88829b8 (diff)
downloadsqlite-26542e722bcdd9511b75cbc8cbf4720c01780632.tar.gz
sqlite-26542e722bcdd9511b75cbc8cbf4720c01780632.zip
Got the sqlite3-api JS bits wrapped up in deferred-load module. Whether that's going to be easier to use, in practice, remains to be seen. Consolidated two of the test-related JS files.
FossilOrigin-Name: dd83cc05f2522d221641807dd66b33df48ac9264f27e5b6f63f312084f109801
Diffstat (limited to 'ext/fiddle/sqlite3-api.js')
-rw-r--r--ext/fiddle/sqlite3-api.js90
1 files changed, 50 insertions, 40 deletions
diff --git a/ext/fiddle/sqlite3-api.js b/ext/fiddle/sqlite3-api.js
index 7dff49980..d88ec9a8b 100644
--- a/ext/fiddle/sqlite3-api.js
+++ b/ext/fiddle/sqlite3-api.js
@@ -10,40 +10,45 @@
***********************************************************************
- This file is intended to be loaded after loading sqlite3.wasm. It
- sets up one of any number of potential bindings using that API, this
- one as closely matching the C-native API as is feasible in JS.
-
- Note that this file is not named sqlite3.js because that file gets
- generated by emscripten as the JS-glue counterpart of sqlite3.wasm.
-
- This code installs an object named self.Module.sqlite3, where self
- is expected to be either the global window or Worker object and
- Module is the object set up by the emscripten infrastructure. The
- sqlite3 object looks like:
-
- {
- api: bindings for much of the core sqlite3 APIs,
- SQLite3: high-level OO API wrapper
- }
-
- The way we export this module is not _really_ modern-JS-friendly
- because it exports/relies on a global symbol (which is admittedly
- not ideal). Exporting it "cleanly," without introducing any
- global-scope symbols, requires using a module loader in all client
- code. As there are several different approaches, none of which this
- developer is currently truly familiar with, the current approach
- will have to do for the time being.
+ This file is intended to be appended to the emcc-generated
+ sqlite3.js via emcc:
+
+ emcc ... -sMODULARIZE -sEXPORT_NAME=initSqlite3Module --post-js=THIS_FILE
+
+ It is loaded by importing the emcc-generated sqlite3.js, then:
+
+ initSqlite3Module({module object}).then(
+ function(theModule){
+ theModule.sqlite3 == an object containing this file's
+ deliverables:
+ {
+ api: bindings for much of the core sqlite3 APIs,
+ SQLite3: high-level OO API wrapper
+ }
+ });
+
+ It is up to the caller to provide a module object compatible with
+ emcc, but it can be a plain empty object. The object passed to
+ initSqlite3Module() will get populated by the emscripten-generated
+ bits and, in part, by the code from this file. Specifically, this file
+ installs the `theModule.sqlite3` part shown above.
+
+ The resulting sqlite3.api object wraps the standard sqlite3 C API in
+ a way as close to its native form as JS allows for. The
+ sqlite3.SQLite3 object provides a higher-level wrapper more
+ appropriate for general client-side use in JS.
Because using certain parts of the low-level API properly requires
some degree of WASM-related magic, it is not recommended that that
API be used as-is in client-level code. Rather, client code should
use the higher-level OO API or write a custom wrapper on top of the
- lower-level API. In short, using any C-style APIs which take
+ lower-level API. In short, most of the C-style API is used in an
+ intuitive manner from JS but any C-style APIs which take
pointers-to-pointer arguments require WASM-specific interfaces
installed by emcscripten-generated code. Those which take or return
only integers, doubles, strings, or "plain" pointers to db or
- statement objects can be used in a straightforward manner.
+ statement objects can be used in "as normal," noting that "pointers"
+ in wasm are simply 32-bit integers.
# Goals and Non-goals of this API
@@ -77,7 +82,10 @@
modern web and requires modern platforms.
*/
-(function(namespace){
+if(!Module.postRun) Module.postRun = [];
+/* ^^^^ the name Module is, in this setup, scope-local in the generated
+ file sqlite3.js, with which this file gets combined at build-time. */
+Module.postRun.push(function(namespace){
'use strict';
/* For reference: sql.js does essentially everything we want and
it solves much of the wasm-related voodoo, but we'll need a
@@ -111,6 +119,8 @@
clear and much experimentation is pending.
*/
+ const SQM = namespace/*the sqlite module object */;
+
/**
Set up the main sqlite3 binding API here, mimicking the C API as
closely as we can.
@@ -157,7 +167,7 @@
will only support UTF8. */
SQLITE_UTF8: 1
};
- const cwrap = Module.cwrap;
+ const cwrap = SQM.cwrap;
[/* C-side functions to bind. Each entry is an array with 3 or 4
elements:
@@ -237,7 +247,6 @@
const k = (4==a.length) ? a.shift() : a[0];
api[k] = cwrap.apply(this, a);
});
- //console.debug("libversion =",api.sqlite3_libversion());
/* What follows is colloquially known as "OO API #1". It is a
binding of the sqlite3 API which is designed to be run within
@@ -418,7 +427,7 @@
delete that._statements[k];
if(s && s._pStmt) s.finalize();
});
- Object.values(this._udfs).forEach(Module.removeFunction);
+ Object.values(this._udfs).forEach(SQM.removeFunction);
delete this._udfs;
delete this._statements;
delete this.filename;
@@ -562,7 +571,7 @@
(opt.callback && opt.rowMode)
? opt.rowMode : false);
try{
- let pSql = allocateUTF8OnStack(arg.sql)
+ let pSql = SQM.allocateUTF8OnStack(arg.sql)
const pzTail = stackAlloc(4);
while(getValue(pSql, "i8")){
setValue(pPtrArg, 0, "i32");
@@ -731,9 +740,10 @@
api.sqlite3_result_null(pCx);
break;
}else if(undefined!==val.length){
- const pBlob = Module.allocate(val, ALLOC_NORMAL);
+ const pBlob =
+ SQM.allocate(val, SQM.ALLOC_NORMAL);
api.sqlite3_result_blob(pCx, pBlob, val.length, -1/*==SQLITE_TRANSIENT*/);
- Module._free(blobptr);
+ SQM._free(blobptr);
break;
}
// else fall through
@@ -749,7 +759,7 @@
api.sqlite3_result_error(pCx, e.message, -1);
}
};
- const pUdf = Module.addFunction(wrapper, "viii");
+ const pUdf = SQM.addFunction(wrapper, "viii");
let fFlags = 0;
if(getOwnOption(opt, 'deterministic')) fFlags |= api.SQLITE_DETERMINISTIC;
if(getOwnOption(opt, 'directOnly')) fFlags |= api.SQLITE_DIRECTONLY;
@@ -762,11 +772,11 @@
api.SQLITE_UTF8 | fFlags, null/*pApp*/, pUdf,
null/*xStep*/, null/*xFinal*/, null/*xDestroy*/));
}catch(e){
- Module.removeFunction(pUdf);
+ SQM.removeFunction(pUdf);
throw e;
}
if(this._udfs.hasOwnProperty(name)){
- Module.removeFunction(this._udfs[name]);
+ SQM.removeFunction(this._udfs[name]);
}
this._udfs[name] = pUdf;
return this;
@@ -911,7 +921,7 @@
f._ = {
string: function(stmt, ndx, val, asBlob){
const bytes = intArrayFromString(val,true);
- const pStr = Module.allocate(bytes, ALLOC_NORMAL);
+ const pStr = SQM.allocate(bytes, ALLOC_NORMAL);
stmt._allocs.push(pStr);
const func = asBlob ? api.sqlite3_bind_blob : api.sqlite3_bind_text;
return func(stmt._pStmt, ndx, pStr, bytes.length, 0);
@@ -950,7 +960,7 @@
toss("Binding a value as a blob requires",
"that it have a length member.");
}
- const pBlob = Module.allocate(val, ALLOC_NORMAL);
+ const pBlob = SQM.allocate(val, ALLOC_NORMAL);
stmt._allocs.push(pBlob);
rc = api.sqlite3_bind_blob(stmt._pStmt, ndx, pBlob, len, 0);
}
@@ -966,7 +976,7 @@
const freeBindMemory = function(stmt){
let m;
while(undefined !== (m = stmt._allocs.pop())){
- Module._free(m);
+ SQM._free(m);
}
return stmt;
};
@@ -1383,4 +1393,4 @@
api: api,
SQLite3
};
-})(self/*worker or window*/.Module);
+});