aboutsummaryrefslogtreecommitdiff
path: root/ext/wasm/api/sqlite3-v-helper.js
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2024-01-11 12:31:58 +0000
committerstephan <stephan@noemail.net>2024-01-11 12:31:58 +0000
commit598328209f421d48e98115dd6816da5114403616 (patch)
tree7d333fc901bd29e575c7b22fd173e93e4ce23866 /ext/wasm/api/sqlite3-v-helper.js
parent6b36d0b46189d217721d25ce475fad171ae0a227 (diff)
downloadsqlite-598328209f421d48e98115dd6816da5114403616.tar.gz
sqlite-598328209f421d48e98115dd6816da5114403616.zip
Split the JS vfs/vtab helper code into discreet units as a step towards a build which optionally elides those pieces. This is an internal restructuring change and does not affect the API.
FossilOrigin-Name: ede945fd2360097d9961b8a4b8fb48fea57399cb9163534ed1c3c6b86588b0a5
Diffstat (limited to 'ext/wasm/api/sqlite3-v-helper.js')
-rw-r--r--ext/wasm/api/sqlite3-v-helper.js718
1 files changed, 0 insertions, 718 deletions
diff --git a/ext/wasm/api/sqlite3-v-helper.js b/ext/wasm/api/sqlite3-v-helper.js
deleted file mode 100644
index e63da8afc..000000000
--- a/ext/wasm/api/sqlite3-v-helper.js
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
-** 2022-11-30
-**
-** 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 installs sqlite3.vfs, and object which exists to assist
- in the creation of JavaScript implementations of sqlite3_vfs, along
- with its virtual table counterpart, sqlite3.vtab.
-*/
-'use strict';
-globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
- const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss3;
- const vfs = Object.create(null), vtab = Object.create(null);
-
- const StructBinder = sqlite3.StructBinder
- /* we require a local alias b/c StructBinder is removed from the sqlite3
- object during the final steps of the API cleanup. */;
- sqlite3.vfs = vfs;
- sqlite3.vtab = vtab;
-
- const sii = capi.sqlite3_index_info;
- /**
- If n is >=0 and less than this.$nConstraint, this function
- returns either a WASM pointer to the 0-based nth entry of
- this.$aConstraint (if passed a truthy 2nd argument) or an
- sqlite3_index_info.sqlite3_index_constraint object wrapping that
- address (if passed a falsy value or no 2nd argument). Returns a
- falsy value if n is out of range.
- */
- sii.prototype.nthConstraint = function(n, asPtr=false){
- if(n<0 || n>=this.$nConstraint) return false;
- const ptr = this.$aConstraint + (
- sii.sqlite3_index_constraint.structInfo.sizeof * n
- );
- return asPtr ? ptr : new sii.sqlite3_index_constraint(ptr);
- };
-
- /**
- Works identically to nthConstraint() but returns state from
- this.$aConstraintUsage, so returns an
- sqlite3_index_info.sqlite3_index_constraint_usage instance
- if passed no 2nd argument or a falsy 2nd argument.
- */
- sii.prototype.nthConstraintUsage = function(n, asPtr=false){
- if(n<0 || n>=this.$nConstraint) return false;
- const ptr = this.$aConstraintUsage + (
- sii.sqlite3_index_constraint_usage.structInfo.sizeof * n
- );
- return asPtr ? ptr : new sii.sqlite3_index_constraint_usage(ptr);
- };
-
- /**
- If n is >=0 and less than this.$nOrderBy, this function
- returns either a WASM pointer to the 0-based nth entry of
- this.$aOrderBy (if passed a truthy 2nd argument) or an
- sqlite3_index_info.sqlite3_index_orderby object wrapping that
- address (if passed a falsy value or no 2nd argument). Returns a
- falsy value if n is out of range.
- */
- sii.prototype.nthOrderBy = function(n, asPtr=false){
- if(n<0 || n>=this.$nOrderBy) return false;
- const ptr = this.$aOrderBy + (
- sii.sqlite3_index_orderby.structInfo.sizeof * n
- );
- return asPtr ? ptr : new sii.sqlite3_index_orderby(ptr);
- };
-
- /**
- Installs a StructBinder-bound function pointer member of the
- given name and function in the given StructType target object.
-
- It creates a WASM proxy for the given function and arranges for
- that proxy to be cleaned up when tgt.dispose() is called. Throws
- on the slightest hint of error, e.g. tgt is-not-a StructType,
- name does not map to a struct-bound member, etc.
-
- As a special case, if the given function is a pointer, then
- `wasm.functionEntry()` is used to validate that it is a known
- function. If so, it is used as-is with no extra level of proxying
- or cleanup, else an exception is thrown. It is legal to pass a
- value of 0, indicating a NULL pointer, with the caveat that 0
- _is_ a legal function pointer in WASM but it will not be accepted
- as such _here_. (Justification: the function at address zero must
- be one which initially came from the WASM module, not a method we
- want to bind to a virtual table or VFS.)
-
- This function returns a proxy for itself which is bound to tgt
- and takes 2 args (name,func). That function returns the same
- thing as this one, permitting calls to be chained.
-
- If called with only 1 arg, it has no side effects but returns a
- func with the same signature as described above.
-
- ACHTUNG: because we cannot generically know how to transform JS
- exceptions into result codes, the installed functions do no
- automatic catching of exceptions. It is critical, to avoid
- undefined behavior in the C layer, that methods mapped via
- this function do not throw. The exception, as it were, to that
- rule is...
-
- If applyArgcCheck is true then each JS function (as opposed to
- function pointers) gets wrapped in a proxy which asserts that it
- is passed the expected number of arguments, throwing if the
- argument count does not match expectations. That is only intended
- for dev-time usage for sanity checking, and will leave the C
- environment in an undefined state.
- */
- const installMethod = function callee(
- tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck
- ){
- if(!(tgt instanceof StructBinder.StructType)){
- toss("Usage error: target object is-not-a StructType.");
- }else if(!(func instanceof Function) && !wasm.isPtr(func)){
- toss("Usage errror: expecting a Function or WASM pointer to one.");
- }
- if(1===arguments.length){
- return (n,f)=>callee(tgt, n, f, applyArgcCheck);
- }
- if(!callee.argcProxy){
- callee.argcProxy = function(tgt, funcName, func,sig){
- return function(...args){
- if(func.length!==arguments.length){
- toss("Argument mismatch for",
- tgt.structInfo.name+"::"+funcName
- +": Native signature is:",sig);
- }
- return func.apply(this, args);
- }
- };
- /* An ondispose() callback for use with
- StructBinder-created types. */
- callee.removeFuncList = function(){
- if(this.ondispose.__removeFuncList){
- this.ondispose.__removeFuncList.forEach(
- (v,ndx)=>{
- if('number'===typeof v){
- try{wasm.uninstallFunction(v)}
- catch(e){/*ignore*/}
- }
- /* else it's a descriptive label for the next number in
- the list. */
- }
- );
- delete this.ondispose.__removeFuncList;
- }
- };
- }/*static init*/
- const sigN = tgt.memberSignature(name);
- if(sigN.length<2){
- toss("Member",name,"does not have a function pointer signature:",sigN);
- }
- const memKey = tgt.memberKey(name);
- const fProxy = (applyArgcCheck && !wasm.isPtr(func))
- /** This middle-man proxy is only for use during development, to
- confirm that we always pass the proper number of
- arguments. We know that the C-level code will always use the
- correct argument count. */
- ? callee.argcProxy(tgt, memKey, func, sigN)
- : func;
- if(wasm.isPtr(fProxy)){
- if(fProxy && !wasm.functionEntry(fProxy)){
- toss("Pointer",fProxy,"is not a WASM function table entry.");
- }
- tgt[memKey] = fProxy;
- }else{
- const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name, true));
- tgt[memKey] = pFunc;
- if(!tgt.ondispose || !tgt.ondispose.__removeFuncList){
- tgt.addOnDispose('ondispose.__removeFuncList handler',
- callee.removeFuncList);
- tgt.ondispose.__removeFuncList = [];
- }
- tgt.ondispose.__removeFuncList.push(memKey, pFunc);
- }
- return (n,f)=>callee(tgt, n, f, applyArgcCheck);
- }/*installMethod*/;
- installMethod.installMethodArgcCheck = false;
-
- /**
- Installs methods into the given StructType-type instance. Each
- entry in the given methods object must map to a known member of
- the given StructType, else an exception will be triggered. See
- installMethod() for more details, including the semantics of the
- 3rd argument.
-
- As an exception to the above, if any two or more methods in the
- 2nd argument are the exact same function, installMethod() is
- _not_ called for the 2nd and subsequent instances, and instead
- those instances get assigned the same method pointer which is
- created for the first instance. This optimization is primarily to
- accommodate special handling of sqlite3_module::xConnect and
- xCreate methods.
-
- On success, returns its first argument. Throws on error.
- */
- const installMethods = function(
- structInstance, methods, applyArgcCheck = installMethod.installMethodArgcCheck
- ){
- const seen = new Map /* map of <Function, memberName> */;
- for(const k of Object.keys(methods)){
- const m = methods[k];
- const prior = seen.get(m);
- if(prior){
- const mkey = structInstance.memberKey(k);
- structInstance[mkey] = structInstance[structInstance.memberKey(prior)];
- }else{
- installMethod(structInstance, k, m, applyArgcCheck);
- seen.set(m, k);
- }
- }
- return structInstance;
- };
-
- /**
- Equivalent to calling installMethod(this,...arguments) with a
- first argument of this object. If called with 1 or 2 arguments
- and the first is an object, it's instead equivalent to calling
- installMethods(this,...arguments).
- */
- StructBinder.StructType.prototype.installMethod = function callee(
- name, func, applyArgcCheck = installMethod.installMethodArgcCheck
- ){
- return (arguments.length < 3 && name && 'object'===typeof name)
- ? installMethods(this, ...arguments)
- : installMethod(this, ...arguments);
- };
-
- /**
- Equivalent to calling installMethods() with a first argument
- of this object.
- */
- StructBinder.StructType.prototype.installMethods = function(
- methods, applyArgcCheck = installMethod.installMethodArgcCheck
- ){
- return installMethods(this, methods, applyArgcCheck);
- };
-
- /**
- Uses sqlite3_vfs_register() to register this
- sqlite3.capi.sqlite3_vfs. This object must have already been
- filled out properly. If the first argument is truthy, the VFS is
- registered as the default VFS, else it is not.
-
- On success, returns this object. Throws on error.
- */
- capi.sqlite3_vfs.prototype.registerVfs = function(asDefault=false){
- if(!(this instanceof sqlite3.capi.sqlite3_vfs)){
- toss("Expecting a sqlite3_vfs-type argument.");
- }
- const rc = capi.sqlite3_vfs_register(this, asDefault ? 1 : 0);
- if(rc){
- toss("sqlite3_vfs_register(",this,") failed with rc",rc);
- }
- if(this.pointer !== capi.sqlite3_vfs_find(this.$zName)){
- toss("BUG: sqlite3_vfs_find(vfs.$zName) failed for just-installed VFS",
- this);
- }
- return this;
- };
-
- /**
- A wrapper for installMethods() or registerVfs() to reduce
- installation of a VFS and/or its I/O methods to a single
- call.
-
- Accepts an object which contains the properties "io" and/or
- "vfs", each of which is itself an object with following properties:
-
- - `struct`: an sqlite3.StructType-type struct. This must be a
- populated (except for the methods) object of type
- sqlite3_io_methods (for the "io" entry) or sqlite3_vfs (for the
- "vfs" entry).
-
- - `methods`: an object mapping sqlite3_io_methods method names
- (e.g. 'xClose') to JS implementations of those methods. The JS
- implementations must be call-compatible with their native
- counterparts.
-
- For each of those object, this function passes its (`struct`,
- `methods`, (optional) `applyArgcCheck`) properties to
- installMethods().
-
- If the `vfs` entry is set then:
-
- - Its `struct` property's registerVfs() is called. The
- `vfs` entry may optionally have an `asDefault` property, which
- gets passed as the argument to registerVfs().
-
- - If `struct.$zName` is falsy and the entry has a string-type
- `name` property, `struct.$zName` is set to the C-string form of
- that `name` value before registerVfs() is called. That string
- gets added to the on-dispose state of the struct.
-
- On success returns this object. Throws on error.
- */
- vfs.installVfs = function(opt){
- let count = 0;
- const propList = ['io','vfs'];
- for(const key of propList){
- const o = opt[key];
- if(o){
- ++count;
- installMethods(o.struct, o.methods, !!o.applyArgcCheck);
- if('vfs'===key){
- if(!o.struct.$zName && 'string'===typeof o.name){
- o.struct.addOnDispose(
- o.struct.$zName = wasm.allocCString(o.name)
- );
- }
- o.struct.registerVfs(!!o.asDefault);
- }
- }
- }
- if(!count) toss("Misuse: installVfs() options object requires at least",
- "one of:", propList);
- return this;
- };
-
- /**
- Internal factory function for xVtab and xCursor impls.
- */
- const __xWrapFactory = function(methodName,StructType){
- return function(ptr,removeMapping=false){
- if(0===arguments.length) ptr = new StructType;
- if(ptr instanceof StructType){
- //T.assert(!this.has(ptr.pointer));
- this.set(ptr.pointer, ptr);
- return ptr;
- }else if(!wasm.isPtr(ptr)){
- sqlite3.SQLite3Error.toss("Invalid argument to",methodName+"()");
- }
- let rc = this.get(ptr);
- if(removeMapping) this.delete(ptr);
- return rc;
- }.bind(new Map);
- };
-
- /**
- A factory function which implements a simple lifetime manager for
- mappings between C struct pointers and their JS-level wrappers.
- The first argument must be the logical name of the manager
- (e.g. 'xVtab' or 'xCursor'), which is only used for error
- reporting. The second must be the capi.XYZ struct-type value,
- e.g. capi.sqlite3_vtab or capi.sqlite3_vtab_cursor.
-
- Returns an object with 4 methods: create(), get(), unget(), and
- dispose(), plus a StructType member with the value of the 2nd
- argument. The methods are documented in the body of this
- function.
- */
- const StructPtrMapper = function(name, StructType){
- const __xWrap = __xWrapFactory(name,StructType);
- /**
- This object houses a small API for managing mappings of (`T*`)
- to StructType<T> objects, specifically within the lifetime
- requirements of sqlite3_module methods.
- */
- return Object.assign(Object.create(null),{
- /** The StructType object for this object's API. */
- StructType,
- /**
- Creates a new StructType object, writes its `pointer`
- value to the given output pointer, and returns that
- object. Its intended usage depends on StructType:
-
- sqlite3_vtab: to be called from sqlite3_module::xConnect()
- or xCreate() implementations.
-
- sqlite3_vtab_cursor: to be called from xOpen().
-
- This will throw if allocation of the StructType instance
- fails or if ppOut is not a pointer-type value.
- */
- create: (ppOut)=>{
- const rc = __xWrap();
- wasm.pokePtr(ppOut, rc.pointer);
- return rc;
- },
- /**
- Returns the StructType object previously mapped to the
- given pointer using create(). Its intended usage depends
- on StructType:
-
- sqlite3_vtab: to be called from sqlite3_module methods which
- take a (sqlite3_vtab*) pointer _except_ for
- xDestroy()/xDisconnect(), in which case unget() or dispose().
-
- sqlite3_vtab_cursor: to be called from any sqlite3_module methods
- which take a `sqlite3_vtab_cursor*` argument except xClose(),
- in which case use unget() or dispose().
-
- Rule to remember: _never_ call dispose() on an instance
- returned by this function.
- */
- get: (pCObj)=>__xWrap(pCObj),
- /**
- Identical to get() but also disconnects the mapping between the
- given pointer and the returned StructType object, such that
- future calls to this function or get() with the same pointer
- will return the undefined value. Its intended usage depends
- on StructType:
-
- sqlite3_vtab: to be called from sqlite3_module::xDisconnect() or
- xDestroy() implementations or in error handling of a failed
- xCreate() or xConnect().
-
- sqlite3_vtab_cursor: to be called from xClose() or during
- cleanup in a failed xOpen().
-
- Calling this method obligates the caller to call dispose() on
- the returned object when they're done with it.
- */
- unget: (pCObj)=>__xWrap(pCObj,true),
- /**
- Works like unget() plus it calls dispose() on the
- StructType object.
- */
- dispose: (pCObj)=>{
- const o = __xWrap(pCObj,true);
- if(o) o.dispose();
- }
- });
- };
-
- /**
- A lifetime-management object for mapping `sqlite3_vtab*`
- instances in sqlite3_module methods to capi.sqlite3_vtab
- objects.
-
- The API docs are in the API-internal StructPtrMapper().
- */
- vtab.xVtab = StructPtrMapper('xVtab', capi.sqlite3_vtab);
-
- /**
- A lifetime-management object for mapping `sqlite3_vtab_cursor*`
- instances in sqlite3_module methods to capi.sqlite3_vtab_cursor
- objects.
-
- The API docs are in the API-internal StructPtrMapper().
- */
- vtab.xCursor = StructPtrMapper('xCursor', capi.sqlite3_vtab_cursor);
-
- /**
- Convenience form of creating an sqlite3_index_info wrapper,
- intended for use in xBestIndex implementations. Note that the
- caller is expected to call dispose() on the returned object
- before returning. Though not _strictly_ required, as that object
- does not own the pIdxInfo memory, it is nonetheless good form.
- */
- vtab.xIndexInfo = (pIdxInfo)=>new capi.sqlite3_index_info(pIdxInfo);
-
- /**
- Given an error object, this function returns
- sqlite3.capi.SQLITE_NOMEM if (e instanceof
- sqlite3.WasmAllocError), else it returns its
- second argument. Its intended usage is in the methods
- of a sqlite3_vfs or sqlite3_module:
-
- ```
- try{
- let rc = ...
- return rc;
- }catch(e){
- return sqlite3.vtab.exceptionToRc(e, sqlite3.capi.SQLITE_XYZ);
- // where SQLITE_XYZ is some call-appropriate result code.
- }
- ```
- */
- /**vfs.exceptionToRc = vtab.exceptionToRc =
- (e, defaultRc=capi.SQLITE_ERROR)=>(
- (e instanceof sqlite3.WasmAllocError)
- ? capi.SQLITE_NOMEM
- : defaultRc
- );*/
-
- /**
- Given an sqlite3_module method name and error object, this
- function returns sqlite3.capi.SQLITE_NOMEM if (e instanceof
- sqlite3.WasmAllocError), else it returns its second argument. Its
- intended usage is in the methods of a sqlite3_vfs or
- sqlite3_module:
-
- ```
- try{
- let rc = ...
- return rc;
- }catch(e){
- return sqlite3.vtab.xError(
- 'xColumn', e, sqlite3.capi.SQLITE_XYZ);
- // where SQLITE_XYZ is some call-appropriate result code.
- }
- ```
-
- If no 3rd argument is provided, its default depends on
- the error type:
-
- - An sqlite3.WasmAllocError always resolves to capi.SQLITE_NOMEM.
-
- - If err is an SQLite3Error then its `resultCode` property
- is used.
-
- - If all else fails, capi.SQLITE_ERROR is used.
-
- If xError.errorReporter is a function, it is called in
- order to report the error, else the error is not reported.
- If that function throws, that exception is ignored.
- */
- vtab.xError = function f(methodName, err, defaultRc){
- if(f.errorReporter instanceof Function){
- try{f.errorReporter("sqlite3_module::"+methodName+"(): "+err.message);}
- catch(e){/*ignored*/}
- }
- let rc;
- if(err instanceof sqlite3.WasmAllocError) rc = capi.SQLITE_NOMEM;
- else if(arguments.length>2) rc = defaultRc;
- else if(err instanceof sqlite3.SQLite3Error) rc = err.resultCode;
- return rc || capi.SQLITE_ERROR;
- };
- vtab.xError.errorReporter = 1 ? console.error.bind(console) : false;
-
- /**
- "The problem" with this is that it introduces an outer function with
- a different arity than the passed-in method callback. That means we
- cannot do argc validation on these. Additionally, some methods (namely
- xConnect) may have call-specific error handling. It would be a shame to
- hard-coded that per-method support in this function.
- */
- /** vtab.methodCatcher = function(methodName, method, defaultErrRc=capi.SQLITE_ERROR){
- return function(...args){
- try { method(...args); }
- }catch(e){ return vtab.xError(methodName, e, defaultRc) }
- };
- */
-
- /**
- A helper for sqlite3_vtab::xRowid() and xUpdate()
- implementations. It must be passed the final argument to one of
- those methods (an output pointer to an int64 row ID) and the
- value to store at the output pointer's address. Returns the same
- as wasm.poke() and will throw if the 1st or 2nd arguments
- are invalid for that function.
-
- Example xRowid impl:
-
- ```
- const xRowid = (pCursor, ppRowid64)=>{
- const c = vtab.xCursor(pCursor);
- vtab.xRowid(ppRowid64, c.myRowId);
- return 0;
- };
- ```
- */
- vtab.xRowid = (ppRowid64, value)=>wasm.poke(ppRowid64, value, 'i64');
-
- /**
- A helper to initialize and set up an sqlite3_module object for
- later installation into individual databases using
- sqlite3_create_module(). Requires an object with the following
- properties:
-
- - `methods`: an object containing a mapping of properties with
- the C-side names of the sqlite3_module methods, e.g. xCreate,
- xBestIndex, etc., to JS implementations for those functions.
- Certain special-case handling is performed, as described below.
-
- - `catchExceptions` (default=false): if truthy, the given methods
- are not mapped as-is, but are instead wrapped inside wrappers
- which translate exceptions into result codes of SQLITE_ERROR or
- SQLITE_NOMEM, depending on whether the exception is an
- sqlite3.WasmAllocError. In the case of the xConnect and xCreate
- methods, the exception handler also sets the output error
- string to the exception's error string.
-
- - OPTIONAL `struct`: a sqlite3.capi.sqlite3_module() instance. If
- not set, one will be created automatically. If the current
- "this" is-a sqlite3_module then it is unconditionally used in
- place of `struct`.
-
- - OPTIONAL `iVersion`: if set, it must be an integer value and it
- gets assigned to the `$iVersion` member of the struct object.
- If it's _not_ set, and the passed-in `struct` object's `$iVersion`
- is 0 (the default) then this function attempts to define a value
- for that property based on the list of methods it has.
-
- If `catchExceptions` is false, it is up to the client to ensure
- that no exceptions escape the methods, as doing so would move
- them through the C API, leading to undefined
- behavior. (vtab.xError() is intended to assist in reporting
- such exceptions.)
-
- Certain methods may refer to the same implementation. To simplify
- the definition of such methods:
-
- - If `methods.xConnect` is `true` then the value of
- `methods.xCreate` is used in its place, and vice versa. sqlite
- treats xConnect/xCreate functions specially if they are exactly
- the same function (same pointer value).
-
- - If `methods.xDisconnect` is true then the value of
- `methods.xDestroy` is used in its place, and vice versa.
-
- This is to facilitate creation of those methods inline in the
- passed-in object without requiring the client to explicitly get a
- reference to one of them in order to assign it to the other
- one.
-
- The `catchExceptions`-installed handlers will account for
- identical references to the above functions and will install the
- same wrapper function for both.
-
- The given methods are expected to return integer values, as
- expected by the C API. If `catchExceptions` is truthy, the return
- value of the wrapped function will be used as-is and will be
- translated to 0 if the function returns a falsy value (e.g. if it
- does not have an explicit return). If `catchExceptions` is _not_
- active, the method implementations must explicitly return integer
- values.
-
- Throws on error. On success, returns the sqlite3_module object
- (`this` or `opt.struct` or a new sqlite3_module instance,
- depending on how it's called).
- */
- vtab.setupModule = function(opt){
- let createdMod = false;
- const mod = (this instanceof capi.sqlite3_module)
- ? this : (opt.struct || (createdMod = new capi.sqlite3_module()));
- try{
- const methods = opt.methods || toss("Missing 'methods' object.");
- for(const e of Object.entries({
- // -----^ ==> [k,v] triggers a broken code transformation in
- // some versions of the emsdk toolchain.
- xConnect: 'xCreate', xDisconnect: 'xDestroy'
- })){
- // Remap X=true to X=Y for certain X/Y combinations
- const k = e[0], v = e[1];
- if(true === methods[k]) methods[k] = methods[v];
- else if(true === methods[v]) methods[v] = methods[k];
- }
- if(opt.catchExceptions){
- const fwrap = function(methodName, func){
- if(['xConnect','xCreate'].indexOf(methodName) >= 0){
- return function(pDb, pAux, argc, argv, ppVtab, pzErr){
- try{return func(...arguments) || 0}
- catch(e){
- if(!(e instanceof sqlite3.WasmAllocError)){
- wasm.dealloc(wasm.peekPtr(pzErr));
- wasm.pokePtr(pzErr, wasm.allocCString(e.message));
- }
- return vtab.xError(methodName, e);
- }
- };
- }else{
- return function(...args){
- try{return func(...args) || 0}
- catch(e){
- return vtab.xError(methodName, e);
- }
- };
- }
- };
- const mnames = [
- 'xCreate', 'xConnect', 'xBestIndex', 'xDisconnect',
- 'xDestroy', 'xOpen', 'xClose', 'xFilter', 'xNext',
- 'xEof', 'xColumn', 'xRowid', 'xUpdate',
- 'xBegin', 'xSync', 'xCommit', 'xRollback',
- 'xFindFunction', 'xRename', 'xSavepoint', 'xRelease',
- 'xRollbackTo', 'xShadowName'
- ];
- const remethods = Object.create(null);
- for(const k of mnames){
- const m = methods[k];
- if(!(m instanceof Function)) continue;
- else if('xConnect'===k && methods.xCreate===m){
- remethods[k] = methods.xCreate;
- }else if('xCreate'===k && methods.xConnect===m){
- remethods[k] = methods.xConnect;
- }else{
- remethods[k] = fwrap(k, m);
- }
- }
- installMethods(mod, remethods, false);
- }else{
- // No automatic exception handling. Trust the client
- // to not throw.
- installMethods(
- mod, methods, !!opt.applyArgcCheck/*undocumented option*/
- );
- }
- if(0===mod.$iVersion){
- let v;
- if('number'===typeof opt.iVersion) v = opt.iVersion;
- else if(mod.$xShadowName) v = 3;
- else if(mod.$xSavePoint || mod.$xRelease || mod.$xRollbackTo) v = 2;
- else v = 1;
- mod.$iVersion = v;
- }
- }catch(e){
- if(createdMod) createdMod.dispose();
- throw e;
- }
- return mod;
- }/*setupModule()*/;
-
- /**
- Equivalent to calling vtab.setupModule() with this sqlite3_module
- object as the call's `this`.
- */
- capi.sqlite3_module.prototype.setupModule = function(opt){
- return vtab.setupModule.call(this, opt);
- };
-}/*sqlite3ApiBootstrap.initializers.push()*/);