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