Snapshot of upstream SQLite 3.40.1
[sqlcipher.git] / ext / wasm / api / sqlite3-api-prologue.js
blobfed1c56669631f1a92c7bccdce7e0a9684e23454
1 /*
2 2022-05-22
4 The author disclaims copyright to this source code. In place of a
5 legal notice, here is a blessing:
7 * May you do good and not evil.
8 * May you find forgiveness for yourself and forgive others.
9 * May you share freely, never taking more than you give.
11 ***********************************************************************
13 This file is intended to be combined at build-time with other
14 related code, most notably a header and footer which wraps this whole
15 file into an Emscripten Module.postRun() handler which has a parameter
16 named "Module" (the Emscripten Module object). The exact requirements,
17 conventions, and build process are very much under construction and
18 will be (re)documented once they've stopped fluctuating so much.
20 Project home page: https://sqlite.org
22 Documentation home page: https://sqlite.org/wasm
24 Specific goals of this subproject:
26 - Except where noted in the non-goals, provide a more-or-less
27 feature-complete wrapper to the sqlite3 C API, insofar as WASM
28 feature parity with C allows for. In fact, provide at least 4
29 APIs...
31 1) 1-to-1 bindings as exported from WASM, with no automatic
32 type conversions between JS and C.
34 2) A binding of (1) which provides certain JS/C type conversions
35 to greatly simplify its use.
37 3) A higher-level API, more akin to sql.js and node.js-style
38 implementations. This one speaks directly to the low-level
39 API. This API must be used from the same thread as the
40 low-level API.
42 4) A second higher-level API which speaks to the previous APIs via
43 worker messages. This one is intended for use in the main
44 thread, with the lower-level APIs installed in a Worker thread,
45 and talking to them via Worker messages. Because Workers are
46 asynchronouns and have only a single message channel, some
47 acrobatics are needed here to feed async work results back to
48 the client (as we cannot simply pass around callbacks between
49 the main and Worker threads).
51 - Insofar as possible, support client-side storage using JS
52 filesystem APIs. As of this writing, such things are still very
53 much under development.
55 Specific non-goals of this project:
57 - As WASM is a web-centric technology and UTF-8 is the King of
58 Encodings in that realm, there are no currently plans to support
59 the UTF16-related sqlite3 APIs. They would add a complication to
60 the bindings for no appreciable benefit. Though web-related
61 implementation details take priority, and the JavaScript
62 components of the API specifically focus on browser clients, the
63 lower-level WASM module "should" work in non-web WASM
64 environments.
66 - Supporting old or niche-market platforms. WASM is built for a
67 modern web and requires modern platforms.
69 - Though scalar User-Defined Functions (UDFs) may be created in
70 JavaScript, there are currently no plans to add support for
71 aggregate and window functions.
73 Attribution:
75 This project is endebted to the work of sql.js:
77 https://github.com/sql-js/sql.js
79 sql.js was an essential stepping stone in this code's development as
80 it demonstrated how to handle some of the WASM-related voodoo (like
81 handling pointers-to-pointers and adding JS implementations of
82 C-bound callback functions). These APIs have a considerably
83 different shape than sql.js's, however.
86 /**
87 sqlite3ApiBootstrap() is the only global symbol persistently
88 exposed by this API. It is intended to be called one time at the
89 end of the API amalgamation process, passed configuration details
90 for the current environment, and then optionally be removed from
91 the global object using `delete self.sqlite3ApiBootstrap`.
93 This function expects a configuration object, intended to abstract
94 away details specific to any given WASM environment, primarily so
95 that it can be used without any _direct_ dependency on
96 Emscripten. (Note the default values for the config object!) The
97 config object is only honored the first time this is
98 called. Subsequent calls ignore the argument and return the same
99 (configured) object which gets initialized by the first call.
100 This function will throw if any of the required config options are
101 missing.
103 The config object properties include:
105 - `exports`[^1]: the "exports" object for the current WASM
106 environment. In an Emscripten-based build, this should be set to
107 `Module['asm']`.
109 - `memory`[^1]: optional WebAssembly.Memory object, defaulting to
110 `exports.memory`. In Emscripten environments this should be set
111 to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be
112 left undefined/falsy to default to `exports.memory` when using
113 WASM-exported memory.
115 - `bigIntEnabled`: true if BigInt support is enabled. Defaults to
116 true if `self.BigInt64Array` is available, else false. Some APIs
117 will throw exceptions if called without BigInt support, as BigInt
118 is required for marshalling C-side int64 into and out of JS.
120 - `allocExportName`: the name of the function, in `exports`, of the
121 `malloc(3)`-compatible routine for the WASM environment. Defaults
122 to `"malloc"`.
124 - `deallocExportName`: the name of the function, in `exports`, of
125 the `free(3)`-compatible routine for the WASM
126 environment. Defaults to `"free"`.
128 - `wasmfsOpfsDir`[^1]: if the environment supports persistent
129 storage, this directory names the "mount point" for that
130 directory. It must be prefixed by `/` and may contain only a
131 single directory-name part. Using the root directory name is not
132 supported by any current persistent backend. This setting is
133 only used in WASMFS-enabled builds.
136 [^1] = This property may optionally be a function, in which case this
137 function re-assigns it to the value returned from that function,
138 enabling delayed evaluation.
141 'use strict';
142 self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
143 apiConfig = (self.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig)
145 if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */
146 console.warn("sqlite3ApiBootstrap() called multiple times.",
147 "Config and external initializers are ignored on calls after the first.");
148 return sqlite3ApiBootstrap.sqlite3;
150 const config = Object.assign(Object.create(null),{
151 exports: undefined,
152 memory: undefined,
153 bigIntEnabled: (()=>{
154 if('undefined'!==typeof Module){
155 /* Emscripten module will contain HEAPU64 when built with
156 -sWASM_BIGINT=1, else it will not. */
157 return !!Module.HEAPU64;
159 return !!self.BigInt64Array;
160 })(),
161 allocExportName: 'malloc',
162 deallocExportName: 'free',
163 wasmfsOpfsDir: '/opfs'
164 }, apiConfig || {});
167 // If any of these config options are functions, replace them with
168 // the result of calling that function...
169 'exports', 'memory', 'wasmfsOpfsDir'
170 ].forEach((k)=>{
171 if('function' === typeof config[k]){
172 config[k] = config[k]();
176 /**
177 The main sqlite3 binding API gets installed into this object,
178 mimicking the C API as closely as we can. The numerous members
179 names with prefixes 'sqlite3_' and 'SQLITE_' behave, insofar as
180 possible, identically to the C-native counterparts, as documented at:
182 https://www.sqlite.org/c3ref/intro.html
184 A very few exceptions require an additional level of proxy
185 function or may otherwise require special attention in the WASM
186 environment, and all such cases are documented somewhere below
187 in this file or in sqlite3-api-glue.js. capi members which are
188 not documented are installed as 1-to-1 proxies for their
189 C-side counterparts.
191 const capi = Object.create(null);
193 Holds state which are specific to the WASM-related
194 infrastructure and glue code. It is not expected that client
195 code will normally need these, but they're exposed here in case
196 it does. These APIs are _not_ to be considered an
197 official/stable part of the sqlite3 WASM API. They may change
198 as the developers' experience suggests appropriate changes.
200 Note that a number of members of this object are injected
201 dynamically after the api object is fully constructed, so
202 not all are documented in this file.
204 const wasm = Object.create(null);
206 /** Internal helper for SQLite3Error ctor. */
207 const __rcStr = (rc)=>{
208 return (capi.sqlite3_js_rc_str && capi.sqlite3_js_rc_str(rc))
209 || ("Unknown result code #"+rc);
212 /** Internal helper for SQLite3Error ctor. */
213 const __isInt = (n)=>'number'===typeof n && n===(n | 0);
216 An Error subclass specifically for reporting DB-level errors and
217 enabling clients to unambiguously identify such exceptions.
218 The C-level APIs never throw, but some of the higher-level
219 C-style APIs do and the object-oriented APIs use exceptions
220 exclusively to report errors.
222 class SQLite3Error extends Error {
224 Constructs this object with a message depending on its arguments:
226 - If it's passed only a single integer argument, it is assumed
227 to be an sqlite3 C API result code. The message becomes the
228 result of sqlite3.capi.sqlite3_js_rc_str() or (if that returns
229 falsy) a synthesized string which contains that integer.
231 - If passed 2 arguments and the 2nd is a object, it bevaves
232 like the Error(string,object) constructor except that the first
233 argument is subject to the is-integer semantics from the
234 previous point.
236 - Else all arguments are concatenated with a space between each
237 one, using args.join(' '), to create the error message.
239 constructor(...args){
240 if(1===args.length && __isInt(args[0])){
241 super(__rcStr(args[0]));
242 }else if(2===args.length && 'object'===typeof args){
243 if(__isInt(args[0])) super(__rcStr(args[0]), args[1]);
244 else super(...args);
245 }else{
246 super(args.join(' '));
248 this.name = 'SQLite3Error';
253 Functionally equivalent to the SQLite3Error constructor but may
254 be used as part of an expression, e.g.:
257 return someFunction(x) || SQLite3Error.toss(...);
260 SQLite3Error.toss = (...args)=>{
261 throw new SQLite3Error(...args);
263 const toss3 = SQLite3Error.toss;
265 if(config.wasmfsOpfsDir && !/^\/[^/]+$/.test(config.wasmfsOpfsDir)){
266 toss3("config.wasmfsOpfsDir must be falsy or in the form '/dir-name'.");
270 Returns true if n is a 32-bit (signed) integer, else
271 false. This is used for determining when we need to switch to
272 double-type DB operations for integer values in order to keep
273 more precision.
275 const isInt32 = (n)=>{
276 return ('bigint'!==typeof n /*TypeError: can't convert BigInt to number*/)
277 && !!(n===(n|0) && n<=2147483647 && n>=-2147483648);
280 Returns true if the given BigInt value is small enough to fit
281 into an int64 value, else false.
283 const bigIntFits64 = function f(b){
284 if(!f._max){
285 f._max = BigInt("0x7fffffffffffffff");
286 f._min = ~f._max;
288 return b >= f._min && b <= f._max;
292 Returns true if the given BigInt value is small enough to fit
293 into an int32, else false.
295 const bigIntFits32 = (b)=>(b >= (-0x7fffffffn - 1n) && b <= 0x7fffffffn);
298 Returns true if the given BigInt value is small enough to fit
299 into a double value without loss of precision, else false.
301 const bigIntFitsDouble = function f(b){
302 if(!f._min){
303 f._min = Number.MIN_SAFE_INTEGER;
304 f._max = Number.MAX_SAFE_INTEGER;
306 return b >= f._min && b <= f._max;
309 /** Returns v if v appears to be a TypedArray, else false. */
310 const isTypedArray = (v)=>{
311 return (v && v.constructor && isInt32(v.constructor.BYTES_PER_ELEMENT)) ? v : false;
315 /** Internal helper to use in operations which need to distinguish
316 between TypedArrays which are backed by a SharedArrayBuffer
317 from those which are not. */
318 const __SAB = ('undefined'===typeof SharedArrayBuffer)
319 ? function(){} : SharedArrayBuffer;
320 /** Returns true if the given TypedArray object is backed by a
321 SharedArrayBuffer, else false. */
322 const isSharedTypedArray = (aTypedArray)=>(aTypedArray.buffer instanceof __SAB);
325 Returns either aTypedArray.slice(begin,end) (if
326 aTypedArray.buffer is a SharedArrayBuffer) or
327 aTypedArray.subarray(begin,end) (if it's not).
329 This distinction is important for APIs which don't like to
330 work on SABs, e.g. TextDecoder, and possibly for our
331 own APIs which work on memory ranges which "might" be
332 modified by other threads while they're working.
334 const typedArrayPart = (aTypedArray, begin, end)=>{
335 return isSharedTypedArray(aTypedArray)
336 ? aTypedArray.slice(begin, end)
337 : aTypedArray.subarray(begin, end);
341 Returns true if v appears to be one of our bind()-able
342 TypedArray types: Uint8Array or Int8Array. Support for
343 TypedArrays with element sizes >1 is TODO.
345 const isBindableTypedArray = (v)=>{
346 return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
350 Returns true if v appears to be one of the TypedArray types
351 which is legal for holding SQL code (as opposed to binary blobs).
353 Currently this is the same as isBindableTypedArray() but it
354 seems likely that we'll eventually want to add Uint32Array
355 and friends to the isBindableTypedArray() list but not to the
356 isSQLableTypedArray() list.
358 const isSQLableTypedArray = (v)=>{
359 return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
362 /** Returns true if isBindableTypedArray(v) does, else throws with a message
363 that v is not a supported TypedArray value. */
364 const affirmBindableTypedArray = (v)=>{
365 return isBindableTypedArray(v)
366 || toss3("Value is not of a supported TypedArray type.");
369 const utf8Decoder = new TextDecoder('utf-8');
372 Uses TextDecoder to decode the given half-open range of the
373 given TypedArray to a string. This differs from a simple
374 call to TextDecoder in that it accounts for whether the
375 first argument is backed by a SharedArrayBuffer or not,
376 and can work more efficiently if it's not (TextDecoder
377 refuses to act upon an SAB).
379 const typedArrayToString = function(typedArray, begin, end){
380 return utf8Decoder.decode(typedArrayPart(typedArray, begin,end));
384 If v is-a Array, its join("") result is returned. If
385 isSQLableTypedArray(v) is true then typedArrayToString(v) is
386 returned. If it looks like a WASM pointer, wasm.cstringToJs(v) is
387 returned. Else v is returned as-is.
389 const flexibleString = function(v){
390 if(isSQLableTypedArray(v)) return typedArrayToString(v);
391 else if(Array.isArray(v)) return v.join("");
392 else if(wasm.isPtr(v)) v = wasm.cstringToJs(v);
393 return v;
397 An Error subclass specifically for reporting Wasm-level malloc()
398 failure and enabling clients to unambiguously identify such
399 exceptions.
401 class WasmAllocError extends Error {
403 If called with 2 arguments and the 2nd one is an object, it
404 behaves like the Error constructor, else it concatenates all
405 arguments together with a single space between each to
406 construct an error message string. As a special case, if
407 called with no arguments then it uses a default error
408 message.
410 constructor(...args){
411 if(2===args.length && 'object'===typeof args){
412 super(...args);
413 }else if(args.length){
414 super(args.join(' '));
415 }else{
416 super("Allocation failed.");
418 this.name = 'WasmAllocError';
422 Functionally equivalent to the WasmAllocError constructor but may
423 be used as part of an expression, e.g.:
426 return someAllocatingFunction(x) || WasmAllocError.toss(...);
429 WasmAllocError.toss = (...args)=>{
430 throw new WasmAllocError(...args);
433 Object.assign(capi, {
435 sqlite3_create_function_v2() differs from its native
436 counterpart only in the following ways:
438 1) The fourth argument (`eTextRep`) argument must not specify
439 any encoding other than sqlite3.SQLITE_UTF8. The JS API does not
440 currently support any other encoding and likely never
441 will. This function does not replace that argument on its own
442 because it may contain other flags.
444 2) Any of the four final arguments may be either WASM pointers
445 (assumed to be function pointers) or JS Functions. In the
446 latter case, each gets bound to WASM using
447 sqlite3.capi.wasm.installFunction() and that wrapper is passed
448 on to the native implementation.
450 The semantics of JS functions are:
452 xFunc: is passed `(pCtx, ...values)`. Its return value becomes
453 the new SQL function's result.
455 xStep: is passed `(pCtx, ...values)`. Its return value is
456 ignored.
458 xFinal: is passed `(pCtx)`. Its return value becomes the new
459 aggregate SQL function's result.
461 xDestroy: is passed `(void*)`. Its return value is ignored. The
462 pointer passed to it is the one from the 5th argument to
463 sqlite3_create_function_v2().
465 Note that:
467 - `pCtx` in the above descriptions is a `sqlite3_context*`. At
468 least 99 times out of a hundred, that initial argument will
469 be irrelevant for JS UDF bindings, but it needs to be there
470 so that the cases where it _is_ relevant, in particular with
471 window and aggregate functions, have full access to the
472 lower-level sqlite3 APIs.
474 - When wrapping JS functions, the remaining arguments are passd
475 to them as positional arguments, not as an array of
476 arguments, because that allows callback definitions to be
477 more JS-idiomatic than C-like. For example `(pCtx,a,b)=>a+b`
478 is more intuitive and legible than
479 `(pCtx,args)=>args[0]+args[1]`. For cases where an array of
480 arguments would be more convenient, the callbacks simply need
481 to be declared like `(pCtx,...args)=>{...}`, in which case
482 `args` will be an array.
484 - If a JS wrapper throws, it gets translated to
485 sqlite3_result_error() or sqlite3_result_error_nomem(),
486 depending on whether the exception is an
487 sqlite3.WasmAllocError object or not.
489 - When passing on WASM function pointers, arguments are _not_
490 converted or reformulated. They are passed on as-is in raw
491 pointer form using their native C signatures. Only JS
492 functions passed in to this routine, and thus wrapped by this
493 routine, get automatic conversions of arguments and result
494 values. The routines which perform those conversions are
495 exposed for client-side use as
496 sqlite3_create_function_v2.convertUdfArgs() and
497 sqlite3_create_function_v2.setUdfResult(). sqlite3_create_function()
498 and sqlite3_create_window_function() have those same methods.
500 For xFunc(), xStep(), and xFinal():
502 - When called from SQL, arguments to the UDF, and its result,
503 will be converted between JS and SQL with as much fidelity as
504 is feasible, triggering an exception if a type conversion
505 cannot be determined. Some freedom is afforded to numeric
506 conversions due to friction between the JS and C worlds:
507 integers which are larger than 32 bits may be treated as
508 doubles or BigInts.
510 If any JS-side bound functions throw, those exceptions are
511 intercepted and converted to database-side errors with the
512 exception of xDestroy(): any exception from it is ignored,
513 possibly generating a console.error() message. Destructors
514 must not throw.
516 Once installed, there is currently no way to uninstall the
517 automatically-converted WASM-bound JS functions from WASM. They
518 can be uninstalled from the database as documented in the C
519 API, but this wrapper currently has no infrastructure in place
520 to also free the WASM-bound JS wrappers, effectively resulting
521 in a memory leak if the client uninstalls the UDF. Improving that
522 is a potential TODO, but removing client-installed UDFs is rare
523 in practice. If this factor is relevant for a given client,
524 they can create WASM-bound JS functions themselves, hold on to their
525 pointers, and pass the pointers in to here. Later on, they can
526 free those pointers (using `wasm.uninstallFunction()` or
527 equivalent).
529 C reference: https://www.sqlite.org/c3ref/create_function.html
531 Maintenance reminder: the ability to add new
532 WASM-accessible functions to the runtime requires that the
533 WASM build is compiled with emcc's `-sALLOW_TABLE_GROWTH`
534 flag.
536 sqlite3_create_function_v2: function(
537 pDb, funcName, nArg, eTextRep, pApp,
538 xFunc, xStep, xFinal, xDestroy
539 ){/*installed later*/},
541 Equivalent to passing the same arguments to
542 sqlite3_create_function_v2(), with 0 as the final argument.
544 sqlite3_create_function:function(
545 pDb, funcName, nArg, eTextRep, pApp,
546 xFunc, xStep, xFinal
547 ){/*installed later*/},
549 The sqlite3_create_window_function() JS wrapper differs from
550 its native implementation in the exact same way that
551 sqlite3_create_function_v2() does. The additional function,
552 xInverse(), is treated identically to xStep() by the wrapping
553 layer.
555 sqlite3_create_window_function: function(
556 pDb, funcName, nArg, eTextRep, pApp,
557 xStep, xFinal, xValue, xInverse, xDestroy
558 ){/*installed later*/},
560 The sqlite3_prepare_v3() binding handles two different uses
561 with differing JS/WASM semantics:
563 1) sqlite3_prepare_v3(pDb, sqlString, -1, prepFlags, ppStmt , null)
565 2) sqlite3_prepare_v3(pDb, sqlPointer, sqlByteLen, prepFlags, ppStmt, sqlPointerToPointer)
567 Note that the SQL length argument (the 3rd argument) must, for
568 usage (1), always be negative because it must be a byte length
569 and that value is expensive to calculate from JS (where only
570 the character length of strings is readily available). It is
571 retained in this API's interface for code/documentation
572 compatibility reasons but is currently _always_ ignored. With
573 usage (2), the 3rd argument is used as-is but is is still
574 critical that the C-style input string (2nd argument) be
575 terminated with a 0 byte.
577 In usage (1), the 2nd argument must be of type string,
578 Uint8Array, or Int8Array (either of which is assumed to
579 hold SQL). If it is, this function assumes case (1) and
580 calls the underyling C function with the equivalent of:
582 (pDb, sqlAsString, -1, prepFlags, ppStmt, null)
584 The `pzTail` argument is ignored in this case because its
585 result is meaningless when a string-type value is passed
586 through: the string goes through another level of internal
587 conversion for WASM's sake and the result pointer would refer
588 to that transient conversion's memory, not the passed-in
589 string.
591 If the sql argument is not a string, it must be a _pointer_ to
592 a NUL-terminated string which was allocated in the WASM memory
593 (e.g. using capi.wasm.alloc() or equivalent). In that case,
594 the final argument may be 0/null/undefined or must be a pointer
595 to which the "tail" of the compiled SQL is written, as
596 documented for the C-side sqlite3_prepare_v3(). In case (2),
597 the underlying C function is called with the equivalent of:
599 (pDb, sqlAsPointer, sqlByteLen, prepFlags, ppStmt, pzTail)
601 It returns its result and compiled statement as documented in
602 the C API. Fetching the output pointers (5th and 6th
603 parameters) requires using `capi.wasm.getMemValue()` (or
604 equivalent) and the `pzTail` will point to an address relative to
605 the `sqlAsPointer` value.
607 If passed an invalid 2nd argument type, this function will
608 return SQLITE_MISUSE and sqlite3_errmsg() will contain a string
609 describing the problem.
611 Side-note: if given an empty string, or one which contains only
612 comments or an empty SQL expression, 0 is returned but the result
613 output pointer will be NULL.
615 sqlite3_prepare_v3: (dbPtr, sql, sqlByteLen, prepFlags,
616 stmtPtrPtr, strPtrPtr)=>{}/*installed later*/,
619 Equivalent to calling sqlite3_prapare_v3() with 0 as its 4th argument.
621 sqlite3_prepare_v2: (dbPtr, sql, sqlByteLen,
622 stmtPtrPtr,strPtrPtr)=>{}/*installed later*/,
625 This binding enables the callback argument to be a JavaScript.
627 If the callback is a function, then for the duration of the
628 sqlite3_exec() call, it installs a WASM-bound function which
629 acts as a proxy for the given callback. That proxy will also
630 perform a conversion of the callback's arguments from
631 `(char**)` to JS arrays of strings. However, for API
632 consistency's sake it will still honor the C-level callback
633 parameter order and will call it like:
635 `callback(pVoid, colCount, listOfValues, listOfColNames)`
637 If the callback is not a JS function then this binding performs
638 no translation of the callback, but the sql argument is still
639 converted to a WASM string for the call using the
640 "flexible-string" argument converter.
642 sqlite3_exec: (pDb, sql, callback, pVoid, pErrMsg)=>{}/*installed later*/,
645 If passed a single argument which appears to be a byte-oriented
646 TypedArray (Int8Array or Uint8Array), this function treats that
647 TypedArray as an output target, fetches `theArray.byteLength`
648 bytes of randomness, and populates the whole array with it. As
649 a special case, if the array's length is 0, this function
650 behaves as if it were passed (0,0). When called this way, it
651 returns its argument, else it returns the `undefined` value.
653 If called with any other arguments, they are passed on as-is
654 to the C API. Results are undefined if passed any incompatible
655 values.
657 sqlite3_randomness: (n, outPtr)=>{/*installed later*/},
658 }/*capi*/);
661 Various internal-use utilities are added here as needed. They
662 are bound to an object only so that we have access to them in
663 the differently-scoped steps of the API bootstrapping
664 process. At the end of the API setup process, this object gets
665 removed. These are NOT part of the public API.
667 const util = {
668 affirmBindableTypedArray, flexibleString,
669 bigIntFits32, bigIntFits64, bigIntFitsDouble,
670 isBindableTypedArray,
671 isInt32, isSQLableTypedArray, isTypedArray,
672 typedArrayToString,
673 isUIThread: ()=>'undefined'===typeof WorkerGlobalScope,
674 isSharedTypedArray,
675 typedArrayPart
678 Object.assign(wasm, {
680 Emscripten APIs have a deep-seated assumption that all pointers
681 are 32 bits. We'll remain optimistic that that won't always be
682 the case and will use this constant in places where we might
683 otherwise use a hard-coded 4.
685 ptrSizeof: config.wasmPtrSizeof || 4,
687 The WASM IR (Intermediate Representation) value for
688 pointer-type values. It MUST refer to a value type of the
689 size described by this.ptrSizeof _or_ it may be any value
690 which ends in '*', which Emscripten's glue code internally
691 translates to i32.
693 ptrIR: config.wasmPtrIR || "i32",
695 True if BigInt support was enabled via (e.g.) the
696 Emscripten -sWASM_BIGINT flag, else false. When
697 enabled, certain 64-bit sqlite3 APIs are enabled which
698 are not otherwise enabled due to JS/WASM int64
699 impedence mismatches.
701 bigIntEnabled: !!config.bigIntEnabled,
703 The symbols exported by the WASM environment.
705 exports: config.exports
706 || toss3("Missing API config.exports (WASM module exports)."),
709 When Emscripten compiles with `-sIMPORT_MEMORY`, it
710 initalizes the heap and imports it into wasm, as opposed to
711 the other way around. In this case, the memory is not
712 available via this.exports.memory.
714 memory: config.memory || config.exports['memory']
715 || toss3("API config object requires a WebAssembly.Memory object",
716 "in either config.exports.memory (exported)",
717 "or config.memory (imported)."),
720 The API's one single point of access to the WASM-side memory
721 allocator. Works like malloc(3) (and is likely bound to
722 malloc()) but throws an WasmAllocError if allocation fails. It is
723 important that any code which might pass through the sqlite3 C
724 API NOT throw and must instead return SQLITE_NOMEM (or
725 equivalent, depending on the context).
727 Very few cases in the sqlite3 JS APIs can result in
728 client-defined functions propagating exceptions via the C-style
729 API. Most notably, this applies to WASM-bound JS functions
730 which are created directly by clients and passed on _as WASM
731 function pointers_ to functions such as
732 sqlite3_create_function_v2(). Such bindings created
733 transparently by this API will automatically use wrappers which
734 catch exceptions and convert them to appropriate error codes.
736 For cases where non-throwing allocation is required, use
737 sqlite3.wasm.alloc.impl(), which is direct binding of the
738 underlying C-level allocator.
740 Design note: this function is not named "malloc" primarily
741 because Emscripten uses that name and we wanted to avoid any
742 confusion early on in this code's development, when it still
743 had close ties to Emscripten's glue code.
745 alloc: undefined/*installed later*/,
748 The API's one single point of access to the WASM-side memory
749 deallocator. Works like free(3) (and is likely bound to
750 free()).
752 Design note: this function is not named "free" for the same
753 reason that this.alloc() is not called this.malloc().
755 dealloc: undefined/*installed later*/
757 /* Many more wasm-related APIs get installed later on. */
758 }/*wasm*/);
761 wasm.alloc()'s srcTypedArray.byteLength bytes,
762 populates them with the values from the source
763 TypedArray, and returns the pointer to that memory. The
764 returned pointer must eventually be passed to
765 wasm.dealloc() to clean it up.
767 As a special case, to avoid further special cases where
768 this is used, if srcTypedArray.byteLength is 0, it
769 allocates a single byte and sets it to the value
770 0. Even in such cases, calls must behave as if the
771 allocated memory has exactly srcTypedArray.byteLength
772 bytes.
774 ACHTUNG: this currently only works for Uint8Array and
775 Int8Array types and will throw if srcTypedArray is of
776 any other type.
778 wasm.allocFromTypedArray = function(srcTypedArray){
779 affirmBindableTypedArray(srcTypedArray);
780 const pRet = wasm.alloc(srcTypedArray.byteLength || 1);
781 wasm.heapForSize(srcTypedArray.constructor).set(
782 srcTypedArray.byteLength ? srcTypedArray : [0], pRet
784 return pRet;
787 const keyAlloc = config.allocExportName || 'malloc',
788 keyDealloc = config.deallocExportName || 'free';
789 for(const key of [keyAlloc, keyDealloc]){
790 const f = wasm.exports[key];
791 if(!(f instanceof Function)) toss3("Missing required exports[",key,"] function.");
794 wasm.alloc = function f(n){
795 const m = f.impl(n);
796 if(!m) throw new WasmAllocError("Failed to allocate",n," bytes.");
797 return m;
799 wasm.alloc.impl = wasm.exports[keyAlloc];
800 wasm.dealloc = wasm.exports[keyDealloc];
803 Reports info about compile-time options using
804 sqlite_compileoption_get() and sqlite3_compileoption_used(). It
805 has several distinct uses:
807 If optName is an array then it is expected to be a list of
808 compilation options and this function returns an object
809 which maps each such option to true or false, indicating
810 whether or not the given option was included in this
811 build. That object is returned.
813 If optName is an object, its keys are expected to be compilation
814 options and this function sets each entry to true or false,
815 indicating whether the compilation option was used or not. That
816 object is returned.
818 If passed no arguments then it returns an object mapping
819 all known compilation options to their compile-time values,
820 or boolean true if they are defined with no value. This
821 result, which is relatively expensive to compute, is cached
822 and returned for future no-argument calls.
824 In all other cases it returns true if the given option was
825 active when when compiling the sqlite3 module, else false.
827 Compile-time option names may optionally include their
828 "SQLITE_" prefix. When it returns an object of all options,
829 the prefix is elided.
831 wasm.compileOptionUsed = function f(optName){
832 if(!arguments.length){
833 if(f._result) return f._result;
834 else if(!f._opt){
835 f._rx = /^([^=]+)=(.+)/;
836 f._rxInt = /^-?\d+$/;
837 f._opt = function(opt, rv){
838 const m = f._rx.exec(opt);
839 rv[0] = (m ? m[1] : opt);
840 rv[1] = m ? (f._rxInt.test(m[2]) ? +m[2] : m[2]) : true;
843 const rc = {}, ov = [0,0];
844 let i = 0, k;
845 while((k = capi.sqlite3_compileoption_get(i++))){
846 f._opt(k,ov);
847 rc[ov[0]] = ov[1];
849 return f._result = rc;
850 }else if(Array.isArray(optName)){
851 const rc = {};
852 optName.forEach((v)=>{
853 rc[v] = capi.sqlite3_compileoption_used(v);
855 return rc;
856 }else if('object' === typeof optName){
857 Object.keys(optName).forEach((k)=> {
858 optName[k] = capi.sqlite3_compileoption_used(k);
860 return optName;
862 return (
863 'string'===typeof optName
864 ) ? !!capi.sqlite3_compileoption_used(optName) : false;
865 }/*compileOptionUsed()*/;
868 Signatures for the WASM-exported C-side functions. Each entry
869 is an array with 2+ elements:
871 [ "c-side name",
872 "result type" (wasm.xWrap() syntax),
873 [arg types in xWrap() syntax]
874 // ^^^ this needn't strictly be an array: it can be subsequent
875 // elements instead: [x,y,z] is equivalent to x,y,z
878 Note that support for the API-specific data types in the
879 result/argument type strings gets plugged in at a later phase in
880 the API initialization process.
882 wasm.bindingSignatures = [
883 // Please keep these sorted by function name!
884 ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
885 ["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*"
886 /* TODO: we should arguably write a custom wrapper which knows
887 how to handle Blob, TypedArrays, and JS strings. */
889 ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
890 ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
891 ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
892 ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
893 ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
894 ["sqlite3_bind_text","int", "sqlite3_stmt*", "int", "string", "int", "int"
895 /* We should arguably create a hand-written binding of
896 bind_text() which does more flexible text conversion, along
897 the lines of sqlite3_prepare_v3(). The slightly problematic
898 part is the final argument (text destructor). */
900 ["sqlite3_close_v2", "int", "sqlite3*"],
901 ["sqlite3_changes", "int", "sqlite3*"],
902 ["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
903 ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
904 ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
905 ["sqlite3_column_count", "int", "sqlite3_stmt*"],
906 ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
907 ["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
908 ["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
909 ["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
910 ["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
911 ["sqlite3_compileoption_get", "string", "int"],
912 ["sqlite3_compileoption_used", "int", "string"],
913 /* sqlite3_create_function(), sqlite3_create_function_v2(), and
914 sqlite3_create_window_function() use hand-written bindings to
915 simplify handling of their function-type arguments. */
916 ["sqlite3_data_count", "int", "sqlite3_stmt*"],
917 ["sqlite3_db_filename", "string", "sqlite3*", "string"],
918 ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
919 ["sqlite3_db_name", "string", "sqlite3*", "int"],
920 ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
921 /* Careful! Short version: de/serialize() are problematic because they
922 might use a different allocator than the user for managing the
923 deserialized block. de/serialize() are ONLY safe to use with
924 sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. */,
925 ["sqlite3_errmsg", "string", "sqlite3*"],
926 ["sqlite3_error_offset", "int", "sqlite3*"],
927 ["sqlite3_errstr", "string", "int"],
928 /*["sqlite3_exec", "int", "sqlite3*", "string", "*", "*", "**"
929 Handled seperately to perform translation of the callback
930 into a WASM-usable one. ],*/
931 ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
932 ["sqlite3_extended_errcode", "int", "sqlite3*"],
933 ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
934 ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
935 ["sqlite3_finalize", "int", "sqlite3_stmt*"],
936 ["sqlite3_free", undefined,"*"],
937 ["sqlite3_initialize", undefined],
938 /*["sqlite3_interrupt", undefined, "sqlite3*"
939 ^^^ we cannot actually currently support this because JS is
940 single-threaded and we don't have a portable way to access a DB
941 from 2 SharedWorkers concurrently. ],*/
942 ["sqlite3_libversion", "string"],
943 ["sqlite3_libversion_number", "int"],
944 ["sqlite3_malloc", "*","int"],
945 ["sqlite3_open", "int", "string", "*"],
946 ["sqlite3_open_v2", "int", "string", "*", "int", "string"],
947 /* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
948 separately due to us requiring two different sets of semantics
949 for those, depending on how their SQL argument is provided. */
950 /* sqlite3_randomness() uses a hand-written wrapper to extend
951 the range of supported argument types. */
952 ["sqlite3_realloc", "*","*","int"],
953 ["sqlite3_reset", "int", "sqlite3_stmt*"],
954 ["sqlite3_result_blob",undefined, "*", "*", "int", "*"],
955 ["sqlite3_result_double",undefined, "*", "f64"],
956 ["sqlite3_result_error",undefined, "*", "string", "int"],
957 ["sqlite3_result_error_code", undefined, "*", "int"],
958 ["sqlite3_result_error_nomem", undefined, "*"],
959 ["sqlite3_result_error_toobig", undefined, "*"],
960 ["sqlite3_result_int",undefined, "*", "int"],
961 ["sqlite3_result_null",undefined, "*"],
962 ["sqlite3_result_text",undefined, "*", "string", "int", "*"],
963 ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
964 ["sqlite3_shutdown", undefined],
965 ["sqlite3_sourceid", "string"],
966 ["sqlite3_sql", "string", "sqlite3_stmt*"],
967 ["sqlite3_step", "int", "sqlite3_stmt*"],
968 ["sqlite3_strglob", "int", "string","string"],
969 ["sqlite3_strlike", "int", "string","string","int"],
970 ["sqlite3_trace_v2", "int", "sqlite3*", "int", "*", "*"],
971 ["sqlite3_total_changes", "int", "sqlite3*"],
972 ["sqlite3_uri_boolean", "int", "string", "string", "int"],
973 ["sqlite3_uri_key", "string", "string", "int"],
974 ["sqlite3_uri_parameter", "string", "string", "string"],
975 ["sqlite3_user_data","void*", "sqlite3_context*"],
976 ["sqlite3_value_blob", "*", "sqlite3_value*"],
977 ["sqlite3_value_bytes","int", "sqlite3_value*"],
978 ["sqlite3_value_double","f64", "sqlite3_value*"],
979 ["sqlite3_value_int","int", "sqlite3_value*"],
980 ["sqlite3_value_text", "string", "sqlite3_value*"],
981 ["sqlite3_value_type", "int", "sqlite3_value*"],
982 ["sqlite3_vfs_find", "*", "string"],
983 ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
984 ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
985 ]/*wasm.bindingSignatures*/;
987 if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
988 /* ^^^ "the problem" is that this is an option feature and the
989 build-time function-export list does not currently take
990 optional features into account. */
991 wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
995 Functions which require BigInt (int64) support are separated from
996 the others because we need to conditionally bind them or apply
997 dummy impls, depending on the capabilities of the environment.
999 wasm.bindingSignatures.int64 = [
1000 ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
1001 ["sqlite3_changes64","i64", ["sqlite3*"]],
1002 ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
1003 ["sqlite3_malloc64", "*","i64"],
1004 ["sqlite3_msize", "i64", "*"],
1005 ["sqlite3_realloc64", "*","*", "i64"],
1006 ["sqlite3_result_int64",undefined, "*", "i64"],
1007 ["sqlite3_total_changes64", "i64", ["sqlite3*"]],
1008 ["sqlite3_uri_int64", "i64", ["string", "string", "i64"]],
1009 ["sqlite3_value_int64","i64", "sqlite3_value*"],
1013 Functions which are intended solely for API-internal use by the
1014 WASM components, not client code. These get installed into
1015 sqlite3.wasm.
1017 wasm.bindingSignatures.wasm = [
1018 ["sqlite3_wasm_db_reset", "int", "sqlite3*"],
1019 ["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
1020 ["sqlite3_wasm_vfs_create_file", "int",
1021 "sqlite3_vfs*","string","*", "int"],
1022 ["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
1027 sqlite3.wasm.pstack (pseudo-stack) holds a special-case
1028 stack-style allocator intended only for use with _small_ data of
1029 not more than (in total) a few kb in size, managed as if it were
1030 stack-based.
1032 It has only a single intended usage:
1035 const stackPos = pstack.pointer;
1036 try{
1037 const ptr = pstack.alloc(8);
1038 // ==> pstack.pointer === ptr
1039 const otherPtr = pstack.alloc(8);
1040 // ==> pstack.pointer === otherPtr
1042 }finally{
1043 pstack.restore(stackPos);
1044 // ==> pstack.pointer === stackPos
1048 This allocator is much faster than a general-purpose one but is
1049 limited to usage patterns like the one shown above.
1051 It operates from a static range of memory which lives outside of
1052 space managed by Emscripten's stack-management, so does not
1053 collide with Emscripten-provided stack allocation APIs. The
1054 memory lives in the WASM heap and can be used with routines such
1055 as wasm.setMemValue() and any wasm.heap8u().slice().
1057 wasm.pstack = Object.assign(Object.create(null),{
1059 Sets the current pstack position to the given pointer. Results
1060 are undefined if the passed-in value did not come from
1061 this.pointer.
1063 restore: wasm.exports.sqlite3_wasm_pstack_restore,
1065 Attempts to allocate the given number of bytes from the
1066 pstack. On success, it zeroes out a block of memory of the
1067 given size, adjusts the pstack pointer, and returns a pointer
1068 to the memory. On error, returns throws a WasmAllocError. The
1069 memory must eventually be released using restore().
1071 This method always adjusts the given value to be a multiple
1072 of 8 bytes because failing to do so can lead to incorrect
1073 results when reading and writing 64-bit values from/to the WASM
1074 heap. Similarly, the returned address is always 8-byte aligned.
1076 alloc: (n)=>{
1077 return wasm.exports.sqlite3_wasm_pstack_alloc(n)
1078 || WasmAllocError.toss("Could not allocate",n,
1079 "bytes from the pstack.");
1082 alloc()'s n chunks, each sz bytes, as a single memory block and
1083 returns the addresses as an array of n element, each holding
1084 the address of one chunk.
1086 Throws a WasmAllocError if allocation fails.
1088 Example:
1091 const [p1, p2, p3] = wasm.pstack.allocChunks(3,4);
1094 allocChunks: (n,sz)=>{
1095 const mem = wasm.pstack.alloc(n * sz);
1096 const rc = [];
1097 let i = 0, offset = 0;
1098 for(; i < n; offset = (sz * ++i)){
1099 rc.push(mem + offset);
1101 return rc;
1104 A convenience wrapper for allocChunks() which sizes each chunk
1105 as either 8 bytes (safePtrSize is truthy) or wasm.ptrSizeof (if
1106 safePtrSize is falsy).
1108 How it returns its result differs depending on its first
1109 argument: if it's 1, it returns a single pointer value. If it's
1110 more than 1, it returns the same as allocChunks().
1112 When a returned pointers will refer to a 64-bit value, e.g. a
1113 double or int64, and that value must be written or fetched,
1114 e.g. using wasm.setMemValue() or wasm.getMemValue(), it is
1115 important that the pointer in question be aligned to an 8-byte
1116 boundary or else it will not be fetched or written properly and
1117 will corrupt or read neighboring memory.
1119 However, when all pointers involved point to "small" data, it
1120 is safe to pass a falsy value to save a tiny bit of memory.
1122 allocPtr: (n=1,safePtrSize=true)=>{
1123 return 1===n
1124 ? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof)
1125 : wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof);
1127 })/*wasm.pstack*/;
1128 Object.defineProperties(wasm.pstack, {
1130 sqlite3.wasm.pstack.pointer resolves to the current pstack
1131 position pointer. This value is intended _only_ to be saved
1132 for passing to restore(). Writing to this memory, without
1133 first reserving it via wasm.pstack.alloc() and friends, leads
1134 to undefined results.
1136 pointer: {
1137 configurable: false, iterable: true, writeable: false,
1138 get: wasm.exports.sqlite3_wasm_pstack_ptr
1139 //Whether or not a setter as an alternative to restore() is
1140 //clearer or would just lead to confusion is unclear.
1141 //set: wasm.exports.sqlite3_wasm_pstack_restore
1144 sqlite3.wasm.pstack.quota to the total number of bytes
1145 available in the pstack, including any space which is currently
1146 allocated. This value is a compile-time constant.
1148 quota: {
1149 configurable: false, iterable: true, writeable: false,
1150 get: wasm.exports.sqlite3_wasm_pstack_quota
1153 sqlite3.wasm.pstack.remaining resolves to the amount of space
1154 remaining in the pstack.
1156 remaining: {
1157 configurable: false, iterable: true, writeable: false,
1158 get: wasm.exports.sqlite3_wasm_pstack_remaining
1160 })/*wasm.pstack properties*/;
1162 capi.sqlite3_randomness = (...args)=>{
1163 if(1===args.length && util.isTypedArray(args[0])
1164 && 1===args[0].BYTES_PER_ELEMENT){
1165 const ta = args[0];
1166 if(0===ta.byteLength){
1167 wasm.exports.sqlite3_randomness(0,0);
1168 return ta;
1170 const stack = wasm.pstack.pointer;
1171 try {
1172 let n = ta.byteLength, offset = 0;
1173 const r = wasm.exports.sqlite3_randomness;
1174 const heap = wasm.heap8u();
1175 const nAlloc = n < 512 ? n : 512;
1176 const ptr = wasm.pstack.alloc(nAlloc);
1178 const j = (n>nAlloc ? nAlloc : n);
1179 r(j, ptr);
1180 ta.set(typedArrayPart(heap, ptr, ptr+j), offset);
1181 n -= j;
1182 offset += j;
1183 } while(n > 0);
1184 }catch(e){
1185 console.error("Highly unexpected (and ignored!) "+
1186 "exception in sqlite3_randomness():",e);
1187 }finally{
1188 wasm.pstack.restore(stack);
1190 return ta;
1192 wasm.exports.sqlite3_randomness(...args);
1195 /** State for sqlite3_wasmfs_opfs_dir(). */
1196 let __wasmfsOpfsDir = undefined;
1198 If the wasm environment has a WASMFS/OPFS-backed persistent
1199 storage directory, its path is returned by this function. If it
1200 does not then it returns "" (noting that "" is a falsy value).
1202 The first time this is called, this function inspects the current
1203 environment to determine whether persistence support is available
1204 and, if it is, enables it (if needed).
1206 This function currently only recognizes the WASMFS/OPFS storage
1207 combination and its path refers to storage rooted in the
1208 Emscripten-managed virtual filesystem.
1210 capi.sqlite3_wasmfs_opfs_dir = function(){
1211 if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir;
1212 // If we have no OPFS, there is no persistent dir
1213 const pdir = config.wasmfsOpfsDir;
1214 if(!pdir
1215 || !self.FileSystemHandle
1216 || !self.FileSystemDirectoryHandle
1217 || !self.FileSystemFileHandle){
1218 return __wasmfsOpfsDir = "";
1220 try{
1221 if(pdir && 0===wasm.xCallWrapped(
1222 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
1224 return __wasmfsOpfsDir = pdir;
1225 }else{
1226 return __wasmfsOpfsDir = "";
1228 }catch(e){
1229 // sqlite3_wasm_init_wasmfs() is not available
1230 return __wasmfsOpfsDir = "";
1235 Experimental and subject to change or removal.
1237 Returns true if sqlite3.capi.sqlite3_wasmfs_opfs_dir() is a
1238 non-empty string and the given name starts with (that string +
1239 '/'), else returns false.
1241 capi.sqlite3_wasmfs_filename_is_persistent = function(name){
1242 const p = capi.sqlite3_wasmfs_opfs_dir();
1243 return (p && name) ? name.startsWith(p+'/') : false;
1246 // This bit is highly arguable and is incompatible with the fiddle shell.
1247 if(false && 0===wasm.exports.sqlite3_vfs_find(0)){
1248 /* Assume that sqlite3_initialize() has not yet been called.
1249 This will be the case in an SQLITE_OS_KV build. */
1250 wasm.exports.sqlite3_initialize();
1254 Given an `sqlite3*`, an sqlite3_vfs name, and an optional db name
1255 (defaulting to "main"), returns a truthy value (see below) if
1256 that db uses that VFS, else returns false. If pDb is falsy then
1257 the 3rd argument is ignored and this function returns a truthy
1258 value if the default VFS name matches that of the 2nd
1259 argument. Results are undefined if pDb is truthy but refers to an
1260 invalid pointer. The 3rd argument specifies the database name of
1261 the given database connection to check, defaulting to the main
1264 The 2nd and 3rd arguments may either be a JS string or a WASM
1265 C-string. If the 2nd argument is a NULL WASM pointer, the default
1266 VFS is assumed. If the 3rd is a NULL WASM pointer, "main" is
1267 assumed.
1269 The truthy value it returns is a pointer to the `sqlite3_vfs`
1270 object.
1272 To permit safe use of this function from APIs which may be called
1273 via the C stack (like SQL UDFs), this function does not throw: if
1274 bad arguments cause a conversion error when passing into
1275 wasm-space, false is returned.
1277 capi.sqlite3_js_db_uses_vfs = function(pDb,vfsName,dbName=0){
1278 try{
1279 const pK = capi.sqlite3_vfs_find(vfsName);
1280 if(!pK) return false;
1281 else if(!pDb){
1282 return pK===capi.sqlite3_vfs_find(0) ? pK : false;
1283 }else{
1284 return pK===capi.sqlite3_js_db_vfs(pDb,dbName) ? pK : false;
1286 }catch(e){
1287 /* Ignore - probably bad args to a wasm-bound function. */
1288 return false;
1293 Returns an array of the names of all currently-registered sqlite3
1294 VFSes.
1296 capi.sqlite3_js_vfs_list = function(){
1297 const rc = [];
1298 let pVfs = capi.sqlite3_vfs_find(0);
1299 while(pVfs){
1300 const oVfs = new capi.sqlite3_vfs(pVfs);
1301 rc.push(wasm.cstringToJs(oVfs.$zName));
1302 pVfs = oVfs.$pNext;
1303 oVfs.dispose();
1305 return rc;
1309 Serializes the given `sqlite3*` pointer to a Uint8Array, as per
1310 sqlite3_serialize(). On success it returns a Uint8Array. On
1311 error it throws with a description of the problem.
1313 capi.sqlite3_js_db_export = function(pDb){
1314 if(!pDb) toss3('Invalid sqlite3* argument.');
1315 if(!wasm.bigIntEnabled) toss3('BigInt64 support is not enabled.');
1316 const stack = wasm.pstack.pointer;
1317 let pOut;
1318 try{
1319 const pSize = wasm.pstack.alloc(8/*i64*/ + wasm.ptrSizeof);
1320 const ppOut = pSize + 8;
1322 Maintenance reminder, since this cost a full hour of grief
1323 and confusion: if the order of pSize/ppOut are reversed in
1324 that memory block, fetching the value of pSize after the
1325 export reads a garbage size because it's not on an 8-byte
1326 memory boundary!
1328 let rc = wasm.exports.sqlite3_wasm_db_serialize(
1329 pDb, ppOut, pSize, 0
1331 if(rc){
1332 toss3("Database serialization failed with code",
1333 sqlite3.capi.sqlite3_js_rc_str(rc));
1335 pOut = wasm.getPtrValue(ppOut);
1336 const nOut = wasm.getMemValue(pSize, 'i64');
1337 rc = nOut
1338 ? wasm.heap8u().slice(pOut, pOut + Number(nOut))
1339 : new Uint8Array();
1340 return rc;
1341 }finally{
1342 if(pOut) wasm.exports.sqlite3_free(pOut);
1343 wasm.pstack.restore(stack);
1348 Given a `sqlite3*` and a database name (JS string or WASM
1349 C-string pointer, which may be 0), returns a pointer to the
1350 sqlite3_vfs responsible for it. If the given db name is null/0,
1351 or not provided, then "main" is assumed.
1353 capi.sqlite3_js_db_vfs =
1354 (dbPointer, dbName=0)=>wasm.sqlite3_wasm_db_vfs(dbPointer, dbName);
1357 A thin wrapper around capi.sqlite3_aggregate_context() which
1358 behaves the same except that it throws a WasmAllocError if that
1359 function returns 0. As a special case, if n is falsy it does
1360 _not_ throw if that function returns 0. That special case is
1361 intended for use with xFinal() implementations.
1363 capi.sqlite3_js_aggregate_context = (pCtx, n)=>{
1364 return capi.sqlite3_aggregate_context(pCtx, n)
1365 || (n ? WasmAllocError.toss("Cannot allocate",n,
1366 "bytes for sqlite3_aggregate_context()")
1367 : 0);
1370 if( util.isUIThread() ){
1371 /* Features specific to the main window thread... */
1374 Internal helper for sqlite3_js_kvvfs_clear() and friends.
1375 Its argument should be one of ('local','session',"").
1377 const __kvvfsInfo = function(which){
1378 const rc = Object.create(null);
1379 rc.prefix = 'kvvfs-'+which;
1380 rc.stores = [];
1381 if('session'===which || ""===which) rc.stores.push(self.sessionStorage);
1382 if('local'===which || ""===which) rc.stores.push(self.localStorage);
1383 return rc;
1387 Clears all storage used by the kvvfs DB backend, deleting any
1388 DB(s) stored there. Its argument must be either 'session',
1389 'local', or "". In the first two cases, only sessionStorage
1390 resp. localStorage is cleared. If it's an empty string (the
1391 default) then both are cleared. Only storage keys which match
1392 the pattern used by kvvfs are cleared: any other client-side
1393 data are retained.
1395 This function is only available in the main window thread.
1397 Returns the number of entries cleared.
1399 capi.sqlite3_js_kvvfs_clear = function(which=""){
1400 let rc = 0;
1401 const kvinfo = __kvvfsInfo(which);
1402 kvinfo.stores.forEach((s)=>{
1403 const toRm = [] /* keys to remove */;
1404 let i;
1405 for( i = 0; i < s.length; ++i ){
1406 const k = s.key(i);
1407 if(k.startsWith(kvinfo.prefix)) toRm.push(k);
1409 toRm.forEach((kk)=>s.removeItem(kk));
1410 rc += toRm.length;
1412 return rc;
1416 This routine guesses the approximate amount of
1417 window.localStorage and/or window.sessionStorage in use by the
1418 kvvfs database backend. Its argument must be one of
1419 ('session', 'local', ""). In the first two cases, only
1420 sessionStorage resp. localStorage is counted. If it's an empty
1421 string (the default) then both are counted. Only storage keys
1422 which match the pattern used by kvvfs are counted. The returned
1423 value is the "length" value of every matching key and value,
1424 noting that JavaScript stores each character in 2 bytes.
1426 Note that the returned size is not authoritative from the
1427 perspective of how much data can fit into localStorage and
1428 sessionStorage, as the precise algorithms for determining
1429 those limits are unspecified and may include per-entry
1430 overhead invisible to clients.
1432 capi.sqlite3_js_kvvfs_size = function(which=""){
1433 let sz = 0;
1434 const kvinfo = __kvvfsInfo(which);
1435 kvinfo.stores.forEach((s)=>{
1436 let i;
1437 for(i = 0; i < s.length; ++i){
1438 const k = s.key(i);
1439 if(k.startsWith(kvinfo.prefix)){
1440 sz += k.length;
1441 sz += s.getItem(k).length;
1445 return sz * 2 /* because JS uses 2-byte char encoding */;
1448 }/* main-window-only bits */
1451 /* The remainder of the API will be set up in later steps. */
1452 const sqlite3 = {
1453 WasmAllocError: WasmAllocError,
1454 SQLite3Error: SQLite3Error,
1455 capi,
1456 util,
1457 wasm,
1458 config,
1460 Holds the version info of the sqlite3 source tree from which
1461 the generated sqlite3-api.js gets built. Note that its version
1462 may well differ from that reported by sqlite3_libversion(), but
1463 that should be considered a source file mismatch, as the JS and
1464 WASM files are intended to be built and distributed together.
1466 This object is initially a placeholder which gets replaced by a
1467 build-generated object.
1469 version: Object.create(null),
1471 Performs any optional asynchronous library-level initialization
1472 which might be required. This function returns a Promise which
1473 resolves to the sqlite3 namespace object. Any error in the
1474 async init will be fatal to the init as a whole, but init
1475 routines are themselves welcome to install dummy catch()
1476 handlers which are not fatal if their failure should be
1477 considered non-fatal. If called more than once, the second and
1478 subsequent calls are no-ops which return a pre-resolved
1479 Promise.
1481 Ideally this function is called as part of the Promise chain
1482 which handles the loading and bootstrapping of the API. If not
1483 then it must be called by client-level code, which must not use
1484 the library until the returned promise resolves.
1486 Bug: if called while a prior call is still resolving, the 2nd
1487 call will resolve prematurely, before the 1st call has finished
1488 resolving. The current build setup precludes that possibility,
1489 so it's only a hypothetical problem if/when this function
1490 ever needs to be invoked by clients.
1492 In Emscripten-based builds, this function is called
1493 automatically and deleted from this object.
1495 asyncPostInit: async function(){
1496 let lip = sqlite3ApiBootstrap.initializersAsync;
1497 delete sqlite3ApiBootstrap.initializersAsync;
1498 if(!lip || !lip.length) return Promise.resolve(sqlite3);
1499 // Is it okay to resolve these in parallel or do we need them
1500 // to resolve in order? We currently only have 1, so it
1501 // makes no difference.
1502 lip = lip.map((f)=>{
1503 const p = (f instanceof Promise) ? f : f(sqlite3);
1504 return p.catch((e)=>{
1505 console.error("an async sqlite3 initializer failed:",e);
1506 throw e;
1509 //let p = lip.shift();
1510 //while(lip.length) p = p.then(lip.shift());
1511 //return p.then(()=>sqlite3);
1512 return Promise.all(lip).then(()=>sqlite3);
1515 scriptInfo ideally gets injected into this object by the
1516 infrastructure which assembles the JS/WASM module. It contains
1517 state which must be collected before sqlite3ApiBootstrap() can
1518 be declared. It is not necessarily available to any
1519 sqlite3ApiBootstrap.initializers but "should" be in place (if
1520 it's added at all) by the time that
1521 sqlite3ApiBootstrap.initializersAsync is processed.
1523 This state is not part of the public API, only intended for use
1524 with the sqlite3 API bootstrapping and wasm-loading process.
1526 scriptInfo: undefined
1528 try{
1529 sqlite3ApiBootstrap.initializers.forEach((f)=>{
1530 f(sqlite3);
1532 }catch(e){
1533 /* If we don't report this here, it can get completely swallowed
1534 up and disappear into the abyss of Promises and Workers. */
1535 console.error("sqlite3 bootstrap initializer threw:",e);
1536 throw e;
1538 delete sqlite3ApiBootstrap.initializers;
1539 sqlite3ApiBootstrap.sqlite3 = sqlite3;
1540 return sqlite3;
1541 }/*sqlite3ApiBootstrap()*/;
1543 self.sqlite3ApiBootstrap.initializers is an internal detail used by
1544 the various pieces of the sqlite3 API's amalgamation process. It
1545 must not be modified by client code except when plugging such code
1546 into the amalgamation process.
1548 Each component of the amalgamation is expected to append a function
1549 to this array. When sqlite3ApiBootstrap() is called for the first
1550 time, each such function will be called (in their appended order)
1551 and passed the sqlite3 namespace object, into which they can install
1552 their features (noting that most will also require that certain
1553 features alread have been installed). At the end of that process,
1554 this array is deleted.
1556 Note that the order of insertion into this array is significant for
1557 some pieces. e.g. sqlite3.capi and sqlite3.wasm cannot be fully
1558 utilized until the whwasmutil.js part is plugged in via
1559 sqlite3-api-glue.js.
1561 self.sqlite3ApiBootstrap.initializers = [];
1563 self.sqlite3ApiBootstrap.initializersAsync is an internal detail
1564 used by the sqlite3 API's amalgamation process. It must not be
1565 modified by client code except when plugging such code into the
1566 amalgamation process.
1568 The counterpart of self.sqlite3ApiBootstrap.initializers,
1569 specifically for initializers which are asynchronous. All entries in
1570 this list must be either async functions, non-async functions which
1571 return a Promise, or a Promise. Each function in the list is called
1572 with the sqlite3 ojbect as its only argument.
1574 The resolved value of any Promise is ignored and rejection will kill
1575 the asyncPostInit() process (at an indeterminate point because all
1576 of them are run asynchronously in parallel).
1578 This list is not processed until the client calls
1579 sqlite3.asyncPostInit(). This means, for example, that intializers
1580 added to self.sqlite3ApiBootstrap.initializers may push entries to
1581 this list.
1583 self.sqlite3ApiBootstrap.initializersAsync = [];
1585 Client code may assign sqlite3ApiBootstrap.defaultConfig an
1586 object-type value before calling sqlite3ApiBootstrap() (without
1587 arguments) in order to tell that call to use this object as its
1588 default config value. The intention of this is to provide
1589 downstream clients with a reasonably flexible approach for plugging in
1590 an environment-suitable configuration without having to define a new
1591 global-scope symbol.
1593 self.sqlite3ApiBootstrap.defaultConfig = Object.create(null);
1595 Placeholder: gets installed by the first call to
1596 self.sqlite3ApiBootstrap(). However, it is recommended that the
1597 caller of sqlite3ApiBootstrap() capture its return value and delete
1598 self.sqlite3ApiBootstrap after calling it. It returns the same
1599 value which will be stored here.
1601 self.sqlite3ApiBootstrap.sqlite3 = undefined;