1/*
2  2022-05-22
3
4  The author disclaims copyright to this source code.  In place of a
5  legal notice, here is a blessing:
6
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.
10
11  ***********************************************************************
12
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.
19
20  Specific goals of this project:
21
22  - Except where noted in the non-goals, provide a more-or-less
23    feature-complete wrapper to the sqlite3 C API, insofar as WASM
24    feature parity with C allows for. In fact, provide at least 3
25    APIs...
26
27    1) Bind a low-level sqlite3 API which is as close to the native
28       one as feasible in terms of usage.
29
30    2) A higher-level API, more akin to sql.js and node.js-style
31       implementations. This one speaks directly to the low-level
32       API. This API must be used from the same thread as the
33       low-level API.
34
35    3) A second higher-level API which speaks to the previous APIs via
36       worker messages. This one is intended for use in the main
37       thread, with the lower-level APIs installed in a Worker thread,
38       and talking to them via Worker messages. Because Workers are
39       asynchronouns and have only a single message channel, some
40       acrobatics are needed here to feed async work results back to
41       the client (as we cannot simply pass around callbacks between
42       the main and Worker threads).
43
44  - Insofar as possible, support client-side storage using JS
45    filesystem APIs. As of this writing, such things are still very
46    much under development.
47
48  Specific non-goals of this project:
49
50  - As WASM is a web-centric technology and UTF-8 is the King of
51    Encodings in that realm, there are no currently plans to support
52    the UTF16-related sqlite3 APIs. They would add a complication to
53    the bindings for no appreciable benefit. Though web-related
54    implementation details take priority, and the JavaScript
55    components of the API specifically focus on browser clients, the
56    lower-level WASM module "should" work in non-web WASM
57    environments.
58
59  - Supporting old or niche-market platforms. WASM is built for a
60    modern web and requires modern platforms.
61
62  - Though scalar User-Defined Functions (UDFs) may be created in
63    JavaScript, there are currently no plans to add support for
64    aggregate and window functions.
65
66  Attribution:
67
68  This project is endebted to the work of sql.js:
69
70  https://github.com/sql-js/sql.js
71
72  sql.js was an essential stepping stone in this code's development as
73  it demonstrated how to handle some of the WASM-related voodoo (like
74  handling pointers-to-pointers and adding JS implementations of
75  C-bound callback functions). These APIs have a considerably
76  different shape than sql.js's, however.
77*/
78
79/**
80   sqlite3ApiBootstrap() is the only global symbol persistently
81   exposed by this API. It is intended to be called one time at the
82   end of the API amalgamation process, passed configuration details
83   for the current environment, and then optionally be removed from
84   the global object using `delete self.sqlite3ApiBootstrap`.
85
86   This function expects a configuration object, intended to abstract
87   away details specific to any given WASM environment, primarily so
88   that it can be used without any _direct_ dependency on
89   Emscripten. (Note the default values for the config object!) The
90   config object is only honored the first time this is
91   called. Subsequent calls ignore the argument and return the same
92   (configured) object which gets initialized by the first call.
93
94   The config object properties include:
95
96   - `exports`[^1]: the "exports" object for the current WASM
97     environment. In an Emscripten build, this should be set to
98     `Module['asm']`.
99
100   - `memory`[^1]: optional WebAssembly.Memory object, defaulting to
101     `exports.memory`. In Emscripten environments this should be set
102     to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be
103     left undefined/falsy to default to `exports.memory` when using
104     WASM-exported memory.
105
106   - `bigIntEnabled`: true if BigInt support is enabled. Defaults to
107     true if self.BigInt64Array is available, else false. Some APIs
108     will throw exceptions if called without BigInt support, as BigInt
109     is required for marshalling C-side int64 into and out of JS.
110
111   - `allocExportName`: the name of the function, in `exports`, of the
112     `malloc(3)`-compatible routine for the WASM environment. Defaults
113     to `"malloc"`.
114
115   - `deallocExportName`: the name of the function, in `exports`, of
116     the `free(3)`-compatible routine for the WASM
117     environment. Defaults to `"free"`.
118
119   - `wasmfsOpfsDir`[^1]: if the environment supports persistent storage, this
120     directory names the "mount point" for that directory. It must be prefixed
121     by `/` and may currently contain only a single directory-name part. Using
122     the root directory name is not supported by any current persistent backend.
123
124
125   [^1] = This property may optionally be a function, in which case this
126          function re-assigns it to the value returned from that function,
127          enabling delayed evaluation.
128
129*/
130'use strict';
131self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
132  apiConfig = (self.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig)
133){
134  if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */
135    console.warn("sqlite3ApiBootstrap() called multiple times.",
136                 "Config and external initializers are ignored on calls after the first.");
137    return sqlite3ApiBootstrap.sqlite3;
138  }
139  apiConfig = apiConfig || {};
140  const config = Object.create(null);
141  {
142    const configDefaults = {
143      exports: undefined,
144      memory: undefined,
145      bigIntEnabled: (()=>{
146        if('undefined'!==typeof Module){
147          /* Emscripten module will contain HEAPU64 when built with
148             -sWASM_BIGINT=1, else it will not. */
149          return !!Module.HEAPU64;
150        }
151        return !!self.BigInt64Array;
152      })(),
153      allocExportName: 'malloc',
154      deallocExportName: 'free',
155      wasmfsOpfsDir: '/opfs'
156    };
157    Object.keys(configDefaults).forEach(function(k){
158      config[k] = Object.getOwnPropertyDescriptor(apiConfig, k)
159        ? apiConfig[k] : configDefaults[k];
160    });
161    // Copy over any properties apiConfig defines but configDefaults does not...
162    Object.keys(apiConfig).forEach(function(k){
163      if(!Object.getOwnPropertyDescriptor(config, k)){
164        config[k] = apiConfig[k];
165      }
166    });
167  }
168
169  [
170    // If any of these config options are functions, replace them with
171    // the result of calling that function...
172    'exports', 'memory', 'wasmfsOpfsDir'
173  ].forEach((k)=>{
174    if('function' === typeof config[k]){
175      config[k] = config[k]();
176    }
177  });
178
179  /** Throws a new Error, the message of which is the concatenation
180      all args with a space between each. */
181  const toss = (...args)=>{throw new Error(args.join(' '))};
182
183  if(config.wasmfsOpfsDir && !/^\/[^/]+$/.test(config.wasmfsOpfsDir)){
184    toss("config.wasmfsOpfsDir must be falsy or in the form '/dir-name'.");
185  }
186
187  /**
188     Returns true if n is a 32-bit (signed) integer, else
189     false. This is used for determining when we need to switch to
190     double-type DB operations for integer values in order to keep
191     more precision.
192  */
193  const isInt32 = function(n){
194    return ('bigint'!==typeof n /*TypeError: can't convert BigInt to number*/)
195      && !!(n===(n|0) && n<=2147483647 && n>=-2147483648);
196  };
197
198  /** Returns v if v appears to be a TypedArray, else false. */
199  const isTypedArray = (v)=>{
200    return (v && v.constructor && isInt32(v.constructor.BYTES_PER_ELEMENT)) ? v : false;
201  };
202
203  /**
204     Returns true if v appears to be one of our bind()-able
205     TypedArray types: Uint8Array or Int8Array. Support for
206     TypedArrays with element sizes >1 is TODO.
207  */
208  const isBindableTypedArray = (v)=>{
209    return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
210  };
211
212  /**
213     Returns true if v appears to be one of the TypedArray types
214     which is legal for holding SQL code (as opposed to binary blobs).
215
216     Currently this is the same as isBindableTypedArray() but it
217     seems likely that we'll eventually want to add Uint32Array
218     and friends to the isBindableTypedArray() list but not to the
219     isSQLableTypedArray() list.
220  */
221  const isSQLableTypedArray = (v)=>{
222    return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
223  };
224
225  /** Returns true if isBindableTypedArray(v) does, else throws with a message
226      that v is not a supported TypedArray value. */
227  const affirmBindableTypedArray = (v)=>{
228    return isBindableTypedArray(v)
229      || toss("Value is not of a supported TypedArray type.");
230  };
231
232  const utf8Decoder = new TextDecoder('utf-8');
233
234  /** Internal helper to use in operations which need to distinguish
235      between SharedArrayBuffer heap memory and non-shared heap. */
236  const __SAB = ('undefined'===typeof SharedArrayBuffer)
237        ? function(){} : SharedArrayBuffer;
238  const typedArrayToString = function(arrayBuffer, begin, end){
239    return utf8Decoder.decode(
240      (arrayBuffer.buffer instanceof __SAB)
241        ? arrayBuffer.slice(begin, end)
242        : arrayBuffer.subarray(begin, end)
243    );
244  };
245
246  /**
247     If v is-a Array, its join('') result is returned.  If
248     isSQLableTypedArray(v) then typedArrayToString(v) is
249     returned. Else v is returned as-is.
250  */
251  const arrayToString = function(v){
252    if(isSQLableTypedArray(v)) return typedArrayToString(v);
253    else if(Array.isArray(v)) return v.join('');
254    return v;
255  };
256
257  /**
258     An Error subclass specifically for reporting Wasm-level malloc()
259     failure and enabling clients to unambiguously identify such
260     exceptions.
261  */
262  class WasmAllocError extends Error {
263    constructor(...args){
264      super(...args);
265      this.name = 'WasmAllocError';
266    }
267  };
268  WasmAllocError.toss = (...args)=>{
269    throw new WasmAllocError(args.join(' '));
270  };
271
272  /**
273      The main sqlite3 binding API gets installed into this object,
274      mimicking the C API as closely as we can. The numerous members
275      names with prefixes 'sqlite3_' and 'SQLITE_' behave, insofar as
276      possible, identically to the C-native counterparts, as documented at:
277
278      https://www.sqlite.org/c3ref/intro.html
279
280      A very few exceptions require an additional level of proxy
281      function or may otherwise require special attention in the WASM
282      environment, and all such cases are document here. Those not
283      documented here are installed as 1-to-1 proxies for their C-side
284      counterparts.
285  */
286  const capi = {
287    /**
288       When using sqlite3_open_v2() it is important to keep the following
289       in mind:
290
291       https://www.sqlite.org/c3ref/open.html
292
293       - The flags for use with its 3rd argument are installed in this
294       object using their C-side names, e.g. SQLITE_OPEN_CREATE.
295
296       - If the combination of flags passed to it are invalid,
297       behavior is undefined. Thus is is never okay to call this
298       with fewer than 3 arguments, as JS will default the
299       missing arguments to `undefined`, which will result in a
300       flag value of 0. Most of the available SQLITE_OPEN_xxx
301       flags are meaningless in the WASM build, e.g. the mutext-
302       and cache-related flags, but they are retained in this
303       API for consistency's sake.
304
305       - The final argument to this function specifies the VFS to use,
306       which is largely (but not entirely!) meaningless in the WASM
307       environment. It may be null, undefined, or 0 to denote the
308       default.
309    */
310    sqlite3_open_v2: function(filename,dbPtrPtr,flags,vfsStr){}/*installed later*/,
311    /**
312       The sqlite3_prepare_v3() binding handles two different uses
313       with differing JS/WASM semantics:
314
315       1) sqlite3_prepare_v3(pDb, sqlString, -1, prepFlags, ppStmt , null)
316
317       2) sqlite3_prepare_v3(pDb, sqlPointer, sqlByteLen, prepFlags, ppStmt, sqlPointerToPointer)
318
319       Note that the SQL length argument (the 3rd argument) must, for
320       usage (1), always be negative because it must be a byte length
321       and that value is expensive to calculate from JS (where only
322       the character length of strings is readily available). It is
323       retained in this API's interface for code/documentation
324       compatibility reasons but is currently _always_ ignored. With
325       usage (2), the 3rd argument is used as-is but is is still
326       critical that the C-style input string (2nd argument) be
327       terminated with a 0 byte.
328
329       In usage (1), the 2nd argument must be of type string,
330       Uint8Array, or Int8Array (either of which is assumed to
331       hold SQL). If it is, this function assumes case (1) and
332       calls the underyling C function with the equivalent of:
333
334       (pDb, sqlAsString, -1, prepFlags, ppStmt, null)
335
336       The `pzTail` argument is ignored in this case because its
337       result is meaningless when a string-type value is passed
338       through: the string goes through another level of internal
339       conversion for WASM's sake and the result pointer would refer
340       to that transient conversion's memory, not the passed-in
341       string.
342
343       If the sql argument is not a string, it must be a _pointer_ to
344       a NUL-terminated string which was allocated in the WASM memory
345       (e.g. using capi.wasm.alloc() or equivalent). In that case,
346       the final argument may be 0/null/undefined or must be a pointer
347       to which the "tail" of the compiled SQL is written, as
348       documented for the C-side sqlite3_prepare_v3(). In case (2),
349       the underlying C function is called with the equivalent of:
350
351       (pDb, sqlAsPointer, sqlByteLen, prepFlags, ppStmt, pzTail)
352
353       It returns its result and compiled statement as documented in
354       the C API. Fetching the output pointers (5th and 6th
355       parameters) requires using `capi.wasm.getMemValue()` (or
356       equivalent) and the `pzTail` will point to an address relative to
357       the `sqlAsPointer` value.
358
359       If passed an invalid 2nd argument type, this function will
360       return SQLITE_MISUSE and sqlite3_errmsg() will contain a string
361       describing the problem.
362
363       Side-note: if given an empty string, or one which contains only
364       comments or an empty SQL expression, 0 is returned but the result
365       output pointer will be NULL.
366    */
367    sqlite3_prepare_v3: (dbPtr, sql, sqlByteLen, prepFlags,
368                         stmtPtrPtr, strPtrPtr)=>{}/*installed later*/,
369
370    /**
371       Equivalent to calling sqlite3_prapare_v3() with 0 as its 4th argument.
372    */
373    sqlite3_prepare_v2: (dbPtr, sql, sqlByteLen,
374                         stmtPtrPtr,strPtrPtr)=>{}/*installed later*/,
375
376    /**
377       This binding enables the callback argument to be a JavaScript.
378
379       If the callback is a function, then for the duration of the
380       sqlite3_exec() call, it installs a WASM-bound function which
381       acts as a proxy for the given callback. That proxy will
382       also perform a conversion of the callback's arguments from
383       `(char**)` to JS arrays of strings. However, for API
384       consistency's sake it will still honor the C-level
385       callback parameter order and will call it like:
386
387       `callback(pVoid, colCount, listOfValues, listOfColNames)`
388
389       If the callback is not a JS function then this binding performs
390       no translation of the callback, but the sql argument is still
391       converted to a WASM string for the call using the
392       "flexible-string" argument converter.
393    */
394    sqlite3_exec: (pDb, sql, callback, pVoid, pErrMsg)=>{}/*installed later*/,
395    /**
396       Various internal-use utilities are added here as needed. They
397       are bound to an object only so that we have access to them in
398       the differently-scoped steps of the API bootstrapping
399       process. At the end of the API setup process, this object gets
400       removed.
401    */
402    util:{
403      affirmBindableTypedArray, arrayToString, isBindableTypedArray,
404      isInt32, isSQLableTypedArray, isTypedArray,
405      typedArrayToString,
406      isMainWindow: ()=>{
407        return self.window===self && self.document;
408      }
409    },
410
411    /**
412       Holds state which are specific to the WASM-related
413       infrastructure and glue code. It is not expected that client
414       code will normally need these, but they're exposed here in case
415       it does. These APIs are _not_ to be considered an
416       official/stable part of the sqlite3 WASM API. They may change
417       as the developers' experience suggests appropriate changes.
418
419       Note that a number of members of this object are injected
420       dynamically after the api object is fully constructed, so
421       not all are documented inline here.
422    */
423    wasm: {
424    //^^^ TODO?: move wasm from sqlite3.capi.wasm to sqlite3.wasm
425      /**
426         Emscripten APIs have a deep-seated assumption that all pointers
427         are 32 bits. We'll remain optimistic that that won't always be
428         the case and will use this constant in places where we might
429         otherwise use a hard-coded 4.
430      */
431      ptrSizeof: config.wasmPtrSizeof || 4,
432      /**
433         The WASM IR (Intermediate Representation) value for
434         pointer-type values. It MUST refer to a value type of the
435         size described by this.ptrSizeof _or_ it may be any value
436         which ends in '*', which Emscripten's glue code internally
437         translates to i32.
438      */
439      ptrIR: config.wasmPtrIR || "i32",
440      /**
441         True if BigInt support was enabled via (e.g.) the
442         Emscripten -sWASM_BIGINT flag, else false. When
443         enabled, certain 64-bit sqlite3 APIs are enabled which
444         are not otherwise enabled due to JS/WASM int64
445         impedence mismatches.
446      */
447      bigIntEnabled: !!config.bigIntEnabled,
448      /**
449         The symbols exported by the WASM environment.
450      */
451      exports: config.exports
452        || toss("Missing API config.exports (WASM module exports)."),
453
454      /**
455         When Emscripten compiles with `-sIMPORT_MEMORY`, it
456         initalizes the heap and imports it into wasm, as opposed to
457         the other way around. In this case, the memory is not
458         available via this.exports.memory.
459      */
460      memory: config.memory || config.exports['memory']
461        || toss("API config object requires a WebAssembly.Memory object",
462                "in either config.exports.memory (exported)",
463                "or config.memory (imported)."),
464
465      /**
466         The API's one single point of access to the WASM-side memory
467         allocator. Works like malloc(3) (and is likely bound to
468         malloc()) but throws an WasmAllocError if allocation fails. It is
469         important that any code which might pass through the sqlite3 C
470         API NOT throw and must instead return SQLITE_NOMEM (or
471         equivalent, depending on the context).
472
473         That said, very few cases in the API can result in
474         client-defined functions propagating exceptions via the C-style
475         API. Most notably, this applies ot User-defined SQL Functions
476         (UDFs) registered via sqlite3_create_function_v2(). For that
477         specific case it is recommended that all UDF creation be
478         funneled through a utility function and that a wrapper function
479         be added around the UDF which catches any exception and sets
480         the error state to OOM. (The overall complexity of registering
481         UDFs essentially requires a helper for doing so!)
482      */
483      alloc: undefined/*installed later*/,
484      /**
485         The API's one single point of access to the WASM-side memory
486         deallocator. Works like free(3) (and is likely bound to
487         free()).
488      */
489      dealloc: undefined/*installed later*/
490
491      /* Many more wasm-related APIs get installed later on. */
492    }/*wasm*/
493  }/*capi*/;
494
495  /**
496     capi.wasm.alloc()'s srcTypedArray.byteLength bytes,
497     populates them with the values from the source
498     TypedArray, and returns the pointer to that memory. The
499     returned pointer must eventually be passed to
500     capi.wasm.dealloc() to clean it up.
501
502     As a special case, to avoid further special cases where
503     this is used, if srcTypedArray.byteLength is 0, it
504     allocates a single byte and sets it to the value
505     0. Even in such cases, calls must behave as if the
506     allocated memory has exactly srcTypedArray.byteLength
507     bytes.
508
509     ACHTUNG: this currently only works for Uint8Array and
510     Int8Array types and will throw if srcTypedArray is of
511     any other type.
512  */
513  capi.wasm.allocFromTypedArray = function(srcTypedArray){
514    affirmBindableTypedArray(srcTypedArray);
515    const pRet = this.alloc(srcTypedArray.byteLength || 1);
516    this.heapForSize(srcTypedArray.constructor).set(srcTypedArray.byteLength ? srcTypedArray : [0], pRet);
517    return pRet;
518  }.bind(capi.wasm);
519
520  const keyAlloc = config.allocExportName || 'malloc',
521        keyDealloc =  config.deallocExportName || 'free';
522  for(const key of [keyAlloc, keyDealloc]){
523    const f = capi.wasm.exports[key];
524    if(!(f instanceof Function)) toss("Missing required exports[",key,"] function.");
525  }
526
527  capi.wasm.alloc = function(n){
528    const m = this.exports[keyAlloc](n);
529    if(!m) throw new WasmAllocError("Failed to allocate "+n+" bytes.");
530    return m;
531  }.bind(capi.wasm)
532
533  capi.wasm.dealloc = (m)=>capi.wasm.exports[keyDealloc](m);
534
535  /**
536     Reports info about compile-time options using
537     sqlite_compileoption_get() and sqlite3_compileoption_used(). It
538     has several distinct uses:
539
540     If optName is an array then it is expected to be a list of
541     compilation options and this function returns an object
542     which maps each such option to true or false, indicating
543     whether or not the given option was included in this
544     build. That object is returned.
545
546     If optName is an object, its keys are expected to be compilation
547     options and this function sets each entry to true or false,
548     indicating whether the compilation option was used or not. That
549     object is returned.
550
551     If passed no arguments then it returns an object mapping
552     all known compilation options to their compile-time values,
553     or boolean true if they are defined with no value. This
554     result, which is relatively expensive to compute, is cached
555     and returned for future no-argument calls.
556
557     In all other cases it returns true if the given option was
558     active when when compiling the sqlite3 module, else false.
559
560     Compile-time option names may optionally include their
561     "SQLITE_" prefix. When it returns an object of all options,
562     the prefix is elided.
563  */
564  capi.wasm.compileOptionUsed = function f(optName){
565    if(!arguments.length){
566      if(f._result) return f._result;
567      else if(!f._opt){
568        f._rx = /^([^=]+)=(.+)/;
569        f._rxInt = /^-?\d+$/;
570        f._opt = function(opt, rv){
571          const m = f._rx.exec(opt);
572          rv[0] = (m ? m[1] : opt);
573          rv[1] = m ? (f._rxInt.test(m[2]) ? +m[2] : m[2]) : true;
574        };
575      }
576      const rc = {}, ov = [0,0];
577      let i = 0, k;
578      while((k = capi.sqlite3_compileoption_get(i++))){
579        f._opt(k,ov);
580        rc[ov[0]] = ov[1];
581      }
582      return f._result = rc;
583    }else if(Array.isArray(optName)){
584      const rc = {};
585      optName.forEach((v)=>{
586        rc[v] = capi.sqlite3_compileoption_used(v);
587      });
588      return rc;
589    }else if('object' === typeof optName){
590      Object.keys(optName).forEach((k)=> {
591        optName[k] = capi.sqlite3_compileoption_used(k);
592      });
593      return optName;
594    }
595    return (
596      'string'===typeof optName
597    ) ? !!capi.sqlite3_compileoption_used(optName) : false;
598  }/*compileOptionUsed()*/;
599
600  /**
601     Signatures for the WASM-exported C-side functions. Each entry
602     is an array with 2+ elements:
603
604     [ "c-side name",
605       "result type" (capi.wasm.xWrap() syntax),
606       [arg types in xWrap() syntax]
607       // ^^^ this needn't strictly be an array: it can be subsequent
608       // elements instead: [x,y,z] is equivalent to x,y,z
609     ]
610
611     Note that support for the API-specific data types in the
612     result/argument type strings gets plugged in at a later phase in
613     the API initialization process.
614  */
615  capi.wasm.bindingSignatures = [
616    // Please keep these sorted by function name!
617    ["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*"
618     /* We should arguably write a custom wrapper which knows how
619        to handle Blob, TypedArrays, and JS strings. */
620    ],
621    ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
622    ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
623    ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
624    ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
625    ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
626    ["sqlite3_bind_text","int", "sqlite3_stmt*", "int", "string", "int", "int"
627     /* We should arguably create a hand-written binding
628        which does more flexible text conversion, along the lines of
629        sqlite3_prepare_v3(). The slightly problematic part is the
630        final argument (text destructor). */
631    ],
632    ["sqlite3_close_v2", "int", "sqlite3*"],
633    ["sqlite3_changes", "int", "sqlite3*"],
634    ["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
635    ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
636    ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
637    ["sqlite3_column_count", "int", "sqlite3_stmt*"],
638    ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
639    ["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
640    ["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
641    ["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
642    ["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
643    ["sqlite3_compileoption_get", "string", "int"],
644    ["sqlite3_compileoption_used", "int", "string"],
645    ["sqlite3_create_function_v2", "int",
646     "sqlite3*", "string", "int", "int", "*", "*", "*", "*", "*"],
647    ["sqlite3_data_count", "int", "sqlite3_stmt*"],
648    ["sqlite3_db_filename", "string", "sqlite3*", "string"],
649    ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
650    ["sqlite3_db_name", "string", "sqlite3*", "int"],
651    ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
652    /* Careful! Short version: de/serialize() are problematic because they
653       might use a different allocator that the user for managing the
654       deserialized block. de/serialize() are ONLY safe to use with
655       sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. */,
656    ["sqlite3_errmsg", "string", "sqlite3*"],
657    ["sqlite3_error_offset", "int", "sqlite3*"],
658    ["sqlite3_errstr", "string", "int"],
659    /*["sqlite3_exec", "int", "sqlite3*", "string", "*", "*", "**"
660      Handled seperately to perform translation of the callback
661      into a WASM-usable one. ],*/
662    ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
663    ["sqlite3_extended_errcode", "int", "sqlite3*"],
664    ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
665    ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
666    ["sqlite3_finalize", "int", "sqlite3_stmt*"],
667    ["sqlite3_free", undefined,"*"],
668    ["sqlite3_initialize", undefined],
669    ["sqlite3_interrupt", undefined, "sqlite3*"
670     /* ^^^ we cannot actually currently support this because JS is
671        single-threaded and we don't have a portable way to access a DB
672        from 2 SharedWorkers concurrently. */],
673    ["sqlite3_libversion", "string"],
674    ["sqlite3_libversion_number", "int"],
675    ["sqlite3_malloc", "*","int"],
676    ["sqlite3_open", "int", "string", "*"],
677    ["sqlite3_open_v2", "int", "string", "*", "int", "string"],
678    /* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
679       separately due to us requiring two different sets of semantics
680       for those, depending on how their SQL argument is provided. */
681    ["sqlite3_realloc", "*","*","int"],
682    ["sqlite3_reset", "int", "sqlite3_stmt*"],
683    ["sqlite3_result_blob",undefined, "*", "*", "int", "*"],
684    ["sqlite3_result_double",undefined, "*", "f64"],
685    ["sqlite3_result_error",undefined, "*", "string", "int"],
686    ["sqlite3_result_error_code", undefined, "*", "int"],
687    ["sqlite3_result_error_nomem", undefined, "*"],
688    ["sqlite3_result_error_toobig", undefined, "*"],
689    ["sqlite3_result_int",undefined, "*", "int"],
690    ["sqlite3_result_null",undefined, "*"],
691    ["sqlite3_result_text",undefined, "*", "string", "int", "*"],
692    ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
693    ["sqlite3_shutdown", undefined],
694    ["sqlite3_sourceid", "string"],
695    ["sqlite3_sql", "string", "sqlite3_stmt*"],
696    ["sqlite3_step", "int", "sqlite3_stmt*"],
697    ["sqlite3_strglob", "int", "string","string"],
698    ["sqlite3_strlike", "int", "string","string","int"],
699    ["sqlite3_total_changes", "int", "sqlite3*"],
700    ["sqlite3_uri_boolean", "int", "string", "string", "int"],
701    ["sqlite3_uri_key", "string", "string", "int"],
702    ["sqlite3_uri_parameter", "string", "string", "string"],
703    ["sqlite3_value_blob", "*", "*"],
704    ["sqlite3_value_bytes","int", "*"],
705    ["sqlite3_value_double","f64", "*"],
706    ["sqlite3_value_text", "string", "*"],
707    ["sqlite3_value_type", "int", "*"],
708    ["sqlite3_vfs_find", "*", "string"],
709    ["sqlite3_vfs_register", "int", "*", "int"]
710  ]/*capi.wasm.bindingSignatures*/;
711
712  if(false && capi.wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
713    /* ^^^ "the problem" is that this is an option feature and the
714       build-time function-export list does not currently take
715       optional features into account. */
716    capi.wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
717  }
718
719  /**
720     Functions which require BigInt (int64) support are separated from
721     the others because we need to conditionally bind them or apply
722     dummy impls, depending on the capabilities of the environment.
723  */
724  capi.wasm.bindingSignatures.int64 = [
725    ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
726    ["sqlite3_changes64","i64", ["sqlite3*"]],
727    ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
728    ["sqlite3_malloc64", "*","i64"],
729    ["sqlite3_msize", "i64", "*"],
730    ["sqlite3_realloc64", "*","*", "i64"],
731    ["sqlite3_total_changes64", "i64", ["sqlite3*"]],
732    ["sqlite3_uri_int64", "i64", ["string", "string", "i64"]]
733  ];
734
735  /**
736     Functions which are intended solely for API-internal use by the
737     WASM components, not client code. These get installed into
738     capi.wasm.
739
740     TODO: get rid of sqlite3_wasm_vfs_unlink(). It is ill-conceived
741     and only rarely actually useful.
742  */
743  capi.wasm.bindingSignatures.wasm = [
744    ["sqlite3_wasm_vfs_unlink", "int", "string"]
745  ];
746
747
748  /**
749     sqlite3.capi.wasm.pstack (pseudo-stack) holds a special-case
750     stack-style allocator intended only for use with _small_ data of
751     not more than (in total) a few kb in size, managed as if it were
752     stack-based.
753
754     It has only a single intended usage:
755
756     ```
757     const stackPos = pstack.pointer;
758     try{
759       const ptr = pstack.alloc(8);
760       // ==> pstack.pointer === ptr
761       const otherPtr = pstack.alloc(8);
762       // ==> pstack.pointer === otherPtr
763       ...
764     }finally{
765       pstack.restore(stackPos);
766       // ==> pstack.pointer === stackPos
767     }
768     ```
769
770     This allocator is much faster than a general-purpose one but is
771     limited to usage patterns like the one shown above.
772
773     It operates from a static range of memory which lives outside of
774     space managed by Emscripten's stack-management, so does not
775     collide with Emscripten-provided stack allocation APIs. The
776     memory lives in the WASM heap and can be used with routines such
777     as wasm.setMemValue() and any wasm.heap8u().slice().
778  */
779  capi.wasm.pstack = Object.assign(Object.create(null),{
780    /**
781       Sets the current ppstack position to the given pointer.
782       Results are undefined if the passed-in value did not come from
783       this.pointer.
784    */
785    restore: capi.wasm.exports.sqlite3_wasm_pstack_restore,
786    /**
787       Attempts to allocate the given number of bytes from the
788       pstack. On success, it zeroes out a block of memory of the
789       given size, adjusts the pstack pointer, and returns a pointer
790       to the memory. On error, returns throws a WasmAllocError. The
791       memory must eventually be released using restore().
792
793       This method always adjusts the given value to be a multiple
794       of 8 bytes because failing to do so can lead to incorrect
795       results when reading and writing 64-bit values from/to the WASM
796       heap.
797    */
798    alloc: (n)=>{
799      return capi.wasm.exports.sqlite3_wasm_pstack_alloc(n)
800        || WasmAllocError.toss("Could not allocate",n,
801                               "bytes from the pstack.");
802    }
803    // More methods get added after the capi.wasm object is populated
804    // by WhWasmUtilInstaller.
805  });
806  /**
807     sqlite3.capi.wasm.pstack.pointer resolves to the current pstack
808     position pointer. This value is intended _only_ to be passed to restore().
809  */
810  Object.defineProperty(capi.wasm.pstack, 'pointer', {
811    configurable: false, iterable: true, writeable: false,
812    get: capi.wasm.exports.sqlite3_wasm_pstack_ptr
813    //Whether or not a setter as an alternative to restore() is
814    //clearer or would just lead to confusion is unclear.
815    //set: capi.wasm.exports.sqlite3_wasm_pstack_restore
816  });
817  /**
818     sqlite3.capi.wasm.pstack.remaining resolves to the amount of
819     space remaining in the pstack.
820  */
821  Object.defineProperty(capi.wasm.pstack, 'remaining', {
822    configurable: false, iterable: true, writeable: false,
823    get: capi.wasm.exports.sqlite3_wasm_pstack_remaining
824  });
825
826  /**
827     An Error subclass specifically for reporting DB-level errors and
828     enabling clients to unambiguously identify such exceptions.
829     The C-level APIs never throw, but some of the higher-level
830     C-style APIs do and the object-oriented APIs use exceptions
831     exclusively to report errors.
832  */
833  class SQLite3Error extends Error {
834    /**
835       Constructs this object with a message equal to all arguments
836       concatenated with a space between each one.
837    */
838    constructor(...args){
839      super(args.join(' '));
840      this.name = 'SQLite3Error';
841    }
842  };
843  SQLite3Error.toss = (...args)=>{
844    throw new SQLite3Error(args.join(' '));
845  };
846
847  /** State for sqlite3_wasmfs_opfs_dir(). */
848  let __persistentDir = undefined;
849  /**
850     If the wasm environment has a WASMFS/OPFS-backed persistent
851     storage directory, its path is returned by this function. If it
852     does not then it returns "" (noting that "" is a falsy value).
853
854     The first time this is called, this function inspects the current
855     environment to determine whether persistence support is available
856     and, if it is, enables it (if needed).
857
858     This function currently only recognizes the WASMFS/OPFS storage
859     combination and its path refers to storage rooted in the
860     Emscripten-managed virtual filesystem.
861  */
862  capi.sqlite3_wasmfs_opfs_dir = function(){
863    if(undefined !== __persistentDir) return __persistentDir;
864    // If we have no OPFS, there is no persistent dir
865    const pdir = config.wasmfsOpfsDir;
866    if(!pdir
867       || !self.FileSystemHandle
868       || !self.FileSystemDirectoryHandle
869       || !self.FileSystemFileHandle){
870      return __persistentDir = "";
871    }
872    try{
873      if(pdir && 0===capi.wasm.xCallWrapped(
874        'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
875      )){
876        return __persistentDir = pdir;
877      }else{
878        return __persistentDir = "";
879      }
880    }catch(e){
881      // sqlite3_wasm_init_wasmfs() is not available
882      return __persistentDir = "";
883    }
884  };
885
886  /**
887     Experimental and subject to change or removal.
888
889     Returns true if sqlite3.capi.sqlite3_wasmfs_opfs_dir() is a
890     non-empty string and the given name starts with (that string +
891     '/'), else returns false.
892
893     Potential (but arguable) TODO: return true if the name is one of
894     (":localStorage:", "local", ":sessionStorage:", "session") and
895     kvvfs is available.
896  */
897  capi.sqlite3_web_filename_is_persistent = function(name){
898    const p = capi.sqlite3_wasmfs_opfs_dir();
899    return (p && name) ? name.startsWith(p+'/') : false;
900  };
901
902  // This bit is highly arguable and is incompatible with the fiddle shell.
903  if(false && 0===capi.wasm.exports.sqlite3_vfs_find(0)){
904    /* Assume that sqlite3_initialize() has not yet been called.
905       This will be the case in an SQLITE_OS_KV build. */
906    capi.wasm.exports.sqlite3_initialize();
907  }
908
909  /**
910     Given an `sqlite3*`, an sqlite3_vfs name, and an optional db
911     name, returns a truthy value (see below) if that db handle uses
912     that VFS, else returns false. If pDb is falsy then the 3rd
913     argument is ignored and this function returns a truthy value if
914     the default VFS name matches that of the 2nd argument. Results
915     are undefined if pDb is truthy but refers to an invalid
916     pointer. The 3rd argument specifies the database name of the
917     given database connection to check, defaulting to the main db.
918
919     The 2nd and 3rd arguments may either be a JS string or a C-string
920     allocated from the wasm environment.
921
922     The truthy value it returns is a pointer to the `sqlite3_vfs`
923     object.
924
925     To permit safe use of this function from APIs which may be called
926     via the C stack (like SQL UDFs), this function does not throw: if
927     bad arguments cause a conversion error when passing into
928     wasm-space, false is returned.
929  */
930  capi.sqlite3_web_db_uses_vfs = function(pDb,vfsName,dbName="main"){
931    try{
932      const pK = capi.sqlite3_vfs_find(vfsName);
933      if(!pK) return false;
934      else if(!pDb){
935        return capi.sqlite3_vfs_find(0)===pK ? pK : false;
936      }
937      const ppVfs = capi.wasm.allocPtr();
938      try{
939        return (
940          (0===capi.sqlite3_file_control(
941            pDb, dbName, capi.SQLITE_FCNTL_VFS_POINTER, ppVfs
942          )) && (capi.wasm.getPtrValue(ppVfs) === pK)
943        ) ? pK : false;
944      }finally{
945        capi.wasm.dealloc(ppVfs);
946      }
947    }catch(e){
948      /* Ignore - probably bad args to a wasm-bound function. */
949      return false;
950    }
951  };
952
953  /**
954     Returns an array of the names of all currently-registered sqlite3
955     VFSes.
956  */
957  capi.sqlite3_web_vfs_list = function(){
958    const rc = [];
959    let pVfs = capi.sqlite3_vfs_find(0);
960    while(pVfs){
961      const oVfs = new capi.sqlite3_vfs(pVfs);
962      rc.push(capi.wasm.cstringToJs(oVfs.$zName));
963      pVfs = oVfs.$pNext;
964      oVfs.dispose();
965    }
966    return rc;
967  };
968
969  /**
970     Serializes the given `sqlite3*` pointer to a Uint8Array, as per
971     sqlite3_serialize(). On success it returns a Uint8Array. On
972     error it throws with a description of the problem.
973  */
974  capi.sqlite3_web_db_export = function(pDb){
975    if(!pDb) toss('Invalid sqlite3* argument.');
976    const wasm = capi.wasm;
977    if(!wasm.bigIntEnabled) toss('BigInt64 support is not enabled.');
978    const stack = wasm.pstack.pointer;
979    let pOut;
980    try{
981      const pSize = wasm.pstack.alloc(8/*i64*/ + wasm.ptrSizeof);
982      const ppOut = pSize + 8;
983      /**
984         Maintenance reminder, since this cost a full hour of grief
985         and confusion: if the order of pSize/ppOut are reversed in
986         that memory block, fetching the value of pSize after the
987         export reads a garbage size because it's not on an 8-byte
988         memory boundary!
989      */
990      let rc = wasm.exports.sqlite3_wasm_db_serialize(
991        pDb, ppOut, pSize, 0
992      );
993      if(rc){
994        toss("Database serialization failed with code",
995             sqlite3.capi.sqlite3_web_rc_str(rc));
996      }
997      pOut = wasm.getPtrValue(ppOut);
998      const nOut = wasm.getMemValue(pSize, 'i64');
999      rc = nOut
1000        ? wasm.heap8u().slice(pOut, pOut + Number(nOut))
1001        : new Uint8Array();
1002      return rc;
1003    }catch(e){
1004      console.error('internal error?',e);
1005      throw w;
1006    }finally{
1007      if(pOut) wasm.exports.sqlite3_free(pOut);
1008      wasm.pstack.restore(stack);
1009    }
1010  };
1011
1012  if( capi.util.isMainWindow() ){
1013    /* Features specific to the main window thread... */
1014
1015    /**
1016       Internal helper for sqlite3_web_kvvfs_clear() and friends.
1017       Its argument should be one of ('local','session','').
1018    */
1019    const __kvvfsInfo = function(which){
1020      const rc = Object.create(null);
1021      rc.prefix = 'kvvfs-'+which;
1022      rc.stores = [];
1023      if('session'===which || ''===which) rc.stores.push(self.sessionStorage);
1024      if('local'===which || ''===which) rc.stores.push(self.localStorage);
1025      return rc;
1026    };
1027
1028    /**
1029       Clears all storage used by the kvvfs DB backend, deleting any
1030       DB(s) stored there. Its argument must be either 'session',
1031       'local', or ''. In the first two cases, only sessionStorage
1032       resp. localStorage is cleared. If it's an empty string (the
1033       default) then both are cleared. Only storage keys which match
1034       the pattern used by kvvfs are cleared: any other client-side
1035       data are retained.
1036
1037       This function is only available in the main window thread.
1038
1039       Returns the number of entries cleared.
1040    */
1041    capi.sqlite3_web_kvvfs_clear = function(which=''){
1042      let rc = 0;
1043      const kvinfo = __kvvfsInfo(which);
1044      kvinfo.stores.forEach((s)=>{
1045        const toRm = [] /* keys to remove */;
1046        let i;
1047        for( i = 0; i < s.length; ++i ){
1048          const k = s.key(i);
1049          if(k.startsWith(kvinfo.prefix)) toRm.push(k);
1050        }
1051        toRm.forEach((kk)=>s.removeItem(kk));
1052        rc += toRm.length;
1053      });
1054      return rc;
1055    };
1056
1057    /**
1058       This routine guesses the approximate amount of
1059       window.localStorage and/or window.sessionStorage in use by the
1060       kvvfs database backend. Its argument must be one of
1061       ('session', 'local', ''). In the first two cases, only
1062       sessionStorage resp. localStorage is counted. If it's an empty
1063       string (the default) then both are counted. Only storage keys
1064       which match the pattern used by kvvfs are counted. The returned
1065       value is the "length" value of every matching key and value,
1066       noting that JavaScript stores each character in 2 bytes.
1067
1068       Note that the returned size is not authoritative from the
1069       perspective of how much data can fit into localStorage and
1070       sessionStorage, as the precise algorithms for determining
1071       those limits are unspecified and may include per-entry
1072       overhead invisible to clients.
1073    */
1074    capi.sqlite3_web_kvvfs_size = function(which=''){
1075      let sz = 0;
1076      const kvinfo = __kvvfsInfo(which);
1077      kvinfo.stores.forEach((s)=>{
1078        let i;
1079        for(i = 0; i < s.length; ++i){
1080          const k = s.key(i);
1081          if(k.startsWith(kvinfo.prefix)){
1082            sz += k.length;
1083            sz += s.getItem(k).length;
1084          }
1085        }
1086      });
1087      return sz * 2 /* because JS uses 2-byte char encoding */;
1088    };
1089
1090  }/* main-window-only bits */
1091
1092
1093  /* The remainder of the API will be set up in later steps. */
1094  const sqlite3 = {
1095    WasmAllocError: WasmAllocError,
1096    SQLite3Error: SQLite3Error,
1097    capi,
1098    config,
1099    /**
1100       Performs any optional asynchronous library-level initialization
1101       which might be required. This function returns a Promise which
1102       resolves to the sqlite3 namespace object. It _ignores any
1103       errors_ in the asynchronous init process, as such components
1104       are all optional. If called more than once, the second and
1105       subsequent calls are no-ops which return a pre-resolved
1106       Promise.
1107
1108       Ideally this function is called as part of the Promise chain
1109       which handles the loading and bootstrapping of the API.  If not
1110       then it must be called by client-level code, which must not use
1111       the library until the returned promise resolves.
1112
1113       Bug: if called while a prior call is still resolving, the 2nd
1114       call will resolve prematurely, before the 1st call has finished
1115       resolving. The current build setup precludes that possibility,
1116       so it's only a hypothetical problem if/when this function
1117       ever needs to be invoked by clients.
1118
1119       In Emscripten-based builds, this function is called
1120       automatically and deleted from this object.
1121    */
1122    asyncPostInit: async function(){
1123      let lip = sqlite3ApiBootstrap.initializersAsync;
1124      delete sqlite3ApiBootstrap.initializersAsync;
1125      if(!lip || !lip.length) return Promise.resolve(sqlite3);
1126      // Is it okay to resolve these in parallel or do we need them
1127      // to resolve in order? We currently only have 1, so it
1128      // makes no difference.
1129      lip = lip.map((f)=>f(sqlite3).catch(()=>{}));
1130      //let p = lip.shift();
1131      //while(lip.length) p = p.then(lip.shift());
1132      //return p.then(()=>sqlite3);
1133      return Promise.all(lip).then(()=>sqlite3);
1134    }
1135  };
1136  sqlite3ApiBootstrap.initializers.forEach((f)=>f(sqlite3));
1137  delete sqlite3ApiBootstrap.initializers;
1138  sqlite3ApiBootstrap.sqlite3 = sqlite3;
1139  return sqlite3;
1140}/*sqlite3ApiBootstrap()*/;
1141/**
1142  self.sqlite3ApiBootstrap.initializers is an internal detail used by
1143  the various pieces of the sqlite3 API's amalgamation process. It
1144  must not be modified by client code except when plugging such code
1145  into the amalgamation process.
1146
1147  Each component of the amalgamation is expected to append a function
1148  to this array. When sqlite3ApiBootstrap() is called for the first
1149  time, each such function will be called (in their appended order)
1150  and passed the sqlite3 namespace object, into which they can install
1151  their features (noting that most will also require that certain
1152  features alread have been installed).  At the end of that process,
1153  this array is deleted.
1154
1155  Note that the order of insertion into this array is significant for
1156  some pieces. e.g. sqlite3.capi.wasm cannot be fully utilized until
1157  the whwasmutil.js part is plugged in.
1158*/
1159self.sqlite3ApiBootstrap.initializers = [];
1160/**
1161  self.sqlite3ApiBootstrap.initializersAsync is an internal detail
1162  used by the sqlite3 API's amalgamation process. It must not be
1163  modified by client code except when plugging such code into the
1164  amalgamation process.
1165
1166  Counterpart of self.sqlite3ApiBootstrap.initializers, specifically
1167  for initializers which are asynchronous. All functions in this list
1168  take the sqlite3 object as their argument and MUST return a
1169  Promise. Both the resolved value and rejection cases are ignored.
1170
1171  This list is not processed until the client calls
1172  sqlite3.asyncPostInit(). This means, for example, that intializers
1173  added to self.sqlite3ApiBootstrap.initializers may push entries to
1174   this list.
1175*/
1176self.sqlite3ApiBootstrap.initializersAsync = [];
1177/**
1178   Client code may assign sqlite3ApiBootstrap.defaultConfig an
1179   object-type value before calling sqlite3ApiBootstrap() (without
1180   arguments) in order to tell that call to use this object as its
1181   default config value. The intention of this is to provide
1182   downstream clients with a reasonably flexible approach for plugging in
1183   an environment-suitable configuration without having to define a new
1184   global-scope symbol.
1185*/
1186self.sqlite3ApiBootstrap.defaultConfig = Object.create(null);
1187/**
1188   Placeholder: gets installed by the first call to
1189   self.sqlite3ApiBootstrap(). However, it is recommended that the
1190   caller of sqlite3ApiBootstrap() capture its return value and delete
1191   self.sqlite3ApiBootstrap after calling it. It returns the same
1192   value which will be stored here.
1193*/
1194self.sqlite3ApiBootstrap.sqlite3 = undefined;
1195