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