diff options
author | stephan <stephan@noemail.net> | 2022-08-24 05:59:23 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2022-08-24 05:59:23 +0000 |
commit | 9a34509a06ad893ae3ac786363ebf8d29b3e3a7c (patch) | |
tree | 45fe8feae7e32d3a5db59c969857486de728d168 /ext/wasm/api | |
parent | efeee19a958b905cc8e939e54b2959089bb89108 (diff) | |
download | sqlite-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.js | 45 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-api-prologue.js | 48 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-api-worker1.js | 37 |
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}); }); |