]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add sqlite3_wasm_vfs_create_file() to replace Emscripten's FS.createDataFile() in...
authorstephan <stephan@noemail.net>
Wed, 2 Nov 2022 11:53:31 +0000 (11:53 +0000)
committerstephan <stephan@noemail.net>
Wed, 2 Nov 2022 11:53:31 +0000 (11:53 +0000)
FossilOrigin-Name: b35e1225c91a3cadc0d25af1e4e790237256d194990faa13190e343ed03e11c5

ext/wasm/api/sqlite3-api-opfs.js
ext/wasm/api/sqlite3-api-prologue.js
ext/wasm/api/sqlite3-api-worker1.js
ext/wasm/api/sqlite3-opfs-async-proxy.js
ext/wasm/api/sqlite3-wasm.c
ext/wasm/demo-worker1-promiser.js
ext/wasm/demo-worker1.js
ext/wasm/tester1.js
manifest
manifest.uuid

index 90337d52796efad60c72db545ce83b9ef9002e6b..86285df1d349c2c55241f0e93293981a8a131cac 100644 (file)
@@ -316,6 +316,8 @@ const installOpfsVfs = function callee(options){
     */
     state.sq3Codes = Object.create(null);
     [
+      'SQLITE_ACCESS_EXISTS',
+      'SQLITE_ACCESS_READWRITE',
       'SQLITE_ERROR',
       'SQLITE_IOERR',
       'SQLITE_IOERR_ACCESS',
@@ -939,7 +941,7 @@ const installOpfsVfs = function callee(options){
     */
     opfsUtil.entryExists = async function(fsEntryName){
       try {
-        const [dh, fn] = await opfsUtil.getDirForFilename(filename);
+        const [dh, fn] = await opfsUtil.getDirForFilename(fsEntryName);
         await dh.getFileHandle(fn);
         return true;
       }catch(e){
index 5e7f1bae2ee26678eadcf635afecd1275286b690..abee820cf967a25e1da744f3e176509b391b8e88 100644 (file)
@@ -162,33 +162,6 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     }
   });
 
-  /**
-     An Error subclass specifically for reporting DB-level errors and
-     enabling clients to unambiguously identify such exceptions.
-     The C-level APIs never throw, but some of the higher-level
-     C-style APIs do and the object-oriented APIs use exceptions
-     exclusively to report errors.
-  */
-  class SQLite3Error extends Error {
-    /**
-       Constructs this object with a message equal to all arguments
-       concatenated with a space between each one. As a special case,
-       if it's passed only a single integer argument, the string form
-       of that argument is the result of
-       sqlite3.capi.sqlite3_js_rc_str() or (if that returns falsy), a
-       synthesized string which contains that integer.
-    */
-    constructor(...args){
-      if(1===args.length && 'number'===typeof args[0] && args[0]===(args[0] | 0)){
-        super((capi.sqlite3_js_rc_str && capi.sqlite3_js_rc_str(args[0]))
-              || ("Unknown result code #"+args[0]));
-      }else{
-        super(args.join(' '));
-      }
-      this.name = 'SQLite3Error';
-    }
-  };
-
   /** 
       The main sqlite3 binding API gets installed into this object,
       mimicking the C API as closely as we can. The numerous members
@@ -219,6 +192,52 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
   */
   const wasm = Object.create(null);
 
+  /** Internal helper for SQLite3Error ctor. */
+  const __rcStr = (rc)=>{
+    return (capi.sqlite3_js_rc_str && capi.sqlite3_js_rc_str(rc))
+           || ("Unknown result code #"+rc);
+  };
+
+  /** Internal helper for SQLite3Error ctor. */
+  const __isInt = (n)=>'number'===typeof n && n===(n | 0);
+
+  /**
+     An Error subclass specifically for reporting DB-level errors and
+     enabling clients to unambiguously identify such exceptions.
+     The C-level APIs never throw, but some of the higher-level
+     C-style APIs do and the object-oriented APIs use exceptions
+     exclusively to report errors.
+  */
+  class SQLite3Error extends Error {
+    /**
+       Constructs this object with a message depending on its arguments:
+
+       - If it's passed only a single integer argument, it is assumed
+       to be an sqlite3 C API result code. The message becomes the
+       result of sqlite3.capi.sqlite3_js_rc_str() or (if that returns
+       falsy) a synthesized string which contains that integer.
+
+       - If passed 2 arguments and the 2nd is a object, it bevaves
+       like the Error(string,object) constructor except that the first
+       argument is subject to the is-integer semantics from the
+       previous point.
+
+       - Else all arguments are concatenated with a space between each
+       one, using args.join(' '), to create the error message.
+    */
+    constructor(...args){
+      if(1===args.length && __isInt(args[0])){
+        super(__rcStr(args[0]));
+      }else if(2===args.length && 'object'===typeof args){
+        if(__isInt(args[0])) super(__rcStr(args[0]), args[1]);
+        else super(...args);
+      }else{
+        super(args.join(' '));
+      }
+      this.name = 'SQLite3Error';
+    }
+  };
+
   /**
      Functionally equivalent to the SQLite3Error constructor but may
      be used as part of an expression, e.g.:
@@ -959,6 +978,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
   wasm.bindingSignatures.wasm = [
     ["sqlite3_wasm_db_reset", "int", "sqlite3*"],
     ["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
+    ["sqlite3_wasm_vfs_create_file", "int",
+     "sqlite3_vfs*","string","*", "int"],
     ["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
   ];
 
index 532d61b67e3043b0c1dc2c240e28ce3df7233ea6..32fbc5bb17e2d7460d97f3db4174e489bab9b476 100644 (file)
@@ -423,6 +423,15 @@ sqlite3.initWorker1API = function(){
     return wState.dbList[0] && getDbId(wState.dbList[0]);
   };
 
+  const guessVfs = function(filename){
+    const m = /^file:.+(vfs=(\w+))/.exec(filename);
+    return sqlite3.capi.sqlite3_vfs_find(m ? m[2] : 0);
+  };
+
+  const isSpecialDbFilename = (n)=>{
+    return ''===n || ':'===n[0];
+  };
+
   /**
      A level of "organizational abstraction" for the Worker1
      API. Each method in this object must map directly to a Worker1
@@ -441,11 +450,35 @@ sqlite3.initWorker1API = function(){
       }
       const rc = Object.create(null);
       const pDir = sqlite3.capi.sqlite3_wasmfs_opfs_dir();
-      if(!args.filename || ':memory:'===args.filename){
+      let byteArray, pVfs;
+      oargs.vfs = args.vfs;
+      if(isSpecialDbFilename(args.filename)){
         oargs.filename = args.filename || '';
       }else{
         oargs.filename = args.filename;
-        oargs.vfs = args.vfs;
+        byteArray = args.byteArray;
+        if(byteArray) pVfs = guessVfs(args.filename);
+      }
+      if(pVfs){
+        /* 2022-11-02: this feature is as-yet untested except that
+           sqlite3_wasm_vfs_create_file() has been tested from the
+           browser dev console. */
+        let pMem;
+        try{
+          pMem = sqlite3.wasm.allocFromTypedArray(byteArray);
+          const rc = sqlite3.wasm.sqlite3_wasm_vfs_create_file(
+            pVfs, oargs.filename, pMem, byteArray.byteLength
+          );
+          if(rc) sqlite3.SQLite3Error.toss(rc);
+        }catch(e){
+          throw new sqlite3.SQLite3Error(
+            e.name+' creating '+args.filename+": "+e.message, {
+              cause: e
+            }
+          );                           
+        }finally{
+          if(pMem) sqlite3.wasm.dealloc(pMem);
+        }
       }
       const db = wState.open(oargs);
       rc.filename = db.filename;
@@ -462,10 +495,9 @@ sqlite3.initWorker1API = function(){
         filename: db && db.filename
       };
       if(db){
-        // Keep the "unlink" flag undocumented until we figure out how
-        // to apply it consistently, independent of the db storage.
-        wState.close(db, ((ev.args && 'object'===typeof ev.args)
-                          ? !!ev.args.unlink : false));
+        const doUnlink = ((ev.args && 'object'===typeof ev.args)
+                         ? !!ev.args.unlink : false);
+        wState.close(db, doUnlink);
       }
       return response;
     },
