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