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