@@ -542,7 +574,7 @@ sqlite3.initWorker1API = function(){
        sqlite3_serialize(). Response is an object:
 
        {
-         bytearray: Uint8Array (db file contents),
+         byteArray:  Uint8Array (db file contents),
          filename: the current db filename,
          mimetype: 'application/x-sqlite3'
        }
@@ -550,11 +582,11 @@ sqlite3.initWorker1API = function(){
     export: function(ev){
       const db = getMsgDb(ev);
       const response = {
-        bytearray: sqlite3.capi.sqlite3_js_db_export(db.pointer),
+        byteArray: sqlite3.capi.sqlite3_js_db_export(db.pointer),
         filename: db.filename,
         mimetype: 'application/x-sqlite3'
       };
-      wState.xfer.push(response.bytearray.buffer);
+      wState.xfer.push(response.byteArray.buffer);
       return response;
     }/*export()*/,
 
index e3c3b8214668623fc2c46c62faee376ca09bde24..86276910aaac3fece2c35f0376b2ddd5b3911d5b 100644 (file)
@@ -230,6 +230,16 @@ const storeAndNotify = (opName, value)=>{
 const affirmNotRO = function(opName,fh){
   if(fh.readOnly) toss(opName+"(): File is read-only: "+fh.filenameAbs);
 };
+const affirmLocked = function(opName,fh){
+  //if(!fh.syncHandle) toss(opName+"(): File does not have a lock: "+fh.filenameAbs);
+  /**
+     Currently a no-op, as speedtest1 triggers xRead() without a
+     lock (that seems like a bug but it's currently uninvestigated).
+     This means, however, that some OPFS VFS routines may trigger
+     acquisition of a lock but never let it go until xUnlock() is
+     called (which it likely won't be if xLock() was not called).
+  */
+};
 
 /**
    We track 2 different timers: the "metrics" timer records how much
@@ -395,6 +405,7 @@ const vfsAsyncImpls = {
     let rc;
     wTimeStart('xFileSize');
     try{
+      affirmLocked('xFileSize',fh);
       rc = await (await getSyncHandle(fh)).getSize();
       state.s11n.serialize(Number(rc));
       rc = 0;
@@ -473,6 +484,7 @@ const vfsAsyncImpls = {
     let rc = 0, nRead;
     const fh = __openFiles[fid];
     try{
+      affirmLocked('xRead',fh);
       wTimeStart('xRead');
       nRead = (await getSyncHandle(fh)).read(
         fh.sabView.subarray(0, n),
@@ -515,6 +527,7 @@ const vfsAsyncImpls = {
     const fh = __openFiles[fid];
     wTimeStart('xTruncate');
     try{
+      affirmLocked('xTruncate',fh);
       affirmNotRO('xTruncate', fh);
       await (await getSyncHandle(fh)).truncate(size);
     }catch(e){
@@ -547,9 +560,10 @@ const vfsAsyncImpls = {
   xWrite: async function(fid/*sqlite3_file pointer*/,n,offset64){
     mTimeStart('xWrite');
     let rc;
+    const fh = __openFiles[fid];
     wTimeStart('xWrite');
     try{
-      const fh = __openFiles[fid];
+      affirmLocked('xWrite',fh);
       affirmNotRO('xWrite', fh);
       rc = (
         n === (await getSyncHandle(fh))
index 1ca51f0d2fa677ef21cd27180078d72f59fc6d9d..62082edda0c239906b7f5947bb2e9b5449dfaa7b 100644 (file)
@@ -12,7 +12,6 @@
 **
 ** emcc -o sqlite3.wasm ... -I/path/to/sqlite3-c-and-h sqlite3-wasm.c
 */
-
 #define SQLITE_WASM
 #ifdef SQLITE_WASM_ENABLE_C_TESTS
 /*
@@ -928,8 +927,8 @@ int sqlite3_wasm_db_export_chunked( sqlite3* pDb,
 ** sqlite3_free() to free it.
 */
 SQLITE_WASM_KEEP
-int sqlite3_wasm_db_serialize( sqlite3pDb, unsigned char **pOut,
-                               sqlite3_int64 * nOut, unsigned int mFlags ){
+int sqlite3_wasm_db_serialize( sqlite3 *pDb, unsigned char **pOut,
+                               sqlite3_int64 *nOut, unsigned int mFlags ){
   unsigned char * z;
   if( !pDb || !pOut ) return SQLITE_MISUSE;
   if(nOut) *nOut = 0;
@@ -942,6 +941,103 @@ int sqlite3_wasm_db_serialize( sqlite3* pDb, unsigned char **pOut,
   }
 }
 
+/*
+** This function is NOT part of the sqlite3 public API. It is strictly
+** for use by the sqlite project's own JS/WASM bindings.
+**
+** Creates a new file using the I/O API of the given VFS, containing
+** the given number of bytes of the given data. If the file exists,
+** it is truncated to the given length and populated with the given
+** data.
+**
+** This function exists so that we can implement the equivalent of
+** Emscripten's FS.createDataFile() in a VFS-agnostic way. This
+** functionality is intended for use in uploading database files.
+**
+** If pVfs is NULL, sqlite3_vfs_find(0) is used.
+**
+** If zFile is NULL, pVfs is NULL (and sqlite3_vfs_find(0) returns
+** NULL), or nData is negative, SQLITE_MISUSE are returned.
+**
+** On success, it creates a new file with the given name, populated
+** with the fist nData bytes of pData. If pData is NULL, the file is
+** created and/or truncated to nData bytes.
+**
+** Whether or not directory components of zFilename are created
+** automatically or not is unspecified: that detail is left to the
+** VFS. The "opfs" VFS, for example, create them.
+**
+** Not all VFSes support this functionality, e.g. the "kvvfs" does
+** not.
+**
+** If an error happens while populating or truncating the file, the
+** target file will be deleted (if needed) if this function created
+** it. If this function did not create it, it is not deleted but may
+** be left in an undefined state.
+**
+** Returns 0 on success. On error, it returns a code described above
+** or propagates a code from one of the I/O methods.
+**
+** Design note: nData is an integer, instead of int64, for WASM
+** portability, so that the API can still work in builds where BigInt
+** support is disabled or unavailable.
+*/
+SQLITE_WASM_KEEP
+int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs,
+                                  const char *zFilename,
+                                  const unsigned char * pData,
+                                  int nData ){
+  int rc;
+  sqlite3_file *pFile = 0;
+  sqlite3_io_methods const *pIo;
+  const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
+  int flagsOut = 0;
+  int fileExisted = 0;
+  int doUnlock = 0;
+  const unsigned char *pPos = pData;
+  const int blockSize = 512
+    /* Because we are using pFile->pMethods->xWrite() for writing, and
+    ** it may have a buffer limit related to sqlite3's pager size, we
+    ** conservatively write in 512-byte blocks (smallest page
+    ** size). */;
+
+  if( !pVfs ) pVfs = sqlite3_vfs_find(0);
+  if( !pVfs || !zFilename || nData<0 ) return SQLITE_MISUSE;
+  pVfs->xAccess(pVfs, zFilename, SQLITE_ACCESS_EXISTS, &fileExisted);
+  rc = sqlite3OsOpenMalloc(pVfs, zFilename, &pFile, openFlags, &flagsOut);
+  if(rc) return rc;
+  pIo = pFile->pMethods;
+  if( pIo->xLock ) {
+    /* We need xLock() in order to accommodate the OPFS VFS, as it
+    ** obtains a writeable handle via the lock operation and releases
+    ** it in xUnlock(). If we don't do those here, we have to add code
+    ** to the VFS to account check whether it was locked before
+    ** xFileSize(), xTruncate(), and the like, and release the lock
+    ** only if it was unlocked when the op was started. */
+    rc = pIo->xLock(pFile, SQLITE_LOCK_EXCLUSIVE);
+    doUnlock = 0==rc;
+  }
+  if( 0==rc) rc = pIo->xTruncate(pFile, nData);
+  if( 0==rc && 0!=pData && nData>0 ){
+    while( 0==rc && nData>0 ){
+      const int n = nData>=blockSize ? blockSize : nData;
+      rc = pIo->xWrite(pFile, pPos, n, (sqlite3_int64)(pPos - pData));
+      nData -= n;
+      pPos += n;
+    }
+    if( 0==rc && nData>0 ){
+      assert(nData<512);
+      rc = pIo->xWrite(pFile, pPos, nData, (sqlite3_int64)(pPos - pData));
+    }
+  }
+  if( pIo->xUnlock && doUnlock!=0 ) pIo->xUnlock(pFile, SQLITE_LOCK_NONE);
+  pIo->xClose(pFile);
+  if( rc!=0 && 0==fileExisted ){
+    pVfs->xDelete(pVfs, zFilename, 1);
+  }
+  return rc;
+}
+
 /*
 ** This function is NOT part of the sqlite3 public API. It is strictly
 ** for use by the sqlite project's own JS/WASM bindings.
index 3f50ef9e08c9cf1f3e5eb0848e868d5ca9548037..a65cc31b6eeee3a47f5d70116365ff4fa8a90494 100644 (file)
         .assert(2===ev.resultRows[0][0]);
     });
 
+    await wtest('export', function(ev){
+      ev = ev.result;
+      T.assert('string' === typeof ev.filename)
+        .assert(ev.byteArray instanceof Uint8Array)
+        .assert(ev.byteArray.length > 1024)
+        .assert('application/x-sqlite3' === ev.mimetype);
+    });
+
     /***** close() tests must come last. *****/
     await wtest('close',{},function(ev){
       T.assert('string' === typeof ev.result.filename);
index ac4e9f42341a84e2fb9deb27130fc2f51e5eb3fc..cc63f3a7cc54740ce3322e4a781716b7ca097221 100644 (file)
       T.assert(1===ev.resultRows.length)
         .assert(2===ev.resultRows[0][0]);
     });
-    if(0){
-      // export requires reimpl. for portability reasons.
-      runOneTest('export',{}, function(ev){
-        ev = ev.result;
-        T.assert('string' === typeof ev.filename)
-          .assert(ev.buffer instanceof Uint8Array)
-          .assert(ev.buffer.length > 1024)
-          .assert('application/x-sqlite3' === ev.mimetype);
-      });
-    }
+    runOneTest('export',{}, function(ev){
+      ev = ev.result;
+      log("export result:",ev);
+      T.assert('string' === typeof ev.filename)
+        .assert(ev.byteArray instanceof Uint8Array)
+        .assert(ev.byteArray.length > 1024)
+        .assert('application/x-sqlite3' === ev.mimetype);
+    });
     /***** close() tests must come last. *****/
     runOneTest('close',{unlink:true},function(ev){
       ev = ev.result;
     }
   };
   log("Init complete, but async init bits may still be running.");
+  log("Installing Worker into global scope SW for dev purposes.");
+  self.SW = SW;
 })();
index 4f323687010437445e3756e0c6bcc19a2b0fe3de..825d529f6f6b86236a99501bf2fe86d0e5ee95c1 100644 (file)
       }
       try{ throw new sqlite3.SQLite3Error(capi.SQLITE_SCHEMA) }
       catch(e){ T.assert('SQLITE_SCHEMA' === e.message) }
+      try{ sqlite3.SQLite3Error.toss(capi.SQLITE_CORRUPT,{cause: true}) }
+      catch(e){
+        T.assert('SQLITE_CORRUPT'===e.message)
+          .assert(true===e.cause);
+      }
     })
   ////////////////////////////////////////////////////////////////////
     .t('strglob/strlike', function(sqlite3){
           unlink();
         }
 
+        if(1){
+          // Sanity-test sqlite3_wasm_vfs_create_file()...
+          const fSize = 1379;
+          let sh;
+          try{
+            T.assert(!(await opfs.entryExists(filename)));
+            let rc = wasm.sqlite3_wasm_vfs_create_file(
+              pVfs, filename, null, fSize
+            );
+            T.assert(0===rc)
+              .assert(await opfs.entryExists(filename));
+            const fh = await opfs.rootDirectory.getFileHandle(filename);
+            sh = await fh.createSyncAccessHandle();
+            T.assert(fSize === await sh.getSize());
+          }finally{
+            if(sh) sh.close();
+            unlink();
+          }
+        }
+
         // Some sanity checks of the opfs utility functions...
         const testDir = '/sqlite3-opfs-'+opfs.randomFilename(12);
         const aDir = testDir+'/test/dir';
index 618b053ced227d5506f1599a2672d19d800681b8..d045e6e87787d4f5b34d1a98632903764c5937a5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Emcc\sseems\sconfused\sby\sSQLITE_DEBUG,\sfor\sreasons\sunknown.\s\sUse\sNDEBUG\sinstead\nto\ssimplify\sthe\s#ifdef\slogic\sin\ssqlite3recover.c.
-D 2022-11-02T11:25:33.199
+C Add\ssqlite3_wasm_vfs_create_file()\sto\sreplace\sEmscripten's\sFS.createDataFile()\sin\sa\s(mostly)\sVFS-agnostic\sway.\sAdd\sa\stest\sfor\sworker1's\sexport\s(to\sbytearray)\ssupport.\sRe-add\sworker1\sopen-from-bytearray\susing\ssqlite3_wasm_vfs_create_file()\sbut\sit's\suntested\s(requires\sa\snew\sinteractive\stest\sapp\sor\smaybe\sreconsideration).
+D 2022-11-02T11:53:31.000
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -501,13 +501,13 @@ F ext/wasm/api/pre-js.js 287e462f969342b032c03900e668099fa1471d852df7a472de5bc34
 F ext/wasm/api/sqlite3-api-cleanup.js ecdc69dbfccfe26146f04799fcfd4a6f5790d46e7e3b9b6e9b0491f92ed8ae34
 F ext/wasm/api/sqlite3-api-glue.js 9cfa26a9818532c80c2555bc98615de3b170d5db0cf4b141cc3aa83c33c8758f
 F ext/wasm/api/sqlite3-api-oo1.js e9a83489bbb4838ce0aee46eaaa9350e0e25a5b926b565e4f5ae8e840e4fbaed
-F ext/wasm/api/sqlite3-api-opfs.js 59b278ed00764fc47ba88be0582ab3fc3ce725e02b6d86459464cc029b9ac356
-F ext/wasm/api/sqlite3-api-prologue.js 201b9ab9d101fdefa3175b02748ef39cba43bc7abe87a69b6faac24e58cd70f0
-F ext/wasm/api/sqlite3-api-worker1.js 4f920a54fb97d4ca50632d45bd7d011a55016eb5a5883725033abb450903bc6f
+F ext/wasm/api/sqlite3-api-opfs.js cdcbb57acc66f4569ac9e18f9d13d5a3657d8aae195725c6324943da56c1005d
+F ext/wasm/api/sqlite3-api-prologue.js 1f97261b4d8a60a48f30ee41261e1c4a0c3efff35ae08d7ece243fcf49b3eee3
+F ext/wasm/api/sqlite3-api-worker1.js cac2f5c63f950f69b5249c9880d4cd385e914c354c459d4096ed5dbb1248de76
 F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
-F ext/wasm/api/sqlite3-opfs-async-proxy.js 9815bd045b638af06350bfe04eaaae17ddf33c3593a9ca2d3f7fdbfd3c6a2205
+F ext/wasm/api/sqlite3-opfs-async-proxy.js 936f57737eb65afc0f4c3494b93f7b02208055226a7b3cb58f551c38b03ab083
 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
-F ext/wasm/api/sqlite3-wasm.c 14ac9c03f6585332f882703f3427f11ffe8ffe8b6c0e252be2c518f7aac6ab6a
+F ext/wasm/api/sqlite3-wasm.c 41f4c807d5e027d5dd61d507cb0a78d0cee5618220e100860ff4c45ed1bd7c78
 F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
 F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54
 F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
@@ -522,9 +522,9 @@ F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb0
 F ext/wasm/demo-jsstorage.html 409c4be4af5f207fb2877160724b91b33ea36a3cd8c204e8da1acb828ffe588e
 F ext/wasm/demo-jsstorage.js 44e3ae7ec2483b6c511384c3c290beb6f305c721186bcf5398ca4e00004a06b8
 F ext/wasm/demo-worker1-promiser.html 1de7c248c7c2cfd4a5783d2aa154bce62d74c6de98ab22f5786620b3354ed15f
-F ext/wasm/demo-worker1-promiser.js 988ce92220c1cf1dd95fcb6b59734f0ae677942469390ddd8a64f4bbb5f99821
+F ext/wasm/demo-worker1-promiser.js b85a2bb1b918db4f09dfa24419241cb3edad7791389425c2505092e9b715017d
 F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
-F ext/wasm/demo-worker1.js 117e4eedc62e103e287f0e4a694add7e13a200a4d7056e718645032288c4a8ab
+F ext/wasm/demo-worker1.js a619adffc98b75b66c633b00f747b856449a134a9a0357909287d80a182d70fa
 F ext/wasm/dist.make 481289899a07958439d07ee4302ff86235fa0fbb72f17ea05db2be90a94abf90
 F ext/wasm/fiddle.make e570ec1bfc7d803507a2e514fe32f673fe001b2114b85c73c3964a462ba8bcfc
 F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
@@ -549,7 +549,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
 F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
 F ext/wasm/tester1-worker.html 51bf39e2b87f974ae3d5bc3086e2fb36d258f3698c54f6e21ba4b3b99636fa27
 F ext/wasm/tester1.html 624ec41cd9f78a1f2b6d7df70aaa7a6394396b1f2455ecbd6de5775c1275b121
-F ext/wasm/tester1.js 157eb499aad3365e33a7d95d6847c1d58d533335bc19d79bd3bc700b6350d1a5
+F ext/wasm/tester1.js db50ca105d683d1089f540dae4c2baf89a3c101704a05f22cefdcb517587ae8c
 F ext/wasm/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5
 F ext/wasm/wasmfs.make fb2d3c4a298b12cf1ec994ad1d0f1d027ae297449b364cde43d2eb807d68048f
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
@@ -2054,8 +2054,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 5bc83d569594e104e90b1acef1a5fd23655b2089de393a6776e799fdef2082f5
-R 9c17a1415bba7769c29ae72a7a64647a
-U drh
-Z c15361b7db363b8dd30434361c36431b
+P 2610779ac84ac4a1a6901b6244653faf0c49ac6f0a4710a19aaf2a13106ae742
+R 54447cdf301faadeadecf9cb178cd6b7
+U stephan
+Z 0f92ea26c92634fd686db2350d9751fe
 # Remove this line to create a well-formed Fossil manifest.
index 14e359d1403e666a3b61a51913471a37f09e66e7..4b6ad41d7d05045f8280838de476ad32a494b9f5 100644 (file)
@@ -1 +1 @@
-2610779ac84ac4a1a6901b6244653faf0c49ac6f0a4710a19aaf2a13106ae742
\ No newline at end of file
+b35e1225c91a3cadc0d25af1e4e790237256d194990faa13190e343ed03e11c5
\ No newline at end of file