aboutsummaryrefslogtreecommitdiff
path: root/ext/wasm/api
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2022-08-24 05:59:23 +0000
committerstephan <stephan@noemail.net>2022-08-24 05:59:23 +0000
commit9a34509a06ad893ae3ac786363ebf8d29b3e3a7c (patch)
tree45fe8feae7e32d3a5db59c969857486de728d168 /ext/wasm/api
parentefeee19a958b905cc8e939e54b2959089bb89108 (diff)
downloadsqlite-9a34509a06ad893ae3ac786363ebf8d29b3e3a7c.tar.gz
sqlite-9a34509a06ad893ae3ac786363ebf8d29b3e3a7c.zip
More work on how to configure the sqlite3 JS API bootstrapping process from higher-level code. Initial version of sqlite3-worker1-promiser, a Promise-based proxy for the Worker API #1.
FossilOrigin-Name: b030f321bd5a38cdd5d6f6735f201afa62d30d2b0ba02e67f055b4895553a878
Diffstat (limited to 'ext/wasm/api')
-rw-r--r--ext/wasm/api/sqlite3-api-cleanup.js45
-rw-r--r--ext/wasm/api/sqlite3-api-prologue.js48
-rw-r--r--ext/wasm/api/sqlite3-api-worker1.js37
3 files changed, 77 insertions, 53 deletions
diff --git a/ext/wasm/api/sqlite3-api-cleanup.js b/ext/wasm/api/sqlite3-api-cleanup.js
index d989facca..ed6b8c40e 100644
--- a/ext/wasm/api/sqlite3-api-cleanup.js
+++ b/ext/wasm/api/sqlite3-api-cleanup.js
@@ -18,44 +18,24 @@
'use strict';
if('undefined' !== typeof Module){ // presumably an Emscripten build
/**
- Replace sqlite3ApiBootstrap() with a variant which plugs in the
- Emscripten-based config for all config options which the client
- does not provide.
+ Install a suitable default configuration for sqlite3ApiBootstrap().
*/
- const SAB = self.sqlite3ApiBootstrap;
- self.sqlite3ApiBootstrap = function(apiConfig){
- apiConfig = apiConfig || {};
- const configDefaults = {
- Module: Module /* ==> Emscripten-style Module object. Currently
- needs to be exposed here for test code. NOT part
- of the public API. */,
- exports: Module['asm'],
- memory: Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */
- };
- const config = {};
- Object.keys(configDefaults).forEach(function(k){
- config[k] = Object.getOwnPropertyDescriptor(apiConfig, k)
- ? apiConfig[k] : configDefaults[k];
- });
- // Copy over any properties apiConfig defines but configDefaults does not...
- Object.keys(apiConfig).forEach(function(k){
- if(!Object.getOwnPropertyDescriptor(config, k)){
- config[k] = apiConfig[k];
- }
- });
- return SAB(config);
- };
+ const SABC = self.sqlite3ApiBootstrap.defaultConfig;
+ SABC.Module = Module /* ==> Current needs to be exposed here for test code. NOT part
+ of the public API. */;
+ SABC.exports = Module['asm'];
+ SABC.memory = Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */;
/**
For current (2022-08-22) purposes, automatically call
sqlite3ApiBootstrap(). That decision will be revisited at some
point, as we really want client code to be able to call this to
- configure certain parts. If the global sqliteApiConfig property
- is available, it is assumed to be a config object for
- sqlite3ApiBootstrap().
+ configure certain parts. Clients may modify
+ self.sqlite3ApiBootstrap.defaultConfig to tweak the default
+ configuration used by a no-args call to sqlite3ApiBootstrap().
*/
//console.warn("self.sqlite3ApiConfig = ",self.sqlite3ApiConfig);
- const sqlite3 = self.sqlite3ApiBootstrap(self.sqlite3ApiConfig || Object.create(null));
+ const sqlite3 = self.sqlite3ApiBootstrap();
delete self.sqlite3ApiBootstrap;
if(self.location && +self.location.port > 1024){
@@ -67,4 +47,9 @@ if('undefined' !== typeof Module){ // presumably an Emscripten build
delete sqlite3.capi.util /* arguable, but these are (currently) internal-use APIs */;
//console.warn("Module.sqlite3 =",Module.sqlite3);
Module.sqlite3 = sqlite3 /* Currently needed by test code and sqlite3-worker1.js */;
+}else{
+ console.warn("This is not running in an Emscripten module context, so",
+ "self.sqlite3ApiBootstrap() is _not_ being called due to lack",
+ "of config info for the WASM environment.",
+ "It must be called manually.");
}
diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js
index 1a38f0343..d92b948fc 100644
--- a/ext/wasm/api/sqlite3-api-prologue.js
+++ b/ext/wasm/api/sqlite3-api-prologue.js
@@ -93,16 +93,16 @@
The config object properties include:
- - `Module`: Emscripten-style module object. Currently only required
+ - `Module`[^1]: Emscripten-style module object. Currently only required
by certain test code and is _not_ part of the public interface.
(TODO: rename this to EmscriptenModule to be more explicit.)
- - `exports`: the "exports" object for the current WASM
+ - `exports`[^1]: the "exports" object for the current WASM
environment. In an Emscripten build, this should be set to
`Module['asm']`.
- - `memory`: optional WebAssembly.Memory object, defaulting to
- `exports.memory`. In Emscripten environments this should be set
+ - `memory`[^1]: optional WebAssembly.Memory object, defaulting to
+ `exports.memory`. In Emscripten environments this should be set
to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be
left undefined/falsy to default to `exports.memory` when using
WASM-exported memory.
@@ -120,20 +120,26 @@
the `free(3)`-compatible routine for the WASM
environment. Defaults to `"free"`.
- - `persistentDirName`: if the environment supports persistent storage, this
+ - `persistentDirName`[^1]: if the environment supports persistent storage, this
directory names the "mount point" for that directory. It must be prefixed
by `/` and may currently contain only a single directory-name part. Using
the root directory name is not supported by any current persistent backend.
+
+
+ [^1] = This property may optionally be a function, in which case this
+ function re-assigns it to the value returned from that function,
+ enabling delayed evaluation.
+
*/
-self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(apiConfig){
- 'use strict';
-
+'use strict';
+self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
+ apiConfig = (sqlite3ApiBootstrap.defaultConfig || self.sqlite3ApiConfig)
+){
if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */
console.warn("sqlite3ApiBootstrap() called multiple times.",
"Config and external initializers are ignored on calls after the first.");
return sqlite3ApiBootstrap.sqlite3;
}
-
apiConfig = apiConfig || {};
const config = Object.create(null);
{
@@ -158,6 +164,16 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(apiConfig){
});
}
+ [
+ // If any of these config options are functions, replace them with
+ // the result of calling that function...
+ 'Module', 'exports', 'memory', 'persistentDirName'
+ ].forEach((k)=>{
+ if('function' === typeof config[k]){
+ config[k] = config[k]();
+ }
+ });
+
/** Throws a new Error, the message of which is the concatenation
all args with a space between each. */
const toss = (...args)=>{throw new Error(args.join(' '))};
@@ -750,4 +766,16 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(apiConfig){
this array is deleted.
*/
self.sqlite3ApiBootstrap.initializers = [];
-self.sqlite3ApiBootstrap.sqlite3 = undefined /* installed at first call */;
+/**
+ Client code may assign sqlite3ApiBootstrap.defaultConfig an
+ object-type value before calling sqlite3ApiBootstrap() (without
+ arguments) in order to tell that call to use this object as its
+ default config value. The intention of this is to provide
+ downstream clients with a reasonably flexible approach for plugging in
+ an environment-suitable configuration without having to define a new
+ global-scope symbol.
+*/
+self.sqlite3ApiBootstrap.defaultConfig = Object.create(null);
+/** Placeholder: gets installed by the first call to
+ self.sqlite3ApiBootstrap(). */
+self.sqlite3ApiBootstrap.sqlite3 = undefined;
diff --git a/ext/wasm/api/sqlite3-api-worker1.js b/ext/wasm/api/sqlite3-api-worker1.js
index 2e8d5a25d..39263a4ab 100644
--- a/ext/wasm/api/sqlite3-api-worker1.js
+++ b/ext/wasm/api/sqlite3-api-worker1.js
@@ -92,11 +92,8 @@ sqlite3.initWorker1API = function(){
defaultDb: undefined,
idSeq: 0,
idMap: new WeakMap,
- open: function(arg){
- // TODO? if arg is a filename, look for a db in this.dbs with the
- // same filename and close/reopen it (or just pass it back as is?).
- if(!arg && this.defaultDb) return this.defaultDb;
- const db = (Array.isArray(arg) ? new DB(...arg) : new DB(arg));
+ open: function(opt){
+ const db = new DB(opt.filename);
this.dbs[getDbId(db)] = db;
if(!this.defaultDb) this.defaultDb = db;
return db;
@@ -169,14 +166,26 @@ sqlite3.initWorker1API = function(){
envelope to other calls in this API to tell them which
db to use. If it is not provided to future calls, they
will default to operating on the first-opened db.
+
+ persistent: prepend sqlite3.capi.sqlite3_web_persistent_dir()
+ to the given filename so that it is stored
+ in persistent storage _if_ the environment supports it.
+ If persistent storage is not supported, the filename
+ is used as-is.
}
*/
open: function(ev){
- const oargs = [], args = (ev.args || {});
+ const oargs = Object.create(null), args = (ev.args || Object.create(null));
if(args.simulateError){ // undocumented internal testing option
toss("Throwing because of simulateError flag.");
}
- if(args.filename) oargs.push(args.filename);
+ if(args.persistent && args.filename){
+ oargs.filaname = sqlite3.capi.sqlite3_web_persistent_dir() + args.filename;
+ }else if('' === args.filename){
+ oargs.filename = args.filename;
+ }else{
+ oargs.filename = args.filename || ':memory:';
+ }
const db = wState.open(oargs);
return {
filename: db.filename,
@@ -184,15 +193,15 @@ sqlite3.initWorker1API = function(){
};
},
/**
- Proxy for DB.close(). ev.args may either be a boolean or an
- object with an `unlink` property. If that value is truthy then
- the db file (if the db is currently open) will be unlinked from
- the virtual filesystem, else it will be kept intact. The
- result object is:
+ Proxy for DB.close(). ev.args may be elided or an object with
+ an `unlink` property. If that value is truthy then the db file
+ (if the db is currently open) will be unlinked from the virtual
+ filesystem, else it will be kept intact. The result object is:
{
filename: db filename _if_ the db is opened when this
is called, else the undefined value
+ dbId: the ID of the closed b, or undefined if none is closed
}
It does not error if the given db is already closed or no db is
@@ -356,6 +365,7 @@ sqlite3.initWorker1API = function(){
dbId: DB handle ID,
[messageId: if set in the inbound message],
result: {
+ operation: "inbound message's 'type' value",
message: error string,
errorClass: class name of the error type,
input: ev.data
@@ -378,6 +388,7 @@ sqlite3.initWorker1API = function(){
}catch(err){
evType = 'error';
result = {
+ operation: ev.type,
message: err.message,
errorClass: err.name,
input: ev
@@ -405,7 +416,7 @@ sqlite3.initWorker1API = function(){
result: result
}, wMsgHandler.xfer);
};
- setTimeout(()=>self.postMessage({type:'sqlite3-api',result:'worker1-ready'}), 0);
+ self.postMessage({type:'sqlite3-api',result:'worker1-ready'});
}.bind({self, sqlite3});
});