2022-08-10 11:26:08 +00:00
/ *
2022 - 05 - 22
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 is intended to be combined at build - time with other
2022-11-24 16:03:49 +00:00
related code , most notably a header and footer which wraps this
2023-01-21 16:53:01 +00:00
whole file into an Emscripten Module . postRun ( ) handler . The sqlite3
JS API has no hard requirements on Emscripten and does not expose
2022-11-24 16:03:49 +00:00
any Emscripten APIs to clients . It is structured such that its build
can be tweaked to include it in arbitrary WASM environments which
2023-01-21 16:53:01 +00:00
can supply the necessary underlying features ( e . g . a POSIX file I / O
2022-11-24 16:03:49 +00:00
layer ) .
2022-08-10 11:26:08 +00:00
2022-11-24 16:03:49 +00:00
Main project home page : https : //sqlite.org
2022-11-07 12:12:27 +00:00
Documentation home page : https : //sqlite.org/wasm
2022-08-10 11:26:08 +00:00
* /
/ * *
2022-09-13 19:27:03 +00:00
sqlite3ApiBootstrap ( ) is the only global symbol persistently
exposed by this API . It is intended to be called one time at the
end of the API amalgamation process , passed configuration details
for the current environment , and then optionally be removed from
2023-03-07 19:12:06 +00:00
the global object using ` delete globalThis.sqlite3ApiBootstrap ` .
2022-08-10 11:26:08 +00:00
2022-11-24 16:03:49 +00:00
This function is not intended for client - level use . It is intended
for use in creating bundles configured for specific WASM
environments .
2022-08-22 13:34:13 +00:00
This function expects a configuration object , intended to abstract
2022-08-10 11:26:08 +00:00
away details specific to any given WASM environment , primarily so
2022-08-22 13:34:13 +00:00
that it can be used without any _direct _ dependency on
2022-09-13 19:27:03 +00:00
Emscripten . ( Note the default values for the config object ! ) The
config object is only honored the first time this is
called . Subsequent calls ignore the argument and return the same
2023-01-21 16:53:01 +00:00
( configured ) object which gets initialized by the first call . This
function will throw if any of the required config options are
2022-11-07 12:12:27 +00:00
missing .
2022-08-22 13:34:13 +00:00
The config object properties include :
2022-08-24 05:59:23 +00:00
- ` exports ` [ ^ 1 ] : the "exports" object for the current WASM
2022-11-07 12:12:27 +00:00
environment . In an Emscripten - based build , this should be set to
2022-08-22 13:34:13 +00:00
` Module['asm'] ` .
2022-08-24 05:59:23 +00:00
- ` memory ` [ ^ 1 ] : optional WebAssembly . Memory object , defaulting to
` exports.memory ` . In Emscripten environments this should be set
2023-07-12 09:30:13 +00:00
to ` Module.wasmMemory ` if the build uses ` -sIMPORTED_MEMORY ` , or be
2022-08-22 13:34:13 +00:00
left undefined / falsy to default to ` exports.memory ` when using
WASM - exported memory .
- ` bigIntEnabled ` : true if BigInt support is enabled . Defaults to
2023-03-07 19:12:06 +00:00
true if ` globalThis.BigInt64Array ` is available , else false . Some APIs
2022-08-22 13:34:13 +00:00
will throw exceptions if called without BigInt support , as BigInt
is required for marshalling C - side int64 into and out of JS .
2023-01-21 16:53:01 +00:00
( Sidebar : it is technically possible to add int64 support via
marshalling of int32 pairs , but doing so is unduly invasive . )
2022-08-22 13:34:13 +00:00
- ` allocExportName ` : the name of the function , in ` exports ` , of the
` malloc(3) ` - compatible routine for the WASM environment . Defaults
2022-11-30 11:50:16 +00:00
to ` "sqlite3_malloc" ` . Beware that using any allocator other than
sqlite3 _malloc ( ) may require care in certain client - side code
regarding which allocator is uses . Notably , sqlite3 _deserialize ( )
and sqlite3 _serialize ( ) can only safely use memory from different
2023-01-21 16:53:01 +00:00
allocators under very specific conditions . The canonical builds
of this API guaranty that ` sqlite3_malloc() ` is the JS - side
allocator implementation .
2022-08-22 13:34:13 +00:00
- ` deallocExportName ` : the name of the function , in ` exports ` , of
the ` free(3) ` - compatible routine for the WASM
2022-11-30 11:50:16 +00:00
environment . Defaults to ` "sqlite3_free" ` .
2022-08-22 13:34:13 +00:00
2022-12-03 11:16:55 +00:00
- ` reallocExportName ` : the name of the function , in ` exports ` , of
the ` realloc(3) ` - compatible routine for the WASM
environment . Defaults to ` "sqlite3_realloc" ` .
2023-02-06 14:01:19 +00:00
- ` debug ` , ` log ` , ` warn ` , and ` error ` may be functions equivalent
to the like - named methods of the global ` console ` object . By
default , these map directly to their ` console ` counterparts , but
can be replaced with ( e . g . ) empty functions to squelch all such
output .
2023-07-15 11:23:57 +00:00
- ` wasmfsOpfsDir ` [ ^ 1 ] : Specifies the "mount point" of the OPFS - backed
filesystem in WASMFS - capable builds .
2022-08-24 05:59:23 +00:00
2023-07-13 04:26:13 +00:00
[ ^ 1 ] = This property may optionally be a function , in which case
this function calls that function to fetch the value ,
2022-08-24 05:59:23 +00:00
enabling delayed evaluation .
2023-01-21 16:53:01 +00:00
The returned object is the top - level sqlite3 namespace object .
2022-08-10 11:26:08 +00:00
* /
2022-08-24 05:59:23 +00:00
'use strict' ;
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap = function sqlite3ApiBootstrap (
apiConfig = ( globalThis . sqlite3ApiConfig || sqlite3ApiBootstrap . defaultConfig )
2022-08-24 05:59:23 +00:00
) {
2022-08-22 13:34:13 +00:00
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 ;
}
2022-10-02 20:08:53 +00:00
const config = Object . assign ( Object . create ( null ) , {
exports : undefined ,
memory : undefined ,
bigIntEnabled : ( ( ) => {
if ( 'undefined' !== typeof Module ) {
/ * E m s c r i p t e n m o d u l e w i l l c o n t a i n H E A P U 6 4 w h e n b u i l t w i t h
- sWASM _BIGINT = 1 , else it will not . * /
return ! ! Module . HEAPU64 ;
2022-08-22 21:37:17 +00:00
}
2023-03-07 19:12:06 +00:00
return ! ! globalThis . BigInt64Array ;
2022-10-02 20:08:53 +00:00
} ) ( ) ,
2023-02-06 14:01:19 +00:00
debug : console . debug . bind ( console ) ,
warn : console . warn . bind ( console ) ,
error : console . error . bind ( console ) ,
log : console . log . bind ( console ) ,
2022-12-03 13:10:58 +00:00
wasmfsOpfsDir : '/opfs' ,
/ * *
2023-07-15 11:23:57 +00:00
useStdAlloc is just for testing allocator discrepancies . The
2022-12-03 13:10:58 +00:00
docs guarantee that this is false in the canonical builds . For
99 % of purposes it doesn ' t matter which allocators we use , but
2023-07-15 11:23:57 +00:00
it becomes significant with , e . g . , sqlite3 _deserialize ( ) and
certain wasm . xWrap . resultAdapter ( ) s .
2022-12-03 13:10:58 +00:00
* /
useStdAlloc : false
2022-10-02 20:08:53 +00:00
} , apiConfig || { } ) ;
2022-08-10 11:26:08 +00:00
2022-12-03 13:10:58 +00:00
Object . assign ( config , {
allocExportName : config . useStdAlloc ? 'malloc' : 'sqlite3_malloc' ,
deallocExportName : config . useStdAlloc ? 'free' : 'sqlite3_free' ,
reallocExportName : config . useStdAlloc ? 'realloc' : 'sqlite3_realloc'
} , config ) ;
2022-08-24 05:59:23 +00:00
[
// If any of these config options are functions, replace them with
// the result of calling that function...
2023-07-16 16:52:09 +00:00
'exports' , 'memory' , 'wasmfsOpfsDir'
2022-08-24 05:59:23 +00:00
] . forEach ( ( k ) => {
if ( 'function' === typeof config [ k ] ) {
config [ k ] = config [ k ] ( ) ;
}
} ) ;
2022-12-27 14:34:32 +00:00
/ * *
2022-10-31 11:09:14 +00:00
The main sqlite3 binding API gets installed into this object ,
mimicking the C API as closely as we can . The numerous members
names with prefixes 'sqlite3_' and 'SQLITE_' behave , insofar as
possible , identically to the C - native counterparts , as documented at :
https : //www.sqlite.org/c3ref/intro.html
A very few exceptions require an additional level of proxy
function or may otherwise require special attention in the WASM
2022-11-01 11:09:34 +00:00
environment , and all such cases are documented somewhere below
in this file or in sqlite3 - api - glue . js . capi members which are
not documented are installed as 1 - to - 1 proxies for their
2022-10-31 11:09:14 +00:00
C - side counterparts .
* /
const capi = Object . create ( null ) ;
2022-11-01 11:09:34 +00:00
/ * *
Holds state which are specific to the WASM - related
2022-11-24 16:03:49 +00:00
infrastructure and glue code .
2022-11-01 11:09:34 +00:00
Note that a number of members of this object are injected
dynamically after the api object is fully constructed , so
not all are documented in this file .
* /
const wasm = Object . create ( null ) ;
2022-10-31 11:09:14 +00:00
2022-11-02 11:53:31 +00:00
/** Internal helper for SQLite3Error ctor. */
const _ _rcStr = ( rc ) => {
return ( capi . sqlite3 _js _rc _str && capi . sqlite3 _js _rc _str ( rc ) )
|| ( "Unknown result code #" + rc ) ;
} ;
/** Internal helper for SQLite3Error ctor. */
const _ _isInt = ( n ) => 'number' === typeof n && n === ( n | 0 ) ;
/ * *
An Error subclass specifically for reporting DB - level errors and
enabling clients to unambiguously identify such exceptions .
The C - level APIs never throw , but some of the higher - level
C - style APIs do and the object - oriented APIs use exceptions
exclusively to report errors .
* /
class SQLite3Error extends Error {
/ * *
Constructs this object with a message depending on its arguments :
2022-12-07 07:22:34 +00:00
If its first argument is an integer , it is assumed to be
an SQLITE _ ... result code and it is passed to
sqlite3 . capi . sqlite3 _js _rc _str ( ) to stringify it .
If called with exactly 2 arguments and the 2 nd is an object ,
that object is treated as the 2 nd argument to the parent
constructor .
The exception ' s message is created by concatenating its
arguments with a space between each , except for the
two - args - with - an - objec form and that the first argument will
get coerced to a string , as described above , if it ' s an
integer .
If passed an integer first argument , the error object ' s
` resultCode ` member will be set to the given integer value ,
else it will be set to capi . SQLITE _ERROR .
2022-11-02 11:53:31 +00:00
* /
constructor ( ... args ) {
2022-12-07 07:22:34 +00:00
let rc ;
if ( args . length ) {
if ( _ _isInt ( args [ 0 ] ) ) {
rc = args [ 0 ] ;
if ( 1 === args . length ) {
super ( _ _rcStr ( args [ 0 ] ) ) ;
} else {
const rcStr = _ _rcStr ( rc ) ;
if ( 'object' === typeof args [ 1 ] ) {
super ( rcStr , args [ 1 ] ) ;
} else {
args [ 0 ] = rcStr + ':' ;
super ( args . join ( ' ' ) ) ;
}
}
} else {
if ( 2 === args . length && 'object' === typeof args [ 1 ] ) {
super ( ... args ) ;
} else {
super ( args . join ( ' ' ) ) ;
}
}
2022-11-02 11:53:31 +00:00
}
2022-12-07 07:22:34 +00:00
this . resultCode = rc || capi . SQLITE _ERROR ;
2022-11-02 11:53:31 +00:00
this . name = 'SQLite3Error' ;
}
} ;
2022-10-31 11:09:14 +00:00
/ * *
Functionally equivalent to the SQLite3Error constructor but may
be used as part of an expression , e . g . :
` ` `
return someFunction ( x ) || SQLite3Error . toss ( ... ) ;
` ` `
* /
SQLite3Error . toss = ( ... args ) => {
throw new SQLite3Error ( ... args ) ;
} ;
const toss3 = SQLite3Error . toss ;
2022-08-10 11:26:08 +00:00
2022-09-27 09:17:37 +00:00
if ( config . wasmfsOpfsDir && ! /^\/[^/]+$/ . test ( config . wasmfsOpfsDir ) ) {
2022-10-31 11:09:14 +00:00
toss3 ( "config.wasmfsOpfsDir must be falsy or in the form '/dir-name'." ) ;
2022-08-22 13:34:13 +00:00
}
2022-08-10 11:26:08 +00:00
/ * *
Returns true if n is a 32 - bit ( signed ) integer , else
false . This is used for determining when we need to switch to
double - type DB operations for integer values in order to keep
more precision .
* /
2022-10-02 22:50:04 +00:00
const isInt32 = ( n ) => {
2022-08-10 11:26:08 +00:00
return ( 'bigint' !== typeof n /*TypeError: can't convert BigInt to number*/ )
&& ! ! ( n === ( n | 0 ) && n <= 2147483647 && n >= - 2147483648 ) ;
} ;
2022-10-02 22:50:04 +00:00
/ * *
Returns true if the given BigInt value is small enough to fit
into an int64 value , else false .
* /
const bigIntFits64 = function f ( b ) {
if ( ! f . _max ) {
f . _max = BigInt ( "0x7fffffffffffffff" ) ;
f . _min = ~ f . _max ;
}
return b >= f . _min && b <= f . _max ;
} ;
/ * *
Returns true if the given BigInt value is small enough to fit
into an int32 , else false .
* /
const bigIntFits32 = ( b ) => ( b >= ( - 0x7fffffff n - 1 n ) && b <= 0x7fffffff n ) ;
/ * *
Returns true if the given BigInt value is small enough to fit
into a double value without loss of precision , else false .
* /
const bigIntFitsDouble = function f ( b ) {
if ( ! f . _min ) {
f . _min = Number . MIN _SAFE _INTEGER ;
f . _max = Number . MAX _SAFE _INTEGER ;
}
return b >= f . _min && b <= f . _max ;
} ;
2022-08-10 11:26:08 +00:00
/** Returns v if v appears to be a TypedArray, else false. */
const isTypedArray = ( v ) => {
return ( v && v . constructor && isInt32 ( v . constructor . BYTES _PER _ELEMENT ) ) ? v : false ;
} ;
2022-10-27 03:03:16 +00:00
/ * * I n t e r n a l h e l p e r t o u s e i n o p e r a t i o n s w h i c h n e e d t o d i s t i n g u i s h
between TypedArrays which are backed by a SharedArrayBuffer
from those which are not . * /
const _ _SAB = ( 'undefined' === typeof SharedArrayBuffer )
? function ( ) { } : SharedArrayBuffer ;
/ * * R e t u r n s t r u e i f t h e g i v e n T y p e d A r r a y o b j e c t i s b a c k e d b y a
SharedArrayBuffer , else false . * /
const isSharedTypedArray = ( aTypedArray ) => ( aTypedArray . buffer instanceof _ _SAB ) ;
/ * *
Returns either aTypedArray . slice ( begin , end ) ( if
aTypedArray . buffer is a SharedArrayBuffer ) or
aTypedArray . subarray ( begin , end ) ( if it ' s not ) .
This distinction is important for APIs which don ' t like to
work on SABs , e . g . TextDecoder , and possibly for our
own APIs which work on memory ranges which "might" be
2022-10-27 03:57:48 +00:00
modified by other threads while they ' re working .
* /
2022-10-27 03:03:16 +00:00
const typedArrayPart = ( aTypedArray , begin , end ) => {
return isSharedTypedArray ( aTypedArray )
? aTypedArray . slice ( begin , end )
: aTypedArray . subarray ( begin , end ) ;
} ;
2022-08-10 11:26:08 +00:00
/ * *
2022-12-26 14:55:00 +00:00
Returns true if v appears to be one of our bind ( ) - able TypedArray
2022-12-24 15:28:45 +00:00
types : Uint8Array or Int8Array or ArrayBuffer . Support for
TypedArrays with element sizes > 1 is a potential TODO just
waiting on a use case to justify them . Until then , their ` buffer `
property can be used to pass them as an ArrayBuffer . If it ' s not
a bindable array type , a falsy value is returned .
2022-08-10 11:26:08 +00:00
* /
const isBindableTypedArray = ( v ) => {
2022-12-24 15:28:45 +00:00
return v && ( v instanceof Uint8Array
|| v instanceof Int8Array
|| v instanceof ArrayBuffer ) ;
2022-08-10 11:26:08 +00:00
} ;
/ * *
Returns true if v appears to be one of the TypedArray types
which is legal for holding SQL code ( as opposed to binary blobs ) .
Currently this is the same as isBindableTypedArray ( ) but it
seems likely that we ' ll eventually want to add Uint32Array
and friends to the isBindableTypedArray ( ) list but not to the
isSQLableTypedArray ( ) list .
* /
const isSQLableTypedArray = ( v ) => {
2022-12-24 15:28:45 +00:00
return v && ( v instanceof Uint8Array
|| v instanceof Int8Array
|| v instanceof ArrayBuffer ) ;
2022-08-10 11:26:08 +00:00
} ;
/ * * R e t u r n s t r u e i f i s B i n d a b l e T y p e d A r r a y ( v ) d o e s , e l s e t h r o w s w i t h a m e s s a g e
that v is not a supported TypedArray value . * /
const affirmBindableTypedArray = ( v ) => {
return isBindableTypedArray ( v )
2022-10-31 11:09:14 +00:00
|| toss3 ( "Value is not of a supported TypedArray type." ) ;
2022-08-10 11:26:08 +00:00
} ;
const utf8Decoder = new TextDecoder ( 'utf-8' ) ;
2022-08-22 13:34:13 +00:00
2022-10-27 03:03:16 +00:00
/ * *
Uses TextDecoder to decode the given half - open range of the
given TypedArray to a string . This differs from a simple
call to TextDecoder in that it accounts for whether the
2022-10-27 03:57:48 +00:00
first argument is backed by a SharedArrayBuffer or not ,
2022-10-27 03:03:16 +00:00
and can work more efficiently if it ' s not ( TextDecoder
refuses to act upon an SAB ) .
* /
const typedArrayToString = function ( typedArray , begin , end ) {
return utf8Decoder . decode ( typedArrayPart ( typedArray , begin , end ) ) ;
2022-08-22 13:34:13 +00:00
} ;
2022-08-10 11:26:08 +00:00
2022-09-30 20:35:37 +00:00
/ * *
2022-11-03 21:21:10 +00:00
If v is - a Array , its join ( "" ) result is returned . If
2022-10-03 08:21:06 +00:00
isSQLableTypedArray ( v ) is true then typedArrayToString ( v ) is
2022-12-06 08:46:39 +00:00
returned . If it looks like a WASM pointer , wasm . cstrToJs ( v ) is
2022-09-30 20:35:37 +00:00
returned . Else v is returned as - is .
* /
2022-10-03 08:21:06 +00:00
const flexibleString = function ( v ) {
2022-12-26 14:55:00 +00:00
if ( isSQLableTypedArray ( v ) ) {
return typedArrayToString (
( v instanceof ArrayBuffer ) ? new Uint8Array ( v ) : v
) ;
}
2022-11-03 21:21:10 +00:00
else if ( Array . isArray ( v ) ) return v . join ( "" ) ;
2022-12-06 08:46:39 +00:00
else if ( wasm . isPtr ( v ) ) v = wasm . cstrToJs ( v ) ;
2022-09-30 20:35:37 +00:00
return v ;
} ;
2022-08-10 11:26:08 +00:00
/ * *
An Error subclass specifically for reporting Wasm - level malloc ( )
failure and enabling clients to unambiguously identify such
exceptions .
* /
class WasmAllocError extends Error {
2022-11-07 13:06:20 +00:00
/ * *
If called with 2 arguments and the 2 nd one is an object , it
behaves like the Error constructor , else it concatenates all
arguments together with a single space between each to
construct an error message string . As a special case , if
called with no arguments then it uses a default error
message .
* /
2022-08-10 11:26:08 +00:00
constructor ( ... args ) {
2022-12-01 03:55:28 +00:00
if ( 2 === args . length && 'object' === typeof args [ 1 ] ) {
2022-11-07 13:06:20 +00:00
super ( ... args ) ;
} else if ( args . length ) {
super ( args . join ( ' ' ) ) ;
} else {
super ( "Allocation failed." ) ;
}
2022-12-25 14:04:06 +00:00
this . resultCode = capi . SQLITE _NOMEM ;
2022-08-10 11:26:08 +00:00
this . name = 'WasmAllocError' ;
}
} ;
2022-10-20 21:28:31 +00:00
/ * *
Functionally equivalent to the WasmAllocError constructor but may
be used as part of an expression , e . g . :
` ` `
return someAllocatingFunction ( x ) || WasmAllocError . toss ( ... ) ;
` ` `
* /
2022-10-02 03:11:13 +00:00
WasmAllocError . toss = ( ... args ) => {
2022-10-21 05:27:40 +00:00
throw new WasmAllocError ( ... args ) ;
2022-10-02 03:11:13 +00:00
} ;
2022-08-10 11:26:08 +00:00
2022-10-31 11:09:14 +00:00
Object . assign ( capi , {
2022-12-23 23:46:33 +00:00
/ * *
sqlite3 _bind _blob ( ) works exactly like its C counterpart unless
its 3 rd argument is one of :
- JS string : the 3 rd argument is converted to a C string , the
4 th argument is ignored , and the C - string ' s length is used
in its place .
- Array : converted to a string as defined for " flexible
strings " and then it ' s treated as a JS string .
- Int8Array or Uint8Array : wasm . allocFromTypedArray ( ) is used to
conver the memory to the WASM heap . If the 4 th argument is
0 or greater , it is used as - is , otherwise the array ' s byteLength
value is used . This is an exception to the C API ' s undefined
behavior for a negative 4 th argument , but results are undefined
if the given 4 th argument value is greater than the byteLength
of the input array .
- If it ' s an ArrayBuffer , it gets wrapped in a Uint8Array and
treated as that type .
2022-12-24 15:28:45 +00:00
In all of those cases , the final argument ( destructor ) is
ignored and capi . SQLITE _WASM _DEALLOC is assumed .
2022-12-23 23:46:33 +00:00
A 3 rd argument of ` null ` is treated as if it were a WASM pointer
of 0.
If the 3 rd argument is neither a WASM pointer nor one of the
above - described types , capi . SQLITE _MISUSE is returned .
The first argument may be either an ` sqlite3_stmt* ` WASM
pointer or an sqlite3 . oo1 . Stmt instance .
For consistency with the C API , it requires the same number of
arguments . It returns capi . SQLITE _MISUSE if passed any other
argument count .
* /
sqlite3 _bind _blob : undefined /*installed later*/ ,
/ * *
sqlite3 _bind _text ( ) works exactly like its C counterpart unless
its 3 rd argument is one of :
- JS string : the 3 rd argument is converted to a C string , the
4 th argument is ignored , and the C - string ' s length is used
in its place .
- Array : converted to a string as defined for " flexible
strings " . The 4 th argument is ignored and a value of - 1
is assumed .
- Int8Array or Uint8Array : is assumed to contain UTF - 8 text , is
converted to a string . The 4 th argument is ignored , replaced
by the array ' s byteLength value .
- If it ' s an ArrayBuffer , it gets wrapped in a Uint8Array and
treated as that type .
In each of those cases , the final argument ( text destructor ) is
2022-12-24 15:28:45 +00:00
ignored and capi . SQLITE _WASM _DEALLOC is assumed .
2022-12-23 23:46:33 +00:00
A 3 rd argument of ` null ` is treated as if it were a WASM pointer
of 0.
If the 3 rd argument is neither a WASM pointer nor one of the
above - described types , capi . SQLITE _MISUSE is returned .
The first argument may be either an ` sqlite3_stmt* ` WASM
pointer or an sqlite3 . oo1 . Stmt instance .
For consistency with the C API , it requires the same number of
arguments . It returns capi . SQLITE _MISUSE if passed any other
argument count .
If client code needs to bind partial strings , it needs to
either parcel the string up before passing it in here or it
must pass in a WASM pointer for the 3 rd argument and a valid
4 th - argument value , taking care not to pass a value which
truncates a multi - byte UTF - 8 character . When passing
WASM - format strings , it is important that the final argument be
valid or unexpected content can result can result , or even a
crash if the application reads past the WASM heap bounds .
* /
sqlite3 _bind _text : undefined /*installed later*/ ,
2022-08-10 11:26:08 +00:00
/ * *
2022-10-02 18:47:39 +00:00
sqlite3 _create _function _v2 ( ) differs from its native
counterpart only in the following ways :
1 ) The fourth argument ( ` eTextRep ` ) argument must not specify
2022-10-03 22:38:00 +00:00
any encoding other than sqlite3 . SQLITE _UTF8 . The JS API does not
2022-10-02 18:47:39 +00:00
currently support any other encoding and likely never
will . This function does not replace that argument on its own
2022-12-23 21:10:49 +00:00
because it may contain other flags . As a special case , if
the bottom 4 bits of that argument are 0 , SQLITE _UTF8 is
assumed .
2022-10-02 18:47:39 +00:00
2 ) Any of the four final arguments may be either WASM pointers
( assumed to be function pointers ) or JS Functions . In the
latter case , each gets bound to WASM using
sqlite3 . capi . wasm . installFunction ( ) and that wrapper is passed
on to the native implementation .
2022-12-23 21:10:49 +00:00
For consistency with the C API , it requires the same number of
arguments . It returns capi . SQLITE _MISUSE if passed any other
argument count .
2022-10-02 18:47:39 +00:00
The semantics of JS functions are :
2022-10-02 22:50:04 +00:00
xFunc : is passed ` (pCtx, ...values) ` . Its return value becomes
2022-10-02 18:47:39 +00:00
the new SQL function ' s result .
2022-10-02 22:50:04 +00:00
xStep : is passed ` (pCtx, ...values) ` . Its return value is
2022-10-02 18:47:39 +00:00
ignored .
2022-10-02 22:50:04 +00:00
xFinal : is passed ` (pCtx) ` . Its return value becomes the new
aggregate SQL function ' s result .
2022-10-02 18:47:39 +00:00
xDestroy : is passed ` (void*) ` . Its return value is ignored . The
pointer passed to it is the one from the 5 th argument to
sqlite3 _create _function _v2 ( ) .
2022-10-02 22:50:04 +00:00
Note that :
2022-10-03 22:38:00 +00:00
- ` pCtx ` in the above descriptions is a ` sqlite3_context* ` . At
least 99 times out of a hundred , that initial argument will
be irrelevant for JS UDF bindings , but it needs to be there
so that the cases where it _is _ relevant , in particular with
window and aggregate functions , have full access to the
lower - level sqlite3 APIs .
- When wrapping JS functions , the remaining arguments are passd
to them as positional arguments , not as an array of
arguments , because that allows callback definitions to be
more JS - idiomatic than C - like . For example ` (pCtx,a,b)=>a+b `
is more intuitive and legible than
` (pCtx,args)=>args[0]+args[1] ` . For cases where an array of
arguments would be more convenient , the callbacks simply need
to be declared like ` (pCtx,...args)=>{...} ` , in which case
` args ` will be an array .
2022-10-02 22:50:04 +00:00
- If a JS wrapper throws , it gets translated to
sqlite3 _result _error ( ) or sqlite3 _result _error _nomem ( ) ,
depending on whether the exception is an
sqlite3 . WasmAllocError object or not .
- When passing on WASM function pointers , arguments are _not _
converted or reformulated . They are passed on as - is in raw
pointer form using their native C signatures . Only JS
functions passed in to this routine , and thus wrapped by this
routine , get automatic conversions of arguments and result
values . The routines which perform those conversions are
exposed for client - side use as
sqlite3 _create _function _v2 . convertUdfArgs ( ) and
sqlite3 _create _function _v2 . setUdfResult ( ) . sqlite3 _create _function ( )
and sqlite3 _create _window _function ( ) have those same methods .
2022-10-02 18:47:39 +00:00
For xFunc ( ) , xStep ( ) , and xFinal ( ) :
- When called from SQL , arguments to the UDF , and its result ,
will be converted between JS and SQL with as much fidelity as
is feasible , triggering an exception if a type conversion
cannot be determined . Some freedom is afforded to numeric
conversions due to friction between the JS and C worlds :
2022-10-03 22:38:00 +00:00
integers which are larger than 32 bits may be treated as
doubles or BigInts .
2022-10-02 18:47:39 +00:00
2022-10-02 22:50:04 +00:00
If any JS - side bound functions throw , those exceptions are
intercepted and converted to database - side errors with the
exception of xDestroy ( ) : any exception from it is ignored ,
possibly generating a console . error ( ) message . Destructors
must not throw .
2022-10-02 18:47:39 +00:00
Once installed , there is currently no way to uninstall the
2022-10-02 22:50:04 +00:00
automatically - converted WASM - bound JS functions from WASM . They
can be uninstalled from the database as documented in the C
API , but this wrapper currently has no infrastructure in place
to also free the WASM - bound JS wrappers , effectively resulting
in a memory leak if the client uninstalls the UDF . Improving that
is a potential TODO , but removing client - installed UDFs is rare
in practice . If this factor is relevant for a given client ,
they can create WASM - bound JS functions themselves , hold on to their
pointers , and pass the pointers in to here . Later on , they can
free those pointers ( using ` wasm.uninstallFunction() ` or
equivalent ) .
C reference : https : //www.sqlite.org/c3ref/create_function.html
2022-10-02 18:47:39 +00:00
Maintenance reminder : the ability to add new
WASM - accessible functions to the runtime requires that the
WASM build is compiled with emcc ' s ` -sALLOW_TABLE_GROWTH `
flag .
2022-08-10 11:26:08 +00:00
* /
2022-12-23 23:46:33 +00:00
sqlite3 _create _function _v2 : (
2022-10-02 18:47:39 +00:00
pDb , funcName , nArg , eTextRep , pApp ,
2022-10-02 22:50:04 +00:00
xFunc , xStep , xFinal , xDestroy
2022-12-23 23:46:33 +00:00
) => { /*installed later*/ } ,
2022-10-02 18:47:39 +00:00
/ * *
Equivalent to passing the same arguments to
sqlite3 _create _function _v2 ( ) , with 0 as the final argument .
* /
2022-12-23 23:46:33 +00:00
sqlite3 _create _function : (
2022-10-02 18:47:39 +00:00
pDb , funcName , nArg , eTextRep , pApp ,
2022-10-02 22:50:04 +00:00
xFunc , xStep , xFinal
2022-12-23 23:46:33 +00:00
) => { /*installed later*/ } ,
2022-10-02 20:08:53 +00:00
/ * *
The sqlite3 _create _window _function ( ) JS wrapper differs from
its native implementation in the exact same way that
sqlite3 _create _function _v2 ( ) does . The additional function ,
xInverse ( ) , is treated identically to xStep ( ) by the wrapping
layer .
* /
2022-12-23 23:46:33 +00:00
sqlite3 _create _window _function : (
2022-10-02 20:08:53 +00:00
pDb , funcName , nArg , eTextRep , pApp ,
2022-10-02 22:50:04 +00:00
xStep , xFinal , xValue , xInverse , xDestroy
2022-12-23 23:46:33 +00:00
) => { /*installed later*/ } ,
2022-08-10 11:26:08 +00:00
/ * *
The sqlite3 _prepare _v3 ( ) binding handles two different uses
with differing JS / WASM semantics :
2022-09-28 07:53:47 +00:00
1 ) sqlite3 _prepare _v3 ( pDb , sqlString , - 1 , prepFlags , ppStmt , null )
2022-08-10 11:26:08 +00:00
2 ) sqlite3 _prepare _v3 ( pDb , sqlPointer , sqlByteLen , prepFlags , ppStmt , sqlPointerToPointer )
Note that the SQL length argument ( the 3 rd argument ) must , for
usage ( 1 ) , always be negative because it must be a byte length
and that value is expensive to calculate from JS ( where only
the character length of strings is readily available ) . It is
retained in this API ' s interface for code / documentation
compatibility reasons but is currently _always _ ignored . With
usage ( 2 ) , the 3 rd argument is used as - is but is is still
critical that the C - style input string ( 2 nd argument ) be
terminated with a 0 byte .
In usage ( 1 ) , the 2 nd argument must be of type string ,
2022-12-26 15:08:48 +00:00
Uint8Array , Int8Array , or ArrayBuffer ( all of which are assumed
to hold SQL ) . If it is , this function assumes case ( 1 ) and
2022-08-10 11:26:08 +00:00
calls the underyling C function with the equivalent of :
( pDb , sqlAsString , - 1 , prepFlags , ppStmt , null )
2022-09-28 07:53:47 +00:00
The ` pzTail ` argument is ignored in this case because its
result is meaningless when a string - type value is passed
through : the string goes through another level of internal
2022-08-10 11:26:08 +00:00
conversion for WASM ' s sake and the result pointer would refer
to that transient conversion ' s memory , not the passed - in
2022-09-28 07:53:47 +00:00
string .
2022-08-10 11:26:08 +00:00
If the sql argument is not a string , it must be a _pointer _ to
a NUL - terminated string which was allocated in the WASM memory
2022-09-28 07:53:47 +00:00
( e . g . using capi . wasm . alloc ( ) or equivalent ) . In that case ,
2022-08-10 11:26:08 +00:00
the final argument may be 0 / null / undefined or must be a pointer
to which the "tail" of the compiled SQL is written , as
documented for the C - side sqlite3 _prepare _v3 ( ) . In case ( 2 ) ,
the underlying C function is called with the equivalent of :
2022-09-28 07:53:47 +00:00
( pDb , sqlAsPointer , sqlByteLen , prepFlags , ppStmt , pzTail )
2022-08-10 11:26:08 +00:00
It returns its result and compiled statement as documented in
the C API . Fetching the output pointers ( 5 th and 6 th
2022-12-09 09:23:27 +00:00
parameters ) requires using ` capi.wasm.peek() ` ( or
2022-09-28 07:53:47 +00:00
equivalent ) and the ` pzTail ` will point to an address relative to
the ` sqlAsPointer ` value .
2022-08-10 11:26:08 +00:00
If passed an invalid 2 nd argument type , this function will
2022-09-28 07:53:47 +00:00
return SQLITE _MISUSE and sqlite3 _errmsg ( ) will contain a string
describing the problem .
2022-08-10 11:26:08 +00:00
2022-09-28 07:53:47 +00:00
Side - note : if given an empty string , or one which contains only
comments or an empty SQL expression , 0 is returned but the result
output pointer will be NULL .
2022-08-10 11:26:08 +00:00
* /
2022-09-30 20:35:37 +00:00
sqlite3 _prepare _v3 : ( dbPtr , sql , sqlByteLen , prepFlags ,
stmtPtrPtr , strPtrPtr ) => { } /*installed later*/ ,
2022-08-10 11:26:08 +00:00
/ * *
Equivalent to calling sqlite3 _prapare _v3 ( ) with 0 as its 4 th argument .
* /
2022-09-30 20:35:37 +00:00
sqlite3 _prepare _v2 : ( dbPtr , sql , sqlByteLen ,
stmtPtrPtr , strPtrPtr ) => { } /*installed later*/ ,
2022-08-10 11:26:08 +00:00
2022-09-30 20:35:37 +00:00
/ * *
This binding enables the callback argument to be a JavaScript .
If the callback is a function , then for the duration of the
sqlite3 _exec ( ) call , it installs a WASM - bound function which
2022-10-27 03:03:16 +00:00
acts as a proxy for the given callback . That proxy will also
perform a conversion of the callback ' s arguments from
2022-09-30 20:35:37 +00:00
` (char**) ` to JS arrays of strings . However , for API
2022-10-27 03:03:16 +00:00
consistency ' s sake it will still honor the C - level callback
parameter order and will call it like :
2022-09-30 20:35:37 +00:00
` callback(pVoid, colCount, listOfValues, listOfColNames) `
If the callback is not a JS function then this binding performs
no translation of the callback , but the sql argument is still
converted to a WASM string for the call using the
2022-12-05 13:12:48 +00:00
"string:flexible" argument converter .
2022-09-30 20:35:37 +00:00
* /
sqlite3 _exec : ( pDb , sql , callback , pVoid , pErrMsg ) => { } /*installed later*/ ,
2022-10-20 21:28:31 +00:00
2022-10-27 03:03:16 +00:00
/ * *
If passed a single argument which appears to be a byte - oriented
TypedArray ( Int8Array or Uint8Array ) , this function treats that
TypedArray as an output target , fetches ` theArray.byteLength `
bytes of randomness , and populates the whole array with it . As
a special case , if the array ' s length is 0 , this function
behaves as if it were passed ( 0 , 0 ) . When called this way , it
returns its argument , else it returns the ` undefined ` value .
If called with any other arguments , they are passed on as - is
to the C API . Results are undefined if passed any incompatible
values .
* /
sqlite3 _randomness : ( n , outPtr ) => { /*installed later*/ } ,
2022-10-31 11:09:14 +00:00
} /*capi*/ ) ;
2022-10-27 03:03:16 +00:00
2022-10-29 07:54:10 +00:00
/ * *
Various internal - use utilities are added here as needed . They
are bound to an object only so that we have access to them in
the differently - scoped steps of the API bootstrapping
process . At the end of the API setup process , this object gets
removed . These are NOT part of the public API .
* /
const util = {
affirmBindableTypedArray , flexibleString ,
bigIntFits32 , bigIntFits64 , bigIntFitsDouble ,
isBindableTypedArray ,
2022-12-26 14:55:00 +00:00
isInt32 , isSQLableTypedArray , isTypedArray ,
2022-10-29 07:54:10 +00:00
typedArrayToString ,
2023-03-07 19:12:06 +00:00
isUIThread : ( ) => ( globalThis . window === globalThis && ! ! globalThis . document ) ,
2022-11-30 05:27:36 +00:00
// is this true for ESM?: 'undefined'===typeof WorkerGlobalScope
2022-10-29 07:54:10 +00:00
isSharedTypedArray ,
2022-11-30 05:27:36 +00:00
toss : function ( ... args ) { throw new Error ( args . join ( ' ' ) ) } ,
toss3 ,
2023-08-18 14:16:26 +00:00
typedArrayPart ,
/ * *
Given a byte array or ArrayBuffer , this function throws if the
lead bytes of that buffer do not hold a SQLite3 database header ,
else it returns without side effects .
Added in 3.44 .
* /
affirmDbHeader : function ( bytes ) {
if ( bytes instanceof ArrayBuffer ) bytes = new Uint8Array ( bytes ) ;
const header = "SQLite format 3" ;
if ( header . length > bytes . byteLength ) {
toss3 ( "Input does not contain an SQLite3 database header." ) ;
}
for ( let i = 0 ; i < header . length ; ++ i ) {
if ( header . charCodeAt ( i ) !== bytes [ i ] ) {
toss3 ( "Input does not contain an SQLite3 database header." ) ;
}
}
} ,
/ * *
Given a byte array or ArrayBuffer , this function throws if the
database does not , at a cursory glance , appear to be an SQLite3
database . It only examines the size and header , but further
checks may be added in the future .
Added in 3.44 .
* /
affirmIsDb : function ( bytes ) {
if ( bytes instanceof ArrayBuffer ) bytes = new Uint8Array ( bytes ) ;
const n = bytes . byteLength ;
if ( n < 512 || n % 512 !== 0 ) {
toss3 ( "Byte array size" , n , "is invalid for an SQLite3 db." ) ;
}
util . affirmDbHeader ( bytes ) ;
}
} /*util*/ ;
2022-12-23 23:46:33 +00:00
2022-11-01 11:09:34 +00:00
Object . assign ( wasm , {
2022-08-10 11:26:08 +00:00
/ * *
2022-10-29 07:54:10 +00:00
Emscripten APIs have a deep - seated assumption that all pointers
are 32 bits . We 'll remain optimistic that that won' t always be
the case and will use this constant in places where we might
otherwise use a hard - coded 4.
2022-08-10 11:26:08 +00:00
* /
2022-10-29 07:54:10 +00:00
ptrSizeof : config . wasmPtrSizeof || 4 ,
2022-08-10 11:26:08 +00:00
/ * *
2022-10-29 07:54:10 +00:00
The WASM IR ( Intermediate Representation ) value for
pointer - type values . It MUST refer to a value type of the
2022-11-24 16:03:49 +00:00
size described by this . ptrSizeof .
2022-08-10 11:26:08 +00:00
* /
2022-10-29 07:54:10 +00:00
ptrIR : config . wasmPtrIR || "i32" ,
/ * *
True if BigInt support was enabled via ( e . g . ) the
Emscripten - sWASM _BIGINT flag , else false . When
enabled , certain 64 - bit sqlite3 APIs are enabled which
are not otherwise enabled due to JS / WASM int64
impedence mismatches .
* /
bigIntEnabled : ! ! config . bigIntEnabled ,
/ * *
The symbols exported by the WASM environment .
* /
exports : config . exports
2022-10-31 11:09:14 +00:00
|| toss3 ( "Missing API config.exports (WASM module exports)." ) ,
2022-08-17 16:44:05 +00:00
2022-10-29 07:54:10 +00:00
/ * *
2023-07-12 09:30:13 +00:00
When Emscripten compiles with ` -sIMPORTED_MEMORY ` , it
2022-10-29 07:54:10 +00:00
initalizes the heap and imports it into wasm , as opposed to
the other way around . In this case , the memory is not
available via this . exports . memory .
* /
memory : config . memory || config . exports [ 'memory' ]
2022-10-31 11:09:14 +00:00
|| toss3 ( "API config object requires a WebAssembly.Memory object" ,
2022-10-29 07:54:10 +00:00
"in either config.exports.memory (exported)" ,
"or config.memory (imported)." ) ,
2022-08-17 16:44:05 +00:00
2022-10-29 07:54:10 +00:00
/ * *
2022-12-03 11:16:55 +00:00
The API ' s primary point of access to the WASM - side memory
allocator . Works like sqlite3 _malloc ( ) but throws a
WasmAllocError if allocation fails . It is important that any
code which might pass through the sqlite3 C API NOT throw and
must instead return SQLITE _NOMEM ( or equivalent , depending on
the context ) .
2022-10-29 07:54:10 +00:00
2022-11-07 13:06:20 +00:00
Very few cases in the sqlite3 JS APIs can result in
2022-10-29 07:54:10 +00:00
client - defined functions propagating exceptions via the C - style
2022-11-07 13:06:20 +00:00
API . Most notably , this applies to WASM - bound JS functions
which are created directly by clients and passed on _as WASM
function pointers _ to functions such as
sqlite3 _create _function _v2 ( ) . Such bindings created
transparently by this API will automatically use wrappers which
catch exceptions and convert them to appropriate error codes .
For cases where non - throwing allocation is required , use
2022-12-03 11:16:55 +00:00
this . alloc . impl ( ) , which is direct binding of the
2022-11-07 13:06:20 +00:00
underlying C - level allocator .
Design note : this function is not named "malloc" primarily
because Emscripten uses that name and we wanted to avoid any
confusion early on in this code ' s development , when it still
had close ties to Emscripten ' s glue code .
2022-10-29 07:54:10 +00:00
* /
alloc : undefined /*installed later*/ ,
2022-11-07 13:06:20 +00:00
2022-10-29 07:54:10 +00:00
/ * *
2022-12-03 11:16:55 +00:00
Rarely necessary in JS code , this routine works like
sqlite3 _realloc ( M , N ) , where M is either NULL or a pointer
obtained from this function or this . alloc ( ) and N is the number
of bytes to reallocate the block to . Returns a pointer to the
reallocated block or 0 if allocation fails .
If M is NULL and N is positive , this behaves like
this . alloc ( N ) . If N is 0 , it behaves like this . dealloc ( ) .
Results are undefined if N is negative ( sqlite3 _realloc ( )
treats that as 0 , but if this code is built with a different
allocator it may misbehave with negative values ) .
Like this . alloc . impl ( ) , this . realloc . impl ( ) is a direct binding
to the underlying realloc ( ) implementation which does not throw
exceptions , instead returning 0 on allocation error .
* /
realloc : undefined /*installed later*/ ,
/ * *
The API ' s primary point of access to the WASM - side memory
deallocator . Works like sqlite3 _free ( ) .
2022-11-07 13:06:20 +00:00
Design note : this function is not named "free" for the same
reason that this . alloc ( ) is not called this . malloc ( ) .
2022-10-29 07:54:10 +00:00
* /
dealloc : undefined /*installed later*/
2022-08-10 11:26:08 +00:00
2022-10-29 07:54:10 +00:00
/* Many more wasm-related APIs get installed later on. */
2022-11-01 11:09:34 +00:00
} /*wasm*/ ) ;
2022-10-04 01:11:10 +00:00
2022-08-10 11:26:08 +00:00
/ * *
2022-10-04 01:11:10 +00:00
wasm . alloc ( ) ' s srcTypedArray . byteLength bytes ,
2022-08-10 11:26:08 +00:00
populates them with the values from the source
TypedArray , and returns the pointer to that memory . The
returned pointer must eventually be passed to
2022-10-04 01:11:10 +00:00
wasm . dealloc ( ) to clean it up .
2022-08-10 11:26:08 +00:00
2022-12-03 14:58:45 +00:00
The argument may be a Uint8Array , Int8Array , or ArrayBuffer ,
and it throws if passed any other type .
2022-08-10 11:26:08 +00:00
As a special case , to avoid further special cases where
this is used , if srcTypedArray . byteLength is 0 , it
allocates a single byte and sets it to the value
0. Even in such cases , calls must behave as if the
allocated memory has exactly srcTypedArray . byteLength
bytes .
* /
2022-10-04 01:11:10 +00:00
wasm . allocFromTypedArray = function ( srcTypedArray ) {
2022-12-03 14:58:45 +00:00
if ( srcTypedArray instanceof ArrayBuffer ) {
srcTypedArray = new Uint8Array ( srcTypedArray ) ;
}
2022-08-10 11:26:08 +00:00
affirmBindableTypedArray ( srcTypedArray ) ;
2022-10-04 01:11:10 +00:00
const pRet = wasm . alloc ( srcTypedArray . byteLength || 1 ) ;
2022-11-07 13:06:20 +00:00
wasm . heapForSize ( srcTypedArray . constructor ) . set (
srcTypedArray . byteLength ? srcTypedArray : [ 0 ] , pRet
) ;
2022-08-10 11:26:08 +00:00
return pRet ;
2022-10-02 20:08:53 +00:00
} ;
2022-08-10 11:26:08 +00:00
2022-12-03 11:16:55 +00:00
{
// Set up allocators...
const keyAlloc = config . allocExportName ,
keyDealloc = config . deallocExportName ,
keyRealloc = config . reallocExportName ;
for ( const key of [ keyAlloc , keyDealloc , keyRealloc ] ) {
const f = wasm . exports [ key ] ;
if ( ! ( f instanceof Function ) ) toss3 ( "Missing required exports[" , key , "] function." ) ;
}
2022-08-17 16:44:05 +00:00
2022-12-03 11:16:55 +00:00
wasm . alloc = function f ( n ) {
2022-12-03 13:10:58 +00:00
return f . impl ( n ) || WasmAllocError . toss ( "Failed to allocate" , n , " bytes." ) ;
2022-12-03 11:16:55 +00:00
} ;
wasm . alloc . impl = wasm . exports [ keyAlloc ] ;
wasm . realloc = function f ( m , n ) {
const m2 = f . impl ( m , n ) ;
2022-12-03 13:10:58 +00:00
return n ? ( m2 || WasmAllocError . toss ( "Failed to reallocate" , n , " bytes." ) ) : 0 ;
2022-12-03 11:16:55 +00:00
} ;
wasm . realloc . impl = wasm . exports [ keyRealloc ] ;
wasm . dealloc = wasm . exports [ keyDealloc ] ;
}
2022-08-10 11:26:08 +00:00
/ * *
Reports info about compile - time options using
2022-12-01 03:55:28 +00:00
sqlite3 _compileoption _get ( ) and sqlite3 _compileoption _used ( ) . It
2022-08-10 11:26:08 +00:00
has several distinct uses :
If optName is an array then it is expected to be a list of
compilation options and this function returns an object
which maps each such option to true or false , indicating
whether or not the given option was included in this
build . That object is returned .
If optName is an object , its keys are expected to be compilation
options and this function sets each entry to true or false ,
indicating whether the compilation option was used or not . That
object is returned .
If passed no arguments then it returns an object mapping
all known compilation options to their compile - time values ,
or boolean true if they are defined with no value . This
result , which is relatively expensive to compute , is cached
and returned for future no - argument calls .
In all other cases it returns true if the given option was
active when when compiling the sqlite3 module , else false .
Compile - time option names may optionally include their
"SQLITE_" prefix . When it returns an object of all options ,
the prefix is elided .
* /
2022-10-04 01:11:10 +00:00
wasm . compileOptionUsed = function f ( optName ) {
2022-08-10 11:26:08 +00:00
if ( ! arguments . length ) {
if ( f . _result ) return f . _result ;
else if ( ! f . _opt ) {
f . _rx = /^([^=]+)=(.+)/ ;
f . _rxInt = /^-?\d+$/ ;
f . _opt = function ( opt , rv ) {
const m = f . _rx . exec ( opt ) ;
rv [ 0 ] = ( m ? m [ 1 ] : opt ) ;
rv [ 1 ] = m ? ( f . _rxInt . test ( m [ 2 ] ) ? + m [ 2 ] : m [ 2 ] ) : true ;
2022-12-25 10:22:27 +00:00
} ;
2022-08-10 11:26:08 +00:00
}
const rc = { } , ov = [ 0 , 0 ] ;
let i = 0 , k ;
while ( ( k = capi . sqlite3 _compileoption _get ( i ++ ) ) ) {
f . _opt ( k , ov ) ;
rc [ ov [ 0 ] ] = ov [ 1 ] ;
}
return f . _result = rc ;
} else if ( Array . isArray ( optName ) ) {
const rc = { } ;
optName . forEach ( ( v ) => {
rc [ v ] = capi . sqlite3 _compileoption _used ( v ) ;
} ) ;
return rc ;
} else if ( 'object' === typeof optName ) {
Object . keys ( optName ) . forEach ( ( k ) => {
optName [ k ] = capi . sqlite3 _compileoption _used ( k ) ;
} ) ;
return optName ;
}
return (
'string' === typeof optName
) ? ! ! capi . sqlite3 _compileoption _used ( optName ) : false ;
} /*compileOptionUsed()*/ ;
2022-10-01 18:47:42 +00:00
/ * *
2022-10-04 01:11:10 +00:00
sqlite3 . wasm . pstack ( pseudo - stack ) holds a special - case
2022-10-01 18:47:42 +00:00
stack - style allocator intended only for use with _small _ data of
not more than ( in total ) a few kb in size , managed as if it were
stack - based .
It has only a single intended usage :
` ` `
const stackPos = pstack . pointer ;
try {
const ptr = pstack . alloc ( 8 ) ;
// ==> pstack.pointer === ptr
const otherPtr = pstack . alloc ( 8 ) ;
// ==> pstack.pointer === otherPtr
...
} finally {
pstack . restore ( stackPos ) ;
// ==> pstack.pointer === stackPos
}
` ` `
This allocator is much faster than a general - purpose one but is
limited to usage patterns like the one shown above .
It operates from a static range of memory which lives outside of
space managed by Emscripten ' s stack - management , so does not
collide with Emscripten - provided stack allocation APIs . The
memory lives in the WASM heap and can be used with routines such
2023-01-21 16:53:01 +00:00
as wasm . poke ( ) and wasm . heap8u ( ) . slice ( ) .
2022-10-01 18:47:42 +00:00
* /
2022-10-04 01:11:10 +00:00
wasm . pstack = Object . assign ( Object . create ( null ) , {
2022-10-01 18:47:42 +00:00
/ * *
2022-10-20 04:00:05 +00:00
Sets the current pstack position to the given pointer . Results
are undefined if the passed - in value did not come from
2022-10-01 18:47:42 +00:00
this . pointer .
* /
2022-10-04 01:11:10 +00:00
restore : wasm . exports . sqlite3 _wasm _pstack _restore ,
2022-10-01 18:47:42 +00:00
/ * *
Attempts to allocate the given number of bytes from the
pstack . On success , it zeroes out a block of memory of the
given size , adjusts the pstack pointer , and returns a pointer
2023-01-21 16:53:01 +00:00
to the memory . On error , throws a WasmAllocError . The
2022-10-02 03:11:13 +00:00
memory must eventually be released using restore ( ) .
2022-10-01 18:47:42 +00:00
2022-12-25 20:05:11 +00:00
If n is a string , it must be a WASM "IR" value in the set
2022-12-25 22:55:45 +00:00
accepted by wasm . sizeofIR ( ) , which is mapped to the size of
2022-12-25 20:05:11 +00:00
that data type . If passed a string not in that set , it throws a
WasmAllocError .
2022-10-01 18:47:42 +00:00
This method always adjusts the given value to be a multiple
2022-10-02 00:09:40 +00:00
of 8 bytes because failing to do so can lead to incorrect
results when reading and writing 64 - bit values from / to the WASM
2022-10-20 05:14:37 +00:00
heap . Similarly , the returned address is always 8 - byte aligned .
2022-10-01 18:47:42 +00:00
* /
2022-12-25 20:05:11 +00:00
alloc : function ( n ) {
2022-12-25 22:55:45 +00:00
if ( 'string' === typeof n && ! ( n = wasm . sizeofIR ( n ) ) ) {
2022-12-25 20:05:11 +00:00
WasmAllocError . toss ( "Invalid value for pstack.alloc(" , arguments [ 0 ] , ")" ) ;
}
2022-10-04 01:11:10 +00:00
return wasm . exports . sqlite3 _wasm _pstack _alloc ( n )
2022-10-02 03:11:13 +00:00
|| WasmAllocError . toss ( "Could not allocate" , n ,
"bytes from the pstack." ) ;
2022-10-04 01:11:10 +00:00
} ,
/ * *
2022-10-20 04:00:05 +00:00
alloc ( ) ' s n chunks , each sz bytes , as a single memory block and
2022-10-04 01:11:10 +00:00
returns the addresses as an array of n element , each holding
the address of one chunk .
2022-12-25 22:55:45 +00:00
sz may optionally be an IR string accepted by wasm . sizeofIR ( ) .
2022-12-25 20:05:11 +00:00
2022-10-04 01:11:10 +00:00
Throws a WasmAllocError if allocation fails .
Example :
` ` `
const [ p1 , p2 , p3 ] = wasm . pstack . allocChunks ( 3 , 4 ) ;
` ` `
* /
2022-12-25 20:05:11 +00:00
allocChunks : function ( n , sz ) {
2022-12-25 22:55:45 +00:00
if ( 'string' === typeof sz && ! ( sz = wasm . sizeofIR ( sz ) ) ) {
2022-12-25 20:05:11 +00:00
WasmAllocError . toss ( "Invalid size value for allocChunks(" , arguments [ 1 ] , ")" ) ;
}
2022-10-04 01:11:10 +00:00
const mem = wasm . pstack . alloc ( n * sz ) ;
2022-10-13 08:03:31 +00:00
const rc = [ ] ;
2022-10-04 01:11:10 +00:00
let i = 0 , offset = 0 ;
2023-01-21 16:53:01 +00:00
for ( ; i < n ; ++ i , offset += sz ) rc . push ( mem + offset ) ;
2022-10-04 01:11:10 +00:00
return rc ;
} ,
/ * *
2022-10-13 16:48:35 +00:00
A convenience wrapper for allocChunks ( ) which sizes each chunk
2022-10-04 01:11:10 +00:00
as either 8 bytes ( safePtrSize is truthy ) or wasm . ptrSizeof ( if
safePtrSize is falsy ) .
How it returns its result differs depending on its first
argument : if it 's 1, it returns a single pointer value. If it' s
more than 1 , it returns the same as allocChunks ( ) .
When a returned pointers will refer to a 64 - bit value , e . g . a
double or int64 , and that value must be written or fetched ,
2022-12-09 09:23:27 +00:00
e . g . using wasm . poke ( ) or wasm . peek ( ) , it is
2022-10-04 01:11:10 +00:00
important that the pointer in question be aligned to an 8 - byte
boundary or else it will not be fetched or written properly and
will corrupt or read neighboring memory .
However , when all pointers involved point to "small" data , it
2022-10-20 04:00:05 +00:00
is safe to pass a falsy value to save a tiny bit of memory .
2022-10-04 01:11:10 +00:00
* /
allocPtr : ( n = 1 , safePtrSize = true ) => {
return 1 === n
? wasm . pstack . alloc ( safePtrSize ? 8 : wasm . ptrSizeof )
: wasm . pstack . allocChunks ( n , safePtrSize ? 8 : wasm . ptrSizeof ) ;
2023-08-29 15:39:57 +00:00
} ,
/ * *
Records the current pstack position , calls the given function ,
2023-08-29 20:01:01 +00:00
passing it the sqlite3 object , then restores the pstack
regardless of whether the function throws . Returns the result
of the call or propagates an exception on error .
2023-08-29 15:39:57 +00:00
Added in 3.44 .
* /
call : function ( f ) {
const stackPos = wasm . pstack . pointer ;
2023-08-29 20:01:01 +00:00
try { return f ( sqlite3 ) } finally {
2023-08-29 15:39:57 +00:00
wasm . pstack . restore ( stackPos ) ;
}
2022-10-02 03:11:13 +00:00
}
2023-08-29 15:39:57 +00:00
2022-10-04 01:11:10 +00:00
} ) /*wasm.pstack*/ ;
Object . defineProperties ( wasm . pstack , {
/ * *
sqlite3 . wasm . pstack . pointer resolves to the current pstack
2022-10-04 01:21:34 +00:00
position pointer . This value is intended _only _ to be saved
for passing to restore ( ) . Writing to this memory , without
first reserving it via wasm . pstack . alloc ( ) and friends , leads
to undefined results .
2022-10-04 01:11:10 +00:00
* /
pointer : {
configurable : false , iterable : true , writeable : false ,
get : wasm . exports . sqlite3 _wasm _pstack _ptr
//Whether or not a setter as an alternative to restore() is
//clearer or would just lead to confusion is unclear.
//set: wasm.exports.sqlite3_wasm_pstack_restore
} ,
/ * *
2022-10-28 11:40:46 +00:00
sqlite3 . wasm . pstack . quota to the total number of bytes
available in the pstack , including any space which is currently
allocated . This value is a compile - time constant .
2022-10-04 01:11:10 +00:00
* /
quota : {
configurable : false , iterable : true , writeable : false ,
get : wasm . exports . sqlite3 _wasm _pstack _quota
2022-10-28 11:40:46 +00:00
} ,
/ * *
sqlite3 . wasm . pstack . remaining resolves to the amount of space
remaining in the pstack .
* /
remaining : {
configurable : false , iterable : true , writeable : false ,
get : wasm . exports . sqlite3 _wasm _pstack _remaining
}
2022-10-04 01:11:10 +00:00
} ) /*wasm.pstack properties*/ ;
2022-10-27 03:03:16 +00:00
capi . sqlite3 _randomness = ( ... args ) => {
if ( 1 === args . length && util . isTypedArray ( args [ 0 ] )
&& 1 === args [ 0 ] . BYTES _PER _ELEMENT ) {
const ta = args [ 0 ] ;
if ( 0 === ta . byteLength ) {
wasm . exports . sqlite3 _randomness ( 0 , 0 ) ;
return ta ;
}
const stack = wasm . pstack . pointer ;
try {
let n = ta . byteLength , offset = 0 ;
const r = wasm . exports . sqlite3 _randomness ;
const heap = wasm . heap8u ( ) ;
const nAlloc = n < 512 ? n : 512 ;
const ptr = wasm . pstack . alloc ( nAlloc ) ;
do {
const j = ( n > nAlloc ? nAlloc : n ) ;
r ( j , ptr ) ;
ta . set ( typedArrayPart ( heap , ptr , ptr + j ) , offset ) ;
n -= j ;
offset += j ;
} while ( n > 0 ) ;
} catch ( e ) {
console . error ( "Highly unexpected (and ignored!) " +
"exception in sqlite3_randomness():" , e ) ;
} finally {
wasm . pstack . restore ( stack ) ;
}
return ta ;
}
2022-10-29 07:54:10 +00:00
wasm . exports . sqlite3 _randomness ( ... args ) ;
2022-10-27 03:03:16 +00:00
} ;
2022-09-27 13:40:12 +00:00
/** State for sqlite3_wasmfs_opfs_dir(). */
2022-10-27 03:03:16 +00:00
let _ _wasmfsOpfsDir = undefined ;
2022-08-13 13:56:00 +00:00
/ * *
2022-10-01 18:47:42 +00:00
If the wasm environment has a WASMFS / OPFS - backed persistent
storage directory , its path is returned by this function . If it
does not then it returns "" ( noting that "" is a falsy value ) .
2022-08-13 13:56:00 +00:00
2022-08-17 16:44:05 +00:00
The first time this is called , this function inspects the current
2022-10-01 18:47:42 +00:00
environment to determine whether persistence support is available
2023-07-13 18:13:52 +00:00
and , if it is , enables it ( if needed ) . After the first call it
always returns the cached result .
If the returned string is not empty , any files stored under the
given path ( recursively ) are housed in OPFS storage . If the
returned string is empty , this particular persistent storage
option is not available on the client .
Though the mount point name returned by this function is intended
to remain stable , clients should not hard - coded it anywhere . Always call this function to get the path .
2022-08-13 13:56:00 +00:00
2023-07-13 18:13:52 +00:00
Note that this function is a no - op in must builds of this
library , as the WASMFS capability requires a custom
build .
2022-08-13 13:56:00 +00:00
* /
2022-09-27 13:40:12 +00:00
capi . sqlite3 _wasmfs _opfs _dir = function ( ) {
2022-10-27 03:03:16 +00:00
if ( undefined !== _ _wasmfsOpfsDir ) return _ _wasmfsOpfsDir ;
2022-08-13 13:56:00 +00:00
// If we have no OPFS, there is no persistent dir
2022-09-27 09:17:37 +00:00
const pdir = config . wasmfsOpfsDir ;
2022-08-22 13:34:13 +00:00
if ( ! pdir
2023-03-07 19:12:06 +00:00
|| ! globalThis . FileSystemHandle
|| ! globalThis . FileSystemDirectoryHandle
|| ! globalThis . FileSystemFileHandle ) {
2022-10-27 03:03:16 +00:00
return _ _wasmfsOpfsDir = "" ;
2022-08-13 13:56:00 +00:00
}
try {
2022-10-04 01:11:10 +00:00
if ( pdir && 0 === wasm . xCallWrapped (
2022-09-15 06:42:41 +00:00
'sqlite3_wasm_init_wasmfs' , 'i32' , [ 'string' ] , pdir
2022-08-22 13:34:13 +00:00
) ) {
2022-10-27 03:03:16 +00:00
return _ _wasmfsOpfsDir = pdir ;
2022-08-13 13:56:00 +00:00
} else {
2022-10-27 03:03:16 +00:00
return _ _wasmfsOpfsDir = "" ;
2022-08-13 13:56:00 +00:00
}
} catch ( e ) {
2022-09-15 06:42:41 +00:00
// sqlite3_wasm_init_wasmfs() is not available
2022-10-27 03:03:16 +00:00
return _ _wasmfsOpfsDir = "" ;
2022-08-13 13:56:00 +00:00
}
2022-09-12 16:09:50 +00:00
} ;
2022-08-13 13:56:00 +00:00
2022-08-17 16:44:05 +00:00
/ * *
2022-09-27 13:40:12 +00:00
Returns true if sqlite3 . capi . sqlite3 _wasmfs _opfs _dir ( ) is a
2022-09-13 19:27:03 +00:00
non - empty string and the given name starts with ( that string +
'/' ) , else returns false .
2022-08-17 16:44:05 +00:00
* /
2022-10-20 05:14:37 +00:00
capi . sqlite3 _wasmfs _filename _is _persistent = function ( name ) {
2022-09-27 13:40:12 +00:00
const p = capi . sqlite3 _wasmfs _opfs _dir ( ) ;
2022-09-13 19:27:03 +00:00
return ( p && name ) ? name . startsWith ( p + '/' ) : false ;
2022-09-12 16:09:50 +00:00
} ;
2022-09-13 19:27:03 +00:00
2022-09-18 17:32:35 +00:00
/ * *
2022-11-01 07:49:49 +00:00
Given an ` sqlite3* ` , an sqlite3 _vfs name , and an optional db name
( defaulting to "main" ) , returns a truthy value ( see below ) if
that db uses that VFS , else returns false . If pDb is falsy then
the 3 rd argument is ignored and this function returns a truthy
value if the default VFS name matches that of the 2 nd
argument . Results are undefined if pDb is truthy but refers to an
invalid pointer . The 3 rd argument specifies the database name of
the given database connection to check , defaulting to the main
db .
2022-09-26 13:55:10 +00:00
2022-10-20 21:28:31 +00:00
The 2 nd and 3 rd arguments may either be a JS string or a WASM
C - string . If the 2 nd argument is a NULL WASM pointer , the default
VFS is assumed . If the 3 rd is a NULL WASM pointer , "main" is
assumed .
2022-09-18 17:32:35 +00:00
The truthy value it returns is a pointer to the ` sqlite3_vfs `
object .
To permit safe use of this function from APIs which may be called
via the C stack ( like SQL UDFs ) , this function does not throw : if
bad arguments cause a conversion error when passing into
wasm - space , false is returned .
* /
2022-11-01 07:49:49 +00:00
capi . sqlite3 _js _db _uses _vfs = function ( pDb , vfsName , dbName = 0 ) {
2022-09-18 17:32:35 +00:00
try {
2022-09-26 13:55:10 +00:00
const pK = capi . sqlite3 _vfs _find ( vfsName ) ;
2022-09-18 17:32:35 +00:00
if ( ! pK ) return false ;
else if ( ! pDb ) {
2022-10-20 21:28:31 +00:00
return pK === capi . sqlite3 _vfs _find ( 0 ) ? pK : false ;
} else {
2022-11-01 07:49:49 +00:00
return pK === capi . sqlite3 _js _db _vfs ( pDb , dbName ) ? pK : false ;
2022-09-18 17:32:35 +00:00
}
} catch ( e ) {
/* Ignore - probably bad args to a wasm-bound function. */
return false ;
}
} ;
2022-09-19 13:44:23 +00:00
/ * *
Returns an array of the names of all currently - registered sqlite3
VFSes .
* /
2022-10-20 18:31:32 +00:00
capi . sqlite3 _js _vfs _list = function ( ) {
2022-09-19 13:44:23 +00:00
const rc = [ ] ;
let pVfs = capi . sqlite3 _vfs _find ( 0 ) ;
while ( pVfs ) {
const oVfs = new capi . sqlite3 _vfs ( pVfs ) ;
2022-12-06 08:46:39 +00:00
rc . push ( wasm . cstrToJs ( oVfs . $zName ) ) ;
2022-09-19 13:44:23 +00:00
pVfs = oVfs . $pNext ;
oVfs . dispose ( ) ;
}
return rc ;
} ;
2022-10-01 16:01:41 +00:00
/ * *
2022-11-23 21:09:51 +00:00
A convenience wrapper around sqlite3 _serialize ( ) which serializes
2022-12-01 15:22:03 +00:00
the given ` sqlite3* ` pointer to a Uint8Array . The first argument
may be either an ` sqlite3* ` or an sqlite3 . oo1 . DB instance .
2022-11-23 21:03:22 +00:00
2022-11-23 21:09:51 +00:00
On success it returns a Uint8Array . If the schema is empty , an
empty array is returned .
` schema ` is the schema to serialize . It may be a WASM C - string
pointer or a JS string . If it is falsy , it defaults to ` "main" ` .
On error it throws with a description of the problem .
2022-10-01 16:01:41 +00:00
* /
2022-11-23 21:03:22 +00:00
capi . sqlite3 _js _db _export = function ( pDb , schema = 0 ) {
2022-12-01 15:22:03 +00:00
pDb = wasm . xWrap . testConvertArg ( 'sqlite3*' , pDb ) ;
2022-10-31 11:09:14 +00:00
if ( ! pDb ) toss3 ( 'Invalid sqlite3* argument.' ) ;
if ( ! wasm . bigIntEnabled ) toss3 ( 'BigInt64 support is not enabled.' ) ;
2022-11-23 21:03:22 +00:00
const scope = wasm . scopedAllocPush ( ) ;
2022-10-01 16:01:41 +00:00
let pOut ;
try {
2022-11-23 21:03:22 +00:00
const pSize = wasm . scopedAlloc ( 8 /*i64*/ + wasm . ptrSizeof ) ;
2022-10-01 16:01:41 +00:00
const ppOut = pSize + 8 ;
/ * *
Maintenance reminder , since this cost a full hour of grief
and confusion : if the order of pSize / ppOut are reversed in
that memory block , fetching the value of pSize after the
export reads a garbage size because it ' s not on an 8 - byte
memory boundary !
* /
2022-11-23 21:03:22 +00:00
const zSchema = schema
? ( wasm . isPtr ( schema ) ? schema : wasm . scopedAllocCString ( '' + schema ) )
: 0 ;
2022-10-01 16:01:41 +00:00
let rc = wasm . exports . sqlite3 _wasm _db _serialize (
2022-11-23 21:03:22 +00:00
pDb , zSchema , ppOut , pSize , 0
2022-10-01 16:01:41 +00:00
) ;
if ( rc ) {
2022-10-31 11:09:14 +00:00
toss3 ( "Database serialization failed with code" ,
2022-10-20 18:31:32 +00:00
sqlite3 . capi . sqlite3 _js _rc _str ( rc ) ) ;
2022-10-01 16:01:41 +00:00
}
2022-12-09 09:23:27 +00:00
pOut = wasm . peekPtr ( ppOut ) ;
const nOut = wasm . peek ( pSize , 'i64' ) ;
2022-10-01 16:01:41 +00:00
rc = nOut
? wasm . heap8u ( ) . slice ( pOut , pOut + Number ( nOut ) )
: new Uint8Array ( ) ;
return rc ;
} finally {
if ( pOut ) wasm . exports . sqlite3 _free ( pOut ) ;
2022-11-23 21:03:22 +00:00
wasm . scopedAllocPop ( scope ) ;
2022-10-01 16:01:41 +00:00
}
} ;
2022-10-20 21:28:31 +00:00
/ * *
Given a ` sqlite3* ` and a database name ( JS string or WASM
C - string pointer , which may be 0 ) , returns a pointer to the
sqlite3 _vfs responsible for it . If the given db name is null / 0 ,
or not provided , then "main" is assumed .
* /
capi . sqlite3 _js _db _vfs =
( dbPointer , dbName = 0 ) => wasm . sqlite3 _wasm _db _vfs ( dbPointer , dbName ) ;
/ * *
A thin wrapper around capi . sqlite3 _aggregate _context ( ) which
behaves the same except that it throws a WasmAllocError if that
2022-10-20 23:48:38 +00:00
function returns 0. As a special case , if n is falsy it does
_not _ throw if that function returns 0. That special case is
intended for use with xFinal ( ) implementations .
2022-10-20 21:28:31 +00:00
* /
capi . sqlite3 _js _aggregate _context = ( pCtx , n ) => {
return capi . sqlite3 _aggregate _context ( pCtx , n )
2022-10-20 23:48:38 +00:00
|| ( n ? WasmAllocError . toss ( "Cannot allocate" , n ,
"bytes for sqlite3_aggregate_context()" )
: 0 ) ;
2022-10-20 21:28:31 +00:00
} ;
2022-12-01 03:55:28 +00:00
/ * *
2023-08-11 17:38:17 +00:00
If the current environment supports the POSIX file APIs , this routine
creates ( or overwrites ) the given file using those APIs . This is
primarily intended for use in Emscripten - based builds where the POSIX
APIs are transparently proxied by an in - memory virtual filesystem .
It may behave diffrently in other environments .
The first argument must be either a JS string or WASM C - string
holding the filename . Note that this routine does _not _ create
intermediary directories if the filename has a directory part .
The 2 nd argument may either a valid WASM memory pointer , an
ArrayBuffer , or a Uint8Array . The 3 rd must be the length , in
bytes , of the data array to copy . If the 2 nd argument is an
ArrayBuffer or Uint8Array and the 3 rd is not a positive integer
then the 3 rd defaults to the array ' s byteLength value .
Results are undefined if data is a WASM pointer and dataLen is
exceeds data ' s bounds .
Throws if any arguments are invalid or if creating or writing to
the file fails .
Added in 3.43 as an alternative for the deprecated
sqlite3 _js _vfs _create _file ( ) .
* /
capi . sqlite3 _js _posix _create _file = function ( filename , data , dataLen ) {
let pData ;
if ( data && wasm . isPtr ( data ) ) {
pData = data ;
} else if ( data instanceof ArrayBuffer || data instanceof Uint8Array ) {
pData = wasm . allocFromTypedArray ( data ) ;
if ( arguments . length < 3 || ! util . isInt32 ( dataLen ) || dataLen < 0 ) {
dataLen = data . byteLength ;
}
} else {
SQLite3Error . toss ( "Invalid 2nd argument for sqlite3_js_posix_create_file()." ) ;
}
try {
if ( ! util . isInt32 ( dataLen ) || dataLen < 0 ) {
SQLite3Error . toss ( "Invalid 3rd argument for sqlite3_js_posix_create_file()." ) ;
}
const rc = wasm . sqlite3 _wasm _posix _create _file ( filename , pData , dataLen ) ;
if ( rc ) SQLite3Error . toss ( "Creation of file failed with sqlite3 result code" ,
capi . sqlite3 _js _rc _str ( rc ) ) ;
} finally {
wasm . dealloc ( pData ) ;
}
} ;
/ * *
Deprecation warning : this function does not work properly in
debug builds of sqlite3 because its out - of - scope use of the
sqlite3 _vfs API triggers assertions in the core library . That
was unfortunately not discovered until 2023 - 08 - 11. This function
is now deprecated and should not be used in new code .
Alternative options :
- "unix" VFS and its variants can get equivalent functionality
with sqlite3 _js _posix _create _file ( ) .
- OPFS : use either sqlite3 . oo1 . OpfsDb . importDb ( ) , for the "opfs"
VFS , or the importDb ( ) method of the PoolUtil object provided
by the "opfs-sahpool" OPFS ( noting that its VFS name may differ
depending on client - side configuration ) . We cannot proxy those
from here because the former is necessarily asynchronous and
the latter requires information not available to this function .
2023-08-11 14:31:20 +00:00
2022-12-01 03:55:28 +00:00
Creates a file using the storage appropriate for the given
sqlite3 _vfs . The first argument may be a VFS name ( JS string
only , NOT a WASM C - string ) , WASM - managed ` sqlite3_vfs* ` , or
a capi . sqlite3 _vfs instance . Pass 0 ( a NULL pointer ) to use the
default VFS . If passed a string which does not resolve using
sqlite3 _vfs _find ( ) , an exception is thrown . ( Note that a WASM
C - string is not accepted because it is impossible to
distinguish from a C - level ` sqlite3_vfs* ` . )
The second argument , the filename , must be a JS or WASM C - string .
2022-12-01 15:22:03 +00:00
The 3 rd may either be falsy , a valid WASM memory pointer , an
ArrayBuffer , or a Uint8Array . The 4 th must be the length , in
bytes , of the data array to copy . If the 3 rd argument is an
ArrayBuffer or Uint8Array and the 4 th is not a positive integer
then the 4 th defaults to the array ' s byteLength value .
2022-12-01 03:55:28 +00:00
If data is falsy then a file is created with dataLen bytes filled
with uninitialized data ( whatever truncate ( ) leaves there ) . If
data is not falsy then a file is created or truncated and it is
filled with the first dataLen bytes of the data source .
Throws if any arguments are invalid or if creating or writing to
the file fails .
Note that most VFSes do _not _ automatically create directory
parts of filenames , nor do all VFSes have a concept of
directories . If the given filename is not valid for the given
VFS , an exception will be thrown . This function exists primarily
to assist in implementing file - upload capability , with the caveat
that clients must have some idea of the VFS into which they want
to upload and that VFS must support the operation .
VFS - specific notes :
2022-12-01 15:22:03 +00:00
- "memdb" : results are undefined .
2022-12-02 07:14:56 +00:00
- "kvvfs" : will fail with an I / O error due to strict internal
requirments of that VFS ' s xTruncate ( ) .
2022-12-01 03:55:28 +00:00
- "unix" and related : will use the WASM build ' s equivalent of the
2022-12-02 07:14:56 +00:00
POSIX I / O APIs . This will work so long as neither a specific
VFS nor the WASM environment imposes requirements which break it .
2022-12-01 03:55:28 +00:00
2022-12-02 07:14:56 +00:00
- "opfs" : uses OPFS storage and creates directory parts of the
2023-08-11 17:38:17 +00:00
filename . It can only be used to import an SQLite3 database
file and will fail if given anything else .
2022-12-01 03:55:28 +00:00
* /
capi . sqlite3 _js _vfs _create _file = function ( vfs , filename , data , dataLen ) {
2023-08-11 17:38:17 +00:00
config . warn ( "sqlite3_js_vfs_create_file() is deprecated and" ,
"should be avoided because it can lead to C-level crashes." ,
"See its documentation for alternative options." ) ;
2022-12-01 03:55:28 +00:00
let pData ;
2022-12-01 15:22:03 +00:00
if ( data ) {
if ( wasm . isPtr ( data ) ) {
pData = data ;
} else if ( data instanceof ArrayBuffer ) {
data = new Uint8Array ( data ) ;
}
if ( data instanceof Uint8Array ) {
pData = wasm . allocFromTypedArray ( data ) ;
if ( arguments . length < 4 || ! util . isInt32 ( dataLen ) || dataLen < 0 ) {
dataLen = data . byteLength ;
}
} else {
SQLite3Error . toss ( "Invalid 3rd argument type for sqlite3_js_vfs_create_file()." ) ;
2022-12-01 03:55:28 +00:00
}
} else {
2022-12-01 15:22:03 +00:00
pData = 0 ;
2022-12-01 03:55:28 +00:00
}
if ( ! util . isInt32 ( dataLen ) || dataLen < 0 ) {
wasm . dealloc ( pData ) ;
SQLite3Error . toss ( "Invalid 4th argument for sqlite3_js_vfs_create_file()." ) ;
}
try {
const rc = wasm . sqlite3 _wasm _vfs _create _file ( vfs , filename , pData , dataLen ) ;
if ( rc ) SQLite3Error . toss ( "Creation of file failed with sqlite3 result code" ,
capi . sqlite3 _js _rc _str ( rc ) ) ;
} finally {
2023-08-11 17:38:17 +00:00
wasm . dealloc ( pData ) ;
2022-12-01 03:55:28 +00:00
}
} ;
2022-12-25 17:09:34 +00:00
2023-08-29 15:39:57 +00:00
/ * *
2023-08-30 13:07:35 +00:00
Converts SQL input from a variety of convenient formats
to plain strings .
2023-08-29 15:39:57 +00:00
If v is a string , it is returned as - is . If it is - a Array , its
join ( "" ) result is returned . If is is a Uint8Array , Int8Array ,
or ArrayBuffer , it is assumed to hold UTF - 8 - encoded text and is
decoded to a string . If it looks like a WASM pointer ,
wasm . cstrToJs ( sql ) is returned . Else undefined is returned .
Added in 3.44
* /
capi . sqlite3 _js _sql _to _string = ( sql ) => {
if ( 'string' === typeof sql ) {
return sql ;
}
const x = flexibleString ( v ) ;
return x === v ? undefined : x ;
}
2022-10-29 07:54:10 +00:00
if ( util . isUIThread ( ) ) {
2022-09-13 19:27:03 +00:00
/* Features specific to the main window thread... */
/ * *
2022-10-20 18:31:32 +00:00
Internal helper for sqlite3 _js _kvvfs _clear ( ) and friends .
2022-11-03 21:21:10 +00:00
Its argument should be one of ( 'local' , 'session' , "" ) .
2022-09-13 19:27:03 +00:00
* /
const _ _kvvfsInfo = function ( which ) {
const rc = Object . create ( null ) ;
rc . prefix = 'kvvfs-' + which ;
rc . stores = [ ] ;
2023-03-07 19:12:06 +00:00
if ( 'session' === which || "" === which ) rc . stores . push ( globalThis . sessionStorage ) ;
if ( 'local' === which || "" === which ) rc . stores . push ( globalThis . localStorage ) ;
2022-09-13 19:27:03 +00:00
return rc ;
} ;
/ * *
Clears all storage used by the kvvfs DB backend , deleting any
DB ( s ) stored there . Its argument must be either 'session' ,
2022-11-03 21:21:10 +00:00
'local' , or "" . In the first two cases , only sessionStorage
2022-09-13 19:27:03 +00:00
resp . localStorage is cleared . If it ' s an empty string ( the
default ) then both are cleared . Only storage keys which match
the pattern used by kvvfs are cleared : any other client - side
data are retained .
This function is only available in the main window thread .
Returns the number of entries cleared .
* /
2022-11-03 21:21:10 +00:00
capi . sqlite3 _js _kvvfs _clear = function ( which = "" ) {
2022-09-13 19:27:03 +00:00
let rc = 0 ;
const kvinfo = _ _kvvfsInfo ( which ) ;
kvinfo . stores . forEach ( ( s ) => {
const toRm = [ ] /* keys to remove */ ;
let i ;
for ( i = 0 ; i < s . length ; ++ i ) {
const k = s . key ( i ) ;
if ( k . startsWith ( kvinfo . prefix ) ) toRm . push ( k ) ;
}
toRm . forEach ( ( kk ) => s . removeItem ( kk ) ) ;
rc += toRm . length ;
} ) ;
return rc ;
} ;
/ * *
This routine guesses the approximate amount of
window . localStorage and / or window . sessionStorage in use by the
2022-09-18 17:32:35 +00:00
kvvfs database backend . Its argument must be one of
2022-11-03 21:21:10 +00:00
( 'session' , 'local' , "" ) . In the first two cases , only
2022-09-13 19:27:03 +00:00
sessionStorage resp . localStorage is counted . If it ' s an empty
string ( the default ) then both are counted . Only storage keys
which match the pattern used by kvvfs are counted . The returned
value is the "length" value of every matching key and value ,
2022-09-16 12:49:45 +00:00
noting that JavaScript stores each character in 2 bytes .
2022-09-13 19:27:03 +00:00
Note that the returned size is not authoritative from the
perspective of how much data can fit into localStorage and
sessionStorage , as the precise algorithms for determining
those limits are unspecified and may include per - entry
overhead invisible to clients .
* /
2022-11-03 21:21:10 +00:00
capi . sqlite3 _js _kvvfs _size = function ( which = "" ) {
2022-09-13 19:27:03 +00:00
let sz = 0 ;
const kvinfo = _ _kvvfsInfo ( which ) ;
kvinfo . stores . forEach ( ( s ) => {
let i ;
for ( i = 0 ; i < s . length ; ++ i ) {
const k = s . key ( i ) ;
if ( k . startsWith ( kvinfo . prefix ) ) {
sz += k . length ;
sz += s . getItem ( k ) . length ;
}
}
} ) ;
2022-10-01 16:01:41 +00:00
return sz * 2 /* because JS uses 2-byte char encoding */ ;
2022-09-13 19:27:03 +00:00
} ;
} /* main-window-only bits */
2022-12-09 01:49:17 +00:00
/ * *
Wraps all known variants of the C - side variadic
sqlite3 _db _config ( ) .
Full docs : https : //sqlite.org/c3ref/db_config.html
Returns capi . SQLITE _MISUSE if op is not a valid operation ID .
2023-05-01 15:42:59 +00:00
The variants which take ` (int, int*) ` arguments treat a
missing or falsy pointer argument as 0.
2022-12-09 01:49:17 +00:00
* /
2023-03-22 19:57:19 +00:00
capi . sqlite3 _db _config = function ( pDb , op , ... args ) {
2022-12-09 01:49:17 +00:00
if ( ! this . s ) {
this . s = wasm . xWrap ( 'sqlite3_wasm_db_config_s' , 'int' ,
[ 'sqlite3*' , 'int' , 'string:static' ]
/* MAINDBNAME requires a static string */ ) ;
this . pii = wasm . xWrap ( 'sqlite3_wasm_db_config_pii' , 'int' ,
[ 'sqlite3*' , 'int' , '*' , 'int' , 'int' ] ) ;
this . ip = wasm . xWrap ( 'sqlite3_wasm_db_config_ip' , 'int' ,
[ 'sqlite3*' , 'int' , 'int' , '*' ] ) ;
}
switch ( op ) {
2023-03-22 19:57:19 +00:00
case capi . SQLITE _DBCONFIG _ENABLE _FKEY :
case capi . SQLITE _DBCONFIG _ENABLE _TRIGGER :
case capi . SQLITE _DBCONFIG _ENABLE _FTS3 _TOKENIZER :
case capi . SQLITE _DBCONFIG _ENABLE _LOAD _EXTENSION :
case capi . SQLITE _DBCONFIG _NO _CKPT _ON _CLOSE :
case capi . SQLITE _DBCONFIG _ENABLE _QPSG :
case capi . SQLITE _DBCONFIG _TRIGGER _EQP :
case capi . SQLITE _DBCONFIG _RESET _DATABASE :
case capi . SQLITE _DBCONFIG _DEFENSIVE :
case capi . SQLITE _DBCONFIG _WRITABLE _SCHEMA :
case capi . SQLITE _DBCONFIG _LEGACY _ALTER _TABLE :
case capi . SQLITE _DBCONFIG _DQS _DML :
case capi . SQLITE _DBCONFIG _DQS _DDL :
case capi . SQLITE _DBCONFIG _ENABLE _VIEW :
case capi . SQLITE _DBCONFIG _LEGACY _FILE _FORMAT :
case capi . SQLITE _DBCONFIG _TRUSTED _SCHEMA :
2023-05-01 15:42:59 +00:00
case capi . SQLITE _DBCONFIG _STMT _SCANSTATUS :
case capi . SQLITE _DBCONFIG _REVERSE _SCANORDER :
2022-12-09 01:49:17 +00:00
return this . ip ( pDb , op , args [ 0 ] , args [ 1 ] || 0 ) ;
2023-03-22 19:57:19 +00:00
case capi . SQLITE _DBCONFIG _LOOKASIDE :
2022-12-09 01:49:17 +00:00
return this . pii ( pDb , op , args [ 0 ] , args [ 1 ] , args [ 2 ] ) ;
2023-03-22 19:57:19 +00:00
case capi . SQLITE _DBCONFIG _MAINDBNAME :
2022-12-09 01:49:17 +00:00
return this . s ( pDb , op , args [ 0 ] ) ;
default :
2023-03-22 19:57:19 +00:00
return capi . SQLITE _MISUSE ;
2022-12-09 01:49:17 +00:00
}
} . bind ( Object . create ( null ) ) ;
2022-09-27 13:40:12 +00:00
2022-12-09 14:46:24 +00:00
/ * *
Given a ( sqlite3 _value * ) , this function attempts to convert it
to an equivalent JS value with as much fidelity as feasible and
2022-12-09 15:12:07 +00:00
return it .
By default it throws if it cannot determine any sensible
conversion . If passed a falsy second argument , it instead returns
2022-12-10 10:24:46 +00:00
` undefined ` if no suitable conversion is found . Note that there
2022-12-09 15:12:07 +00:00
is no conversion from SQL to JS which results in the ` undefined `
2022-12-10 10:24:46 +00:00
value , so ` undefined ` has an unambiguous meaning here . It will
always throw a WasmAllocError if allocating memory for a
conversion fails .
2022-12-09 15:12:07 +00:00
Caveats :
- It does not support sqlite3 _value _to _pointer ( ) conversions
because those require a type name string which this function
does not have and cannot sensibly be given at the level of the
API where this is used ( e . g . automatically converting UDF
arguments ) . Clients using sqlite3 _value _to _pointer ( ) , and its
related APIs , will need to manage those themselves .
2022-12-09 14:46:24 +00:00
* /
2022-12-09 15:12:07 +00:00
capi . sqlite3 _value _to _js = function ( pVal , throwIfCannotConvert = true ) {
2022-12-09 14:46:24 +00:00
let arg ;
const valType = capi . sqlite3 _value _type ( pVal ) ;
switch ( valType ) {
case capi . SQLITE _INTEGER :
if ( wasm . bigIntEnabled ) {
arg = capi . sqlite3 _value _int64 ( pVal ) ;
if ( util . bigIntFitsDouble ( arg ) ) arg = Number ( arg ) ;
}
else arg = capi . sqlite3 _value _double ( pVal ) /*yes, double, for larger integers*/ ;
break ;
case capi . SQLITE _FLOAT :
arg = capi . sqlite3 _value _double ( pVal ) ;
break ;
case capi . SQLITE _TEXT :
arg = capi . sqlite3 _value _text ( pVal ) ;
break ;
case capi . SQLITE _BLOB : {
const n = capi . sqlite3 _value _bytes ( pVal ) ;
const pBlob = capi . sqlite3 _value _blob ( pVal ) ;
if ( n && ! pBlob ) sqlite3 . WasmAllocError . toss (
"Cannot allocate memory for blob argument of" , n , "byte(s)"
) ;
arg = n ? wasm . heap8u ( ) . slice ( pBlob , pBlob + Number ( n ) ) : null ;
break ;
}
case capi . SQLITE _NULL :
arg = null ; break ;
default :
2022-12-09 15:12:07 +00:00
if ( throwIfCannotConvert ) {
toss3 ( capi . SQLITE _MISMATCH ,
"Unhandled sqlite3_value_type():" , valType ) ;
}
arg = undefined ;
2022-12-09 14:46:24 +00:00
}
return arg ;
} ;
2022-12-10 10:24:46 +00:00
/ * *
Requires a C - style array of ` sqlite3_value* ` objects and the
number of entries in that array . Returns a JS array containing
the results of passing each C array entry to
sqlite3 _value _to _js ( ) . The 3 rd argument to this function is
passed on as the 2 nd argument to that one .
* /
capi . sqlite3 _values _to _js = function ( argc , pArgv , throwIfCannotConvert = true ) {
let i ;
const tgt = [ ] ;
for ( i = 0 ; i < argc ; ++ i ) {
/ * *
Curiously : despite ostensibly requiring 8 - byte
alignment , the pArgv array is parcelled into chunks of
4 bytes ( 1 pointer each ) . The values those point to
have 8 - byte alignment but the individual argv entries
do not .
* /
tgt . push ( capi . sqlite3 _value _to _js (
2023-08-03 16:22:59 +00:00
wasm . peekPtr ( pArgv + ( wasm . ptrSizeof * i ) ) ,
throwIfCannotConvert
2022-12-10 10:24:46 +00:00
) ) ;
}
return tgt ;
} ;
/ * *
Calls either sqlite3 _result _error _nomem ( ) , if e is - a
WasmAllocError , or sqlite3 _result _error ( ) . In the latter case ,
the second arugment is coerced to a string to create the error
message .
The first argument is a ( sqlite3 _context * ) . Returns void .
Does not throw .
* /
capi . sqlite3 _result _error _js = function ( pCtx , e ) {
if ( e instanceof WasmAllocError ) {
capi . sqlite3 _result _error _nomem ( pCtx ) ;
} else {
/ * M a i n t e n a n c e r e m i n d e r : ' ' + e , r a t h e r t h a n e . m e s s a g e ,
will prefix e . message with e . name , so it includes
the exception ' s type name in the result . * / ;
capi . sqlite3 _result _error ( pCtx , '' + e , - 1 ) ;
}
} ;
2022-12-24 15:28:45 +00:00
2022-12-10 10:24:46 +00:00
/ * *
This function passes its 2 nd argument to one of the
sqlite3 _result _xyz ( ) routines , depending on the type of that
argument :
- If ( val instanceof Error ) , this function passes it to
sqlite3 _result _error _js ( ) .
- ` null ` : ` sqlite3_result_null() `
- ` boolean ` : ` sqlite3_result_int() ` with a value of 0 or 1.
- ` number ` : ` sqlite3_result_int() ` , ` sqlite3_result_int64() ` , or
` sqlite3_result_double() ` , depending on the range of the number
and whether or not int64 support is enabled .
- ` bigint ` : similar to ` number ` but will trigger an error if the
value is too big to store in an int64 .
- ` string ` : ` sqlite3_result_text() `
2022-12-24 15:28:45 +00:00
- Uint8Array or Int8Array or ArrayBuffer : ` sqlite3_result_blob() `
2022-12-10 10:24:46 +00:00
- ` undefined ` : is a no - op provided to simplify certain use cases .
Anything else triggers ` sqlite3_result_error() ` with a
description of the problem .
The first argument to this function is a ` (sqlite3_context*) ` .
Returns void . Does not throw .
* /
capi . sqlite3 _result _js = function ( pCtx , val ) {
if ( val instanceof Error ) {
capi . sqlite3 _result _error _js ( pCtx , val ) ;
return ;
}
try {
switch ( typeof val ) {
case 'undefined' :
/ * T h i s i s a n o - o p . T h i s r o u t i n e o r i g i n a t e d i n t h e c r e a t e _ f u n c t i o n ( )
family of APIs and in that context , passing in undefined indicated
that the caller was responsible for calling sqlite3 _result _xxx ( )
( if needed ) . * /
break ;
case 'boolean' :
capi . sqlite3 _result _int ( pCtx , val ? 1 : 0 ) ;
break ;
case 'bigint' :
if ( util . bigIntFits32 ( val ) ) {
capi . sqlite3 _result _int ( pCtx , Number ( val ) ) ;
} else if ( util . bigIntFitsDouble ( val ) ) {
capi . sqlite3 _result _double ( pCtx , Number ( val ) ) ;
} else if ( wasm . bigIntEnabled ) {
if ( util . bigIntFits64 ( val ) ) capi . sqlite3 _result _int64 ( pCtx , val ) ;
else toss3 ( "BigInt value" , val . toString ( ) , "is too BigInt for int64." ) ;
} else {
toss3 ( "BigInt value" , val . toString ( ) , "is too BigInt." ) ;
}
break ;
case 'number' : {
let f ;
if ( util . isInt32 ( val ) ) {
f = capi . sqlite3 _result _int ;
} else if ( wasm . bigIntEnabled
&& Number . isInteger ( val )
&& util . bigIntFits64 ( BigInt ( val ) ) ) {
f = capi . sqlite3 _result _int64 ;
} else {
f = capi . sqlite3 _result _double ;
}
f ( pCtx , val ) ;
break ;
}
2022-12-24 15:28:45 +00:00
case 'string' : {
const [ p , n ] = wasm . allocCString ( val , true ) ;
capi . sqlite3 _result _text ( pCtx , p , n , capi . SQLITE _WASM _DEALLOC ) ;
2022-12-10 10:24:46 +00:00
break ;
2022-12-24 15:28:45 +00:00
}
2022-12-10 10:24:46 +00:00
case 'object' :
if ( null === val /*yes, typeof null === 'object'*/ ) {
capi . sqlite3 _result _null ( pCtx ) ;
break ;
} else if ( util . isBindableTypedArray ( val ) ) {
const pBlob = wasm . allocFromTypedArray ( val ) ;
capi . sqlite3 _result _blob (
pCtx , pBlob , val . byteLength ,
2022-12-24 15:28:45 +00:00
capi . SQLITE _WASM _DEALLOC
2022-12-10 10:24:46 +00:00
) ;
break ;
}
// else fall through
default :
toss3 ( "Don't not how to handle this UDF result value:" , ( typeof val ) , val ) ;
}
} catch ( e ) {
capi . sqlite3 _result _error _js ( pCtx , e ) ;
}
} ;
2022-12-10 15:13:29 +00:00
/ * *
Returns the result sqlite3 _column _value ( pStmt , iCol ) passed to
sqlite3 _value _to _js ( ) . The 3 rd argument of this function is
ignored by this function except to pass it on as the second
argument of sqlite3 _value _to _js ( ) . If the sqlite3 _column _value ( )
returns NULL ( e . g . because the column index is out of range ) ,
this function returns ` undefined ` , regardless of the 3 rd
2022-12-25 10:22:27 +00:00
argument . If the 3 rd argument is falsy and conversion fails ,
` undefined ` will be returned .
2022-12-10 15:13:29 +00:00
Note that sqlite3 _column _value ( ) returns an "unprotected" value
object , but in a single - threaded environment ( like this one )
there is no distinction between protected and unprotected values .
* /
capi . sqlite3 _column _js = function ( pStmt , iCol , throwIfCannotConvert = true ) {
const v = capi . sqlite3 _column _value ( pStmt , iCol ) ;
return ( 0 === v ) ? undefined : capi . sqlite3 _value _to _js ( v , throwIfCannotConvert ) ;
} ;
2022-12-27 14:34:32 +00:00
/ * *
2022-12-27 22:46:49 +00:00
Internal impl of sqlite3 _preupdate _new / old _js ( ) and
sqlite3changeset _new / old _js ( ) .
2022-12-27 14:34:32 +00:00
* /
2022-12-27 22:46:49 +00:00
const _ _newOldValue = function ( pObj , iCol , impl ) {
2022-12-27 14:34:32 +00:00
impl = capi [ impl ] ;
if ( ! this . ptr ) this . ptr = wasm . allocPtr ( ) ;
else wasm . pokePtr ( this . ptr , 0 ) ;
2022-12-27 22:46:49 +00:00
const rc = impl ( pObj , iCol , this . ptr ) ;
if ( rc ) return SQLite3Error . toss ( rc , arguments [ 2 ] + "() failed with code " + rc ) ;
const pv = wasm . peekPtr ( this . ptr ) ;
return pv ? capi . sqlite3 _value _to _js ( pv , true ) : undefined ;
2022-12-27 14:34:32 +00:00
} . bind ( Object . create ( null ) ) ;
/ * *
A wrapper around sqlite3 _preupdate _new ( ) which fetches the
sqlite3 _value at the given index and returns the result of
passing it to sqlite3 _value _to _js ( ) . Throws on error .
* /
capi . sqlite3 _preupdate _new _js =
2022-12-27 22:46:49 +00:00
( pDb , iCol ) => _ _newOldValue ( pDb , iCol , 'sqlite3_preupdate_new' ) ;
2022-12-27 14:34:32 +00:00
/ * *
2022-12-27 22:46:49 +00:00
The sqlite3 _preupdate _old ( ) counterpart of
sqlite3 _preupdate _new _js ( ) , with an identical interface .
* /
capi . sqlite3 _preupdate _old _js =
( pDb , iCol ) => _ _newOldValue ( pDb , iCol , 'sqlite3_preupdate_old' ) ;
/ * *
A wrapper around sqlite3changeset _new ( ) which fetches the
2022-12-27 14:34:32 +00:00
sqlite3 _value at the given index and returns the result of
passing it to sqlite3 _value _to _js ( ) . Throws on error .
2022-12-27 22:46:49 +00:00
If sqlite3changeset _new ( ) succeeds but has no value to report ,
this function returns the undefined value , noting that undefined
is a valid conversion from an ` sqlite3_value ` , so is unambiguous .
2022-12-27 14:34:32 +00:00
* /
2022-12-27 22:46:49 +00:00
capi . sqlite3changeset _new _js =
( pChangesetIter , iCol ) => _ _newOldValue ( pChangesetIter , iCol ,
'sqlite3changeset_new' ) ;
/ * *
The sqlite3changeset _old ( ) counterpart of
sqlite3changeset _new _js ( ) , with an identical interface .
* /
capi . sqlite3changeset _old _js =
( pChangesetIter , iCol ) => _ _newOldValue ( pChangesetIter , iCol ,
'sqlite3changeset_old' ) ;
2022-12-27 14:34:32 +00:00
2022-08-10 11:26:08 +00:00
/* The remainder of the API will be set up in later steps. */
2022-08-22 13:34:13 +00:00
const sqlite3 = {
2022-08-17 16:44:05 +00:00
WasmAllocError : WasmAllocError ,
2022-10-02 00:09:40 +00:00
SQLite3Error : SQLite3Error ,
2022-08-10 11:26:08 +00:00
capi ,
2022-10-29 07:54:10 +00:00
util ,
wasm ,
2022-09-27 13:40:12 +00:00
config ,
2022-10-16 16:38:15 +00:00
/ * *
Holds the version info of the sqlite3 source tree from which
the generated sqlite3 - api . js gets built . Note that its version
may well differ from that reported by sqlite3 _libversion ( ) , but
that should be considered a source file mismatch , as the JS and
WASM files are intended to be built and distributed together .
This object is initially a placeholder which gets replaced by a
build - generated object .
* /
version : Object . create ( null ) ,
2022-12-13 10:54:12 +00:00
/ * *
The library reserves the 'client' property for client - side use
and promises to never define a property with this name nor to
ever rely on specific contents of it . It makes no such guarantees
for other properties .
* /
client : undefined ,
2022-09-27 13:40:12 +00:00
/ * *
2023-07-20 23:25:32 +00:00
This function is not part of the public interface , but a
piece of internal bootstrapping infrastructure .
2022-09-27 13:40:12 +00:00
Performs any optional asynchronous library - level initialization
which might be required . This function returns a Promise which
2022-10-09 15:12:37 +00:00
resolves to the sqlite3 namespace object . Any error in the
async init will be fatal to the init as a whole , but init
routines are themselves welcome to install dummy catch ( )
handlers which are not fatal if their failure should be
considered non - fatal . If called more than once , the second and
2022-09-27 13:40:12 +00:00
subsequent calls are no - ops which return a pre - resolved
Promise .
2022-09-30 16:49:03 +00:00
Ideally this function is called as part of the Promise chain
which handles the loading and bootstrapping of the API . If not
then it must be called by client - level code , which must not use
the library until the returned promise resolves .
2022-09-27 13:40:12 +00:00
2023-07-18 18:52:41 +00:00
If called multiple times it will return the same promise on
subsequent calls . The current build setup precludes that
possibility , so it ' s only a hypothetical problem if / w h e n t h i s
function ever needs to be invoked by clients .
2022-09-29 13:17:50 +00:00
In Emscripten - based builds , this function is called
automatically and deleted from this object .
2022-09-27 13:40:12 +00:00
* /
2023-07-20 23:25:32 +00:00
asyncPostInit : async function ff ( ) {
if ( ff . isReady instanceof Promise ) return ff . isReady ;
2023-07-21 09:10:42 +00:00
let lia = sqlite3ApiBootstrap . initializersAsync ;
2022-09-27 13:40:12 +00:00
delete sqlite3ApiBootstrap . initializersAsync ;
2023-07-21 09:10:42 +00:00
const postInit = async ( ) => {
2022-11-30 05:27:36 +00:00
if ( ! sqlite3 . _ _isUnderTest ) {
/ * D e l e t e r e f e r e n c e s t o i n t e r n a l - o n l y A P I s w h i c h a r e u s e d b y
some initializers . Retain them when running in test mode
so that we can add tests for them . * /
delete sqlite3 . util ;
2022-12-12 11:22:05 +00:00
/ * I t ' s c o n c e i v a b l e t h a t w e m i g h t w a n t t o e x p o s e
StructBinder to client - side code , but it ' s only useful if
clients build their own sqlite3 . wasm which contains their
2023-07-20 23:25:32 +00:00
own C struct types . * /
2022-11-30 05:27:36 +00:00
delete sqlite3 . StructBinder ;
}
return sqlite3 ;
2022-11-30 07:17:29 +00:00
} ;
2023-07-21 09:10:42 +00:00
const catcher = ( e ) => {
config . error ( "an async sqlite3 initializer failed:" , e ) ;
throw e ;
} ;
if ( ! lia || ! lia . length ) {
return ff . isReady = postInit ( ) . catch ( catcher ) ;
2022-11-30 07:17:29 +00:00
}
2023-07-21 09:10:42 +00:00
lia = lia . map ( ( f ) => {
return ( f instanceof Function ) ? async x => f ( sqlite3 ) : f ;
} ) ;
lia . push ( postInit ) ;
let p = Promise . resolve ( sqlite3 ) ;
while ( lia . length ) p = p . then ( lia . shift ( ) ) ;
return ff . isReady = p . catch ( catcher ) ;
2022-10-19 04:44:58 +00:00
} ,
/ * *
scriptInfo ideally gets injected into this object by the
infrastructure which assembles the JS / WASM module . It contains
state which must be collected before sqlite3ApiBootstrap ( ) can
be declared . It is not necessarily available to any
sqlite3ApiBootstrap . initializers but "should" be in place ( if
it ' s added at all ) by the time that
sqlite3ApiBootstrap . initializersAsync is processed .
This state is not part of the public API , only intended for use
with the sqlite3 API bootstrapping and wasm - loading process .
* /
scriptInfo : undefined
2022-08-10 11:26:08 +00:00
} ;
2022-10-04 17:06:51 +00:00
try {
sqlite3ApiBootstrap . initializers . forEach ( ( f ) => {
f ( sqlite3 ) ;
} ) ;
} catch ( e ) {
/ * I f w e d o n ' t r e p o r t t h i s h e r e , i t c a n g e t c o m p l e t e l y s w a l l o w e d
up and disappear into the abyss of Promises and Workers . * /
console . error ( "sqlite3 bootstrap initializer threw:" , e ) ;
throw e ;
}
2022-08-22 13:34:13 +00:00
delete sqlite3ApiBootstrap . initializers ;
sqlite3ApiBootstrap . sqlite3 = sqlite3 ;
return sqlite3 ;
2022-08-10 11:26:08 +00:00
} /*sqlite3ApiBootstrap()*/ ;
2022-08-22 13:34:13 +00:00
/ * *
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap . initializers is an internal detail used by
2022-08-22 13:34:13 +00:00
the various pieces of the sqlite3 API ' s amalgamation process . It
must not be modified by client code except when plugging such code
into the amalgamation process .
Each component of the amalgamation is expected to append a function
to this array . When sqlite3ApiBootstrap ( ) is called for the first
time , each such function will be called ( in their appended order )
and passed the sqlite3 namespace object , into which they can install
their features ( noting that most will also require that certain
features alread have been installed ) . At the end of that process ,
this array is deleted .
2022-09-27 13:40:12 +00:00
Note that the order of insertion into this array is significant for
2022-10-29 07:54:10 +00:00
some pieces . e . g . sqlite3 . capi and sqlite3 . wasm cannot be fully
2022-10-09 15:12:37 +00:00
utilized until the whwasmutil . js part is plugged in via
sqlite3 - api - glue . js .
2022-08-22 13:34:13 +00:00
* /
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap . initializers = [ ] ;
2022-09-27 13:40:12 +00:00
/ * *
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap . initializersAsync is an internal detail
2022-09-27 13:40:12 +00:00
used by the sqlite3 API ' s amalgamation process . It must not be
modified by client code except when plugging such code into the
amalgamation process .
2023-03-07 19:12:06 +00:00
The counterpart of globalThis . sqlite3ApiBootstrap . initializers ,
2022-10-09 15:12:37 +00:00
specifically for initializers which are asynchronous . All entries in
this list must be either async functions , non - async functions which
return a Promise , or a Promise . Each function in the list is called
2023-07-20 23:25:32 +00:00
with the sqlite3 object as its only argument .
2022-10-09 15:12:37 +00:00
The resolved value of any Promise is ignored and rejection will kill
the asyncPostInit ( ) process ( at an indeterminate point because all
of them are run asynchronously in parallel ) .
2022-09-27 13:40:12 +00:00
This list is not processed until the client calls
sqlite3 . asyncPostInit ( ) . This means , for example , that intializers
2023-03-07 19:12:06 +00:00
added to globalThis . sqlite3ApiBootstrap . initializers may push entries to
2022-10-04 01:11:10 +00:00
this list .
2022-09-27 13:40:12 +00:00
* /
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap . initializersAsync = [ ] ;
2022-08-24 05:59:23 +00:00
/ * *
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 .
* /
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap . defaultConfig = Object . create ( null ) ;
2022-09-13 19:27:03 +00:00
/ * *
Placeholder : gets installed by the first call to
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap ( ) . However , it is recommended that the
2022-09-13 19:27:03 +00:00
caller of sqlite3ApiBootstrap ( ) capture its return value and delete
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap after calling it . It returns the same
2022-09-13 19:27:03 +00:00
value which will be stored here .
* /
2023-03-07 19:12:06 +00:00
globalThis . sqlite3ApiBootstrap . sqlite3 = undefined ;