4 ** The author disclaims copyright to this source code. In place of a
5 ** legal notice, here is a blessing:
7 ** * May you do good and not evil.
8 ** * May you find forgiveness for yourself and forgive others.
9 ** * May you share freely, never taking more than you give.
13 This file installs sqlite3.vfs, and object which exists to assist
14 in the creation of JavaScript implementations of sqlite3_vfs, along
15 with its virtual table counterpart, sqlite3.vtab.
18 globalThis
.sqlite3ApiBootstrap
.initializers
.push(function(sqlite3
){
19 const wasm
= sqlite3
.wasm
, capi
= sqlite3
.capi
, toss
= sqlite3
.util
.toss3
;
20 const vfs
= Object
.create(null), vtab
= Object
.create(null);
22 const StructBinder
= sqlite3
.StructBinder
23 /* we require a local alias b/c StructBinder is removed from the sqlite3
24 object during the final steps of the API cleanup. */;
28 const sii
= capi
.sqlite3_index_info
;
30 If n is >=0 and less than this.$nConstraint, this function
31 returns either a WASM pointer to the 0-based nth entry of
32 this.$aConstraint (if passed a truthy 2nd argument) or an
33 sqlite3_index_info.sqlite3_index_constraint object wrapping that
34 address (if passed a falsy value or no 2nd argument). Returns a
35 falsy value if n is out of range.
37 sii
.prototype.nthConstraint = function(n
, asPtr
=false){
38 if(n
<0 || n
>=this.$nConstraint
) return false;
39 const ptr
= this.$aConstraint
+ (
40 sii
.sqlite3_index_constraint
.structInfo
.sizeof
* n
42 return asPtr
? ptr
: new sii
.sqlite3_index_constraint(ptr
);
46 Works identically to nthConstraint() but returns state from
47 this.$aConstraintUsage, so returns an
48 sqlite3_index_info.sqlite3_index_constraint_usage instance
49 if passed no 2nd argument or a falsy 2nd argument.
51 sii
.prototype.nthConstraintUsage = function(n
, asPtr
=false){
52 if(n
<0 || n
>=this.$nConstraint
) return false;
53 const ptr
= this.$aConstraintUsage
+ (
54 sii
.sqlite3_index_constraint_usage
.structInfo
.sizeof
* n
56 return asPtr
? ptr
: new sii
.sqlite3_index_constraint_usage(ptr
);
60 If n is >=0 and less than this.$nOrderBy, this function
61 returns either a WASM pointer to the 0-based nth entry of
62 this.$aOrderBy (if passed a truthy 2nd argument) or an
63 sqlite3_index_info.sqlite3_index_orderby object wrapping that
64 address (if passed a falsy value or no 2nd argument). Returns a
65 falsy value if n is out of range.
67 sii
.prototype.nthOrderBy = function(n
, asPtr
=false){
68 if(n
<0 || n
>=this.$nOrderBy
) return false;
69 const ptr
= this.$aOrderBy
+ (
70 sii
.sqlite3_index_orderby
.structInfo
.sizeof
* n
72 return asPtr
? ptr
: new sii
.sqlite3_index_orderby(ptr
);
76 Installs a StructBinder-bound function pointer member of the
77 given name and function in the given StructType target object.
79 It creates a WASM proxy for the given function and arranges for
80 that proxy to be cleaned up when tgt.dispose() is called. Throws
81 on the slightest hint of error, e.g. tgt is-not-a StructType,
82 name does not map to a struct-bound member, etc.
84 As a special case, if the given function is a pointer, then
85 `wasm.functionEntry()` is used to validate that it is a known
86 function. If so, it is used as-is with no extra level of proxying
87 or cleanup, else an exception is thrown. It is legal to pass a
88 value of 0, indicating a NULL pointer, with the caveat that 0
89 _is_ a legal function pointer in WASM but it will not be accepted
90 as such _here_. (Justification: the function at address zero must
91 be one which initially came from the WASM module, not a method we
92 want to bind to a virtual table or VFS.)
94 This function returns a proxy for itself which is bound to tgt
95 and takes 2 args (name,func). That function returns the same
96 thing as this one, permitting calls to be chained.
98 If called with only 1 arg, it has no side effects but returns a
99 func with the same signature as described above.
101 ACHTUNG: because we cannot generically know how to transform JS
102 exceptions into result codes, the installed functions do no
103 automatic catching of exceptions. It is critical, to avoid
104 undefined behavior in the C layer, that methods mapped via
105 this function do not throw. The exception, as it were, to that
108 If applyArgcCheck is true then each JS function (as opposed to
109 function pointers) gets wrapped in a proxy which asserts that it
110 is passed the expected number of arguments, throwing if the
111 argument count does not match expectations. That is only intended
112 for dev-time usage for sanity checking, and will leave the C
113 environment in an undefined state.
115 const installMethod
= function callee(
116 tgt
, name
, func
, applyArgcCheck
= callee
.installMethodArgcCheck
118 if(!(tgt
instanceof StructBinder
.StructType
)){
119 toss("Usage error: target object is-not-a StructType.");
120 }else if(!(func
instanceof Function
) && !wasm
.isPtr(func
)){
121 toss("Usage errror: expecting a Function or WASM pointer to one.");
123 if(1===arguments
.length
){
124 return (n
,f
)=>callee(tgt
, n
, f
, applyArgcCheck
);
126 if(!callee
.argcProxy
){
127 callee
.argcProxy = function(tgt
, funcName
, func
,sig
){
128 return function(...args
){
129 if(func
.length
!==arguments
.length
){
130 toss("Argument mismatch for",
131 tgt
.structInfo
.name
+"::"+funcName
132 +": Native signature is:",sig
);
134 return func
.apply(this, args
);
137 /* An ondispose() callback for use with
138 StructBinder-created types. */
139 callee
.removeFuncList = function(){
140 if(this.ondispose
.__removeFuncList
){
141 this.ondispose
.__removeFuncList
.forEach(
143 if('number'===typeof v
){
144 try{wasm
.uninstallFunction(v
)}
147 /* else it's a descriptive label for the next number in
151 delete this.ondispose
.__removeFuncList
;
155 const sigN
= tgt
.memberSignature(name
);
157 toss("Member",name
,"does not have a function pointer signature:",sigN
);
159 const memKey
= tgt
.memberKey(name
);
160 const fProxy
= (applyArgcCheck
&& !wasm
.isPtr(func
))
161 /** This middle-man proxy is only for use during development, to
162 confirm that we always pass the proper number of
163 arguments. We know that the C-level code will always use the
164 correct argument count. */
165 ? callee
.argcProxy(tgt
, memKey
, func
, sigN
)
167 if(wasm
.isPtr(fProxy
)){
168 if(fProxy
&& !wasm
.functionEntry(fProxy
)){
169 toss("Pointer",fProxy
,"is not a WASM function table entry.");
171 tgt
[memKey
] = fProxy
;
173 const pFunc
= wasm
.installFunction(fProxy
, tgt
.memberSignature(name
, true));
175 if(!tgt
.ondispose
|| !tgt
.ondispose
.__removeFuncList
){
176 tgt
.addOnDispose('ondispose.__removeFuncList handler',
177 callee
.removeFuncList
);
178 tgt
.ondispose
.__removeFuncList
= [];
180 tgt
.ondispose
.__removeFuncList
.push(memKey
, pFunc
);
182 return (n
,f
)=>callee(tgt
, n
, f
, applyArgcCheck
);
184 installMethod
.installMethodArgcCheck
= false;
187 Installs methods into the given StructType-type instance. Each
188 entry in the given methods object must map to a known member of
189 the given StructType, else an exception will be triggered. See
190 installMethod() for more details, including the semantics of the
193 As an exception to the above, if any two or more methods in the
194 2nd argument are the exact same function, installMethod() is
195 _not_ called for the 2nd and subsequent instances, and instead
196 those instances get assigned the same method pointer which is
197 created for the first instance. This optimization is primarily to
198 accommodate special handling of sqlite3_module::xConnect and
201 On success, returns its first argument. Throws on error.
203 const installMethods = function(
204 structInstance
, methods
, applyArgcCheck
= installMethod
.installMethodArgcCheck
206 const seen
= new Map
/* map of <Function, memberName> */;
207 for(const k
of Object
.keys(methods
)){
208 const m
= methods
[k
];
209 const prior
= seen
.get(m
);
211 const mkey
= structInstance
.memberKey(k
);
212 structInstance
[mkey
] = structInstance
[structInstance
.memberKey(prior
)];
214 installMethod(structInstance
, k
, m
, applyArgcCheck
);
218 return structInstance
;
222 Equivalent to calling installMethod(this,...arguments) with a
223 first argument of this object. If called with 1 or 2 arguments
224 and the first is an object, it's instead equivalent to calling
225 installMethods(this,...arguments).
227 StructBinder
.StructType
.prototype.installMethod
= function callee(
228 name
, func
, applyArgcCheck
= installMethod
.installMethodArgcCheck
230 return (arguments
.length
< 3 && name
&& 'object'===typeof name
)
231 ? installMethods(this, ...arguments
)
232 : installMethod(this, ...arguments
);
236 Equivalent to calling installMethods() with a first argument
239 StructBinder
.StructType
.prototype.installMethods = function(
240 methods
, applyArgcCheck
= installMethod
.installMethodArgcCheck
242 return installMethods(this, methods
, applyArgcCheck
);
246 Uses sqlite3_vfs_register() to register this
247 sqlite3.capi.sqlite3_vfs. This object must have already been
248 filled out properly. If the first argument is truthy, the VFS is
249 registered as the default VFS, else it is not.
251 On success, returns this object. Throws on error.
253 capi
.sqlite3_vfs
.prototype.registerVfs = function(asDefault
=false){
254 if(!(this instanceof sqlite3
.capi
.sqlite3_vfs
)){
255 toss("Expecting a sqlite3_vfs-type argument.");
257 const rc
= capi
.sqlite3_vfs_register(this, asDefault
? 1 : 0);
259 toss("sqlite3_vfs_register(",this,") failed with rc",rc
);
261 if(this.pointer
!== capi
.sqlite3_vfs_find(this.$zName
)){
262 toss("BUG: sqlite3_vfs_find(vfs.$zName) failed for just-installed VFS",
269 A wrapper for installMethods() or registerVfs() to reduce
270 installation of a VFS and/or its I/O methods to a single
273 Accepts an object which contains the properties "io" and/or
274 "vfs", each of which is itself an object with following properties:
276 - `struct`: an sqlite3.StructType-type struct. This must be a
277 populated (except for the methods) object of type
278 sqlite3_io_methods (for the "io" entry) or sqlite3_vfs (for the
281 - `methods`: an object mapping sqlite3_io_methods method names
282 (e.g. 'xClose') to JS implementations of those methods. The JS
283 implementations must be call-compatible with their native
286 For each of those object, this function passes its (`struct`,
287 `methods`, (optional) `applyArgcCheck`) properties to
290 If the `vfs` entry is set then:
292 - Its `struct` property's registerVfs() is called. The
293 `vfs` entry may optionally have an `asDefault` property, which
294 gets passed as the argument to registerVfs().
296 - If `struct.$zName` is falsy and the entry has a string-type
297 `name` property, `struct.$zName` is set to the C-string form of
298 that `name` value before registerVfs() is called.
300 On success returns this object. Throws on error.
302 vfs
.installVfs = function(opt
){
304 const propList
= ['io','vfs'];
305 for(const key
of propList
){
309 installMethods(o
.struct
, o
.methods
, !!o
.applyArgcCheck
);
311 if(!o
.struct
.$zName
&& 'string'===typeof o
.name
){
312 o
.struct
.addOnDispose(
313 o
.struct
.$zName
= wasm
.allocCString(o
.name
)
316 o
.struct
.registerVfs(!!o
.asDefault
);
320 if(!count
) toss("Misuse: installVfs() options object requires at least",
321 "one of:", propList
);
326 Internal factory function for xVtab and xCursor impls.
328 const __xWrapFactory = function(methodName
,StructType
){
329 return function(ptr
,removeMapping
=false){
330 if(0===arguments
.length
) ptr
= new StructType
;
331 if(ptr
instanceof StructType
){
332 //T.assert(!this.has(ptr.pointer));
333 this.set(ptr
.pointer
, ptr
);
335 }else if(!wasm
.isPtr(ptr
)){
336 sqlite3
.SQLite3Error
.toss("Invalid argument to",methodName
+"()");
338 let rc
= this.get(ptr
);
339 if(removeMapping
) this.delete(ptr
);
345 A factory function which implements a simple lifetime manager for
346 mappings between C struct pointers and their JS-level wrappers.
347 The first argument must be the logical name of the manager
348 (e.g. 'xVtab' or 'xCursor'), which is only used for error
349 reporting. The second must be the capi.XYZ struct-type value,
350 e.g. capi.sqlite3_vtab or capi.sqlite3_vtab_cursor.
352 Returns an object with 4 methods: create(), get(), unget(), and
353 dispose(), plus a StructType member with the value of the 2nd
354 argument. The methods are documented in the body of this
357 const StructPtrMapper = function(name
, StructType
){
358 const __xWrap
= __xWrapFactory(name
,StructType
);
360 This object houses a small API for managing mappings of (`T*`)
361 to StructType<T> objects, specifically within the lifetime
362 requirements of sqlite3_module methods.
364 return Object
.assign(Object
.create(null),{
365 /** The StructType object for this object's API. */
368 Creates a new StructType object, writes its `pointer`
369 value to the given output pointer, and returns that
370 object. Its intended usage depends on StructType:
372 sqlite3_vtab: to be called from sqlite3_module::xConnect()
373 or xCreate() implementations.
375 sqlite3_vtab_cursor: to be called from xOpen().
377 This will throw if allocation of the StructType instance
378 fails or if ppOut is not a pointer-type value.
381 const rc
= __xWrap();
382 wasm
.pokePtr(ppOut
, rc
.pointer
);
386 Returns the StructType object previously mapped to the
387 given pointer using create(). Its intended usage depends
390 sqlite3_vtab: to be called from sqlite3_module methods which
391 take a (sqlite3_vtab*) pointer _except_ for
392 xDestroy()/xDisconnect(), in which case unget() or dispose().
394 sqlite3_vtab_cursor: to be called from any sqlite3_module methods
395 which take a `sqlite3_vtab_cursor*` argument except xClose(),
396 in which case use unget() or dispose().
398 Rule to remember: _never_ call dispose() on an instance
399 returned by this function.
401 get: (pCObj
)=>__xWrap(pCObj
),
403 Identical to get() but also disconnects the mapping between the
404 given pointer and the returned StructType object, such that
405 future calls to this function or get() with the same pointer
406 will return the undefined value. Its intended usage depends
409 sqlite3_vtab: to be called from sqlite3_module::xDisconnect() or
410 xDestroy() implementations or in error handling of a failed
411 xCreate() or xConnect().
413 sqlite3_vtab_cursor: to be called from xClose() or during
414 cleanup in a failed xOpen().
416 Calling this method obligates the caller to call dispose() on
417 the returned object when they're done with it.
419 unget
: (pCObj
)=>__xWrap(pCObj
,true),
421 Works like unget() plus it calls dispose() on the
425 const o
= __xWrap(pCObj
,true);
432 A lifetime-management object for mapping `sqlite3_vtab*`
433 instances in sqlite3_module methods to capi.sqlite3_vtab
436 The API docs are in the API-internal StructPtrMapper().
438 vtab
.xVtab
= StructPtrMapper('xVtab', capi
.sqlite3_vtab
);
441 A lifetime-management object for mapping `sqlite3_vtab_cursor*`
442 instances in sqlite3_module methods to capi.sqlite3_vtab_cursor
445 The API docs are in the API-internal StructPtrMapper().
447 vtab
.xCursor
= StructPtrMapper('xCursor', capi
.sqlite3_vtab_cursor
);
450 Convenience form of creating an sqlite3_index_info wrapper,
451 intended for use in xBestIndex implementations. Note that the
452 caller is expected to call dispose() on the returned object
453 before returning. Though not _strictly_ required, as that object
454 does not own the pIdxInfo memory, it is nonetheless good form.
456 vtab
.xIndexInfo
= (pIdxInfo
)=>new capi
.sqlite3_index_info(pIdxInfo
);
459 Given an error object, this function returns
460 sqlite3.capi.SQLITE_NOMEM if (e instanceof
461 sqlite3.WasmAllocError), else it returns its
462 second argument. Its intended usage is in the methods
463 of a sqlite3_vfs or sqlite3_module:
470 return sqlite3.vtab.exceptionToRc(e, sqlite3.capi.SQLITE_XYZ);
471 // where SQLITE_XYZ is some call-appropriate result code.
475 /**vfs.exceptionToRc = vtab.exceptionToRc =
476 (e, defaultRc=capi.SQLITE_ERROR)=>(
477 (e instanceof sqlite3.WasmAllocError)
483 Given an sqlite3_module method name and error object, this
484 function returns sqlite3.capi.SQLITE_NOMEM if (e instanceof
485 sqlite3.WasmAllocError), else it returns its second argument. Its
486 intended usage is in the methods of a sqlite3_vfs or
494 return sqlite3.vtab.xError(
495 'xColumn', e, sqlite3.capi.SQLITE_XYZ);
496 // where SQLITE_XYZ is some call-appropriate result code.
500 If no 3rd argument is provided, its default depends on
503 - An sqlite3.WasmAllocError always resolves to capi.SQLITE_NOMEM.
505 - If err is an SQLite3Error then its `resultCode` property
508 - If all else fails, capi.SQLITE_ERROR is used.
510 If xError.errorReporter is a function, it is called in
511 order to report the error, else the error is not reported.
512 If that function throws, that exception is ignored.
514 vtab
.xError
= function f(methodName
, err
, defaultRc
){
515 if(f
.errorReporter
instanceof Function
){
516 try{f
.errorReporter("sqlite3_module::"+methodName
+"(): "+err
.message
);}
517 catch(e
){/*ignored*/}
520 if(err
instanceof sqlite3
.WasmAllocError
) rc
= capi
.SQLITE_NOMEM
;
521 else if(arguments
.length
>2) rc
= defaultRc
;
522 else if(err
instanceof sqlite3
.SQLite3Error
) rc
= err
.resultCode
;
523 return rc
|| capi
.SQLITE_ERROR
;
525 vtab
.xError
.errorReporter
= 1 ? console
.error
.bind(console
) : false;
528 "The problem" with this is that it introduces an outer function with
529 a different arity than the passed-in method callback. That means we
530 cannot do argc validation on these. Additionally, some methods (namely
531 xConnect) may have call-specific error handling. It would be a shame to
532 hard-coded that per-method support in this function.
534 /** vtab.methodCatcher = function(methodName, method, defaultErrRc=capi.SQLITE_ERROR){
535 return function(...args){
536 try { method(...args); }
537 }catch(e){ return vtab.xError(methodName, e, defaultRc) }
542 A helper for sqlite3_vtab::xRowid() and xUpdate()
543 implementations. It must be passed the final argument to one of
544 those methods (an output pointer to an int64 row ID) and the
545 value to store at the output pointer's address. Returns the same
546 as wasm.poke() and will throw if the 1st or 2nd arguments
547 are invalid for that function.
552 const xRowid = (pCursor, ppRowid64)=>{
553 const c = vtab.xCursor(pCursor);
554 vtab.xRowid(ppRowid64, c.myRowId);
559 vtab
.xRowid
= (ppRowid64
, value
)=>wasm
.poke(ppRowid64
, value
, 'i64');
562 A helper to initialize and set up an sqlite3_module object for
563 later installation into individual databases using
564 sqlite3_create_module(). Requires an object with the following
567 - `methods`: an object containing a mapping of properties with
568 the C-side names of the sqlite3_module methods, e.g. xCreate,
569 xBestIndex, etc., to JS implementations for those functions.
570 Certain special-case handling is performed, as described below.
572 - `catchExceptions` (default=false): if truthy, the given methods
573 are not mapped as-is, but are instead wrapped inside wrappers
574 which translate exceptions into result codes of SQLITE_ERROR or
575 SQLITE_NOMEM, depending on whether the exception is an
576 sqlite3.WasmAllocError. In the case of the xConnect and xCreate
577 methods, the exception handler also sets the output error
578 string to the exception's error string.
580 - OPTIONAL `struct`: a sqlite3.capi.sqlite3_module() instance. If
581 not set, one will be created automatically. If the current
582 "this" is-a sqlite3_module then it is unconditionally used in
585 - OPTIONAL `iVersion`: if set, it must be an integer value and it
586 gets assigned to the `$iVersion` member of the struct object.
587 If it's _not_ set, and the passed-in `struct` object's `$iVersion`
588 is 0 (the default) then this function attempts to define a value
589 for that property based on the list of methods it has.
591 If `catchExceptions` is false, it is up to the client to ensure
592 that no exceptions escape the methods, as doing so would move
593 them through the C API, leading to undefined
594 behavior. (vtab.xError() is intended to assist in reporting
597 Certain methods may refer to the same implementation. To simplify
598 the definition of such methods:
600 - If `methods.xConnect` is `true` then the value of
601 `methods.xCreate` is used in its place, and vice versa. sqlite
602 treats xConnect/xCreate functions specially if they are exactly
603 the same function (same pointer value).
605 - If `methods.xDisconnect` is true then the value of
606 `methods.xDestroy` is used in its place, and vice versa.
608 This is to facilitate creation of those methods inline in the
609 passed-in object without requiring the client to explicitly get a
610 reference to one of them in order to assign it to the other
613 The `catchExceptions`-installed handlers will account for
614 identical references to the above functions and will install the
615 same wrapper function for both.
617 The given methods are expected to return integer values, as
618 expected by the C API. If `catchExceptions` is truthy, the return
619 value of the wrapped function will be used as-is and will be
620 translated to 0 if the function returns a falsy value (e.g. if it
621 does not have an explicit return). If `catchExceptions` is _not_
622 active, the method implementations must explicitly return integer
625 Throws on error. On success, returns the sqlite3_module object
626 (`this` or `opt.struct` or a new sqlite3_module instance,
627 depending on how it's called).
629 vtab
.setupModule = function(opt
){
630 let createdMod
= false;
631 const mod
= (this instanceof capi
.sqlite3_module
)
632 ? this : (opt
.struct
|| (createdMod
= new capi
.sqlite3_module()));
634 const methods
= opt
.methods
|| toss("Missing 'methods' object.");
635 for(const e
of Object
.entries({
636 // -----^ ==> [k,v] triggers a broken code transformation in
637 // some versions of the emsdk toolchain.
638 xConnect
: 'xCreate', xDisconnect
: 'xDestroy'
640 // Remap X=true to X=Y for certain X/Y combinations
641 const k
= e
[0], v
= e
[1];
642 if(true === methods
[k
]) methods
[k
] = methods
[v
];
643 else if(true === methods
[v
]) methods
[v
] = methods
[k
];
645 if(opt
.catchExceptions
){
646 const fwrap = function(methodName
, func
){
647 if(['xConnect','xCreate'].indexOf(methodName
) >= 0){
648 return function(pDb
, pAux
, argc
, argv
, ppVtab
, pzErr
){
649 try{return func(...arguments
) || 0}
651 if(!(e
instanceof sqlite3
.WasmAllocError
)){
652 wasm
.dealloc(wasm
.peekPtr(pzErr
));
653 wasm
.pokePtr(pzErr
, wasm
.allocCString(e
.message
));
655 return vtab
.xError(methodName
, e
);
659 return function(...args
){
660 try{return func(...args
) || 0}
662 return vtab
.xError(methodName
, e
);
668 'xCreate', 'xConnect', 'xBestIndex', 'xDisconnect',
669 'xDestroy', 'xOpen', 'xClose', 'xFilter', 'xNext',
670 'xEof', 'xColumn', 'xRowid', 'xUpdate',
671 'xBegin', 'xSync', 'xCommit', 'xRollback',
672 'xFindFunction', 'xRename', 'xSavepoint', 'xRelease',
673 'xRollbackTo', 'xShadowName'
675 const remethods
= Object
.create(null);
676 for(const k
of mnames
){
677 const m
= methods
[k
];
678 if(!(m
instanceof Function
)) continue;
679 else if('xConnect'===k
&& methods
.xCreate
===m
){
680 remethods
[k
] = methods
.xCreate
;
681 }else if('xCreate'===k
&& methods
.xConnect
===m
){
682 remethods
[k
] = methods
.xConnect
;
684 remethods
[k
] = fwrap(k
, m
);
687 installMethods(mod
, remethods
, false);
689 // No automatic exception handling. Trust the client
692 mod
, methods
, !!opt
.applyArgcCheck
/*undocumented option*/
695 if(0===mod
.$iVersion
){
697 if('number'===typeof opt
.iVersion
) v
= opt
.iVersion
;
698 else if(mod
.$xShadowName
) v
= 3;
699 else if(mod
.$xSavePoint
|| mod
.$xRelease
|| mod
.$xRollbackTo
) v
= 2;
704 if(createdMod
) createdMod
.dispose();
711 Equivalent to calling vtab.setupModule() with this sqlite3_module
712 object as the call's `this`.
714 capi
.sqlite3_module
.prototype.setupModule = function(opt
){
715 return vtab
.setupModule
.call(this, opt
);
717 }/*sqlite3ApiBootstrap.initializers.push()*/);