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 const config = Object.assign(Object.create(null),{ 140 exports: undefined, 141 memory: undefined, 142 bigIntEnabled: (()=>{ 143 if('undefined'!==typeof Module){ 144 /* Emscripten module will contain HEAPU64 when built with 145 -sWASM_BIGINT=1, else it will not. */ 146 return !!Module.HEAPU64; 147 } 148 return !!self.BigInt64Array; 149 })(), 150 allocExportName: 'malloc', 151 deallocExportName: 'free', 152 wasmfsOpfsDir: '/opfs' 153 }, apiConfig || {}); 154 155 [ 156 // If any of these config options are functions, replace them with 157 // the result of calling that function... 158 'exports', 'memory', 'wasmfsOpfsDir' 159 ].forEach((k)=>{ 160 if('function' === typeof config[k]){ 161 config[k] = config[k](); 162 } 163 }); 164 165 /** Throws a new Error, the message of which is the concatenation 166 all args with a space between each. */ 167 const toss = (...args)=>{throw new Error(args.join(' '))}; 168 169 if(config.wasmfsOpfsDir && !/^\/[^/]+$/.test(config.wasmfsOpfsDir)){ 170 toss("config.wasmfsOpfsDir must be falsy or in the form '/dir-name'."); 171 } 172 173 /** 174 Returns true if n is a 32-bit (signed) integer, else 175 false. This is used for determining when we need to switch to 176 double-type DB operations for integer values in order to keep 177 more precision. 178 */ 179 const isInt32 = (n)=>{ 180 return ('bigint'!==typeof n /*TypeError: can't convert BigInt to number*/) 181 && !!(n===(n|0) && n<=2147483647 && n>=-2147483648); 182 }; 183 /** 184 Returns true if the given BigInt value is small enough to fit 185 into an int64 value, else false. 186 */ 187 const bigIntFits64 = function f(b){ 188 if(!f._max){ 189 f._max = BigInt("0x7fffffffffffffff"); 190 f._min = ~f._max; 191 } 192 return b >= f._min && b <= f._max; 193 }; 194 195 /** 196 Returns true if the given BigInt value is small enough to fit 197 into an int32, else false. 198 */ 199 const bigIntFits32 = (b)=>(b >= (-0x7fffffffn - 1n) && b <= 0x7fffffffn); 200 201 /** 202 Returns true if the given BigInt value is small enough to fit 203 into a double value without loss of precision, else false. 204 */ 205 const bigIntFitsDouble = function f(b){ 206 if(!f._min){ 207 f._min = Number.MIN_SAFE_INTEGER; 208 f._max = Number.MAX_SAFE_INTEGER; 209 } 210 return b >= f._min && b <= f._max; 211 }; 212 213 /** Returns v if v appears to be a TypedArray, else false. */ 214 const isTypedArray = (v)=>{ 215 return (v && v.constructor && isInt32(v.constructor.BYTES_PER_ELEMENT)) ? v : false; 216 }; 217 218 219 /** Internal helper to use in operations which need to distinguish 220 between TypedArrays which are backed by a SharedArrayBuffer 221 from those which are not. */ 222 const __SAB = ('undefined'===typeof SharedArrayBuffer) 223 ? function(){} : SharedArrayBuffer; 224 /** Returns true if the given TypedArray object is backed by a 225 SharedArrayBuffer, else false. */ 226 const isSharedTypedArray = (aTypedArray)=>(aTypedArray.buffer instanceof __SAB); 227 228 /** 229 Returns either aTypedArray.slice(begin,end) (if 230 aTypedArray.buffer is a SharedArrayBuffer) or 231 aTypedArray.subarray(begin,end) (if it's not). 232 233 This distinction is important for APIs which don't like to 234 work on SABs, e.g. TextDecoder, and possibly for our 235 own APIs which work on memory ranges which "might" be 236 modified by other threads while they're working. 237 */ 238 const typedArrayPart = (aTypedArray, begin, end)=>{ 239 return isSharedTypedArray(aTypedArray) 240 ? aTypedArray.slice(begin, end) 241 : aTypedArray.subarray(begin, end); 242 }; 243 244 /** 245 Returns true if v appears to be one of our bind()-able 246 TypedArray types: Uint8Array or Int8Array. Support for 247 TypedArrays with element sizes >1 is TODO. 248 */ 249 const isBindableTypedArray = (v)=>{ 250 return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT); 251 }; 252 253 /** 254 Returns true if v appears to be one of the TypedArray types 255 which is legal for holding SQL code (as opposed to binary blobs). 256 257 Currently this is the same as isBindableTypedArray() but it 258 seems likely that we'll eventually want to add Uint32Array 259 and friends to the isBindableTypedArray() list but not to the 260 isSQLableTypedArray() list. 261 */ 262 const isSQLableTypedArray = (v)=>{ 263 return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT); 264 }; 265 266 /** Returns true if isBindableTypedArray(v) does, else throws with a message 267 that v is not a supported TypedArray value. */ 268 const affirmBindableTypedArray = (v)=>{ 269 return isBindableTypedArray(v) 270 || toss("Value is not of a supported TypedArray type."); 271 }; 272 273 const utf8Decoder = new TextDecoder('utf-8'); 274 275 /** 276 Uses TextDecoder to decode the given half-open range of the 277 given TypedArray to a string. This differs from a simple 278 call to TextDecoder in that it accounts for whether the 279 first argument is backed by a SharedArrayBuffer or not, 280 and can work more efficiently if it's not (TextDecoder 281 refuses to act upon an SAB). 282 */ 283 const typedArrayToString = function(typedArray, begin, end){ 284 return utf8Decoder.decode(typedArrayPart(typedArray, begin,end)); 285 }; 286 287 /** 288 If v is-a Array, its join('') result is returned. If 289 isSQLableTypedArray(v) is true then typedArrayToString(v) is 290 returned. Else v is returned as-is. 291 */ 292 const flexibleString = function(v){ 293 if(isSQLableTypedArray(v)) return typedArrayToString(v); 294 else if(Array.isArray(v)) return v.join(''); 295 return v; 296 }; 297 298 /** 299 An Error subclass specifically for reporting Wasm-level malloc() 300 failure and enabling clients to unambiguously identify such 301 exceptions. 302 */ 303 class WasmAllocError extends Error { 304 constructor(...args){ 305 super(...args); 306 this.name = 'WasmAllocError'; 307 } 308 }; 309 /** 310 Functionally equivalent to the WasmAllocError constructor but may 311 be used as part of an expression, e.g.: 312 313 ``` 314 return someAllocatingFunction(x) || WasmAllocError.toss(...); 315 ``` 316 */ 317 WasmAllocError.toss = (...args)=>{ 318 throw new WasmAllocError(...args); 319 }; 320 321 /** 322 The main sqlite3 binding API gets installed into this object, 323 mimicking the C API as closely as we can. The numerous members 324 names with prefixes 'sqlite3_' and 'SQLITE_' behave, insofar as 325 possible, identically to the C-native counterparts, as documented at: 326 327 https://www.sqlite.org/c3ref/intro.html 328 329 A very few exceptions require an additional level of proxy 330 function or may otherwise require special attention in the WASM 331 environment, and all such cases are document here. Those not 332 documented here are installed as 1-to-1 proxies for their C-side 333 counterparts. 334 */ 335 const capi = { 336 /** 337 sqlite3_create_function_v2() differs from its native 338 counterpart only in the following ways: 339 340 1) The fourth argument (`eTextRep`) argument must not specify 341 any encoding other than sqlite3.SQLITE_UTF8. The JS API does not 342 currently support any other encoding and likely never 343 will. This function does not replace that argument on its own 344 because it may contain other flags. 345 346 2) Any of the four final arguments may be either WASM pointers 347 (assumed to be function pointers) or JS Functions. In the 348 latter case, each gets bound to WASM using 349 sqlite3.capi.wasm.installFunction() and that wrapper is passed 350 on to the native implementation. 351 352 The semantics of JS functions are: 353 354 xFunc: is passed `(pCtx, ...values)`. Its return value becomes 355 the new SQL function's result. 356 357 xStep: is passed `(pCtx, ...values)`. Its return value is 358 ignored. 359 360 xFinal: is passed `(pCtx)`. Its return value becomes the new 361 aggregate SQL function's result. 362 363 xDestroy: is passed `(void*)`. Its return value is ignored. The 364 pointer passed to it is the one from the 5th argument to 365 sqlite3_create_function_v2(). 366 367 Note that: 368 369 - `pCtx` in the above descriptions is a `sqlite3_context*`. At 370 least 99 times out of a hundred, that initial argument will 371 be irrelevant for JS UDF bindings, but it needs to be there 372 so that the cases where it _is_ relevant, in particular with 373 window and aggregate functions, have full access to the 374 lower-level sqlite3 APIs. 375 376 - When wrapping JS functions, the remaining arguments are passd 377 to them as positional arguments, not as an array of 378 arguments, because that allows callback definitions to be 379 more JS-idiomatic than C-like. For example `(pCtx,a,b)=>a+b` 380 is more intuitive and legible than 381 `(pCtx,args)=>args[0]+args[1]`. For cases where an array of 382 arguments would be more convenient, the callbacks simply need 383 to be declared like `(pCtx,...args)=>{...}`, in which case 384 `args` will be an array. 385 386 - If a JS wrapper throws, it gets translated to 387 sqlite3_result_error() or sqlite3_result_error_nomem(), 388 depending on whether the exception is an 389 sqlite3.WasmAllocError object or not. 390 391 - When passing on WASM function pointers, arguments are _not_ 392 converted or reformulated. They are passed on as-is in raw 393 pointer form using their native C signatures. Only JS 394 functions passed in to this routine, and thus wrapped by this 395 routine, get automatic conversions of arguments and result 396 values. The routines which perform those conversions are 397 exposed for client-side use as 398 sqlite3_create_function_v2.convertUdfArgs() and 399 sqlite3_create_function_v2.setUdfResult(). sqlite3_create_function() 400 and sqlite3_create_window_function() have those same methods. 401 402 For xFunc(), xStep(), and xFinal(): 403 404 - When called from SQL, arguments to the UDF, and its result, 405 will be converted between JS and SQL with as much fidelity as 406 is feasible, triggering an exception if a type conversion 407 cannot be determined. Some freedom is afforded to numeric 408 conversions due to friction between the JS and C worlds: 409 integers which are larger than 32 bits may be treated as 410 doubles or BigInts. 411 412 If any JS-side bound functions throw, those exceptions are 413 intercepted and converted to database-side errors with the 414 exception of xDestroy(): any exception from it is ignored, 415 possibly generating a console.error() message. Destructors 416 must not throw. 417 418 Once installed, there is currently no way to uninstall the 419 automatically-converted WASM-bound JS functions from WASM. They 420 can be uninstalled from the database as documented in the C 421 API, but this wrapper currently has no infrastructure in place 422 to also free the WASM-bound JS wrappers, effectively resulting 423 in a memory leak if the client uninstalls the UDF. Improving that 424 is a potential TODO, but removing client-installed UDFs is rare 425 in practice. If this factor is relevant for a given client, 426 they can create WASM-bound JS functions themselves, hold on to their 427 pointers, and pass the pointers in to here. Later on, they can 428 free those pointers (using `wasm.uninstallFunction()` or 429 equivalent). 430 431 C reference: https://www.sqlite.org/c3ref/create_function.html 432 433 Maintenance reminder: the ability to add new 434 WASM-accessible functions to the runtime requires that the 435 WASM build is compiled with emcc's `-sALLOW_TABLE_GROWTH` 436 flag. 437 */ 438 sqlite3_create_function_v2: function( 439 pDb, funcName, nArg, eTextRep, pApp, 440 xFunc, xStep, xFinal, xDestroy 441 ){/*installed later*/}, 442 /** 443 Equivalent to passing the same arguments to 444 sqlite3_create_function_v2(), with 0 as the final argument. 445 */ 446 sqlite3_create_function:function( 447 pDb, funcName, nArg, eTextRep, pApp, 448 xFunc, xStep, xFinal 449 ){/*installed later*/}, 450 /** 451 The sqlite3_create_window_function() JS wrapper differs from 452 its native implementation in the exact same way that 453 sqlite3_create_function_v2() does. The additional function, 454 xInverse(), is treated identically to xStep() by the wrapping 455 layer. 456 */ 457 sqlite3_create_window_function: function( 458 pDb, funcName, nArg, eTextRep, pApp, 459 xStep, xFinal, xValue, xInverse, xDestroy 460 ){/*installed later*/}, 461 /** 462 The sqlite3_prepare_v3() binding handles two different uses 463 with differing JS/WASM semantics: 464 465 1) sqlite3_prepare_v3(pDb, sqlString, -1, prepFlags, ppStmt , null) 466 467 2) sqlite3_prepare_v3(pDb, sqlPointer, sqlByteLen, prepFlags, ppStmt, sqlPointerToPointer) 468 469 Note that the SQL length argument (the 3rd argument) must, for 470 usage (1), always be negative because it must be a byte length 471 and that value is expensive to calculate from JS (where only 472 the character length of strings is readily available). It is 473 retained in this API's interface for code/documentation 474 compatibility reasons but is currently _always_ ignored. With 475 usage (2), the 3rd argument is used as-is but is is still 476 critical that the C-style input string (2nd argument) be 477 terminated with a 0 byte. 478 479 In usage (1), the 2nd argument must be of type string, 480 Uint8Array, or Int8Array (either of which is assumed to 481 hold SQL). If it is, this function assumes case (1) and 482 calls the underyling C function with the equivalent of: 483 484 (pDb, sqlAsString, -1, prepFlags, ppStmt, null) 485 486 The `pzTail` argument is ignored in this case because its 487 result is meaningless when a string-type value is passed 488 through: the string goes through another level of internal 489 conversion for WASM's sake and the result pointer would refer 490 to that transient conversion's memory, not the passed-in 491 string. 492 493 If the sql argument is not a string, it must be a _pointer_ to 494 a NUL-terminated string which was allocated in the WASM memory 495 (e.g. using capi.wasm.alloc() or equivalent). In that case, 496 the final argument may be 0/null/undefined or must be a pointer 497 to which the "tail" of the compiled SQL is written, as 498 documented for the C-side sqlite3_prepare_v3(). In case (2), 499 the underlying C function is called with the equivalent of: 500 501 (pDb, sqlAsPointer, sqlByteLen, prepFlags, ppStmt, pzTail) 502 503 It returns its result and compiled statement as documented in 504 the C API. Fetching the output pointers (5th and 6th 505 parameters) requires using `capi.wasm.getMemValue()` (or 506 equivalent) and the `pzTail` will point to an address relative to 507 the `sqlAsPointer` value. 508 509 If passed an invalid 2nd argument type, this function will 510 return SQLITE_MISUSE and sqlite3_errmsg() will contain a string 511 describing the problem. 512 513 Side-note: if given an empty string, or one which contains only 514 comments or an empty SQL expression, 0 is returned but the result 515 output pointer will be NULL. 516 */ 517 sqlite3_prepare_v3: (dbPtr, sql, sqlByteLen, prepFlags, 518 stmtPtrPtr, strPtrPtr)=>{}/*installed later*/, 519 520 /** 521 Equivalent to calling sqlite3_prapare_v3() with 0 as its 4th argument. 522 */ 523 sqlite3_prepare_v2: (dbPtr, sql, sqlByteLen, 524 stmtPtrPtr,strPtrPtr)=>{}/*installed later*/, 525 526 /** 527 This binding enables the callback argument to be a JavaScript. 528 529 If the callback is a function, then for the duration of the 530 sqlite3_exec() call, it installs a WASM-bound function which 531 acts as a proxy for the given callback. That proxy will also 532 perform a conversion of the callback's arguments from 533 `(char**)` to JS arrays of strings. However, for API 534 consistency's sake it will still honor the C-level callback 535 parameter order and will call it like: 536 537 `callback(pVoid, colCount, listOfValues, listOfColNames)` 538 539 If the callback is not a JS function then this binding performs 540 no translation of the callback, but the sql argument is still 541 converted to a WASM string for the call using the 542 "flexible-string" argument converter. 543 */ 544 sqlite3_exec: (pDb, sql, callback, pVoid, pErrMsg)=>{}/*installed later*/, 545 546 /** 547 If passed a single argument which appears to be a byte-oriented 548 TypedArray (Int8Array or Uint8Array), this function treats that 549 TypedArray as an output target, fetches `theArray.byteLength` 550 bytes of randomness, and populates the whole array with it. As 551 a special case, if the array's length is 0, this function 552 behaves as if it were passed (0,0). When called this way, it 553 returns its argument, else it returns the `undefined` value. 554 555 If called with any other arguments, they are passed on as-is 556 to the C API. Results are undefined if passed any incompatible 557 values. 558 */ 559 sqlite3_randomness: (n, outPtr)=>{/*installed later*/}, 560 561 /** 562 Various internal-use utilities are added here as needed. They 563 are bound to an object only so that we have access to them in 564 the differently-scoped steps of the API bootstrapping 565 process. At the end of the API setup process, this object gets 566 removed. These are NOT part of the public API. 567 */ 568 util:{ 569 affirmBindableTypedArray, flexibleString, 570 bigIntFits32, bigIntFits64, bigIntFitsDouble, 571 isBindableTypedArray, 572 isInt32, isSQLableTypedArray, isTypedArray, 573 typedArrayToString, 574 isUIThread: ()=>'undefined'===typeof WorkerGlobalScope, 575 isSharedTypedArray, 576 typedArrayPart 577 }, 578 579 /** 580 Holds state which are specific to the WASM-related 581 infrastructure and glue code. It is not expected that client 582 code will normally need these, but they're exposed here in case 583 it does. These APIs are _not_ to be considered an 584 official/stable part of the sqlite3 WASM API. They may change 585 as the developers' experience suggests appropriate changes. 586 587 Note that a number of members of this object are injected 588 dynamically after the api object is fully constructed, so 589 not all are documented inline here. 590 */ 591 wasm: { 592 //^^^ TODO?: move wasm from sqlite3.capi.wasm to sqlite3.wasm 593 /** 594 Emscripten APIs have a deep-seated assumption that all pointers 595 are 32 bits. We'll remain optimistic that that won't always be 596 the case and will use this constant in places where we might 597 otherwise use a hard-coded 4. 598 */ 599 ptrSizeof: config.wasmPtrSizeof || 4, 600 /** 601 The WASM IR (Intermediate Representation) value for 602 pointer-type values. It MUST refer to a value type of the 603 size described by this.ptrSizeof _or_ it may be any value 604 which ends in '*', which Emscripten's glue code internally 605 translates to i32. 606 */ 607 ptrIR: config.wasmPtrIR || "i32", 608 /** 609 True if BigInt support was enabled via (e.g.) the 610 Emscripten -sWASM_BIGINT flag, else false. When 611 enabled, certain 64-bit sqlite3 APIs are enabled which 612 are not otherwise enabled due to JS/WASM int64 613 impedence mismatches. 614 */ 615 bigIntEnabled: !!config.bigIntEnabled, 616 /** 617 The symbols exported by the WASM environment. 618 */ 619 exports: config.exports 620 || toss("Missing API config.exports (WASM module exports)."), 621 622 /** 623 When Emscripten compiles with `-sIMPORT_MEMORY`, it 624 initalizes the heap and imports it into wasm, as opposed to 625 the other way around. In this case, the memory is not 626 available via this.exports.memory. 627 */ 628 memory: config.memory || config.exports['memory'] 629 || toss("API config object requires a WebAssembly.Memory object", 630 "in either config.exports.memory (exported)", 631 "or config.memory (imported)."), 632 633 /** 634 The API's one single point of access to the WASM-side memory 635 allocator. Works like malloc(3) (and is likely bound to 636 malloc()) but throws an WasmAllocError if allocation fails. It is 637 important that any code which might pass through the sqlite3 C 638 API NOT throw and must instead return SQLITE_NOMEM (or 639 equivalent, depending on the context). 640 641 That said, very few cases in the API can result in 642 client-defined functions propagating exceptions via the C-style 643 API. Most notably, this applies ot User-defined SQL Functions 644 (UDFs) registered via sqlite3_create_function_v2(). For that 645 specific case it is recommended that all UDF creation be 646 funneled through a utility function and that a wrapper function 647 be added around the UDF which catches any exception and sets 648 the error state to OOM. (The overall complexity of registering 649 UDFs essentially requires a helper for doing so!) 650 */ 651 alloc: undefined/*installed later*/, 652 /** 653 The API's one single point of access to the WASM-side memory 654 deallocator. Works like free(3) (and is likely bound to 655 free()). 656 */ 657 dealloc: undefined/*installed later*/ 658 659 /* Many more wasm-related APIs get installed later on. */ 660 }/*wasm*/ 661 }/*capi*/; 662 663 const wasm = capi.wasm, util = capi.util; 664 665 /** 666 wasm.alloc()'s srcTypedArray.byteLength bytes, 667 populates them with the values from the source 668 TypedArray, and returns the pointer to that memory. The 669 returned pointer must eventually be passed to 670 wasm.dealloc() to clean it up. 671 672 As a special case, to avoid further special cases where 673 this is used, if srcTypedArray.byteLength is 0, it 674 allocates a single byte and sets it to the value 675 0. Even in such cases, calls must behave as if the 676 allocated memory has exactly srcTypedArray.byteLength 677 bytes. 678 679 ACHTUNG: this currently only works for Uint8Array and 680 Int8Array types and will throw if srcTypedArray is of 681 any other type. 682 */ 683 wasm.allocFromTypedArray = function(srcTypedArray){ 684 affirmBindableTypedArray(srcTypedArray); 685 const pRet = wasm.alloc(srcTypedArray.byteLength || 1); 686 wasm.heapForSize(srcTypedArray.constructor).set(srcTypedArray.byteLength ? srcTypedArray : [0], pRet); 687 return pRet; 688 }; 689 690 const keyAlloc = config.allocExportName || 'malloc', 691 keyDealloc = config.deallocExportName || 'free'; 692 for(const key of [keyAlloc, keyDealloc]){ 693 const f = wasm.exports[key]; 694 if(!(f instanceof Function)) toss("Missing required exports[",key,"] function."); 695 } 696 697 wasm.alloc = function(n){ 698 const m = wasm.exports[keyAlloc](n); 699 if(!m) throw new WasmAllocError("Failed to allocate "+n+" bytes."); 700 return m; 701 }; 702 703 wasm.dealloc = (m)=>wasm.exports[keyDealloc](m); 704 705 /** 706 Reports info about compile-time options using 707 sqlite_compileoption_get() and sqlite3_compileoption_used(). It 708 has several distinct uses: 709 710 If optName is an array then it is expected to be a list of 711 compilation options and this function returns an object 712 which maps each such option to true or false, indicating 713 whether or not the given option was included in this 714 build. That object is returned. 715 716 If optName is an object, its keys are expected to be compilation 717 options and this function sets each entry to true or false, 718 indicating whether the compilation option was used or not. That 719 object is returned. 720 721 If passed no arguments then it returns an object mapping 722 all known compilation options to their compile-time values, 723 or boolean true if they are defined with no value. This 724 result, which is relatively expensive to compute, is cached 725 and returned for future no-argument calls. 726 727 In all other cases it returns true if the given option was 728 active when when compiling the sqlite3 module, else false. 729 730 Compile-time option names may optionally include their 731 "SQLITE_" prefix. When it returns an object of all options, 732 the prefix is elided. 733 */ 734 wasm.compileOptionUsed = function f(optName){ 735 if(!arguments.length){ 736 if(f._result) return f._result; 737 else if(!f._opt){ 738 f._rx = /^([^=]+)=(.+)/; 739 f._rxInt = /^-?\d+$/; 740 f._opt = function(opt, rv){ 741 const m = f._rx.exec(opt); 742 rv[0] = (m ? m[1] : opt); 743 rv[1] = m ? (f._rxInt.test(m[2]) ? +m[2] : m[2]) : true; 744 }; 745 } 746 const rc = {}, ov = [0,0]; 747 let i = 0, k; 748 while((k = capi.sqlite3_compileoption_get(i++))){ 749 f._opt(k,ov); 750 rc[ov[0]] = ov[1]; 751 } 752 return f._result = rc; 753 }else if(Array.isArray(optName)){ 754 const rc = {}; 755 optName.forEach((v)=>{ 756 rc[v] = capi.sqlite3_compileoption_used(v); 757 }); 758 return rc; 759 }else if('object' === typeof optName){ 760 Object.keys(optName).forEach((k)=> { 761 optName[k] = capi.sqlite3_compileoption_used(k); 762 }); 763 return optName; 764 } 765 return ( 766 'string'===typeof optName 767 ) ? !!capi.sqlite3_compileoption_used(optName) : false; 768 }/*compileOptionUsed()*/; 769 770 /** 771 Signatures for the WASM-exported C-side functions. Each entry 772 is an array with 2+ elements: 773 774 [ "c-side name", 775 "result type" (wasm.xWrap() syntax), 776 [arg types in xWrap() syntax] 777 // ^^^ this needn't strictly be an array: it can be subsequent 778 // elements instead: [x,y,z] is equivalent to x,y,z 779 ] 780 781 Note that support for the API-specific data types in the 782 result/argument type strings gets plugged in at a later phase in 783 the API initialization process. 784 */ 785 wasm.bindingSignatures = [ 786 // Please keep these sorted by function name! 787 ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"], 788 ["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*" 789 /* TODO: we should arguably write a custom wrapper which knows 790 how to handle Blob, TypedArrays, and JS strings. */ 791 ], 792 ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"], 793 ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"], 794 ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"], 795 ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"], 796 ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"], 797 ["sqlite3_bind_text","int", "sqlite3_stmt*", "int", "string", "int", "int" 798 /* We should arguably create a hand-written binding of 799 bind_text() which does more flexible text conversion, along 800 the lines of sqlite3_prepare_v3(). The slightly problematic 801 part is the final argument (text destructor). */ 802 ], 803 ["sqlite3_close_v2", "int", "sqlite3*"], 804 ["sqlite3_changes", "int", "sqlite3*"], 805 ["sqlite3_clear_bindings","int", "sqlite3_stmt*"], 806 ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"], 807 ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"], 808 ["sqlite3_column_count", "int", "sqlite3_stmt*"], 809 ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"], 810 ["sqlite3_column_int","int", "sqlite3_stmt*", "int"], 811 ["sqlite3_column_name","string", "sqlite3_stmt*", "int"], 812 ["sqlite3_column_text","string", "sqlite3_stmt*", "int"], 813 ["sqlite3_column_type","int", "sqlite3_stmt*", "int"], 814 ["sqlite3_compileoption_get", "string", "int"], 815 ["sqlite3_compileoption_used", "int", "string"], 816 /* sqlite3_create_function(), sqlite3_create_function_v2(), and 817 sqlite3_create_window_function() use hand-written bindings to 818 simplify handling of their function-type arguments. */ 819 ["sqlite3_data_count", "int", "sqlite3_stmt*"], 820 ["sqlite3_db_filename", "string", "sqlite3*", "string"], 821 ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"], 822 ["sqlite3_db_name", "string", "sqlite3*", "int"], 823 ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"] 824 /* Careful! Short version: de/serialize() are problematic because they 825 might use a different allocator than the user for managing the 826 deserialized block. de/serialize() are ONLY safe to use with 827 sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. */, 828 ["sqlite3_errmsg", "string", "sqlite3*"], 829 ["sqlite3_error_offset", "int", "sqlite3*"], 830 ["sqlite3_errstr", "string", "int"], 831 /*["sqlite3_exec", "int", "sqlite3*", "string", "*", "*", "**" 832 Handled seperately to perform translation of the callback 833 into a WASM-usable one. ],*/ 834 ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"], 835 ["sqlite3_extended_errcode", "int", "sqlite3*"], 836 ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"], 837 ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"], 838 ["sqlite3_finalize", "int", "sqlite3_stmt*"], 839 ["sqlite3_free", undefined,"*"], 840 ["sqlite3_initialize", undefined], 841 ["sqlite3_interrupt", undefined, "sqlite3*" 842 /* ^^^ we cannot actually currently support this because JS is 843 single-threaded and we don't have a portable way to access a DB 844 from 2 SharedWorkers concurrently. */], 845 ["sqlite3_libversion", "string"], 846 ["sqlite3_libversion_number", "int"], 847 ["sqlite3_malloc", "*","int"], 848 ["sqlite3_open", "int", "string", "*"], 849 ["sqlite3_open_v2", "int", "string", "*", "int", "string"], 850 /* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled 851 separately due to us requiring two different sets of semantics 852 for those, depending on how their SQL argument is provided. */ 853 /* sqlite3_randomness() uses a hand-written wrapper to extend 854 the range of supported argument types. */ 855 ["sqlite3_realloc", "*","*","int"], 856 ["sqlite3_reset", "int", "sqlite3_stmt*"], 857 ["sqlite3_result_blob",undefined, "*", "*", "int", "*"], 858 ["sqlite3_result_double",undefined, "*", "f64"], 859 ["sqlite3_result_error",undefined, "*", "string", "int"], 860 ["sqlite3_result_error_code", undefined, "*", "int"], 861 ["sqlite3_result_error_nomem", undefined, "*"], 862 ["sqlite3_result_error_toobig", undefined, "*"], 863 ["sqlite3_result_int",undefined, "*", "int"], 864 ["sqlite3_result_null",undefined, "*"], 865 ["sqlite3_result_text",undefined, "*", "string", "int", "*"], 866 ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"], 867 ["sqlite3_shutdown", undefined], 868 ["sqlite3_sourceid", "string"], 869 ["sqlite3_sql", "string", "sqlite3_stmt*"], 870 ["sqlite3_step", "int", "sqlite3_stmt*"], 871 ["sqlite3_strglob", "int", "string","string"], 872 ["sqlite3_strlike", "int", "string","string","int"], 873 ["sqlite3_trace_v2", "int", "sqlite3*", "int", "*", "*"], 874 ["sqlite3_total_changes", "int", "sqlite3*"], 875 ["sqlite3_uri_boolean", "int", "string", "string", "int"], 876 ["sqlite3_uri_key", "string", "string", "int"], 877 ["sqlite3_uri_parameter", "string", "string", "string"], 878 ["sqlite3_user_data","void*", "sqlite3_context*"], 879 ["sqlite3_value_blob", "*", "sqlite3_value*"], 880 ["sqlite3_value_bytes","int", "sqlite3_value*"], 881 ["sqlite3_value_double","f64", "sqlite3_value*"], 882 ["sqlite3_value_int","int", "sqlite3_value*"], 883 ["sqlite3_value_text", "string", "sqlite3_value*"], 884 ["sqlite3_value_type", "int", "sqlite3_value*"], 885 ["sqlite3_vfs_find", "*", "string"], 886 ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"], 887 ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"] 888 ]/*wasm.bindingSignatures*/; 889 890 if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ 891 /* ^^^ "the problem" is that this is an option feature and the 892 build-time function-export list does not currently take 893 optional features into account. */ 894 wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); 895 } 896 897 /** 898 Functions which require BigInt (int64) support are separated from 899 the others because we need to conditionally bind them or apply 900 dummy impls, depending on the capabilities of the environment. 901 */ 902 wasm.bindingSignatures.int64 = [ 903 ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]], 904 ["sqlite3_changes64","i64", ["sqlite3*"]], 905 ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]], 906 ["sqlite3_malloc64", "*","i64"], 907 ["sqlite3_msize", "i64", "*"], 908 ["sqlite3_realloc64", "*","*", "i64"], 909 ["sqlite3_result_int64",undefined, "*", "i64"], 910 ["sqlite3_total_changes64", "i64", ["sqlite3*"]], 911 ["sqlite3_uri_int64", "i64", ["string", "string", "i64"]], 912 ["sqlite3_value_int64","i64", "sqlite3_value*"], 913 ]; 914 915 /** 916 Functions which are intended solely for API-internal use by the 917 WASM components, not client code. These get installed into 918 capi.wasm. 919 */ 920 wasm.bindingSignatures.wasm = [ 921 ["sqlite3_wasm_db_reset", "int", "sqlite3*"], 922 ["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"], 923 ["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"] 924 ]; 925 926 927 /** 928 sqlite3.wasm.pstack (pseudo-stack) holds a special-case 929 stack-style allocator intended only for use with _small_ data of 930 not more than (in total) a few kb in size, managed as if it were 931 stack-based. 932 933 It has only a single intended usage: 934 935 ``` 936 const stackPos = pstack.pointer; 937 try{ 938 const ptr = pstack.alloc(8); 939 // ==> pstack.pointer === ptr 940 const otherPtr = pstack.alloc(8); 941 // ==> pstack.pointer === otherPtr 942 ... 943 }finally{ 944 pstack.restore(stackPos); 945 // ==> pstack.pointer === stackPos 946 } 947 ``` 948 949 This allocator is much faster than a general-purpose one but is 950 limited to usage patterns like the one shown above. 951 952 It operates from a static range of memory which lives outside of 953 space managed by Emscripten's stack-management, so does not 954 collide with Emscripten-provided stack allocation APIs. The 955 memory lives in the WASM heap and can be used with routines such 956 as wasm.setMemValue() and any wasm.heap8u().slice(). 957 */ 958 wasm.pstack = Object.assign(Object.create(null),{ 959 /** 960 Sets the current pstack position to the given pointer. Results 961 are undefined if the passed-in value did not come from 962 this.pointer. 963 */ 964 restore: wasm.exports.sqlite3_wasm_pstack_restore, 965 /** 966 Attempts to allocate the given number of bytes from the 967 pstack. On success, it zeroes out a block of memory of the 968 given size, adjusts the pstack pointer, and returns a pointer 969 to the memory. On error, returns throws a WasmAllocError. The 970 memory must eventually be released using restore(). 971 972 This method always adjusts the given value to be a multiple 973 of 8 bytes because failing to do so can lead to incorrect 974 results when reading and writing 64-bit values from/to the WASM 975 heap. Similarly, the returned address is always 8-byte aligned. 976 */ 977 alloc: (n)=>{ 978 return wasm.exports.sqlite3_wasm_pstack_alloc(n) 979 || WasmAllocError.toss("Could not allocate",n, 980 "bytes from the pstack."); 981 }, 982 /** 983 alloc()'s n chunks, each sz bytes, as a single memory block and 984 returns the addresses as an array of n element, each holding 985 the address of one chunk. 986 987 Throws a WasmAllocError if allocation fails. 988 989 Example: 990 991 ``` 992 const [p1, p2, p3] = wasm.pstack.allocChunks(3,4); 993 ``` 994 */ 995 allocChunks: (n,sz)=>{ 996 const mem = wasm.pstack.alloc(n * sz); 997 const rc = []; 998 let i = 0, offset = 0; 999 for(; i < n; offset = (sz * ++i)){ 1000 rc.push(mem + offset); 1001 } 1002 return rc; 1003 }, 1004 /** 1005 A convenience wrapper for allocChunks() which sizes each chunk 1006 as either 8 bytes (safePtrSize is truthy) or wasm.ptrSizeof (if 1007 safePtrSize is falsy). 1008 1009 How it returns its result differs depending on its first 1010 argument: if it's 1, it returns a single pointer value. If it's 1011 more than 1, it returns the same as allocChunks(). 1012 1013 When a returned pointers will refer to a 64-bit value, e.g. a 1014 double or int64, and that value must be written or fetched, 1015 e.g. using wasm.setMemValue() or wasm.getMemValue(), it is 1016 important that the pointer in question be aligned to an 8-byte 1017 boundary or else it will not be fetched or written properly and 1018 will corrupt or read neighboring memory. 1019 1020 However, when all pointers involved point to "small" data, it 1021 is safe to pass a falsy value to save a tiny bit of memory. 1022 */ 1023 allocPtr: (n=1,safePtrSize=true)=>{ 1024 return 1===n 1025 ? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof) 1026 : wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof); 1027 } 1028 })/*wasm.pstack*/; 1029 Object.defineProperties(wasm.pstack, { 1030 /** 1031 sqlite3.wasm.pstack.pointer resolves to the current pstack 1032 position pointer. This value is intended _only_ to be saved 1033 for passing to restore(). Writing to this memory, without 1034 first reserving it via wasm.pstack.alloc() and friends, leads 1035 to undefined results. 1036 */ 1037 pointer: { 1038 configurable: false, iterable: true, writeable: false, 1039 get: wasm.exports.sqlite3_wasm_pstack_ptr 1040 //Whether or not a setter as an alternative to restore() is 1041 //clearer or would just lead to confusion is unclear. 1042 //set: wasm.exports.sqlite3_wasm_pstack_restore 1043 }, 1044 /** 1045 Resolves to the total number of bytes available in the pstack, 1046 including any space which is currently allocated. This value is 1047 a compile-time constant. 1048 */ 1049 quota: { 1050 configurable: false, iterable: true, writeable: false, 1051 get: wasm.exports.sqlite3_wasm_pstack_quota 1052 } 1053 })/*wasm.pstack properties*/; 1054 1055 /** 1056 sqlite3.wasm.pstack.remaining resolves to the amount of 1057 space remaining in the pstack. 1058 */ 1059 Object.defineProperty(wasm.pstack, 'remaining', { 1060 configurable: false, iterable: true, writeable: false, 1061 get: wasm.exports.sqlite3_wasm_pstack_remaining 1062 }); 1063 1064 /** 1065 An Error subclass specifically for reporting DB-level errors and 1066 enabling clients to unambiguously identify such exceptions. 1067 The C-level APIs never throw, but some of the higher-level 1068 C-style APIs do and the object-oriented APIs use exceptions 1069 exclusively to report errors. 1070 */ 1071 class SQLite3Error extends Error { 1072 /** 1073 Constructs this object with a message equal to all arguments 1074 concatenated with a space between each one. As a special case, 1075 if it's passed only a single integer argument, the string form 1076 of that argument is the result of 1077 sqlite3.capi.sqlite3_js_rc_str() or (if that returns falsy), a 1078 synthesized string which contains that integer. 1079 */ 1080 constructor(...args){ 1081 if(1===args.length && 'number'===typeof args[0] && args[0]===(args[0] | 0)){ 1082 super(capi.sqlite3_js_rc_str(args[0]) || ("Unknown result code #"+args[0])); 1083 }else{ 1084 super(args.join(' ')); 1085 } 1086 this.name = 'SQLite3Error'; 1087 } 1088 }; 1089 /** 1090 Functionally equivalent to the SQLite3Error constructor but may 1091 be used as part of an expression, e.g.: 1092 1093 ``` 1094 return someFunction(x) || SQLite3Error.toss(...); 1095 ``` 1096 */ 1097 SQLite3Error.toss = (...args)=>{ 1098 throw new SQLite3Error(...args); 1099 }; 1100 1101 capi.sqlite3_randomness = (...args)=>{ 1102 if(1===args.length && util.isTypedArray(args[0]) 1103 && 1===args[0].BYTES_PER_ELEMENT){ 1104 const ta = args[0]; 1105 if(0===ta.byteLength){ 1106 wasm.exports.sqlite3_randomness(0,0); 1107 return ta; 1108 } 1109 const stack = wasm.pstack.pointer; 1110 try { 1111 let n = ta.byteLength, offset = 0; 1112 const r = wasm.exports.sqlite3_randomness; 1113 const heap = wasm.heap8u(); 1114 const nAlloc = n < 512 ? n : 512; 1115 const ptr = wasm.pstack.alloc(nAlloc); 1116 do{ 1117 const j = (n>nAlloc ? nAlloc : n); 1118 r(j, ptr); 1119 ta.set(typedArrayPart(heap, ptr, ptr+j), offset); 1120 n -= j; 1121 offset += j; 1122 } while(n > 0); 1123 }catch(e){ 1124 console.error("Highly unexpected (and ignored!) "+ 1125 "exception in sqlite3_randomness():",e); 1126 }finally{ 1127 wasm.pstack.restore(stack); 1128 } 1129 return ta; 1130 } 1131 capi.wasm.exports.sqlite3_randomness(...args); 1132 }; 1133 1134 /** State for sqlite3_wasmfs_opfs_dir(). */ 1135 let __wasmfsOpfsDir = undefined; 1136 /** 1137 If the wasm environment has a WASMFS/OPFS-backed persistent 1138 storage directory, its path is returned by this function. If it 1139 does not then it returns "" (noting that "" is a falsy value). 1140 1141 The first time this is called, this function inspects the current 1142 environment to determine whether persistence support is available 1143 and, if it is, enables it (if needed). 1144 1145 This function currently only recognizes the WASMFS/OPFS storage 1146 combination and its path refers to storage rooted in the 1147 Emscripten-managed virtual filesystem. 1148 */ 1149 capi.sqlite3_wasmfs_opfs_dir = function(){ 1150 if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir; 1151 // If we have no OPFS, there is no persistent dir 1152 const pdir = config.wasmfsOpfsDir; 1153 if(!pdir 1154 || !self.FileSystemHandle 1155 || !self.FileSystemDirectoryHandle 1156 || !self.FileSystemFileHandle){ 1157 return __wasmfsOpfsDir = ""; 1158 } 1159 try{ 1160 if(pdir && 0===wasm.xCallWrapped( 1161 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir 1162 )){ 1163 return __wasmfsOpfsDir = pdir; 1164 }else{ 1165 return __wasmfsOpfsDir = ""; 1166 } 1167 }catch(e){ 1168 // sqlite3_wasm_init_wasmfs() is not available 1169 return __wasmfsOpfsDir = ""; 1170 } 1171 }; 1172 1173 /** 1174 Experimental and subject to change or removal. 1175 1176 Returns true if sqlite3.capi.sqlite3_wasmfs_opfs_dir() is a 1177 non-empty string and the given name starts with (that string + 1178 '/'), else returns false. 1179 */ 1180 capi.sqlite3_wasmfs_filename_is_persistent = function(name){ 1181 const p = capi.sqlite3_wasmfs_opfs_dir(); 1182 return (p && name) ? name.startsWith(p+'/') : false; 1183 }; 1184 1185 // This bit is highly arguable and is incompatible with the fiddle shell. 1186 if(false && 0===wasm.exports.sqlite3_vfs_find(0)){ 1187 /* Assume that sqlite3_initialize() has not yet been called. 1188 This will be the case in an SQLITE_OS_KV build. */ 1189 wasm.exports.sqlite3_initialize(); 1190 } 1191 1192 /** 1193 Given an `sqlite3*`, an sqlite3_vfs name, and an optional db 1194 name, returns a truthy value (see below) if that db handle uses 1195 that VFS, else returns false. If pDb is falsy then the 3rd 1196 argument is ignored and this function returns a truthy value if 1197 the default VFS name matches that of the 2nd argument. Results 1198 are undefined if pDb is truthy but refers to an invalid 1199 pointer. The 3rd argument specifies the database name of the 1200 given database connection to check, defaulting to the main db. 1201 1202 The 2nd and 3rd arguments may either be a JS string or a WASM 1203 C-string. If the 2nd argument is a NULL WASM pointer, the default 1204 VFS is assumed. If the 3rd is a NULL WASM pointer, "main" is 1205 assumed. 1206 1207 The truthy value it returns is a pointer to the `sqlite3_vfs` 1208 object. 1209 1210 To permit safe use of this function from APIs which may be called 1211 via the C stack (like SQL UDFs), this function does not throw: if 1212 bad arguments cause a conversion error when passing into 1213 wasm-space, false is returned. 1214 */ 1215 capi.sqlite3_js_db_uses_vfs = function(pDb,vfsName,dbName="main"){ 1216 try{ 1217 const pK = capi.sqlite3_vfs_find(vfsName); 1218 if(!pK) return false; 1219 else if(!pDb){ 1220 return pK===capi.sqlite3_vfs_find(0) ? pK : false; 1221 }else{ 1222 return pK===capi.sqlite3_js_db_vfs(pDb) ? pK : false; 1223 } 1224 }catch(e){ 1225 /* Ignore - probably bad args to a wasm-bound function. */ 1226 return false; 1227 } 1228 }; 1229 1230 /** 1231 Returns an array of the names of all currently-registered sqlite3 1232 VFSes. 1233 */ 1234 capi.sqlite3_js_vfs_list = function(){ 1235 const rc = []; 1236 let pVfs = capi.sqlite3_vfs_find(0); 1237 while(pVfs){ 1238 const oVfs = new capi.sqlite3_vfs(pVfs); 1239 rc.push(wasm.cstringToJs(oVfs.$zName)); 1240 pVfs = oVfs.$pNext; 1241 oVfs.dispose(); 1242 } 1243 return rc; 1244 }; 1245 1246 /** 1247 Serializes the given `sqlite3*` pointer to a Uint8Array, as per 1248 sqlite3_serialize(). On success it returns a Uint8Array. On 1249 error it throws with a description of the problem. 1250 */ 1251 capi.sqlite3_js_db_export = function(pDb){ 1252 if(!pDb) toss('Invalid sqlite3* argument.'); 1253 if(!wasm.bigIntEnabled) toss('BigInt64 support is not enabled.'); 1254 const stack = wasm.pstack.pointer; 1255 let pOut; 1256 try{ 1257 const pSize = wasm.pstack.alloc(8/*i64*/ + wasm.ptrSizeof); 1258 const ppOut = pSize + 8; 1259 /** 1260 Maintenance reminder, since this cost a full hour of grief 1261 and confusion: if the order of pSize/ppOut are reversed in 1262 that memory block, fetching the value of pSize after the 1263 export reads a garbage size because it's not on an 8-byte 1264 memory boundary! 1265 */ 1266 let rc = wasm.exports.sqlite3_wasm_db_serialize( 1267 pDb, ppOut, pSize, 0 1268 ); 1269 if(rc){ 1270 toss("Database serialization failed with code", 1271 sqlite3.capi.sqlite3_js_rc_str(rc)); 1272 } 1273 pOut = wasm.getPtrValue(ppOut); 1274 const nOut = wasm.getMemValue(pSize, 'i64'); 1275 rc = nOut 1276 ? wasm.heap8u().slice(pOut, pOut + Number(nOut)) 1277 : new Uint8Array(); 1278 return rc; 1279 }finally{ 1280 if(pOut) wasm.exports.sqlite3_free(pOut); 1281 wasm.pstack.restore(stack); 1282 } 1283 }; 1284 1285 /** 1286 Given a `sqlite3*` and a database name (JS string or WASM 1287 C-string pointer, which may be 0), returns a pointer to the 1288 sqlite3_vfs responsible for it. If the given db name is null/0, 1289 or not provided, then "main" is assumed. 1290 */ 1291 capi.sqlite3_js_db_vfs = 1292 (dbPointer, dbName=0)=>wasm.sqlite3_wasm_db_vfs(dbPointer, dbName); 1293 1294 /** 1295 A thin wrapper around capi.sqlite3_aggregate_context() which 1296 behaves the same except that it throws a WasmAllocError if that 1297 function returns 0. As a special case, if n is falsy it does 1298 _not_ throw if that function returns 0. That special case is 1299 intended for use with xFinal() implementations. 1300 */ 1301 capi.sqlite3_js_aggregate_context = (pCtx, n)=>{ 1302 return capi.sqlite3_aggregate_context(pCtx, n) 1303 || (n ? WasmAllocError.toss("Cannot allocate",n, 1304 "bytes for sqlite3_aggregate_context()") 1305 : 0); 1306 }; 1307 1308 if( capi.util.isUIThread() ){ 1309 /* Features specific to the main window thread... */ 1310 1311 /** 1312 Internal helper for sqlite3_js_kvvfs_clear() and friends. 1313 Its argument should be one of ('local','session',''). 1314 */ 1315 const __kvvfsInfo = function(which){ 1316 const rc = Object.create(null); 1317 rc.prefix = 'kvvfs-'+which; 1318 rc.stores = []; 1319 if('session'===which || ''===which) rc.stores.push(self.sessionStorage); 1320 if('local'===which || ''===which) rc.stores.push(self.localStorage); 1321 return rc; 1322 }; 1323 1324 /** 1325 Clears all storage used by the kvvfs DB backend, deleting any 1326 DB(s) stored there. Its argument must be either 'session', 1327 'local', or ''. In the first two cases, only sessionStorage 1328 resp. localStorage is cleared. If it's an empty string (the 1329 default) then both are cleared. Only storage keys which match 1330 the pattern used by kvvfs are cleared: any other client-side 1331 data are retained. 1332 1333 This function is only available in the main window thread. 1334 1335 Returns the number of entries cleared. 1336 */ 1337 capi.sqlite3_js_kvvfs_clear = function(which=''){ 1338 let rc = 0; 1339 const kvinfo = __kvvfsInfo(which); 1340 kvinfo.stores.forEach((s)=>{ 1341 const toRm = [] /* keys to remove */; 1342 let i; 1343 for( i = 0; i < s.length; ++i ){ 1344 const k = s.key(i); 1345 if(k.startsWith(kvinfo.prefix)) toRm.push(k); 1346 } 1347 toRm.forEach((kk)=>s.removeItem(kk)); 1348 rc += toRm.length; 1349 }); 1350 return rc; 1351 }; 1352 1353 /** 1354 This routine guesses the approximate amount of 1355 window.localStorage and/or window.sessionStorage in use by the 1356 kvvfs database backend. Its argument must be one of 1357 ('session', 'local', ''). In the first two cases, only 1358 sessionStorage resp. localStorage is counted. If it's an empty 1359 string (the default) then both are counted. Only storage keys 1360 which match the pattern used by kvvfs are counted. The returned 1361 value is the "length" value of every matching key and value, 1362 noting that JavaScript stores each character in 2 bytes. 1363 1364 Note that the returned size is not authoritative from the 1365 perspective of how much data can fit into localStorage and 1366 sessionStorage, as the precise algorithms for determining 1367 those limits are unspecified and may include per-entry 1368 overhead invisible to clients. 1369 */ 1370 capi.sqlite3_js_kvvfs_size = function(which=''){ 1371 let sz = 0; 1372 const kvinfo = __kvvfsInfo(which); 1373 kvinfo.stores.forEach((s)=>{ 1374 let i; 1375 for(i = 0; i < s.length; ++i){ 1376 const k = s.key(i); 1377 if(k.startsWith(kvinfo.prefix)){ 1378 sz += k.length; 1379 sz += s.getItem(k).length; 1380 } 1381 } 1382 }); 1383 return sz * 2 /* because JS uses 2-byte char encoding */; 1384 }; 1385 1386 }/* main-window-only bits */ 1387 1388 1389 /* The remainder of the API will be set up in later steps. */ 1390 const sqlite3 = { 1391 WasmAllocError: WasmAllocError, 1392 SQLite3Error: SQLite3Error, 1393 capi, 1394 config, 1395 /** 1396 Holds the version info of the sqlite3 source tree from which 1397 the generated sqlite3-api.js gets built. Note that its version 1398 may well differ from that reported by sqlite3_libversion(), but 1399 that should be considered a source file mismatch, as the JS and 1400 WASM files are intended to be built and distributed together. 1401 1402 This object is initially a placeholder which gets replaced by a 1403 build-generated object. 1404 */ 1405 version: Object.create(null), 1406 /** 1407 Performs any optional asynchronous library-level initialization 1408 which might be required. This function returns a Promise which 1409 resolves to the sqlite3 namespace object. Any error in the 1410 async init will be fatal to the init as a whole, but init 1411 routines are themselves welcome to install dummy catch() 1412 handlers which are not fatal if their failure should be 1413 considered non-fatal. If called more than once, the second and 1414 subsequent calls are no-ops which return a pre-resolved 1415 Promise. 1416 1417 Ideally this function is called as part of the Promise chain 1418 which handles the loading and bootstrapping of the API. If not 1419 then it must be called by client-level code, which must not use 1420 the library until the returned promise resolves. 1421 1422 Bug: if called while a prior call is still resolving, the 2nd 1423 call will resolve prematurely, before the 1st call has finished 1424 resolving. The current build setup precludes that possibility, 1425 so it's only a hypothetical problem if/when this function 1426 ever needs to be invoked by clients. 1427 1428 In Emscripten-based builds, this function is called 1429 automatically and deleted from this object. 1430 */ 1431 asyncPostInit: async function(){ 1432 let lip = sqlite3ApiBootstrap.initializersAsync; 1433 delete sqlite3ApiBootstrap.initializersAsync; 1434 if(!lip || !lip.length) return Promise.resolve(sqlite3); 1435 // Is it okay to resolve these in parallel or do we need them 1436 // to resolve in order? We currently only have 1, so it 1437 // makes no difference. 1438 lip = lip.map((f)=>{ 1439 const p = (f instanceof Promise) ? f : f(sqlite3); 1440 return p.catch((e)=>{ 1441 console.error("an async sqlite3 initializer failed:",e); 1442 throw e; 1443 }); 1444 }); 1445 //let p = lip.shift(); 1446 //while(lip.length) p = p.then(lip.shift()); 1447 //return p.then(()=>sqlite3); 1448 return Promise.all(lip).then(()=>sqlite3); 1449 }, 1450 /** 1451 scriptInfo ideally gets injected into this object by the 1452 infrastructure which assembles the JS/WASM module. It contains 1453 state which must be collected before sqlite3ApiBootstrap() can 1454 be declared. It is not necessarily available to any 1455 sqlite3ApiBootstrap.initializers but "should" be in place (if 1456 it's added at all) by the time that 1457 sqlite3ApiBootstrap.initializersAsync is processed. 1458 1459 This state is not part of the public API, only intended for use 1460 with the sqlite3 API bootstrapping and wasm-loading process. 1461 */ 1462 scriptInfo: undefined 1463 }; 1464 try{ 1465 sqlite3ApiBootstrap.initializers.forEach((f)=>{ 1466 f(sqlite3); 1467 }); 1468 }catch(e){ 1469 /* If we don't report this here, it can get completely swallowed 1470 up and disappear into the abyss of Promises and Workers. */ 1471 console.error("sqlite3 bootstrap initializer threw:",e); 1472 throw e; 1473 } 1474 delete sqlite3ApiBootstrap.initializers; 1475 sqlite3ApiBootstrap.sqlite3 = sqlite3; 1476 return sqlite3; 1477}/*sqlite3ApiBootstrap()*/; 1478/** 1479 self.sqlite3ApiBootstrap.initializers is an internal detail used by 1480 the various pieces of the sqlite3 API's amalgamation process. It 1481 must not be modified by client code except when plugging such code 1482 into the amalgamation process. 1483 1484 Each component of the amalgamation is expected to append a function 1485 to this array. When sqlite3ApiBootstrap() is called for the first 1486 time, each such function will be called (in their appended order) 1487 and passed the sqlite3 namespace object, into which they can install 1488 their features (noting that most will also require that certain 1489 features alread have been installed). At the end of that process, 1490 this array is deleted. 1491 1492 Note that the order of insertion into this array is significant for 1493 some pieces. e.g. sqlite3.capi and sqlite3.capi.wasm cannot be fully 1494 utilized until the whwasmutil.js part is plugged in via 1495 sqlite3-api-glue.js. 1496*/ 1497self.sqlite3ApiBootstrap.initializers = []; 1498/** 1499 self.sqlite3ApiBootstrap.initializersAsync is an internal detail 1500 used by the sqlite3 API's amalgamation process. It must not be 1501 modified by client code except when plugging such code into the 1502 amalgamation process. 1503 1504 The counterpart of self.sqlite3ApiBootstrap.initializers, 1505 specifically for initializers which are asynchronous. All entries in 1506 this list must be either async functions, non-async functions which 1507 return a Promise, or a Promise. Each function in the list is called 1508 with the sqlite3 ojbect as its only argument. 1509 1510 The resolved value of any Promise is ignored and rejection will kill 1511 the asyncPostInit() process (at an indeterminate point because all 1512 of them are run asynchronously in parallel). 1513 1514 This list is not processed until the client calls 1515 sqlite3.asyncPostInit(). This means, for example, that intializers 1516 added to self.sqlite3ApiBootstrap.initializers may push entries to 1517 this list. 1518*/ 1519self.sqlite3ApiBootstrap.initializersAsync = []; 1520/** 1521 Client code may assign sqlite3ApiBootstrap.defaultConfig an 1522 object-type value before calling sqlite3ApiBootstrap() (without 1523 arguments) in order to tell that call to use this object as its 1524 default config value. The intention of this is to provide 1525 downstream clients with a reasonably flexible approach for plugging in 1526 an environment-suitable configuration without having to define a new 1527 global-scope symbol. 1528*/ 1529self.sqlite3ApiBootstrap.defaultConfig = Object.create(null); 1530/** 1531 Placeholder: gets installed by the first call to 1532 self.sqlite3ApiBootstrap(). However, it is recommended that the 1533 caller of sqlite3ApiBootstrap() capture its return value and delete 1534 self.sqlite3ApiBootstrap after calling it. It returns the same 1535 value which will be stored here. 1536*/ 1537self.sqlite3ApiBootstrap.sqlite3 = undefined; 1538 1539