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