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