Fixes default log output to console for macOS
[sqlcipher.git] / ext / wasm / api / sqlite3-api-glue.js
blob83b2ee1721aeb4ac20bd925f22b865d5c0a27b76
1 /*
2   2022-07-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 glues together disparate pieces of JS which are loaded in
14   previous steps of the sqlite3-api.js bootstrapping process:
15   sqlite3-api-prologue.js, whwasmutil.js, and jaccwabyt.js. It
16   initializes the main API pieces so that the downstream components
17   (e.g. sqlite3-api-oo1.js) have all of the infrastructure that they
18   need.
20 globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
21   'use strict';
22   const toss = (...args)=>{throw new Error(args.join(' '))};
23   const toss3 = sqlite3.SQLite3Error.toss;
24   const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util;
25   globalThis.WhWasmUtilInstaller(wasm);
26   delete globalThis.WhWasmUtilInstaller;
28   if(0){
29     /**
30        Please keep this block around as a maintenance reminder
31        that we cannot rely on this type of check.
33        This block fails on Safari, per a report at
34        https://sqlite.org/forum/forumpost/e5b20e1feb.
36        It turns out that what Safari serves from the indirect function
37        table (e.g. wasm.functionEntry(X)) is anonymous functions which
38        wrap the WASM functions, rather than returning the WASM
39        functions themselves. That means comparison of such functions
40        is useless for determining whether or not we have a specific
41        function from wasm.exports. i.e. if function X is indirection
42        function table entry N then wasm.exports.X is not equal to
43        wasm.functionEntry(N) in Safari, despite being so in the other
44        browsers.
45     */
46     /**
47        Find a mapping for SQLITE_WASM_DEALLOC, which the API
48        guarantees is a WASM pointer to the same underlying function as
49        wasm.dealloc() (noting that wasm.dealloc() is permitted to be a
50        JS wrapper around the WASM function). There is unfortunately no
51        O(1) algorithm for finding this pointer: we have to walk the
52        WASM indirect function table to find it. However, experience
53        indicates that that particular function is always very close to
54        the front of the table (it's been entry #3 in all relevant
55        tests).
56     */
57     const dealloc = wasm.exports[sqlite3.config.deallocExportName];
58     const nFunc = wasm.functionTable().length;
59     let i;
60     for(i = 0; i < nFunc; ++i){
61       const e = wasm.functionEntry(i);
62       if(dealloc === e){
63         capi.SQLITE_WASM_DEALLOC = i;
64         break;
65       }
66     }
67     if(dealloc !== wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){
68       toss("Internal error: cannot find function pointer for SQLITE_WASM_DEALLOC.");
69     }
70   }
72   /**
73      Signatures for the WASM-exported C-side functions. Each entry
74      is an array with 2+ elements:
76      [ "c-side name",
77        "result type" (wasm.xWrap() syntax),
78        [arg types in xWrap() syntax]
79        // ^^^ this needn't strictly be an array: it can be subsequent
80        // elements instead: [x,y,z] is equivalent to x,y,z
81      ]
83      Note that support for the API-specific data types in the
84      result/argument type strings gets plugged in at a later phase in
85      the API initialization process.
86   */
87   wasm.bindingSignatures = [
88     // Please keep these sorted by function name!
89     ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
90     /* sqlite3_auto_extension() has a hand-written binding. */
91     /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written
92        bindings to permit more flexible inputs. */
93     ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
94     ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
95     ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
96     ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
97     ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
98     ["sqlite3_bind_pointer", "int",
99      "sqlite3_stmt*", "int", "*", "string:static", "*"],
100     ["sqlite3_busy_handler","int", [
101       "sqlite3*",
102       new wasm.xWrap.FuncPtrAdapter({
103         signature: 'i(pi)',
104         contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
105       }),
106       "*"
107     ]],
108     ["sqlite3_busy_timeout","int", "sqlite3*", "int"],
109     /* sqlite3_cancel_auto_extension() has a hand-written binding. */
110     /* sqlite3_close_v2() is implemented by hand to perform some
111        extra work. */
112     ["sqlite3_changes", "int", "sqlite3*"],
113     ["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
114     ["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
115     ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
116     ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
117     ["sqlite3_column_count", "int", "sqlite3_stmt*"],
118     ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
119     ["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
120     ["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
121     ["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
122     ["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
123     ["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
124     ["sqlite3_commit_hook", "void*", [
125       "sqlite3*",
126       new wasm.xWrap.FuncPtrAdapter({
127         name: 'sqlite3_commit_hook',
128         signature: 'i(p)',
129         contextKey: (argv)=>argv[0/* sqlite3* */]
130       }),
131       '*'
132     ]],
133     ["sqlite3_compileoption_get", "string", "int"],
134     ["sqlite3_compileoption_used", "int", "string"],
135     ["sqlite3_complete", "int", "string:flexible"],
136     ["sqlite3_context_db_handle", "sqlite3*", "sqlite3_context*"],
138     /* sqlite3_create_function(), sqlite3_create_function_v2(), and
139        sqlite3_create_window_function() use hand-written bindings to
140        simplify handling of their function-type arguments. */
141     /* sqlite3_create_collation() and sqlite3_create_collation_v2()
142        use hand-written bindings to simplify passing of the callback
143        function.
144       ["sqlite3_create_collation", "int",
145      "sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
146      "*", "*"],
147     ["sqlite3_create_collation_v2", "int",
148      "sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
149      "*", "*", "*"],
150     */
151     ["sqlite3_data_count", "int", "sqlite3_stmt*"],
152     ["sqlite3_db_filename", "string", "sqlite3*", "string"],
153     ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
154     ["sqlite3_db_name", "string", "sqlite3*", "int"],
155     ["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"],
156     ["sqlite3_errcode", "int", "sqlite3*"],
157     ["sqlite3_errmsg", "string", "sqlite3*"],
158     ["sqlite3_error_offset", "int", "sqlite3*"],
159     ["sqlite3_errstr", "string", "int"],
160     ["sqlite3_exec", "int", [
161       "sqlite3*", "string:flexible",
162       new wasm.xWrap.FuncPtrAdapter({
163         signature: 'i(pipp)',
164         bindScope: 'transient',
165         callProxy: (callback)=>{
166           let aNames;
167           return (pVoid, nCols, pColVals, pColNames)=>{
168             try {
169               const aVals = wasm.cArgvToJs(nCols, pColVals);
170               if(!aNames) aNames = wasm.cArgvToJs(nCols, pColNames);
171               return callback(aVals, aNames) | 0;
172             }catch(e){
173               /* If we set the db error state here, the higher-level
174                  exec() call replaces it with its own, so we have no way
175                  of reporting the exception message except the console. We
176                  must not propagate exceptions through the C API. Though
177                  we make an effort to report OOM here, sqlite3_exec()
178                  translates that into SQLITE_ABORT as well. */
179               return e.resultCode || capi.SQLITE_ERROR;
180             }
181           }
182         }
183       }),
184       "*", "**"
185     ]],
186     ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
187     ["sqlite3_extended_errcode", "int", "sqlite3*"],
188     ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
189     ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
190     ["sqlite3_finalize", "int", "sqlite3_stmt*"],
191     ["sqlite3_free", undefined,"*"],
192     ["sqlite3_get_autocommit", "int", "sqlite3*"],
193     ["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
194     ["sqlite3_initialize", undefined],
195     /*["sqlite3_interrupt", undefined, "sqlite3*"
196        ^^^ we cannot actually currently support this because JS is
197         single-threaded and we don't have a portable way to access a DB
198         from 2 SharedWorkers concurrently. ],*/
199     ["sqlite3_keyword_count", "int"],
200     ["sqlite3_keyword_name", "int", ["int", "**", "*"]],
201     ["sqlite3_keyword_check", "int", ["string", "int"]],
202     ["sqlite3_libversion", "string"],
203     ["sqlite3_libversion_number", "int"],
204     ["sqlite3_limit", "int", ["sqlite3*", "int", "int"]],
205     ["sqlite3_malloc", "*","int"],
206     ["sqlite3_open", "int", "string", "*"],
207     ["sqlite3_open_v2", "int", "string", "*", "int", "string"],
208     /* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
209        separately due to us requiring two different sets of semantics
210        for those, depending on how their SQL argument is provided. */
211     /* sqlite3_randomness() uses a hand-written wrapper to extend
212        the range of supported argument types. */
213     ["sqlite3_progress_handler", undefined, [
214       "sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
215         name: 'xProgressHandler',
216         signature: 'i(p)',
217         bindScope: 'context',
218         contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
219       }), "*"
220     ]],
221     ["sqlite3_realloc", "*","*","int"],
222     ["sqlite3_reset", "int", "sqlite3_stmt*"],
223     /* sqlite3_reset_auto_extension() has a hand-written binding. */
224     ["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
225     ["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
226     ["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
227     ["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"],
228     ["sqlite3_result_error_nomem", undefined, "sqlite3_context*"],
229     ["sqlite3_result_error_toobig", undefined, "sqlite3_context*"],
230     ["sqlite3_result_int", undefined, "sqlite3_context*", "int"],
231     ["sqlite3_result_null", undefined, "sqlite3_context*"],
232     ["sqlite3_result_pointer", undefined,
233      "sqlite3_context*", "*", "string:static", "*"],
234     ["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
235     ["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
236     ["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
237     ["sqlite3_rollback_hook", "void*", [
238       "sqlite3*",
239       new wasm.xWrap.FuncPtrAdapter({
240         name: 'sqlite3_rollback_hook',
241         signature: 'v(p)',
242         contextKey: (argv)=>argv[0/* sqlite3* */]
243       }),
244       '*'
245     ]],
246     ["sqlite3_set_authorizer", "int", [
247       "sqlite3*",
248       new wasm.xWrap.FuncPtrAdapter({
249         name: "sqlite3_set_authorizer::xAuth",
250         signature: "i(pi"+"ssss)",
251         contextKey: (argv, argIndex)=>argv[0/*(sqlite3*)*/],
252         callProxy: (callback)=>{
253           return (pV, iCode, s0, s1, s2, s3)=>{
254             try{
255               s0 = s0 && wasm.cstrToJs(s0); s1 = s1 && wasm.cstrToJs(s1);
256               s2 = s2 && wasm.cstrToJs(s2); s3 = s3 && wasm.cstrToJs(s3);
257               return callback(pV, iCode, s0, s1, s2, s3) || 0;
258             }catch(e){
259               return e.resultCode || capi.SQLITE_ERROR;
260             }
261           }
262         }
263       }),
264       "*"/*pUserData*/
265     ]],
266     ["sqlite3_set_auxdata", undefined, [
267       "sqlite3_context*", "int", "*",
268       new wasm.xWrap.FuncPtrAdapter({
269         name: 'xDestroyAuxData',
270         signature: 'v(*)',
271         contextKey: (argv, argIndex)=>argv[0/* sqlite3_context* */]
272       })
273     ]],
274     ["sqlite3_shutdown", undefined],
275     ["sqlite3_sourceid", "string"],
276     ["sqlite3_sql", "string", "sqlite3_stmt*"],
277     ["sqlite3_status", "int", "int", "*", "*", "int"],
278     ["sqlite3_step", "int", "sqlite3_stmt*"],
279     ["sqlite3_stmt_isexplain", "int", ["sqlite3_stmt*"]],
280     ["sqlite3_stmt_readonly", "int", ["sqlite3_stmt*"]],
281     ["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"],
282     ["sqlite3_strglob", "int", "string","string"],
283     ["sqlite3_stricmp", "int", "string", "string"],
284     ["sqlite3_strlike", "int", "string", "string","int"],
285     ["sqlite3_strnicmp", "int", "string", "string", "int"],
286     ["sqlite3_table_column_metadata", "int",
287      "sqlite3*", "string", "string", "string",
288      "**", "**", "*", "*", "*"],
289     ["sqlite3_total_changes", "int", "sqlite3*"],
290     ["sqlite3_trace_v2", "int", [
291       "sqlite3*", "int",
292       new wasm.xWrap.FuncPtrAdapter({
293         name: 'sqlite3_trace_v2::callback',
294         signature: 'i(ippp)',
295         contextKey: (argv,argIndex)=>argv[0/* sqlite3* */]
296       }),
297       "*"
298     ]],
299     ["sqlite3_txn_state", "int", ["sqlite3*","string"]],
300     /* Note that sqlite3_uri_...() have very specific requirements for
301        their first C-string arguments, so we cannot perform any value
302        conversion on those. */
303     ["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
304     ["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
305     ["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
306     ["sqlite3_user_data","void*", "sqlite3_context*"],
307     ["sqlite3_value_blob", "*", "sqlite3_value*"],
308     ["sqlite3_value_bytes","int", "sqlite3_value*"],
309     ["sqlite3_value_double","f64", "sqlite3_value*"],
310     ["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"],
311     ["sqlite3_value_free", undefined, "sqlite3_value*"],
312     ["sqlite3_value_frombind", "int", "sqlite3_value*"],
313     ["sqlite3_value_int","int", "sqlite3_value*"],
314     ["sqlite3_value_nochange", "int", "sqlite3_value*"],
315     ["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
316     ["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
317     ["sqlite3_value_subtype", "int", "sqlite3_value*"],
318     ["sqlite3_value_text", "string", "sqlite3_value*"],
319     ["sqlite3_value_type", "int", "sqlite3_value*"],
320     ["sqlite3_vfs_find", "*", "string"],
321     ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
322     ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
323   ]/*wasm.bindingSignatures*/;
325   if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
326     /* ^^^ "the problem" is that this is an option feature and the
327        build-time function-export list does not currently take
328        optional features into account. */
329     wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
330   }
332 //#if enable-see
333   if(wasm.exports.sqlite3_key_v2 instanceof Function){
334     /**
335        This code is capable of using an SEE build but note that an SEE
336        WASM build is generally incompatible with SEE's license
337        conditions. It is permitted for use internally in organizations
338        which have licensed SEE, but not for public sites because
339        exposing an SEE build of sqlite3.wasm effectively provides all
340        clients with a working copy of the commercial SEE code.
341     */
342     wasm.bindingSignatures.push(
343       ["sqlite3_key", "int", "sqlite3*", "string", "int"],
344       ["sqlite3_key_v2","int","sqlite3*","string","*","int"],
345       ["sqlite3_rekey", "int", "sqlite3*", "string", "int"],
346       ["sqlite3_rekey_v2", "int", "sqlite3*", "string", "*", "int"],
347       ["sqlite3_activate_see", undefined, "string"]
348     );
349   }
350 //#endif enable-see
352   /**
353      Functions which require BigInt (int64) support are separated from
354      the others because we need to conditionally bind them or apply
355      dummy impls, depending on the capabilities of the environment.
356      (That said: we never actually build without BigInt support,
357      and such builds are untested.)
359      Note that not all of these functions directly require int64
360      but are only for use with APIs which require int64. For example,
361      the vtab-related functions.
362   */
363   wasm.bindingSignatures.int64 = [
364     ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
365     ["sqlite3_changes64","i64", ["sqlite3*"]],
366     ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
367     ["sqlite3_create_module", "int",
368      ["sqlite3*","string","sqlite3_module*","*"]],
369     ["sqlite3_create_module_v2", "int",
370      ["sqlite3*","string","sqlite3_module*","*","*"]],
371     ["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
372     ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
373     /* Careful! Short version: de/serialize() are problematic because they
374        might use a different allocator than the user for managing the
375        deserialized block. de/serialize() are ONLY safe to use with
376        sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. Because
377        of this, the canonical builds of sqlite3.wasm/js guarantee that
378        sqlite3.wasm.alloc() and friends use those allocators. Custom builds
379        may not guarantee that, however. */,
380     ["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
381     ["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
382     ["sqlite3_malloc64", "*","i64"],
383     ["sqlite3_msize", "i64", "*"],
384     ["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
385     ["sqlite3_preupdate_blobwrite", "int", "sqlite3*"],
386     ["sqlite3_preupdate_count", "int", "sqlite3*"],
387     ["sqlite3_preupdate_depth", "int", "sqlite3*"],
388     ["sqlite3_preupdate_hook", "*", [
389       "sqlite3*",
390       new wasm.xWrap.FuncPtrAdapter({
391         name: 'sqlite3_preupdate_hook',
392         signature: "v(ppippjj)",
393         contextKey: (argv)=>argv[0/* sqlite3* */],
394         callProxy: (callback)=>{
395           return (p,db,op,zDb,zTbl,iKey1,iKey2)=>{
396             callback(p, db, op, wasm.cstrToJs(zDb), wasm.cstrToJs(zTbl),
397                      iKey1, iKey2);
398           };
399         }
400       }),
401       "*"
402     ]],
403     ["sqlite3_preupdate_new", "int", ["sqlite3*", "int", "**"]],
404     ["sqlite3_preupdate_old", "int", ["sqlite3*", "int", "**"]],
405     ["sqlite3_realloc64", "*","*", "i64"],
406     ["sqlite3_result_int64", undefined, "*", "i64"],
407     ["sqlite3_result_zeroblob64", "int", "*", "i64"],
408     ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
409     ["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
410     ["sqlite3_status64", "int", "int", "*", "*", "int"],
411     ["sqlite3_total_changes64", "i64", ["sqlite3*"]],
412     ["sqlite3_update_hook", "*", [
413       "sqlite3*",
414       new wasm.xWrap.FuncPtrAdapter({
415         name: 'sqlite3_update_hook',
416         signature: "v(iippj)",
417         contextKey: (argv)=>argv[0/* sqlite3* */],
418         callProxy: (callback)=>{
419           return (p,op,z0,z1,rowid)=>{
420             callback(p, op, wasm.cstrToJs(z0), wasm.cstrToJs(z1), rowid);
421           };
422         }
423       }),
424       "*"
425     ]],
426     ["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
427     ["sqlite3_value_int64","i64", "sqlite3_value*"],
428     ["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
429     ["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
430     ["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
431     ["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"],
432     ["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"],
433     /*["sqlite3_vtab_config" is variadic and requires a hand-written
434       proxy.] */
435     ["sqlite3_vtab_nochange","int", "sqlite3_context*"],
436     ["sqlite3_vtab_on_conflict","int", "sqlite3*"],
437     ["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
438   ];
440   // Add session/changeset APIs...
441   if(wasm.bigIntEnabled && !!wasm.exports.sqlite3changegroup_add){
442     /**
443        FuncPtrAdapter options for session-related callbacks with the
444        native signature "i(ps)". This proxy converts the 2nd argument
445        from a C string to a JS string before passing the arguments on
446        to the client-provided JS callback.
447     */
448     const __ipsProxy = {
449       signature: 'i(ps)',
450       callProxy:(callback)=>{
451         return (p,s)=>{
452           try{return callback(p, wasm.cstrToJs(s)) | 0}
453           catch(e){return e.resultCode || capi.SQLITE_ERROR}
454         }
455       }
456     };
458     wasm.bindingSignatures.int64.push(...[
459       ['sqlite3changegroup_add', 'int', ['sqlite3_changegroup*', 'int', 'void*']],
460       ['sqlite3changegroup_add_strm', 'int', [
461         'sqlite3_changegroup*',
462         new wasm.xWrap.FuncPtrAdapter({
463           name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
464         }),
465         'void*'
466       ]],
467       ['sqlite3changegroup_delete', undefined, ['sqlite3_changegroup*']],
468       ['sqlite3changegroup_new', 'int', ['**']],
469       ['sqlite3changegroup_output', 'int', ['sqlite3_changegroup*', 'int*', '**']],
470       ['sqlite3changegroup_output_strm', 'int', [
471         'sqlite3_changegroup*',
472         new wasm.xWrap.FuncPtrAdapter({
473           name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
474         }),
475         'void*'
476       ]],
477       ['sqlite3changeset_apply', 'int', [
478         'sqlite3*', 'int', 'void*',
479         new wasm.xWrap.FuncPtrAdapter({
480           name: 'xFilter', bindScope: 'transient', ...__ipsProxy
481         }),
482         new wasm.xWrap.FuncPtrAdapter({
483           name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
484         }),
485         'void*'
486       ]],
487       ['sqlite3changeset_apply_strm', 'int', [
488         'sqlite3*',
489         new wasm.xWrap.FuncPtrAdapter({
490           name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
491         }),
492         'void*',
493         new wasm.xWrap.FuncPtrAdapter({
494           name: 'xFilter', bindScope: 'transient', ...__ipsProxy
495         }),
496         new wasm.xWrap.FuncPtrAdapter({
497           name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
498         }),
499         'void*'
500       ]],
501       ['sqlite3changeset_apply_v2', 'int', [
502         'sqlite3*', 'int', 'void*',
503         new wasm.xWrap.FuncPtrAdapter({
504           name: 'xFilter', bindScope: 'transient', ...__ipsProxy
505         }),
506         new wasm.xWrap.FuncPtrAdapter({
507           name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
508         }),
509         'void*', '**', 'int*', 'int'
511       ]],
512       ['sqlite3changeset_apply_v2_strm', 'int', [
513         'sqlite3*',
514         new wasm.xWrap.FuncPtrAdapter({
515           name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
516         }),
517         'void*',
518         new wasm.xWrap.FuncPtrAdapter({
519           name: 'xFilter', bindScope: 'transient', ...__ipsProxy
520         }),
521         new wasm.xWrap.FuncPtrAdapter({
522           name: 'xConflict', signature: 'i(pip)', bindScope: 'transient'
523         }),
524         'void*', '**', 'int*', 'int'
525       ]],
526       ['sqlite3changeset_concat', 'int', ['int','void*', 'int', 'void*', 'int*', '**']],
527       ['sqlite3changeset_concat_strm', 'int', [
528         new wasm.xWrap.FuncPtrAdapter({
529           name: 'xInputA', signature: 'i(ppp)', bindScope: 'transient'
530         }),
531         'void*',
532         new wasm.xWrap.FuncPtrAdapter({
533           name: 'xInputB', signature: 'i(ppp)', bindScope: 'transient'
534         }),
535         'void*',
536         new wasm.xWrap.FuncPtrAdapter({
537           name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
538         }),
539         'void*'
540       ]],
541       ['sqlite3changeset_conflict', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
542       ['sqlite3changeset_finalize', 'int', ['sqlite3_changeset_iter*']],
543       ['sqlite3changeset_fk_conflicts', 'int', ['sqlite3_changeset_iter*', 'int*']],
544       ['sqlite3changeset_invert', 'int', ['int', 'void*', 'int*', '**']],
545       ['sqlite3changeset_invert_strm', 'int', [
546         new wasm.xWrap.FuncPtrAdapter({
547           name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
548         }),
549         'void*',
550         new wasm.xWrap.FuncPtrAdapter({
551           name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient'
552         }),
553         'void*'
554       ]],
555       ['sqlite3changeset_new', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
556       ['sqlite3changeset_next', 'int', ['sqlite3_changeset_iter*']],
557       ['sqlite3changeset_old', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
558       ['sqlite3changeset_op', 'int', [
559         'sqlite3_changeset_iter*', '**', 'int*', 'int*','int*'
560       ]],
561       ['sqlite3changeset_pk', 'int', ['sqlite3_changeset_iter*', '**', 'int*']],
562       ['sqlite3changeset_start', 'int', ['**', 'int', '*']],
563       ['sqlite3changeset_start_strm', 'int', [
564         '**',
565         new wasm.xWrap.FuncPtrAdapter({
566           name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
567         }),
568         'void*'
569       ]],
570       ['sqlite3changeset_start_v2', 'int', ['**', 'int', '*', 'int']],
571       ['sqlite3changeset_start_v2_strm', 'int', [
572         '**',
573         new wasm.xWrap.FuncPtrAdapter({
574           name: 'xInput', signature: 'i(ppp)', bindScope: 'transient'
575         }),
576         'void*', 'int'
577       ]],
578       ['sqlite3session_attach', 'int', ['sqlite3_session*', 'string']],
579       ['sqlite3session_changeset', 'int', ['sqlite3_session*', 'int*', '**']],
580       ['sqlite3session_changeset_size', 'i64', ['sqlite3_session*']],
581       ['sqlite3session_changeset_strm', 'int', [
582         'sqlite3_session*',
583         new wasm.xWrap.FuncPtrAdapter({
584           name: 'xOutput', signature: 'i(ppp)', bindScope: 'transient'
585         }),
586         'void*'
587       ]],
588       ['sqlite3session_config', 'int', ['int', 'void*']],
589       ['sqlite3session_create', 'int', ['sqlite3*', 'string', '**']],
590       //sqlite3session_delete() is bound manually
591       ['sqlite3session_diff', 'int', ['sqlite3_session*', 'string', 'string', '**']],
592       ['sqlite3session_enable', 'int', ['sqlite3_session*', 'int']],
593       ['sqlite3session_indirect', 'int', ['sqlite3_session*', 'int']],
594       ['sqlite3session_isempty', 'int', ['sqlite3_session*']],
595       ['sqlite3session_memory_used', 'i64', ['sqlite3_session*']],
596       ['sqlite3session_object_config', 'int', ['sqlite3_session*', 'int', 'void*']],
597       ['sqlite3session_patchset', 'int', ['sqlite3_session*', '*', '**']],
598       ['sqlite3session_patchset_strm', 'int', [
599         'sqlite3_session*',
600         new wasm.xWrap.FuncPtrAdapter({
601           name: 'xOutput', signature: 'i(ppp)', bindScope: 'transient'
602         }),
603         'void*'
604       ]],
605       ['sqlite3session_table_filter', undefined, [
606         'sqlite3_session*',
607         new wasm.xWrap.FuncPtrAdapter({
608           name: 'xFilter', ...__ipsProxy,
609           contextKey: (argv,argIndex)=>argv[0/* (sqlite3_session*) */]
610         }),
611         '*'
612       ]]
613     ]);
614   }/*session/changeset APIs*/
616   /**
617      Functions which are intended solely for API-internal use by the
618      WASM components, not client code. These get installed into
619      sqlite3.util. Some of them get exposed to clients via variants
620      in sqlite3_js_...().
622      2024-01-11: these were renamed, with two underscores in the
623      prefix, to ensure that clients do not accidentally depend on
624      them.  They have always been documented as internal-use-only, so
625      no clients "should" be depending on the old names.
626   */
627   wasm.bindingSignatures.wasmInternal = [
628     ["sqlite3__wasm_db_reset", "int", "sqlite3*"],
629     ["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
630     [/* DO NOT USE. This is deprecated since 2023-08-11 because it can
631         trigger assert() in debug builds when used with file sizes
632         which are not sizes to a multiple of a valid db page size. */
633       "sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"
634     ],
635     ["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
636     ["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
637     ["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
638   ];
640   /**
641      Install JS<->C struct bindings for the non-opaque struct types we
642      need... */
643   sqlite3.StructBinder = globalThis.Jaccwabyt({
644     heap: 0 ? wasm.memory : wasm.heap8u,
645     alloc: wasm.alloc,
646     dealloc: wasm.dealloc,
647     bigIntEnabled: wasm.bigIntEnabled,
648     memberPrefix: /* Never change this: this prefix is baked into any
649                      amount of code and client-facing docs. */ '$'
650   });
651   delete globalThis.Jaccwabyt;
653   {// wasm.xWrap() bindings...
655     /* Convert Arrays and certain TypedArrays to strings for
656        'string:flexible'-type arguments */
657     const __xString = wasm.xWrap.argAdapter('string');
658     wasm.xWrap.argAdapter(
659       'string:flexible', (v)=>__xString(util.flexibleString(v))
660     );
662     /**
663        The 'string:static' argument adapter treats its argument as
664        either...
666        - WASM pointer: assumed to be a long-lived C-string which gets
667          returned as-is.
669        - Anything else: gets coerced to a JS string for use as a map
670          key. If a matching entry is found (as described next), it is
671          returned, else wasm.allocCString() is used to create a a new
672          string, map its pointer to (''+v) for the remainder of the
673          application's life, and returns that pointer value for this
674          call and all future calls which are passed a
675          string-equivalent argument.
677        Use case: sqlite3_bind_pointer() and sqlite3_result_pointer()
678        call for "a static string and preferably a string
679        literal." This converter is used to ensure that the string
680        value seen by those functions is long-lived and behaves as they
681        need it to.
682     */
683     wasm.xWrap.argAdapter(
684       'string:static',
685       function(v){
686         if(wasm.isPtr(v)) return v;
687         v = ''+v;
688         let rc = this[v];
689         return rc || (this[v] = wasm.allocCString(v));
690       }.bind(Object.create(null))
691     );
693     /**
694        Add some descriptive xWrap() aliases for '*' intended to (A)
695        initially improve readability/correctness of
696        wasm.bindingSignatures and (B) provide automatic conversion
697        from higher-level representations, e.g. capi.sqlite3_vfs to
698        `sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
699     */
700     const __xArgPtr = wasm.xWrap.argAdapter('*');
701     const nilType = function(){
702       /*a class which no value can ever be an instance of*/
703     };
704     wasm.xWrap.argAdapter('sqlite3_filename', __xArgPtr)
705     ('sqlite3_context*', __xArgPtr)
706     ('sqlite3_value*', __xArgPtr)
707     ('void*', __xArgPtr)
708     ('sqlite3_changegroup*', __xArgPtr)
709     ('sqlite3_changeset_iter*', __xArgPtr)
710     ('sqlite3_session*', __xArgPtr)
711     ('sqlite3_stmt*', (v)=>
712       __xArgPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType))
713            ? v.pointer : v))
714     ('sqlite3*', (v)=>
715       __xArgPtr((v instanceof (sqlite3?.oo1?.DB || nilType))
716            ? v.pointer : v))
717     ('sqlite3_index_info*', (v)=>
718       __xArgPtr((v instanceof (capi.sqlite3_index_info || nilType))
719            ? v.pointer : v))
720     ('sqlite3_module*', (v)=>
721       __xArgPtr((v instanceof (capi.sqlite3_module || nilType))
722            ? v.pointer : v))
723     /**
724        `sqlite3_vfs*`:
726        - v is-a string: use the result of sqlite3_vfs_find(v) but
727          throw if it returns 0.
728        - v is-a capi.sqlite3_vfs: use v.pointer.
729        - Else return the same as the `'*'` argument conversion.
730     */
731     ('sqlite3_vfs*', (v)=>{
732       if('string'===typeof v){
733         /* A NULL sqlite3_vfs pointer will be treated as the default
734            VFS in many contexts. We specifically do not want that
735            behavior here. */
736         return capi.sqlite3_vfs_find(v)
737           || sqlite3.SQLite3Error.toss(
738             capi.SQLITE_NOTFOUND,
739             "Unknown sqlite3_vfs name:", v
740           );
741       }
742       return __xArgPtr((v instanceof (capi.sqlite3_vfs || nilType))
743                        ? v.pointer : v);
744     });
746     const __xRcPtr = wasm.xWrap.resultAdapter('*');
747     wasm.xWrap.resultAdapter('sqlite3*', __xRcPtr)
748     ('sqlite3_context*', __xRcPtr)
749     ('sqlite3_stmt*', __xRcPtr)
750     ('sqlite3_value*', __xRcPtr)
751     ('sqlite3_vfs*', __xRcPtr)
752     ('void*', __xRcPtr);
754     /**
755        Populate api object with sqlite3_...() by binding the "raw" wasm
756        exports into type-converting proxies using wasm.xWrap().
757     */
758     if(0 === wasm.exports.sqlite3_step.length){
759       /* This environment wraps exports in nullary functions, which means
760          we must disable the arg-count validation we otherwise perform
761          on the wrappers. */
762       wasm.xWrap.doArgcCheck = false;
763       sqlite3.config.warn(
764         "Disabling sqlite3.wasm.xWrap.doArgcCheck due to environmental quirks."
765       );
766     }
767     for(const e of wasm.bindingSignatures){
768       capi[e[0]] = wasm.xWrap.apply(null, e);
769     }
770     for(const e of wasm.bindingSignatures.wasmInternal){
771       util[e[0]] = wasm.xWrap.apply(null, e);
772     }
774     /* For C API functions which cannot work properly unless
775        wasm.bigIntEnabled is true, install a bogus impl which throws
776        if called when bigIntEnabled is false. The alternative would be
777        to elide these functions altogether, which seems likely to
778        cause more confusion. */
779     const fI64Disabled = function(fname){
780       return ()=>toss(fname+"() is unavailable due to lack",
781                       "of BigInt support in this build.");
782     };
783     for(const e of wasm.bindingSignatures.int64){
784       capi[e[0]] = wasm.bigIntEnabled
785         ? wasm.xWrap.apply(null, e)
786         : fI64Disabled(e[0]);
787     }
789     /* There's no need to expose bindingSignatures to clients,
790        implicitly making it part of the public interface. */
791     delete wasm.bindingSignatures;
793     if(wasm.exports.sqlite3__wasm_db_error){
794       const __db_err = wasm.xWrap(
795         'sqlite3__wasm_db_error', 'int', 'sqlite3*', 'int', 'string'
796       );
797       /**
798          Sets the given db's error state. Accepts:
800          - (sqlite3*, int code, string msg)
801          - (sqlite3*, Error e [,string msg = ''+e])
803          If passed a WasmAllocError, the message is ignored and the
804          result code is SQLITE_NOMEM. If passed any other Error type,
805          the result code defaults to SQLITE_ERROR unless the Error
806          object has a resultCode property, in which case that is used
807          (e.g. SQLite3Error has that). If passed a non-WasmAllocError
808          exception, the message string defaults to theError.message.
810          Returns the resulting code. Pass (pDb,0,0) to clear the error
811          state.
812        */
813       util.sqlite3__wasm_db_error = function(pDb, resultCode, message){
814         if(resultCode instanceof sqlite3.WasmAllocError){
815           resultCode = capi.SQLITE_NOMEM;
816           message = 0 /*avoid allocating message string*/;
817         }else if(resultCode instanceof Error){
818           message = message || ''+resultCode;
819           resultCode = (resultCode.resultCode || capi.SQLITE_ERROR);
820         }
821         return pDb ? __db_err(pDb, resultCode, message) : resultCode;
822       };
823     }else{
824       util.sqlite3__wasm_db_error = function(pDb,errCode,msg){
825         console.warn("sqlite3__wasm_db_error() is not exported.",arguments);
826         return errCode;
827       };
828     }
829   }/*xWrap() bindings*/
831   {/* Import C-level constants and structs... */
832     const cJson = wasm.xCall('sqlite3__wasm_enum_json');
833     if(!cJson){
834       toss("Maintenance required: increase sqlite3__wasm_enum_json()'s",
835            "static buffer size!");
836     }
837     //console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
838     wasm.ctype = JSON.parse(wasm.cstrToJs(cJson));
839     // Groups of SQLITE_xyz macros...
840     const defineGroups = ['access', 'authorizer',
841                           'blobFinalizers', 'changeset',
842                           'config', 'dataTypes',
843                           'dbConfig', 'dbStatus',
844                           'encodings', 'fcntl', 'flock', 'ioCap',
845                           'limits', 'openFlags',
846                           'prepareFlags', 'resultCodes',
847                           'sqlite3Status',
848                           'stmtStatus', 'syncFlags',
849                           'trace', 'txnState', 'udfFlags',
850                           'version' ];
851     if(wasm.bigIntEnabled){
852       defineGroups.push('serialize', 'session', 'vtab');
853     }
854     for(const t of defineGroups){
855       for(const e of Object.entries(wasm.ctype[t])){
856         // ^^^ [k,v] there triggers a buggy code transformation via
857         // one of the Emscripten-driven optimizers.
858         capi[e[0]] = e[1];
859       }
860     }
861     if(!wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){
862       toss("Internal error: cannot resolve exported function",
863            "entry SQLITE_WASM_DEALLOC (=="+capi.SQLITE_WASM_DEALLOC+").");
864     }
865     const __rcMap = Object.create(null);
866     for(const t of ['resultCodes']){
867       for(const e of Object.entries(wasm.ctype[t])){
868         __rcMap[e[1]] = e[0];
869       }
870     }
871     /**
872        For the given integer, returns the SQLITE_xxx result code as a
873        string, or undefined if no such mapping is found.
874     */
875     capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc];
876     /* Bind all registered C-side structs... */
877     const notThese = Object.assign(Object.create(null),{
878       // For each struct to NOT register, map its name to true:
879       WasmTestStruct: true,
880       /* We unregister the kvvfs VFS from Worker threads below. */
881       sqlite3_kvvfs_methods: !util.isUIThread(),
882       /* sqlite3_index_info and friends require int64: */
883       sqlite3_index_info: !wasm.bigIntEnabled,
884       sqlite3_index_constraint: !wasm.bigIntEnabled,
885       sqlite3_index_orderby: !wasm.bigIntEnabled,
886       sqlite3_index_constraint_usage: !wasm.bigIntEnabled
887     });
888     for(const s of wasm.ctype.structs){
889       if(!notThese[s.name]){
890         capi[s.name] = sqlite3.StructBinder(s);
891       }
892     }
893     if(capi.sqlite3_index_info){
894       /* Move these inner structs into sqlite3_index_info.  Binding
895       ** them to WASM requires that we create global-scope structs to
896       ** model them with, but those are no longer needed after we've
897       ** passed them to StructBinder. */
898       for(const k of ['sqlite3_index_constraint',
899                       'sqlite3_index_orderby',
900                       'sqlite3_index_constraint_usage']){
901         capi.sqlite3_index_info[k] = capi[k];
902         delete capi[k];
903       }
904       capi.sqlite3_vtab_config = wasm.xWrap(
905         'sqlite3__wasm_vtab_config','int',[
906           'sqlite3*', 'int', 'int']
907       );
908     }/* end vtab-related setup */
909   }/*end C constant and struct imports*/
911   /**
912      Internal helper to assist in validating call argument counts in
913      the hand-written sqlite3_xyz() wrappers. We do this only for
914      consistency with non-special-case wrappings.
915   */
916   const __dbArgcMismatch = (pDb,f,n)=>{
917     return util.sqlite3__wasm_db_error(pDb, capi.SQLITE_MISUSE,
918                                       f+"() requires "+n+" argument"+
919                                       (1===n?"":'s')+".");
920   };
922   /** Code duplication reducer for functions which take an encoding
923       argument and require SQLITE_UTF8.  Sets the db error code to
924       SQLITE_FORMAT and returns that code. */
925   const __errEncoding = (pDb)=>{
926     return util.sqlite3__wasm_db_error(
927       pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding."
928     );
929   };
931   /**
932      __dbCleanupMap is infrastructure for recording registration of
933      UDFs and collations so that sqlite3_close_v2() can clean up any
934      automated JS-to-WASM function conversions installed by those.
935   */
936   const __argPDb = (pDb)=>wasm.xWrap.argAdapter('sqlite3*')(pDb);
937   const __argStr = (str)=>wasm.isPtr(str) ? wasm.cstrToJs(str) : str;
938   const __dbCleanupMap = function(
939     pDb, mode/*0=remove, >0=create if needed, <0=do not create if missing*/
940   ){
941     pDb = __argPDb(pDb);
942     let m = this.dbMap.get(pDb);
943     if(!mode){
944       this.dbMap.delete(pDb);
945       return m;
946     }else if(!m && mode>0){
947       this.dbMap.set(pDb, (m = Object.create(null)));
948     }
949     return m;
950   }.bind(Object.assign(Object.create(null),{
951     dbMap: new Map
952   }));
954   __dbCleanupMap.addCollation = function(pDb, name){
955     const m = __dbCleanupMap(pDb, 1);
956     if(!m.collation) m.collation = new Set;
957     m.collation.add(__argStr(name).toLowerCase());
958   };
960   __dbCleanupMap._addUDF = function(pDb, name, arity, map){
961     /* Map UDF name to a Set of arity values */
962     name = __argStr(name).toLowerCase();
963     let u = map.get(name);
964     if(!u) map.set(name, (u = new Set));
965     u.add((arity<0) ? -1 : arity);
966   };
968   __dbCleanupMap.addFunction = function(pDb, name, arity){
969     const m = __dbCleanupMap(pDb, 1);
970     if(!m.udf) m.udf = new Map;
971     this._addUDF(pDb, name, arity, m.udf);
972   };
974   __dbCleanupMap.addWindowFunc = function(pDb, name, arity){
975     const m = __dbCleanupMap(pDb, 1);
976     if(!m.wudf) m.wudf = new Map;
977     this._addUDF(pDb, name, arity, m.wudf);
978   };
980   /**
981      Intended to be called _only_ from sqlite3_close_v2(),
982      passed its non-0 db argument.
984      This function frees up certain automatically-installed WASM
985      function bindings which were installed on behalf of the given db,
986      as those may otherwise leak.
988      Notable caveat: this is only ever run via
989      sqlite3.capi.sqlite3_close_v2(). If a client, for whatever
990      reason, uses sqlite3.wasm.exports.sqlite3_close_v2() (the
991      function directly exported from WASM), this cleanup will not
992      happen.
994      This is not a silver bullet for avoiding automation-related
995      leaks but represents "an honest effort."
997      The issue being addressed here is covered at:
999      https://sqlite.org/wasm/doc/trunk/api-c-style.md#convert-func-ptr
1000   */
1001   __dbCleanupMap.cleanup = function(pDb){
1002     pDb = __argPDb(pDb);
1003     //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
1004     /**
1005        Installing NULL functions in the C API will remove those
1006        bindings. The FuncPtrAdapter which sits between us and the C
1007        API will also treat that as an opportunity to
1008        wasm.uninstallFunction() any WASM function bindings it has
1009        installed for pDb.
1010     */
1011     const closeArgs = [pDb];
1012     for(const name of [
1013       'sqlite3_busy_handler',
1014       'sqlite3_commit_hook',
1015       'sqlite3_preupdate_hook',
1016       'sqlite3_progress_handler',
1017       'sqlite3_rollback_hook',
1018       'sqlite3_set_authorizer',
1019       'sqlite3_trace_v2',
1020       'sqlite3_update_hook'
1021     ]) {
1022       const x = wasm.exports[name];
1023       closeArgs.length = x.length/*==argument count*/
1024       /* recall that undefined entries translate to 0 when passed to
1025          WASM. */;
1026       try{ capi[name](...closeArgs) }
1027       catch(e){
1028         console.warn("close-time call of",name+"(",closeArgs,") threw:",e);
1029       }
1030     }
1031     const m = __dbCleanupMap(pDb, 0);
1032     if(!m) return;
1033     if(m.collation){
1034       for(const name of m.collation){
1035         try{
1036           capi.sqlite3_create_collation_v2(
1037             pDb, name, capi.SQLITE_UTF8, 0, 0, 0
1038           );
1039         }catch(e){
1040           /*ignored*/
1041         }
1042       }
1043       delete m.collation;
1044     }
1045     let i;
1046     for(i = 0; i < 2; ++i){ /* Clean up UDFs... */
1047       const fmap = i ? m.wudf : m.udf;
1048       if(!fmap) continue;
1049       const func = i
1050             ? capi.sqlite3_create_window_function
1051             : capi.sqlite3_create_function_v2;
1052       for(const e of fmap){
1053         const name = e[0], arities = e[1];
1054         const fargs = [pDb, name, 0/*arity*/, capi.SQLITE_UTF8, 0, 0, 0, 0, 0];
1055         if(i) fargs.push(0);
1056         for(const arity of arities){
1057           try{ fargs[2] = arity; func.apply(null, fargs); }
1058           catch(e){/*ignored*/}
1059         }
1060         arities.clear();
1061       }
1062       fmap.clear();
1063     }
1064     delete m.udf;
1065     delete m.wudf;
1066   }/*__dbCleanupMap.cleanup()*/;
1068   {/* Binding of sqlite3_close_v2() */
1069     const __sqlite3CloseV2 = wasm.xWrap("sqlite3_close_v2", "int", "sqlite3*");
1070     capi.sqlite3_close_v2 = function(pDb){
1071       if(1!==arguments.length) return __dbArgcMismatch(pDb, 'sqlite3_close_v2', 1);
1072       if(pDb){
1073         try{__dbCleanupMap.cleanup(pDb)} catch(e){/*ignored*/}
1074       }
1075       return __sqlite3CloseV2(pDb);
1076     };
1077   }/*sqlite3_close_v2()*/
1079   if(capi.sqlite3session_table_filter){
1080     const __sqlite3SessionDelete = wasm.xWrap(
1081       'sqlite3session_delete', undefined, ['sqlite3_session*']
1082     );
1083     capi.sqlite3session_delete = function(pSession){
1084       if(1!==arguments.length){
1085         return __dbArgcMismatch(pDb, 'sqlite3session_delete', 1);
1086         /* Yes, we're returning a value from a void function. That seems
1087            like the lesser evil compared to not maintaining arg-count
1088            consistency as we do with other similar bindings. */
1089       }
1090       else if(pSession){
1091         //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
1092         capi.sqlite3session_table_filter(pSession, 0, 0);
1093       }
1094       __sqlite3SessionDelete(pSession);
1095     };
1096   }
1098   {/* Bindings for sqlite3_create_collation[_v2]() */
1099     // contextKey() impl for wasm.xWrap.FuncPtrAdapter
1100     const contextKey = (argv,argIndex)=>{
1101       return 'argv['+argIndex+']:'+argv[0/* sqlite3* */]+
1102         ':'+wasm.cstrToJs(argv[1/* collation name */]).toLowerCase()
1103     };
1104     const __sqlite3CreateCollationV2 = wasm.xWrap(
1105       'sqlite3_create_collation_v2', 'int', [
1106         'sqlite3*', 'string', 'int', '*',
1107         new wasm.xWrap.FuncPtrAdapter({
1108           /* int(*xCompare)(void*,int,const void*,int,const void*) */
1109           name: 'xCompare', signature: 'i(pipip)', contextKey
1110         }),
1111         new wasm.xWrap.FuncPtrAdapter({
1112           /* void(*xDestroy(void*) */
1113           name: 'xDestroy', signature: 'v(p)', contextKey
1114         })
1115       ]
1116     );
1118     /**
1119        Works exactly like C's sqlite3_create_collation_v2() except that:
1121        1) It returns capi.SQLITE_FORMAT if the 3rd argument contains
1122           any encoding-related value other than capi.SQLITE_UTF8.  No
1123           other encodings are supported. As a special case, if the
1124           bottom 4 bits of that argument are 0, SQLITE_UTF8 is
1125           assumed.
1127        2) It accepts JS functions for its function-pointer arguments,
1128           for which it will install WASM-bound proxies. The bindings
1129           are "permanent," in that they will stay in the WASM environment
1130           until it shuts down unless the client calls this again with the
1131           same collation name and a value of 0 or null for the
1132           the function pointer(s).
1134        For consistency with the C API, it requires the same number of
1135        arguments. It returns capi.SQLITE_MISUSE if passed any other
1136        argument count.
1138        Returns 0 on success, non-0 on error, in which case the error
1139        state of pDb (of type `sqlite3*` or argument-convertible to it)
1140        may contain more information.
1141     */
1142     capi.sqlite3_create_collation_v2 = function(pDb,zName,eTextRep,pArg,xCompare,xDestroy){
1143       if(6!==arguments.length) return __dbArgcMismatch(pDb, 'sqlite3_create_collation_v2', 6);
1144       else if( 0 === (eTextRep & 0xf) ){
1145         eTextRep |= capi.SQLITE_UTF8;
1146       }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
1147         return __errEncoding(pDb);
1148       }
1149       try{
1150         const rc = __sqlite3CreateCollationV2(pDb, zName, eTextRep, pArg, xCompare, xDestroy);
1151         if(0===rc && xCompare instanceof Function){
1152           __dbCleanupMap.addCollation(pDb, zName);
1153         }
1154         return rc;
1155       }catch(e){
1156         return util.sqlite3__wasm_db_error(pDb, e);
1157       }
1158     };
1160     capi.sqlite3_create_collation = (pDb,zName,eTextRep,pArg,xCompare)=>{
1161       return (5===arguments.length)
1162         ? capi.sqlite3_create_collation_v2(pDb,zName,eTextRep,pArg,xCompare,0)
1163         : __dbArgcMismatch(pDb, 'sqlite3_create_collation', 5);
1164     };
1166   }/*sqlite3_create_collation() and friends*/
1168   {/* Special-case handling of sqlite3_create_function_v2()
1169       and sqlite3_create_window_function(). */
1170     /** FuncPtrAdapter for contextKey() for sqlite3_create_function()
1171         and friends. */
1172     const contextKey = function(argv,argIndex){
1173       return (
1174         argv[0/* sqlite3* */]
1175           +':'+(argv[2/*number of UDF args*/] < 0 ? -1 : argv[2])
1176           +':'+argIndex/*distinct for each xAbc callback type*/
1177           +':'+wasm.cstrToJs(argv[1]).toLowerCase()
1178       )
1179     };
1181     /**
1182        JS proxies for the various sqlite3_create[_window]_function()
1183        callbacks, structured in a form usable by wasm.xWrap.FuncPtrAdapter.
1184     */
1185     const __cfProxy = Object.assign(Object.create(null), {
1186       xInverseAndStep: {
1187         signature:'v(pip)', contextKey,
1188         callProxy: (callback)=>{
1189           return (pCtx, argc, pArgv)=>{
1190             try{ callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv)) }
1191             catch(e){ capi.sqlite3_result_error_js(pCtx, e) }
1192           };
1193         }
1194       },
1195       xFinalAndValue: {
1196         signature:'v(p)', contextKey,
1197         callProxy: (callback)=>{
1198           return (pCtx)=>{
1199             try{ capi.sqlite3_result_js(pCtx, callback(pCtx)) }
1200             catch(e){ capi.sqlite3_result_error_js(pCtx, e) }
1201           };
1202         }
1203       },
1204       xFunc: {
1205         signature:'v(pip)', contextKey,
1206         callProxy: (callback)=>{
1207           return (pCtx, argc, pArgv)=>{
1208             try{
1209               capi.sqlite3_result_js(
1210                 pCtx,
1211                 callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv))
1212               );
1213             }catch(e){
1214               //console.error('xFunc() caught:',e);
1215               capi.sqlite3_result_error_js(pCtx, e);
1216             }
1217           };
1218         }
1219       },
1220       xDestroy: {
1221         signature:'v(p)', contextKey,
1222         //Arguable: a well-behaved destructor doesn't require a proxy.
1223         callProxy: (callback)=>{
1224           return (pVoid)=>{
1225             try{ callback(pVoid) }
1226             catch(e){ console.error("UDF xDestroy method threw:",e) }
1227           };
1228         }
1229       }
1230     })/*__cfProxy*/;
1232     const __sqlite3CreateFunction = wasm.xWrap(
1233       "sqlite3_create_function_v2", "int", [
1234         "sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
1235         "int"/*eTextRep*/, "*"/*pApp*/,
1236         new wasm.xWrap.FuncPtrAdapter({name: 'xFunc', ...__cfProxy.xFunc}),
1237         new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
1238         new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
1239         new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
1240       ]
1241     );
1243     const __sqlite3CreateWindowFunction = wasm.xWrap(
1244       "sqlite3_create_window_function", "int", [
1245         "sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
1246         "int"/*eTextRep*/, "*"/*pApp*/,
1247         new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
1248         new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
1249         new wasm.xWrap.FuncPtrAdapter({name: 'xValue', ...__cfProxy.xFinalAndValue}),
1250         new wasm.xWrap.FuncPtrAdapter({name: 'xInverse', ...__cfProxy.xInverseAndStep}),
1251         new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
1252       ]
1253     );
1255     /* Documented in the api object's initializer. */
1256     capi.sqlite3_create_function_v2 = function f(
1257       pDb, funcName, nArg, eTextRep, pApp,
1258       xFunc,   //void (*xFunc)(sqlite3_context*,int,sqlite3_value**)
1259       xStep,   //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
1260       xFinal,  //void (*xFinal)(sqlite3_context*)
1261       xDestroy //void (*xDestroy)(void*)
1262     ){
1263       if( f.length!==arguments.length ){
1264         return __dbArgcMismatch(pDb,"sqlite3_create_function_v2",f.length);
1265       }else if( 0 === (eTextRep & 0xf) ){
1266         eTextRep |= capi.SQLITE_UTF8;
1267       }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
1268         return __errEncoding(pDb);
1269       }
1270       try{
1271         const rc = __sqlite3CreateFunction(pDb, funcName, nArg, eTextRep,
1272                                            pApp, xFunc, xStep, xFinal, xDestroy);
1273         if(0===rc && (xFunc instanceof Function
1274                       || xStep instanceof Function
1275                       || xFinal instanceof Function
1276                       || xDestroy instanceof Function)){
1277           __dbCleanupMap.addFunction(pDb, funcName, nArg);
1278         }
1279         return rc;
1280       }catch(e){
1281         console.error("sqlite3_create_function_v2() setup threw:",e);
1282         return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
1283       }
1284     };
1286     /* Documented in the api object's initializer. */
1287     capi.sqlite3_create_function = function f(
1288       pDb, funcName, nArg, eTextRep, pApp,
1289       xFunc, xStep, xFinal
1290     ){
1291       return (f.length===arguments.length)
1292         ? capi.sqlite3_create_function_v2(pDb, funcName, nArg, eTextRep,
1293                                           pApp, xFunc, xStep, xFinal, 0)
1294         : __dbArgcMismatch(pDb,"sqlite3_create_function",f.length);
1295     };
1297     /* Documented in the api object's initializer. */
1298     capi.sqlite3_create_window_function = function f(
1299       pDb, funcName, nArg, eTextRep, pApp,
1300       xStep,   //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
1301       xFinal,  //void (*xFinal)(sqlite3_context*)
1302       xValue,  //void (*xValue)(sqlite3_context*)
1303       xInverse,//void (*xInverse)(sqlite3_context*,int,sqlite3_value**)
1304       xDestroy //void (*xDestroy)(void*)
1305     ){
1306       if( f.length!==arguments.length ){
1307         return __dbArgcMismatch(pDb,"sqlite3_create_window_function",f.length);
1308       }else if( 0 === (eTextRep & 0xf) ){
1309         eTextRep |= capi.SQLITE_UTF8;
1310       }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
1311         return __errEncoding(pDb);
1312       }
1313       try{
1314         const rc = __sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
1315                                                  pApp, xStep, xFinal, xValue,
1316                                                  xInverse, xDestroy);
1317         if(0===rc && (xStep instanceof Function
1318                       || xFinal instanceof Function
1319                       || xValue instanceof Function
1320                       || xInverse instanceof Function
1321                       || xDestroy instanceof Function)){
1322           __dbCleanupMap.addWindowFunc(pDb, funcName, nArg);
1323         }
1324         return rc;
1325       }catch(e){
1326         console.error("sqlite3_create_window_function() setup threw:",e);
1327         return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
1328       }
1329     };
1330     /**
1331        A _deprecated_ alias for capi.sqlite3_result_js() which
1332        predates the addition of that function in the public API.
1333     */
1334     capi.sqlite3_create_function_v2.udfSetResult =
1335       capi.sqlite3_create_function.udfSetResult =
1336       capi.sqlite3_create_window_function.udfSetResult = capi.sqlite3_result_js;
1338     /**
1339        A _deprecated_ alias for capi.sqlite3_values_to_js() which
1340        predates the addition of that function in the public API.
1341     */
1342     capi.sqlite3_create_function_v2.udfConvertArgs =
1343       capi.sqlite3_create_function.udfConvertArgs =
1344       capi.sqlite3_create_window_function.udfConvertArgs = capi.sqlite3_values_to_js;
1346     /**
1347        A _deprecated_ alias for capi.sqlite3_result_error_js() which
1348        predates the addition of that function in the public API.
1349     */
1350     capi.sqlite3_create_function_v2.udfSetError =
1351       capi.sqlite3_create_function.udfSetError =
1352       capi.sqlite3_create_window_function.udfSetError = capi.sqlite3_result_error_js;
1354   }/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/;
1356   {/* Special-case handling of sqlite3_prepare_v2() and
1357       sqlite3_prepare_v3() */
1359     /**
1360        Helper for string:flexible conversions which require a
1361        byte-length counterpart argument. Passed a value and its
1362        ostensible length, this function returns [V,N], where V is
1363        either v or a transformed copy of v and N is either n, -1, or
1364        the byte length of v (if it's a byte array or ArrayBuffer).
1365     */
1366     const __flexiString = (v,n)=>{
1367       if('string'===typeof v){
1368         n = -1;
1369       }else if(util.isSQLableTypedArray(v)){
1370         n = v.byteLength;
1371         v = util.typedArrayToString(
1372           (v instanceof ArrayBuffer) ? new Uint8Array(v) : v
1373         );
1374       }else if(Array.isArray(v)){
1375         v = v.join("");
1376         n = -1;
1377       }
1378       return [v, n];
1379     };
1381     /**
1382        Scope-local holder of the two impls of sqlite3_prepare_v2/v3().
1383     */
1384     const __prepare = {
1385       /**
1386          This binding expects a JS string as its 2nd argument and
1387          null as its final argument. In order to compile multiple
1388          statements from a single string, the "full" impl (see
1389          below) must be used.
1390       */
1391       basic: wasm.xWrap('sqlite3_prepare_v3',
1392                         "int", ["sqlite3*", "string",
1393                                 "int"/*ignored for this impl!*/,
1394                                 "int", "**",
1395                                 "**"/*MUST be 0 or null or undefined!*/]),
1396       /**
1397          Impl which requires that the 2nd argument be a pointer
1398          to the SQL string, instead of being converted to a
1399          string. This variant is necessary for cases where we
1400          require a non-NULL value for the final argument
1401          (exec()'ing multiple statements from one input
1402          string). For simpler cases, where only the first
1403          statement in the SQL string is required, the wrapper
1404          named sqlite3_prepare_v2() is sufficient and easier to
1405          use because it doesn't require dealing with pointers.
1406       */
1407       full: wasm.xWrap('sqlite3_prepare_v3',
1408                        "int", ["sqlite3*", "*", "int", "int",
1409                                "**", "**"])
1410     };
1412     /* Documented in the capi object's initializer. */
1413     capi.sqlite3_prepare_v3 = function f(pDb, sql, sqlLen, prepFlags, ppStmt, pzTail){
1414       if(f.length!==arguments.length){
1415         return __dbArgcMismatch(pDb,"sqlite3_prepare_v3",f.length);
1416       }
1417       const [xSql, xSqlLen] = __flexiString(sql, sqlLen);
1418       switch(typeof xSql){
1419           case 'string': return __prepare.basic(pDb, xSql, xSqlLen, prepFlags, ppStmt, null);
1420           case 'number': return __prepare.full(pDb, xSql, xSqlLen, prepFlags, ppStmt, pzTail);
1421           default:
1422             return util.sqlite3__wasm_db_error(
1423               pDb, capi.SQLITE_MISUSE,
1424               "Invalid SQL argument type for sqlite3_prepare_v2/v3()."
1425             );
1426       }
1427     };
1429     /* Documented in the capi object's initializer. */
1430     capi.sqlite3_prepare_v2 = function f(pDb, sql, sqlLen, ppStmt, pzTail){
1431       return (f.length===arguments.length)
1432         ? capi.sqlite3_prepare_v3(pDb, sql, sqlLen, 0, ppStmt, pzTail)
1433         : __dbArgcMismatch(pDb,"sqlite3_prepare_v2",f.length);
1434     };
1436   }/*sqlite3_prepare_v2/v3()*/
1438   {/*sqlite3_bind_text/blob()*/
1439     const __bindText = wasm.xWrap("sqlite3_bind_text", "int", [
1440       "sqlite3_stmt*", "int", "string", "int", "*"
1441     ]);
1442     const __bindBlob = wasm.xWrap("sqlite3_bind_blob", "int", [
1443       "sqlite3_stmt*", "int", "*", "int", "*"
1444     ]);
1446     /** Documented in the capi object's initializer. */
1447     capi.sqlite3_bind_text = function f(pStmt, iCol, text, nText, xDestroy){
1448       if(f.length!==arguments.length){
1449         return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt),
1450                                 "sqlite3_bind_text", f.length);
1451       }else if(wasm.isPtr(text) || null===text){
1452         return __bindText(pStmt, iCol, text, nText, xDestroy);
1453       }else if(text instanceof ArrayBuffer){
1454         text = new Uint8Array(text);
1455       }else if(Array.isArray(pMem)){
1456         text = pMem.join('');
1457       }
1458       let p, n;
1459       try{
1460         if(util.isSQLableTypedArray(text)){
1461           p = wasm.allocFromTypedArray(text);
1462           n = text.byteLength;
1463         }else if('string'===typeof text){
1464           [p, n] = wasm.allocCString(text);
1465         }else{
1466           return util.sqlite3__wasm_db_error(
1467             capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
1468             "Invalid 3rd argument type for sqlite3_bind_text()."
1469           );
1470         }
1471         return __bindText(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
1472       }catch(e){
1473         wasm.dealloc(p);
1474         return util.sqlite3__wasm_db_error(
1475           capi.sqlite3_db_handle(pStmt), e
1476         );
1477       }
1478     }/*sqlite3_bind_text()*/;
1480     /** Documented in the capi object's initializer. */
1481     capi.sqlite3_bind_blob = function f(pStmt, iCol, pMem, nMem, xDestroy){
1482       if(f.length!==arguments.length){
1483         return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt),
1484                                 "sqlite3_bind_blob", f.length);
1485       }else if(wasm.isPtr(pMem) || null===pMem){
1486         return __bindBlob(pStmt, iCol, pMem, nMem, xDestroy);
1487       }else if(pMem instanceof ArrayBuffer){
1488         pMem = new Uint8Array(pMem);
1489       }else if(Array.isArray(pMem)){
1490         pMem = pMem.join('');
1491       }
1492       let p, n;
1493       try{
1494         if(util.isBindableTypedArray(pMem)){
1495           p = wasm.allocFromTypedArray(pMem);
1496           n = nMem>=0 ? nMem : pMem.byteLength;
1497         }else if('string'===typeof pMem){
1498           [p, n] = wasm.allocCString(pMem);
1499         }else{
1500           return util.sqlite3__wasm_db_error(
1501             capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
1502             "Invalid 3rd argument type for sqlite3_bind_blob()."
1503           );
1504         }
1505         return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
1506       }catch(e){
1507         wasm.dealloc(p);
1508         return util.sqlite3__wasm_db_error(
1509           capi.sqlite3_db_handle(pStmt), e
1510         );
1511       }
1512     }/*sqlite3_bind_blob()*/;
1514   }/*sqlite3_bind_text/blob()*/
1516   {/* sqlite3_config() */
1517     /**
1518        Wraps a small subset of the C API's sqlite3_config() options.
1519        Unsupported options trigger the return of capi.SQLITE_NOTFOUND.
1520        Passing fewer than 2 arguments triggers return of
1521        capi.SQLITE_MISUSE.
1522     */
1523     capi.sqlite3_config = function(op, ...args){
1524       if(arguments.length<2) return capi.SQLITE_MISUSE;
1525       switch(op){
1526           case capi.SQLITE_CONFIG_COVERING_INDEX_SCAN: // 20  /* int */
1527           case capi.SQLITE_CONFIG_MEMSTATUS:// 9  /* boolean */
1528           case capi.SQLITE_CONFIG_SMALL_MALLOC: // 27  /* boolean */
1529           case capi.SQLITE_CONFIG_SORTERREF_SIZE: // 28  /* int nByte */
1530           case capi.SQLITE_CONFIG_STMTJRNL_SPILL: // 26  /* int nByte */
1531           case capi.SQLITE_CONFIG_URI:// 17  /* int */
1532             return wasm.exports.sqlite3__wasm_config_i(op, args[0]);
1533           case capi.SQLITE_CONFIG_LOOKASIDE: // 13  /* int int */
1534             return wasm.exports.sqlite3__wasm_config_ii(op, args[0], args[1]);
1535           case capi.SQLITE_CONFIG_MEMDB_MAXSIZE: // 29  /* sqlite3_int64 */
1536             return wasm.exports.sqlite3__wasm_config_j(op, args[0]);
1537           case capi.SQLITE_CONFIG_GETMALLOC: // 5 /* sqlite3_mem_methods* */
1538           case capi.SQLITE_CONFIG_GETMUTEX: // 11  /* sqlite3_mutex_methods* */
1539           case capi.SQLITE_CONFIG_GETPCACHE2: // 19  /* sqlite3_pcache_methods2* */
1540           case capi.SQLITE_CONFIG_GETPCACHE: // 15  /* no-op */
1541           case capi.SQLITE_CONFIG_HEAP: // 8  /* void*, int nByte, int min */
1542           case capi.SQLITE_CONFIG_LOG: // 16  /* xFunc, void* */
1543           case capi.SQLITE_CONFIG_MALLOC:// 4  /* sqlite3_mem_methods* */
1544           case capi.SQLITE_CONFIG_MMAP_SIZE: // 22  /* sqlite3_int64, sqlite3_int64 */
1545           case capi.SQLITE_CONFIG_MULTITHREAD: // 2 /* nil */
1546           case capi.SQLITE_CONFIG_MUTEX: // 10  /* sqlite3_mutex_methods* */
1547           case capi.SQLITE_CONFIG_PAGECACHE: // 7  /* void*, int sz, int N */
1548           case capi.SQLITE_CONFIG_PCACHE2: // 18  /* sqlite3_pcache_methods2* */
1549           case capi.SQLITE_CONFIG_PCACHE: // 14  /* no-op */
1550           case capi.SQLITE_CONFIG_PCACHE_HDRSZ: // 24  /* int *psz */
1551           case capi.SQLITE_CONFIG_PMASZ: // 25  /* unsigned int szPma */
1552           case capi.SQLITE_CONFIG_SERIALIZED: // 3 /* nil */
1553           case capi.SQLITE_CONFIG_SINGLETHREAD: // 1 /* nil */:
1554           case capi.SQLITE_CONFIG_SQLLOG: // 21  /* xSqllog, void* */
1555           case capi.SQLITE_CONFIG_WIN32_HEAPSIZE: // 23  /* int nByte */
1556           default:
1557           /* maintenance note: we specifically do not include
1558              SQLITE_CONFIG_ROWID_IN_VIEW here, on the grounds that
1559              it's only for legacy support and no apps written with
1560              this API require that. */
1561             return capi.SQLITE_NOTFOUND;
1562       }
1563     };
1564   }/* sqlite3_config() */
1566   {/*auto-extension bindings.*/
1567     const __autoExtFptr = new Set;
1569     capi.sqlite3_auto_extension = function(fPtr){
1570       if( fPtr instanceof Function ){
1571         fPtr = wasm.installFunction('i(ppp)', fPtr);
1572       }else if( 1!==arguments.length || !wasm.isPtr(fPtr) ){
1573         return capi.SQLITE_MISUSE;
1574       }
1575       const rc = wasm.exports.sqlite3_auto_extension(fPtr);
1576       if( fPtr!==arguments[0] ){
1577         if(0===rc) __autoExtFptr.add(fPtr);
1578         else wasm.uninstallFunction(fPtr);
1579       }
1580       return rc;
1581     };
1583     capi.sqlite3_cancel_auto_extension = function(fPtr){
1584      /* We do not do an automatic JS-to-WASM function conversion here
1585         because it would be senseless: the converted pointer would
1586         never possibly match an already-installed one. */;
1587       if(!fPtr || 1!==arguments.length || !wasm.isPtr(fPtr)) return 0;
1588       return wasm.exports.sqlite3_cancel_auto_extension(fPtr);
1589       /* Note that it "cannot happen" that a client passes a pointer which
1590          is in __autoExtFptr because __autoExtFptr only contains automatic
1591          conversions created inside sqlite3_auto_extension() and
1592          never exposed to the client. */
1593     };
1595     capi.sqlite3_reset_auto_extension = function(){
1596       wasm.exports.sqlite3_reset_auto_extension();
1597       for(const fp of __autoExtFptr) wasm.uninstallFunction(fp);
1598       __autoExtFptr.clear();
1599     };
1600   }/* auto-extension */
1602   const pKvvfs = capi.sqlite3_vfs_find("kvvfs");
1603   if( pKvvfs ){/* kvvfs-specific glue */
1604     if(util.isUIThread()){
1605       const kvvfsMethods = new capi.sqlite3_kvvfs_methods(
1606         wasm.exports.sqlite3__wasm_kvvfs_methods()
1607       );
1608       delete capi.sqlite3_kvvfs_methods;
1610       const kvvfsMakeKey = wasm.exports.sqlite3__wasm_kvvfsMakeKeyOnPstack,
1611             pstack = wasm.pstack;
1613       const kvvfsStorage = (zClass)=>
1614             ((115/*=='s'*/===wasm.peek(zClass))
1615              ? sessionStorage : localStorage);
1617       /**
1618          Implementations for members of the object referred to by
1619          sqlite3__wasm_kvvfs_methods(). We swap out the native
1620          implementations with these, which use localStorage or
1621          sessionStorage for their backing store.
1622       */
1623       const kvvfsImpls = {
1624         xRead: (zClass, zKey, zBuf, nBuf)=>{
1625           const stack = pstack.pointer,
1626                 astack = wasm.scopedAllocPush();
1627           try {
1628             const zXKey = kvvfsMakeKey(zClass,zKey);
1629             if(!zXKey) return -3/*OOM*/;
1630             const jKey = wasm.cstrToJs(zXKey);
1631             const jV = kvvfsStorage(zClass).getItem(jKey);
1632             if(!jV) return -1;
1633             const nV = jV.length /* Note that we are relying 100% on v being
1634                                     ASCII so that jV.length is equal to the
1635                                     C-string's byte length. */;
1636             if(nBuf<=0) return nV;
1637             else if(1===nBuf){
1638               wasm.poke(zBuf, 0);
1639               return nV;
1640             }
1641             const zV = wasm.scopedAllocCString(jV);
1642             if(nBuf > nV + 1) nBuf = nV + 1;
1643             wasm.heap8u().copyWithin(zBuf, zV, zV + nBuf - 1);
1644             wasm.poke(zBuf + nBuf - 1, 0);
1645             return nBuf - 1;
1646           }catch(e){
1647             console.error("kvstorageRead()",e);
1648             return -2;
1649           }finally{
1650             pstack.restore(stack);
1651             wasm.scopedAllocPop(astack);
1652           }
1653         },
1654         xWrite: (zClass, zKey, zData)=>{
1655           const stack = pstack.pointer;
1656           try {
1657             const zXKey = kvvfsMakeKey(zClass,zKey);
1658             if(!zXKey) return 1/*OOM*/;
1659             const jKey = wasm.cstrToJs(zXKey);
1660             kvvfsStorage(zClass).setItem(jKey, wasm.cstrToJs(zData));
1661             return 0;
1662           }catch(e){
1663             console.error("kvstorageWrite()",e);
1664             return capi.SQLITE_IOERR;
1665           }finally{
1666             pstack.restore(stack);
1667           }
1668         },
1669         xDelete: (zClass, zKey)=>{
1670           const stack = pstack.pointer;
1671           try {
1672             const zXKey = kvvfsMakeKey(zClass,zKey);
1673             if(!zXKey) return 1/*OOM*/;
1674             kvvfsStorage(zClass).removeItem(wasm.cstrToJs(zXKey));
1675             return 0;
1676           }catch(e){
1677             console.error("kvstorageDelete()",e);
1678             return capi.SQLITE_IOERR;
1679           }finally{
1680             pstack.restore(stack);
1681           }
1682         }
1683       }/*kvvfsImpls*/;
1684       for(const k of Object.keys(kvvfsImpls)){
1685         kvvfsMethods[kvvfsMethods.memberKey(k)] =
1686           wasm.installFunction(
1687             kvvfsMethods.memberSignature(k),
1688             kvvfsImpls[k]
1689           );
1690       }
1691     }else{
1692       /* Worker thread: unregister kvvfs to avoid it being used
1693          for anything other than local/sessionStorage. It "can"
1694          be used that way but it's not really intended to be. */
1695       capi.sqlite3_vfs_unregister(pKvvfs);
1696     }
1697   }/*pKvvfs*/
1699   /* Warn if client-level code makes use of FuncPtrAdapter. */
1700   wasm.xWrap.FuncPtrAdapter.warnOnUse = true;
1702   const StructBinder = sqlite3.StructBinder
1703   /* we require a local alias b/c StructBinder is removed from the sqlite3
1704      object during the final steps of the API cleanup. */;
1705   /**
1706      Installs a StructBinder-bound function pointer member of the
1707      given name and function in the given StructBinder.StructType
1708      target object.
1710      It creates a WASM proxy for the given function and arranges for
1711      that proxy to be cleaned up when tgt.dispose() is called. Throws
1712      on the slightest hint of error, e.g. tgt is-not-a StructType,
1713      name does not map to a struct-bound member, etc.
1715      As a special case, if the given function is a pointer, then
1716      `wasm.functionEntry()` is used to validate that it is a known
1717      function. If so, it is used as-is with no extra level of proxying
1718      or cleanup, else an exception is thrown. It is legal to pass a
1719      value of 0, indicating a NULL pointer, with the caveat that 0
1720      _is_ a legal function pointer in WASM but it will not be accepted
1721      as such _here_. (Justification: the function at address zero must
1722      be one which initially came from the WASM module, not a method we
1723      want to bind to a virtual table or VFS.)
1725      This function returns a proxy for itself which is bound to tgt
1726      and takes 2 args (name,func). That function returns the same
1727      thing as this one, permitting calls to be chained.
1729      If called with only 1 arg, it has no side effects but returns a
1730      func with the same signature as described above.
1732      ACHTUNG: because we cannot generically know how to transform JS
1733      exceptions into result codes, the installed functions do no
1734      automatic catching of exceptions. It is critical, to avoid
1735      undefined behavior in the C layer, that methods mapped via
1736      this function do not throw. The exception, as it were, to that
1737      rule is...
1739      If applyArgcCheck is true then each JS function (as opposed to
1740      function pointers) gets wrapped in a proxy which asserts that it
1741      is passed the expected number of arguments, throwing if the
1742      argument count does not match expectations. That is only intended
1743      for dev-time usage for sanity checking, and may leave the C
1744      environment in an undefined state.
1745   */
1746   const installMethod = function callee(
1747     tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck
1748   ){
1749     if(!(tgt instanceof StructBinder.StructType)){
1750       toss("Usage error: target object is-not-a StructType.");
1751     }else if(!(func instanceof Function) && !wasm.isPtr(func)){
1752       toss("Usage errror: expecting a Function or WASM pointer to one.");
1753     }
1754     if(1===arguments.length){
1755       return (n,f)=>callee(tgt, n, f, applyArgcCheck);
1756     }
1757     if(!callee.argcProxy){
1758       callee.argcProxy = function(tgt, funcName, func,sig){
1759         return function(...args){
1760           if(func.length!==arguments.length){
1761             toss("Argument mismatch for",
1762                  tgt.structInfo.name+"::"+funcName
1763                  +": Native signature is:",sig);
1764           }
1765           return func.apply(this, args);
1766         }
1767       };
1768       /* An ondispose() callback for use with
1769          StructBinder-created types. */
1770       callee.removeFuncList = function(){
1771         if(this.ondispose.__removeFuncList){
1772           this.ondispose.__removeFuncList.forEach(
1773             (v,ndx)=>{
1774               if('number'===typeof v){
1775                 try{wasm.uninstallFunction(v)}
1776                 catch(e){/*ignore*/}
1777               }
1778               /* else it's a descriptive label for the next number in
1779                  the list. */
1780             }
1781           );
1782           delete this.ondispose.__removeFuncList;
1783         }
1784       };
1785     }/*static init*/
1786     const sigN = tgt.memberSignature(name);
1787     if(sigN.length<2){
1788       toss("Member",name,"does not have a function pointer signature:",sigN);
1789     }
1790     const memKey = tgt.memberKey(name);
1791     const fProxy = (applyArgcCheck && !wasm.isPtr(func))
1792     /** This middle-man proxy is only for use during development, to
1793         confirm that we always pass the proper number of
1794         arguments. We know that the C-level code will always use the
1795         correct argument count. */
1796           ? callee.argcProxy(tgt, memKey, func, sigN)
1797           : func;
1798     if(wasm.isPtr(fProxy)){
1799       if(fProxy && !wasm.functionEntry(fProxy)){
1800         toss("Pointer",fProxy,"is not a WASM function table entry.");
1801       }
1802       tgt[memKey] = fProxy;
1803     }else{
1804       const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name, true));
1805       tgt[memKey] = pFunc;
1806       if(!tgt.ondispose || !tgt.ondispose.__removeFuncList){
1807         tgt.addOnDispose('ondispose.__removeFuncList handler',
1808                          callee.removeFuncList);
1809         tgt.ondispose.__removeFuncList = [];
1810       }
1811       tgt.ondispose.__removeFuncList.push(memKey, pFunc);
1812     }
1813     return (n,f)=>callee(tgt, n, f, applyArgcCheck);
1814   }/*installMethod*/;
1815   installMethod.installMethodArgcCheck = false;
1817   /**
1818      Installs methods into the given StructBinder.StructType-type
1819      instance. Each entry in the given methods object must map to a
1820      known member of the given StructType, else an exception will be
1821      triggered.  See installMethod() for more details, including the
1822      semantics of the 3rd argument.
1824      As an exception to the above, if any two or more methods in the
1825      2nd argument are the exact same function, installMethod() is
1826      _not_ called for the 2nd and subsequent instances, and instead
1827      those instances get assigned the same method pointer which is
1828      created for the first instance. This optimization is primarily to
1829      accommodate special handling of sqlite3_module::xConnect and
1830      xCreate methods.
1832      On success, returns its first argument. Throws on error.
1833   */
1834   const installMethods = function(
1835     structInstance, methods, applyArgcCheck = installMethod.installMethodArgcCheck
1836   ){
1837     const seen = new Map /* map of <Function, memberName> */;
1838     for(const k of Object.keys(methods)){
1839       const m = methods[k];
1840       const prior = seen.get(m);
1841       if(prior){
1842         const mkey = structInstance.memberKey(k);
1843         structInstance[mkey] = structInstance[structInstance.memberKey(prior)];
1844       }else{
1845         installMethod(structInstance, k, m, applyArgcCheck);
1846         seen.set(m, k);
1847       }
1848     }
1849     return structInstance;
1850   };
1852   /**
1853      Equivalent to calling installMethod(this,...arguments) with a
1854      first argument of this object. If called with 1 or 2 arguments
1855      and the first is an object, it's instead equivalent to calling
1856      installMethods(this,...arguments).
1857   */
1858   StructBinder.StructType.prototype.installMethod = function callee(
1859     name, func, applyArgcCheck = installMethod.installMethodArgcCheck
1860   ){
1861     return (arguments.length < 3 && name && 'object'===typeof name)
1862       ? installMethods(this, ...arguments)
1863       : installMethod(this, ...arguments);
1864   };
1866   /**
1867      Equivalent to calling installMethods() with a first argument
1868      of this object.
1869   */
1870   StructBinder.StructType.prototype.installMethods = function(
1871     methods, applyArgcCheck = installMethod.installMethodArgcCheck
1872   ){
1873     return installMethods(this, methods, applyArgcCheck);
1874   };