diff options
author | stephan <stephan@noemail.net> | 2022-05-25 08:51:07 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2022-05-25 08:51:07 +0000 |
commit | 26542e722bcdd9511b75cbc8cbf4720c01780632 (patch) | |
tree | 83cdd0a9c13528e8161b4cfb44cb45b2bbb0c4ae /ext/fiddle/sqlite3-api.js | |
parent | e599cc427f72c117d08e56387f7cd556a88829b8 (diff) | |
download | sqlite-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.js | 90 |
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); +}); |