xref: /sqlite-3.40.0/ext/wasm/api/sqlite3-wasm.c (revision 3d645484)
1 /*
2 ** This file requires access to sqlite3.c static state in order to
3 ** implement certain WASM-specific features, and thus directly
4 ** includes that file. Unlike the rest of sqlite3.c, this file
5 ** requires compiling with -std=c99 (or equivalent, or a later C
6 ** version) because it makes use of features not available in C89.
7 **
8 ** At it's simplest, to build sqlite3.wasm either place this file
9 ** in the same directory as sqlite3.c/h before compilation or use the
10 ** -I/path flag to tell the compiler where to find both of those
11 ** files, then compile this file. For example:
12 **
13 ** emcc -o sqlite3.wasm ... -I/path/to/sqlite3-c-and-h sqlite3-wasm.c
14 */
15 
16 #ifndef SQLITE_DEFAULT_UNIX_VFS
17 # define SQLITE_DEFAULT_UNIX_VFS "unix-none"
18 #endif
19 #ifndef SQLITE_OMIT_DEPRECATED
20 # define SQLITE_OMIT_DEPRECATED
21 #endif
22 #ifndef SQLITE_OMIT_LOAD_EXTENSION
23 # define SQLITE_OMIT_LOAD_EXTENSION
24 #endif
25 #ifndef SQLITE_OMIT_SHARED_CACHE
26 # define SQLITE_OMIT_SHARED_CACHE
27 #endif
28 #ifndef SQLITE_OMIT_UTF16
29 # define SQLITE_OMIT_UTF16
30 #endif
31 #ifndef SQLITE_OS_KV_OPTIONAL
32 # define SQLITE_OS_KV_OPTIONAL 1
33 #endif
34 #ifndef SQLITE_TEMP_STORE
35 # define SQLITE_TEMP_STORE 3
36 #endif
37 #ifndef SQLITE_THREADSAFE
38 # define SQLITE_THREADSAFE 0
39 #endif
40 
41 #include "sqlite3.c" /* yes, .c instead of .h. */
42 
43 /*
44 ** WASM_KEEP is identical to EMSCRIPTEN_KEEPALIVE but is not
45 ** Emscripten-specific. It explicitly marks functions for export into
46 ** the target wasm file without requiring explicit listing of those
47 ** functions in Emscripten's -sEXPORTED_FUNCTIONS=... list (or
48 ** equivalent in other build platforms). Any function with neither
49 ** this attribute nor which is listed as an explicit export will not
50 ** be exported from the wasm file (but may still be used internally
51 ** within the wasm file).
52 **
53 ** The functions in this file (sqlite3-wasm.c) which require exporting
54 ** are marked with this flag. They may also be added to any explicit
55 ** build-time export list but need not be. All of these APIs are
56 ** intended for use only within the project's own JS/WASM code, and
57 ** not by client code, so an argument can be made for reducing their
58 ** visibility by not including them in any build-time export lists.
59 **
60 ** 2022-09-11: it's not yet _proven_ that this approach works in
61 ** non-Emscripten builds. If not, such builds will need to export
62 ** those using the --export=... wasm-ld flag (or equivalent). As of
63 ** this writing we are tied to Emscripten for various reasons
64 ** and cannot test the library with other build environments.
65 */
66 #define WASM_KEEP __attribute__((used,visibility("default")))
67 // See also:
68 //__attribute__((export_name("theExportedName"), used, visibility("default")))
69 
70 /*
71 ** This function is NOT part of the sqlite3 public API. It is strictly
72 ** for use by the sqlite project's own JS/WASM bindings.
73 **
74 ** For purposes of certain hand-crafted C/Wasm function bindings, we
75 ** need a way of reporting errors which is consistent with the rest of
76 ** the C API, as opposed to throwing JS exceptions. To that end, this
77 ** internal-use-only function is a thin proxy around
78 ** sqlite3ErrorWithMessage(). The intent is that it only be used from
79 ** Wasm bindings such as sqlite3_prepare_v2/v3(), and definitely not
80 ** from client code.
81 **
82 ** Returns err_code.
83 */
84 WASM_KEEP
85 int sqlite3_wasm_db_error(sqlite3*db, int err_code, const char *zMsg){
86   if(0!=zMsg){
87     const int nMsg = sqlite3Strlen30(zMsg);
88     sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg);
89   }else{
90     sqlite3ErrorWithMsg(db, err_code, NULL);
91   }
92   return err_code;
93 }
94 
95 /*
96 ** This function is NOT part of the sqlite3 public API. It is strictly
97 ** for use by the sqlite project's own JS/WASM bindings. Unlike the
98 ** rest of the sqlite3 API, this part requires C99 for snprintf() and
99 ** variadic macros.
100 **
101 ** Returns a string containing a JSON-format "enum" of C-level
102 ** constants intended to be imported into the JS environment. The JSON
103 ** is initialized the first time this function is called and that
104 ** result is reused for all future calls.
105 **
106 ** If this function returns NULL then it means that the internal
107 ** buffer is not large enough for the generated JSON. In debug builds
108 ** that will trigger an assert().
109 */
110 WASM_KEEP
111 const char * sqlite3_wasm_enum_json(void){
112   static char strBuf[1024 * 12] = {0} /* where the JSON goes */;
113   int n = 0, childCount = 0, structCount = 0
114     /* output counters for figuring out where commas go */;
115   char * pos = &strBuf[1] /* skip first byte for now to help protect
116                           ** against a small race condition */;
117   char const * const zEnd = pos + sizeof(strBuf) /* one-past-the-end */;
118   if(strBuf[0]) return strBuf;
119   /* Leave strBuf[0] at 0 until the end to help guard against a tiny
120   ** race condition. If this is called twice concurrently, they might
121   ** end up both writing to strBuf, but they'll both write the same
122   ** thing, so that's okay. If we set byte 0 up front then the 2nd
123   ** instance might return and use the string before the 1st instance
124   ** is done filling it. */
125 
126 /* Core output macros... */
127 #define lenCheck assert(pos < zEnd - 128 \
128   && "sqlite3_wasm_enum_json() buffer is too small."); \
129   if(pos >= zEnd - 128) return 0
130 #define outf(format,...) \
131   pos += snprintf(pos, ((size_t)(zEnd - pos)), format, __VA_ARGS__); \
132   lenCheck
133 #define out(TXT) outf("%s",TXT)
134 #define CloseBrace(LEVEL) \
135   assert(LEVEL<5); memset(pos, '}', LEVEL); pos+=LEVEL; lenCheck
136 
137 /* Macros for emitting maps of integer- and string-type macros to
138 ** their values. */
139 #define DefGroup(KEY) n = 0; \
140   outf("%s\"" #KEY "\": {",(childCount++ ? "," : ""));
141 #define DefInt(KEY)                                     \
142   outf("%s\"%s\": %d", (n++ ? ", " : ""), #KEY, (int)KEY)
143 #define DefStr(KEY)                                     \
144   outf("%s\"%s\": \"%s\"", (n++ ? ", " : ""), #KEY, KEY)
145 #define _DefGroup CloseBrace(1)
146 
147   DefGroup(version) {
148     DefInt(SQLITE_VERSION_NUMBER);
149     DefStr(SQLITE_VERSION);
150     DefStr(SQLITE_SOURCE_ID);
151   } _DefGroup;
152 
153   DefGroup(resultCodes) {
154     DefInt(SQLITE_OK);
155     DefInt(SQLITE_ERROR);
156     DefInt(SQLITE_INTERNAL);
157     DefInt(SQLITE_PERM);
158     DefInt(SQLITE_ABORT);
159     DefInt(SQLITE_BUSY);
160     DefInt(SQLITE_LOCKED);
161     DefInt(SQLITE_NOMEM);
162     DefInt(SQLITE_READONLY);
163     DefInt(SQLITE_INTERRUPT);
164     DefInt(SQLITE_IOERR);
165     DefInt(SQLITE_CORRUPT);
166     DefInt(SQLITE_NOTFOUND);
167     DefInt(SQLITE_FULL);
168     DefInt(SQLITE_CANTOPEN);
169     DefInt(SQLITE_PROTOCOL);
170     DefInt(SQLITE_EMPTY);
171     DefInt(SQLITE_SCHEMA);
172     DefInt(SQLITE_TOOBIG);
173     DefInt(SQLITE_CONSTRAINT);
174     DefInt(SQLITE_MISMATCH);
175     DefInt(SQLITE_MISUSE);
176     DefInt(SQLITE_NOLFS);
177     DefInt(SQLITE_AUTH);
178     DefInt(SQLITE_FORMAT);
179     DefInt(SQLITE_RANGE);
180     DefInt(SQLITE_NOTADB);
181     DefInt(SQLITE_NOTICE);
182     DefInt(SQLITE_WARNING);
183     DefInt(SQLITE_ROW);
184     DefInt(SQLITE_DONE);
185 
186     // Extended Result Codes
187     DefInt(SQLITE_ERROR_MISSING_COLLSEQ);
188     DefInt(SQLITE_ERROR_RETRY);
189     DefInt(SQLITE_ERROR_SNAPSHOT);
190     DefInt(SQLITE_IOERR_READ);
191     DefInt(SQLITE_IOERR_SHORT_READ);
192     DefInt(SQLITE_IOERR_WRITE);
193     DefInt(SQLITE_IOERR_FSYNC);
194     DefInt(SQLITE_IOERR_DIR_FSYNC);
195     DefInt(SQLITE_IOERR_TRUNCATE);
196     DefInt(SQLITE_IOERR_FSTAT);
197     DefInt(SQLITE_IOERR_UNLOCK);
198     DefInt(SQLITE_IOERR_RDLOCK);
199     DefInt(SQLITE_IOERR_DELETE);
200     DefInt(SQLITE_IOERR_BLOCKED);
201     DefInt(SQLITE_IOERR_NOMEM);
202     DefInt(SQLITE_IOERR_ACCESS);
203     DefInt(SQLITE_IOERR_CHECKRESERVEDLOCK);
204     DefInt(SQLITE_IOERR_LOCK);
205     DefInt(SQLITE_IOERR_CLOSE);
206     DefInt(SQLITE_IOERR_DIR_CLOSE);
207     DefInt(SQLITE_IOERR_SHMOPEN);
208     DefInt(SQLITE_IOERR_SHMSIZE);
209     DefInt(SQLITE_IOERR_SHMLOCK);
210     DefInt(SQLITE_IOERR_SHMMAP);
211     DefInt(SQLITE_IOERR_SEEK);
212     DefInt(SQLITE_IOERR_DELETE_NOENT);
213     DefInt(SQLITE_IOERR_MMAP);
214     DefInt(SQLITE_IOERR_GETTEMPPATH);
215     DefInt(SQLITE_IOERR_CONVPATH);
216     DefInt(SQLITE_IOERR_VNODE);
217     DefInt(SQLITE_IOERR_AUTH);
218     DefInt(SQLITE_IOERR_BEGIN_ATOMIC);
219     DefInt(SQLITE_IOERR_COMMIT_ATOMIC);
220     DefInt(SQLITE_IOERR_ROLLBACK_ATOMIC);
221     DefInt(SQLITE_IOERR_DATA);
222     DefInt(SQLITE_IOERR_CORRUPTFS);
223     DefInt(SQLITE_LOCKED_SHAREDCACHE);
224     DefInt(SQLITE_LOCKED_VTAB);
225     DefInt(SQLITE_BUSY_RECOVERY);
226     DefInt(SQLITE_BUSY_SNAPSHOT);
227     DefInt(SQLITE_BUSY_TIMEOUT);
228     DefInt(SQLITE_CANTOPEN_NOTEMPDIR);
229     DefInt(SQLITE_CANTOPEN_ISDIR);
230     DefInt(SQLITE_CANTOPEN_FULLPATH);
231     DefInt(SQLITE_CANTOPEN_CONVPATH);
232     //DefInt(SQLITE_CANTOPEN_DIRTYWAL)/*docs say not used*/;
233     DefInt(SQLITE_CANTOPEN_SYMLINK);
234     DefInt(SQLITE_CORRUPT_VTAB);
235     DefInt(SQLITE_CORRUPT_SEQUENCE);
236     DefInt(SQLITE_CORRUPT_INDEX);
237     DefInt(SQLITE_READONLY_RECOVERY);
238     DefInt(SQLITE_READONLY_CANTLOCK);
239     DefInt(SQLITE_READONLY_ROLLBACK);
240     DefInt(SQLITE_READONLY_DBMOVED);
241     DefInt(SQLITE_READONLY_CANTINIT);
242     DefInt(SQLITE_READONLY_DIRECTORY);
243     DefInt(SQLITE_ABORT_ROLLBACK);
244     DefInt(SQLITE_CONSTRAINT_CHECK);
245     DefInt(SQLITE_CONSTRAINT_COMMITHOOK);
246     DefInt(SQLITE_CONSTRAINT_FOREIGNKEY);
247     DefInt(SQLITE_CONSTRAINT_FUNCTION);
248     DefInt(SQLITE_CONSTRAINT_NOTNULL);
249     DefInt(SQLITE_CONSTRAINT_PRIMARYKEY);
250     DefInt(SQLITE_CONSTRAINT_TRIGGER);
251     DefInt(SQLITE_CONSTRAINT_UNIQUE);
252     DefInt(SQLITE_CONSTRAINT_VTAB);
253     DefInt(SQLITE_CONSTRAINT_ROWID);
254     DefInt(SQLITE_CONSTRAINT_PINNED);
255     DefInt(SQLITE_CONSTRAINT_DATATYPE);
256     DefInt(SQLITE_NOTICE_RECOVER_WAL);
257     DefInt(SQLITE_NOTICE_RECOVER_ROLLBACK);
258     DefInt(SQLITE_WARNING_AUTOINDEX);
259     DefInt(SQLITE_AUTH_USER);
260     DefInt(SQLITE_OK_LOAD_PERMANENTLY);
261     //DefInt(SQLITE_OK_SYMLINK) /* internal use only */;
262   } _DefGroup;
263 
264   DefGroup(dataTypes) {
265     DefInt(SQLITE_INTEGER);
266     DefInt(SQLITE_FLOAT);
267     DefInt(SQLITE_TEXT);
268     DefInt(SQLITE_BLOB);
269     DefInt(SQLITE_NULL);
270   } _DefGroup;
271 
272   DefGroup(encodings) {
273     /* Noting that the wasm binding only aims to support UTF-8. */
274     DefInt(SQLITE_UTF8);
275     DefInt(SQLITE_UTF16LE);
276     DefInt(SQLITE_UTF16BE);
277     DefInt(SQLITE_UTF16);
278     /*deprecated DefInt(SQLITE_ANY); */
279     DefInt(SQLITE_UTF16_ALIGNED);
280   } _DefGroup;
281 
282   DefGroup(blobFinalizers) {
283     /* SQLITE_STATIC/TRANSIENT need to be handled explicitly as
284     ** integers to avoid casting-related warnings. */
285     out("\"SQLITE_STATIC\":0, \"SQLITE_TRANSIENT\":-1");
286   } _DefGroup;
287 
288   DefGroup(udfFlags) {
289     DefInt(SQLITE_DETERMINISTIC);
290     DefInt(SQLITE_DIRECTONLY);
291     DefInt(SQLITE_INNOCUOUS);
292   } _DefGroup;
293 
294   DefGroup(openFlags) {
295     /* Noting that not all of these will have any effect in
296     ** WASM-space. */
297     DefInt(SQLITE_OPEN_READONLY);
298     DefInt(SQLITE_OPEN_READWRITE);
299     DefInt(SQLITE_OPEN_CREATE);
300     DefInt(SQLITE_OPEN_URI);
301     DefInt(SQLITE_OPEN_MEMORY);
302     DefInt(SQLITE_OPEN_NOMUTEX);
303     DefInt(SQLITE_OPEN_FULLMUTEX);
304     DefInt(SQLITE_OPEN_SHAREDCACHE);
305     DefInt(SQLITE_OPEN_PRIVATECACHE);
306     DefInt(SQLITE_OPEN_EXRESCODE);
307     DefInt(SQLITE_OPEN_NOFOLLOW);
308     /* OPEN flags for use with VFSes... */
309     DefInt(SQLITE_OPEN_MAIN_DB);
310     DefInt(SQLITE_OPEN_MAIN_JOURNAL);
311     DefInt(SQLITE_OPEN_TEMP_DB);
312     DefInt(SQLITE_OPEN_TEMP_JOURNAL);
313     DefInt(SQLITE_OPEN_TRANSIENT_DB);
314     DefInt(SQLITE_OPEN_SUBJOURNAL);
315     DefInt(SQLITE_OPEN_SUPER_JOURNAL);
316     DefInt(SQLITE_OPEN_WAL);
317     DefInt(SQLITE_OPEN_DELETEONCLOSE);
318     DefInt(SQLITE_OPEN_EXCLUSIVE);
319   } _DefGroup;
320 
321   DefGroup(syncFlags) {
322     DefInt(SQLITE_SYNC_NORMAL);
323     DefInt(SQLITE_SYNC_FULL);
324     DefInt(SQLITE_SYNC_DATAONLY);
325   } _DefGroup;
326 
327   DefGroup(prepareFlags) {
328     DefInt(SQLITE_PREPARE_PERSISTENT);
329     DefInt(SQLITE_PREPARE_NORMALIZE);
330     DefInt(SQLITE_PREPARE_NO_VTAB);
331   } _DefGroup;
332 
333   DefGroup(flock) {
334     DefInt(SQLITE_LOCK_NONE);
335     DefInt(SQLITE_LOCK_SHARED);
336     DefInt(SQLITE_LOCK_RESERVED);
337     DefInt(SQLITE_LOCK_PENDING);
338     DefInt(SQLITE_LOCK_EXCLUSIVE);
339   } _DefGroup;
340 
341   DefGroup(ioCap) {
342     DefInt(SQLITE_IOCAP_ATOMIC);
343     DefInt(SQLITE_IOCAP_ATOMIC512);
344     DefInt(SQLITE_IOCAP_ATOMIC1K);
345     DefInt(SQLITE_IOCAP_ATOMIC2K);
346     DefInt(SQLITE_IOCAP_ATOMIC4K);
347     DefInt(SQLITE_IOCAP_ATOMIC8K);
348     DefInt(SQLITE_IOCAP_ATOMIC16K);
349     DefInt(SQLITE_IOCAP_ATOMIC32K);
350     DefInt(SQLITE_IOCAP_ATOMIC64K);
351     DefInt(SQLITE_IOCAP_SAFE_APPEND);
352     DefInt(SQLITE_IOCAP_SEQUENTIAL);
353     DefInt(SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN);
354     DefInt(SQLITE_IOCAP_POWERSAFE_OVERWRITE);
355     DefInt(SQLITE_IOCAP_IMMUTABLE);
356     DefInt(SQLITE_IOCAP_BATCH_ATOMIC);
357   } _DefGroup;
358 
359   DefGroup(fcntl) {
360     DefInt(SQLITE_FCNTL_LOCKSTATE);
361     DefInt(SQLITE_FCNTL_GET_LOCKPROXYFILE);
362     DefInt(SQLITE_FCNTL_SET_LOCKPROXYFILE);
363     DefInt(SQLITE_FCNTL_LAST_ERRNO);
364     DefInt(SQLITE_FCNTL_SIZE_HINT);
365     DefInt(SQLITE_FCNTL_CHUNK_SIZE);
366     DefInt(SQLITE_FCNTL_FILE_POINTER);
367     DefInt(SQLITE_FCNTL_SYNC_OMITTED);
368     DefInt(SQLITE_FCNTL_WIN32_AV_RETRY);
369     DefInt(SQLITE_FCNTL_PERSIST_WAL);
370     DefInt(SQLITE_FCNTL_OVERWRITE);
371     DefInt(SQLITE_FCNTL_VFSNAME);
372     DefInt(SQLITE_FCNTL_POWERSAFE_OVERWRITE);
373     DefInt(SQLITE_FCNTL_PRAGMA);
374     DefInt(SQLITE_FCNTL_BUSYHANDLER);
375     DefInt(SQLITE_FCNTL_TEMPFILENAME);
376     DefInt(SQLITE_FCNTL_MMAP_SIZE);
377     DefInt(SQLITE_FCNTL_TRACE);
378     DefInt(SQLITE_FCNTL_HAS_MOVED);
379     DefInt(SQLITE_FCNTL_SYNC);
380     DefInt(SQLITE_FCNTL_COMMIT_PHASETWO);
381     DefInt(SQLITE_FCNTL_WIN32_SET_HANDLE);
382     DefInt(SQLITE_FCNTL_WAL_BLOCK);
383     DefInt(SQLITE_FCNTL_ZIPVFS);
384     DefInt(SQLITE_FCNTL_RBU);
385     DefInt(SQLITE_FCNTL_VFS_POINTER);
386     DefInt(SQLITE_FCNTL_JOURNAL_POINTER);
387     DefInt(SQLITE_FCNTL_WIN32_GET_HANDLE);
388     DefInt(SQLITE_FCNTL_PDB);
389     DefInt(SQLITE_FCNTL_BEGIN_ATOMIC_WRITE);
390     DefInt(SQLITE_FCNTL_COMMIT_ATOMIC_WRITE);
391     DefInt(SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE);
392     DefInt(SQLITE_FCNTL_LOCK_TIMEOUT);
393     DefInt(SQLITE_FCNTL_DATA_VERSION);
394     DefInt(SQLITE_FCNTL_SIZE_LIMIT);
395     DefInt(SQLITE_FCNTL_CKPT_DONE);
396     DefInt(SQLITE_FCNTL_RESERVE_BYTES);
397     DefInt(SQLITE_FCNTL_CKPT_START);
398     DefInt(SQLITE_FCNTL_EXTERNAL_READER);
399     DefInt(SQLITE_FCNTL_CKSM_FILE);
400   } _DefGroup;
401 
402   DefGroup(access){
403     DefInt(SQLITE_ACCESS_EXISTS);
404     DefInt(SQLITE_ACCESS_READWRITE);
405     DefInt(SQLITE_ACCESS_READ)/*docs say this is unused*/;
406   } _DefGroup;
407 
408 #undef DefGroup
409 #undef DefStr
410 #undef DefInt
411 #undef _DefGroup
412 
413   /*
414   ** Emit an array of "StructBinder" struct descripions, which look
415   ** like:
416   **
417   ** {
418   **   "name": "MyStruct",
419   **   "sizeof": 16,
420   **   "members": {
421   **     "member1": {"offset": 0,"sizeof": 4,"signature": "i"},
422   **     "member2": {"offset": 4,"sizeof": 4,"signature": "p"},
423   **     "member3": {"offset": 8,"sizeof": 8,"signature": "j"}
424   **   }
425   ** }
426   **
427   ** Detailed documentation for those bits are in the docs for the
428   ** Jaccwabyt JS-side component.
429   */
430 
431   /** Macros for emitting StructBinder description. */
432 #define StructBinder__(TYPE)                 \
433   n = 0;                                     \
434   outf("%s{", (structCount++ ? ", " : ""));  \
435   out("\"name\": \"" # TYPE "\",");         \
436   outf("\"sizeof\": %d", (int)sizeof(TYPE)); \
437   out(",\"members\": {");
438 #define StructBinder_(T) StructBinder__(T)
439   /** ^^^ indirection needed to expand CurrentStruct */
440 #define StructBinder StructBinder_(CurrentStruct)
441 #define _StructBinder CloseBrace(2)
442 #define M(MEMBER,SIG)                                         \
443   outf("%s\"%s\": "                                           \
444        "{\"offset\":%d,\"sizeof\": %d,\"signature\":\"%s\"}", \
445        (n++ ? ", " : ""), #MEMBER,                            \
446        (int)offsetof(CurrentStruct,MEMBER),                   \
447        (int)sizeof(((CurrentStruct*)0)->MEMBER),              \
448        SIG)
449 
450   structCount = 0;
451   out(", \"structs\": ["); {
452 
453 #define CurrentStruct sqlite3_vfs
454     StructBinder {
455       M(iVersion,"i");
456       M(szOsFile,"i");
457       M(mxPathname,"i");
458       M(pNext,"p");
459       M(zName,"s");
460       M(pAppData,"p");
461       M(xOpen,"i(pppip)");
462       M(xDelete,"i(ppi)");
463       M(xAccess,"i(ppip)");
464       M(xFullPathname,"i(ppip)");
465       M(xDlOpen,"p(pp)");
466       M(xDlError,"p(pip)");
467       M(xDlSym,"p()");
468       M(xDlClose,"v(pp)");
469       M(xRandomness,"i(pip)");
470       M(xSleep,"i(pi)");
471       M(xCurrentTime,"i(pp)");
472       M(xGetLastError,"i(pip)");
473       M(xCurrentTimeInt64,"i(pp)");
474       M(xSetSystemCall,"i(ppp)");
475       M(xGetSystemCall,"p(pp)");
476       M(xNextSystemCall,"p(pp)");
477     } _StructBinder;
478 #undef CurrentStruct
479 
480 #define CurrentStruct sqlite3_io_methods
481     StructBinder {
482       M(iVersion,"i");
483       M(xClose,"i(p)");
484       M(xRead,"i(ppij)");
485       M(xWrite,"i(ppij)");
486       M(xTruncate,"i(pj)");
487       M(xSync,"i(pi)");
488       M(xFileSize,"i(pp)");
489       M(xLock,"i(pi)");
490       M(xUnlock,"i(pi)");
491       M(xCheckReservedLock,"i(pp)");
492       M(xFileControl,"i(pip)");
493       M(xSectorSize,"i(p)");
494       M(xDeviceCharacteristics,"i(p)");
495       M(xShmMap,"i(piiip)");
496       M(xShmLock,"i(piii)");
497       M(xShmBarrier,"v(p)");
498       M(xShmUnmap,"i(pi)");
499       M(xFetch,"i(pjip)");
500       M(xUnfetch,"i(pjp)");
501     } _StructBinder;
502 #undef CurrentStruct
503 
504 #define CurrentStruct sqlite3_file
505     StructBinder {
506       M(pMethods,"p");
507     } _StructBinder;
508 #undef CurrentStruct
509 
510   } out( "]"/*structs*/);
511 
512   out("}"/*top-level object*/);
513   *pos = 0;
514   strBuf[0] = '{'/*end of the race-condition workaround*/;
515   return strBuf;
516 #undef StructBinder
517 #undef StructBinder_
518 #undef StructBinder__
519 #undef M
520 #undef _StructBinder
521 #undef CloseBrace
522 #undef out
523 #undef outf
524 #undef lenCheck
525 }
526 
527 /*
528 ** This function is NOT part of the sqlite3 public API. It is strictly
529 ** for use by the sqlite project's own JS/WASM bindings.
530 **
531 ** This function invokes the xDelete method of the default VFS,
532 ** passing on the given filename. If zName is NULL, no default VFS is
533 ** found, or it has no xDelete method, SQLITE_MISUSE is returned, else
534 ** the result of the xDelete() call is returned.
535 */
536 WASM_KEEP
537 int sqlite3_wasm_vfs_unlink(const char * zName){
538   int rc = SQLITE_MISUSE /* ??? */;
539   sqlite3_vfs * const pVfs = sqlite3_vfs_find(0);
540   if( zName && pVfs && pVfs->xDelete ){
541     rc = pVfs->xDelete(pVfs, zName, 1);
542   }
543   return rc;
544 }
545 
546 #if defined(__EMSCRIPTEN__) && defined(SQLITE_WASM_WASMFS)
547 #include <emscripten/wasmfs.h>
548 #include <emscripten/console.h>
549 
550 /*
551 ** This function is NOT part of the sqlite3 public API. It is strictly
552 ** for use by the sqlite project's own JS/WASM bindings, specifically
553 ** only when building with Emscripten's WASMFS support.
554 **
555 ** This function should only be called if the JS side detects the
556 ** existence of the Origin-Private FileSystem (OPFS) APIs in the
557 ** client. The first time it is called, this function instantiates a
558 ** WASMFS backend impl for OPFS. On success, subsequent calls are
559 ** no-ops.
560 **
561 ** This function may be passed a "mount point" name, which must have a
562 ** leading "/" and is currently restricted to a single path component,
563 ** e.g. "/foo" is legal but "/foo/" and "/foo/bar" are not. If it is
564 ** NULL or empty, it defaults to "/persistent".
565 **
566 ** Returns 0 on success, SQLITE_NOMEM if instantiation of the backend
567 ** object fails, SQLITE_IOERR if mkdir() of the zMountPoint dir in
568 ** the virtual FS fails. In builds compiled without SQLITE_WASM_WASMFS
569 ** defined, SQLITE_NOTFOUND is returned without side effects.
570 */
571 WASM_KEEP
572 int sqlite3_wasm_init_wasmfs(const char *zMountPoint){
573   static backend_t pOpfs = 0;
574   if( !zMountPoint || !*zMountPoint ) zMountPoint = "/opfs";
575   if( !pOpfs ){
576     pOpfs = wasmfs_create_opfs_backend();
577     if( pOpfs ){
578       emscripten_console_log("Created WASMFS OPFS backend.");
579     }
580   }
581   /** It's not enough to instantiate the backend. We have to create a
582       mountpoint in the VFS and attach the backend to it. */
583   if( pOpfs && 0!=access(zMountPoint, F_OK) ){
584     /* mkdir() simply hangs when called from fiddle app. Cause is
585        not yet determined but the hypothesis is an init-order
586        issue. */
587     /* Note that this check and is not robust but it will
588        hypothetically suffice for the transient wasm-based virtual
589        filesystem we're currently running in. */
590     const int rc = wasmfs_create_directory(zMountPoint, 0777, pOpfs);
591     emscripten_console_logf("OPFS mkdir(%s) rc=%d", zMountPoint, rc);
592     if(rc) return SQLITE_IOERR;
593   }
594   return pOpfs ? 0 : SQLITE_NOMEM;
595 }
596 #else
597 WASM_KEEP
598 int sqlite3_wasm_init_wasmfs(const char *zUnused){
599   if(zUnused){/*unused*/}
600   return SQLITE_NOTFOUND;
601 }
602 #endif /* __EMSCRIPTEN__ && SQLITE_WASM_WASMFS */
603 
604 
605 #undef WASM_KEEP
606