]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add JS wrapper for sqlite3_exec() which knows how to handle a JS callback. Add some...
authorstephan <stephan@noemail.net>
Fri, 30 Sep 2022 20:35:37 +0000 (20:35 +0000)
committerstephan <stephan@noemail.net>
Fri, 30 Sep 2022 20:35:37 +0000 (20:35 +0000)
FossilOrigin-Name: 96818aa83f4ccc574f558231249ecbdd39763b4351cf4cf6d33f53774a3ee5e6

ext/wasm/api/extern-post-js.js
ext/wasm/api/sqlite3-api-cleanup.js
ext/wasm/api/sqlite3-api-glue.js
ext/wasm/api/sqlite3-api-prologue.js
ext/wasm/testing1.js
ext/wasm/testing2.js
manifest
manifest.uuid

index 25d2d1b32803fd2840f4ce3b18ffe52049303f65..5ebb5a31e7c47c1e102f1676bddb4b58f5ef95a4 100644 (file)
@@ -15,7 +15,6 @@
   if(!originalInit){
     throw new Error("Expecting self.sqlite3InitModule to be defined by the Emscripten build.");
   }
-  self.sqlite3InitModule.ready = originalInit.ready;
   self.sqlite3InitModule = (...args)=>{
     //console.warn("Using replaced sqlite3InitModule()",self.location);
     return originalInit(...args).then((EmscriptenModule)=>{
       const f = EmscriptenModule.sqlite3.asyncPostInit;
       delete EmscriptenModule.sqlite3.asyncPostInit;
       return f();
+    }).catch((e)=>{
+      console.error("Exception loading sqlite3 module:",e);
+      throw e;
     });
   };
+  self.sqlite3InitModule.ready = originalInit.ready;
   //console.warn("Replaced sqlite3InitModule()");
 })();
index 12d766886433c15ce407f1b15d11ad96ac31d2d1..c2a342589122fa64378bf2b6c0bcf2cbab29e97c 100644 (file)
@@ -46,6 +46,9 @@ if('undefined' !== typeof Module){ // presumably an Emscripten build
   let sqlite3;
   try{
     sqlite3 = self.sqlite3ApiBootstrap();
+  }catch(e){
+    console.error("sqlite3ApiBootstrap() error:",e);
+    throw e;
   }finally{
     delete self.sqlite3ApiBootstrap;
     if(rmApiConfig) delete self.sqlite3ApiConfig;
index 2082f427b96f39a7bfa4e55a4374b8b18d9864dd..347c03bc44df338c3248a47a24bff0959bd217c2 100644 (file)
@@ -33,20 +33,27 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        to a C-style sqlite3_xxx function which takes an `sqlite3*`
        argument.
     */
-    const oldP = wasm.xWrap.argAdapter('pointer');
+    const xPointer = wasm.xWrap.argAdapter('pointer');
     const adapter = function(v){
-      if(v && 'object'===typeof v && v.constructor){
+      if(v && v.constructor){
         const x = v.pointer;
         if(Number.isInteger(x)) return x;
-        else toss("Invalid (object) type for pointer-type argument.");
+        else toss("Invalid (object) type for .pointer-type argument.");
       }
-      return oldP(v);
+      return xPointer(v);
     };
     wasm.xWrap.argAdapter('.pointer', adapter);
   } /* ".pointer" xWrap() argument adapter */
 
-  // WhWasmUtil.xWrap() bindings...
-  {
+  if(1){/* Convert Arrays and certain TypedArrays to strings for
+           'flexible-string'-type arguments */
+    const xString = wasm.xWrap.argAdapter('string');
+    wasm.xWrap.argAdapter(
+      'flexible-string', (v)=>xString(util.arrayToString(v))
+    );
+  }
+  
+  if(1){// WhWasmUtil.xWrap() bindings...
     /**
        Add some descriptive xWrap() aliases for '*' intended to
        (A) initially improve readability/correctness of capi.signatures
@@ -107,51 +114,139 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
   }/*xWrap() bindings*/;
 
   /**
-     Scope-local holder of the two impls of sqlite3_prepare_v2/v3().
+     Internal helper to assist in validating call argument counts in
+     the hand-written sqlite3_xyz() wrappers. We do this only for
+     consistency with non-special-case wrappings.
   */
-  const __prepare = Object.create(null);
-  /**
-     This binding expects a JS string as its 2nd argument and
-     null as its final argument. In order to compile multiple
-     statements from a single string, the "full" impl (see
-     below) must be used.
-  */
-  __prepare.basic = wasm.xWrap('sqlite3_prepare_v3',
-                               "int", ["sqlite3*", "string",
-                                       "int"/*ignored for this impl!*/,
-                                       "int", "**",
-                                       "**"/*MUST be 0 or null or undefined!*/]);
+  const __dbArgcMismatch = (pDb,f,n)=>{
+    return sqlite3.util.sqlite3_wasm_db_error(pDb, capi.SQLITE_MISUSE,
+                                              f+"() requires "+n+" argument"+
+                                              (1===n?'':'s')+".");
+  };
+
   /**
-     Impl which requires that the 2nd argument be a pointer
-     to the SQL string, instead of being converted to a
-     string. This variant is necessary for cases where we
-     require a non-NULL value for the final argument
-     (exec()'ing multiple statements from one input
-     string). For simpler cases, where only the first
-     statement in the SQL string is required, the wrapper
-     named sqlite3_prepare_v2() is sufficient and easier to
-     use because it doesn't require dealing with pointers.
+     Helper for flexible-string conversions which require a
+     byte-length counterpart argument. Passed a value and its
+     ostensible length, this function returns [V,N], where V
+     is either v or a transformed copy of v and N is either n,
+     -1, or the byte length of v (if it's a byte array).
   */
-  __prepare.full = wasm.xWrap('sqlite3_prepare_v3',
-                              "int", ["sqlite3*", "*", "int", "int",
-                                      "**", "**"]);
-
-  /* Documented in the api object's initializer. */
-  capi.sqlite3_prepare_v3 = function f(pDb, sql, sqlLen, prepFlags, ppStmt, pzTail){
-    if(util.isSQLableTypedArray(sql)) sql = util.typedArrayToString(sql);
-    switch(typeof sql){
-        case 'string': return __prepare.basic(pDb, sql, -1, prepFlags, ppStmt, null);
-        case 'number': return __prepare.full(pDb, sql, sqlLen, prepFlags, ppStmt, pzTail);
-        default:
-          return util.sqlite3_wasm_db_error(
-            pDb, capi.SQLITE_MISUSE,
-            "Invalid SQL argument type for sqlite3_prepare_v2/v3()."
-          );
+  const __flexiString = function(v,n){
+    if('string'===typeof v){
+      n = -1;
+    }else if(util.isSQLableTypedArray(v)){
+      n = v.byteLength;
+      v = util.typedArrayToString(v);
+    }else if(Array.isArray(v)){
+      v = v.join('');
+      n = -1;
     }
+    return [v, n];
   };
 
-  capi.sqlite3_prepare_v2 =
-    (pDb, sql, sqlLen, ppStmt, pzTail)=>capi.sqlite3_prepare_v3(pDb, sql, sqlLen, 0, ppStmt, pzTail);
+  if(1){/* Special-case handling of sqlite3_exec() */
+    const __exec = wasm.xWrap("sqlite3_exec", "int",
+                              ["sqlite3*", "flexible-string", "*", "*", "**"]);
+    /* Documented in the api object's initializer. */
+    capi.sqlite3_exec = function(pDb, sql, callback, pVoid, pErrMsg){
+      if(5!==arguments.length){
+        return __dbArgcMismatch(pDb,"sqlite3_exec",5);
+      }else if('function' !== typeof callback){
+        return __exec(pDb, sql, callback, pVoid, pErrMsg);
+      }
+      /* Wrap the callback in a WASM-bound function and convert the callback's
+         `(char**)` arguments to arrays of strings... */
+      const wasm = capi.wasm;
+      const cbwrap = function(pVoid, nCols, pColVals, pColNames){
+        let rc = capi.SQLITE_ERROR;
+        try {
+          let aVals = [], aNames = [], i = 0, offset = 0;
+          for( ; i < nCols; offset += (wasm.ptrSizeof * ++i) ){
+            aVals.push( wasm.cstringToJs(wasm.getPtrValue(pColVals + offset)) );
+            aNames.push( wasm.cstringToJs(wasm.getPtrValue(pColNames + offset)) );
+          }
+          rc = callback(pVoid, nCols, aVals, aNames) | 0;
+          /* The first 2 args of the callback are useless for JS but
+             we want the JS mapping of the C API to be as close to the
+             C API as possible. */
+        }catch(e){
+          /* If we set the db error state here, the higher-level exec() call
+             replaces it with its own, so we have no way of reporting the
+             exception message except the console. We must not propagate
+             exceptions through the C API. */
+        }
+        return rc;
+      };
+      let pFunc, rc;
+      try{
+        pFunc = wasm.installFunction("ipipp", cbwrap);
+        rc = __exec(pDb, sql, pFunc, pVoid, pErrMsg);
+      }catch(e){
+        rc = util.sqlite3_wasm_db_error(pDb, capi.SQLITE_ERROR,
+                                        "Error running exec(): "+e.message);
+      }finally{
+        if(pFunc) wasm.uninstallFunction(pFunc);
+      }
+      return rc;
+    };
+  }/*sqlite3_exec() proxy*/;
+
+  if(1){/* Special-case handling of sqlite3_prepare_v2() and
+      sqlite3_prepare_v3() */
+    /**
+       Scope-local holder of the two impls of sqlite3_prepare_v2/v3().
+    */
+    const __prepare = Object.create(null);
+    /**
+       This binding expects a JS string as its 2nd argument and
+       null as its final argument. In order to compile multiple
+       statements from a single string, the "full" impl (see
+       below) must be used.
+    */
+    __prepare.basic = wasm.xWrap('sqlite3_prepare_v3',
+                                 "int", ["sqlite3*", "string",
+                                         "int"/*ignored for this impl!*/,
+                                         "int", "**",
+                                         "**"/*MUST be 0 or null or undefined!*/]);
+    /**
+       Impl which requires that the 2nd argument be a pointer
+       to the SQL string, instead of being converted to a
+       string. This variant is necessary for cases where we
+       require a non-NULL value for the final argument
+       (exec()'ing multiple statements from one input
+       string). For simpler cases, where only the first
+       statement in the SQL string is required, the wrapper
+       named sqlite3_prepare_v2() is sufficient and easier to
+       use because it doesn't require dealing with pointers.
+    */
+    __prepare.full = wasm.xWrap('sqlite3_prepare_v3',
+                                "int", ["sqlite3*", "*", "int", "int",
+                                        "**", "**"]);
+
+    /* Documented in the api object's initializer. */
+    capi.sqlite3_prepare_v3 = function f(pDb, sql, sqlLen, prepFlags, ppStmt, pzTail){
+      if(6!==arguments.length){
+        return __dbArgcMismatch(pDb,"sqlite3_prepare_v3",6);
+      }
+      const [xSql, xSqlLen] = __flexiString(sql, sqlLen);
+      switch(typeof xSql){
+          case 'string': return __prepare.basic(pDb, xSql, xSqlLen, prepFlags, ppStmt, null);
+          case 'number': return __prepare.full(pDb, xSql, xSqlLen, prepFlags, ppStmt, pzTail);
+          default:
+            return util.sqlite3_wasm_db_error(
+              pDb, capi.SQLITE_MISUSE,
+              "Invalid SQL argument type for sqlite3_prepare_v2/v3()."
+            );
+      }
+    };
+
+    /* Documented in the api object's initializer. */
+    capi.sqlite3_prepare_v2 = function(pDb, sql, sqlLen, ppStmt, pzTail){
+      return (5==arguments.length)
+        ? capi.sqlite3_prepare_v3(pDb, sql, sqlLen, 0, ppStmt, pzTail)
+        : __dbArgcMismatch(pDb,"sqlite3_prepare_v2",5);
+    };
+  }/*sqlite3_prepare_v2/v3()*/;
 
   /**
      Install JS<->C struct bindings for the non-opaque struct types we
@@ -208,3 +303,4 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     sourceId: sqlite3.capi.sqlite3_sourceid()
   });
 });
+
index 760c4b0b4a8304d2700e080c7b8ca2afec1ffb75..b738485cb82f83dbdb135d99600468b276451ba5 100644 (file)
@@ -243,6 +243,17 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     );
   };
 
+  /**
+     If v is-a Array, its join('') result is returned.  If
+     isSQLableTypedArray(v) then typedArrayToString(v) is
+     returned. Else v is returned as-is.
+  */
+  const arrayToString = function(v){
+    if(isSQLableTypedArray(v)) return typedArrayToString(v);
+    else if(Array.isArray(v)) return v.join('');
+    return v;
+  };
+
   /**
      An Error subclass specifically for reporting Wasm-level malloc()
      failure and enabling clients to unambiguously identify such
@@ -350,15 +361,34 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        comments or an empty SQL expression, 0 is returned but the result
        output pointer will be NULL.
     */
-    sqlite3_prepare_v3: function(dbPtr, sql, sqlByteLen, prepFlags,
-                                 stmtPtrPtr, strPtrPtr){}/*installed later*/,
+    sqlite3_prepare_v3: (dbPtr, sql, sqlByteLen, prepFlags,
+                         stmtPtrPtr, strPtrPtr)=>{}/*installed later*/,
 
     /**
        Equivalent to calling sqlite3_prapare_v3() with 0 as its 4th argument.
     */
-    sqlite3_prepare_v2: function(dbPtr, sql, sqlByteLen, stmtPtrPtr,
-                                 strPtrPtr){}/*installed later*/,
+    sqlite3_prepare_v2: (dbPtr, sql, sqlByteLen,
+                         stmtPtrPtr,strPtrPtr)=>{}/*installed later*/,
 
+    /**
+       This binding enables the callback argument to be a JavaScript.
+
+       If the callback is a function, then for the duration of the
+       sqlite3_exec() call, it installs a WASM-bound function which
+       acts as a proxy for the given callback. That proxy will
+       also perform a conversion of the callback's arguments from
+       `(char**)` to JS arrays of strings. However, for API
+       consistency's sake it will still honor the C-level
+       callback parameter order and will call it like:
+
+       `callback(pVoid, colCount, listOfValues, listOfColNames)`
+
+       If the callback is not a JS function then this binding performs
+       no translation of the callback, but the sql argument is still
+       converted to a WASM string for the call using the
+       "flexible-string" argument converter.
+    */
+    sqlite3_exec: (pDb, sql, callback, pVoid, pErrMsg)=>{}/*installed later*/,
     /**
        Various internal-use utilities are added here as needed. They
        are bound to an object only so that we have access to them in
@@ -367,8 +397,9 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        removed.
     */
     util:{
-      isInt32, isTypedArray, isBindableTypedArray, isSQLableTypedArray,
-      affirmBindableTypedArray, typedArrayToString,
+      affirmBindableTypedArray, arrayToString, isBindableTypedArray,
+      isInt32, isSQLableTypedArray, isTypedArray, 
+      typedArrayToString,
       isMainWindow: ()=>{
         return self.window===self && self.document;
       }
@@ -614,10 +645,9 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     ["sqlite3_errmsg", "string", "sqlite3*"],
     ["sqlite3_error_offset", "int", "sqlite3*"],
     ["sqlite3_errstr", "string", "int"],
-    ["sqlite3_exec", "int", "sqlite3*", "string", "*", "*", "**"],
-    // TODO?: ^^^ add a wrapper around sqlite3_exec() which accepts a
-    // JS callback function and handles the (un)installation of that
-    // function before/after the exec call.
+    /*["sqlite3_exec", "int", "sqlite3*", "string", "*", "*", "**"
+      Handled seperately to perform translation of the callback
+      into a WASM-usable one. ],*/
     ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
     ["sqlite3_extended_errcode", "int", "sqlite3*"],
     ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
index 5b3d6189db43746dbbe67c74750766abf6181b6c..916f81babcfaecfcb85e4d7dcb835f3caaa7566e 100644 (file)
     // Custom db error message handling via sqlite3_prepare_v2/v3()
     if(capi.wasm.exports.sqlite3_wasm_db_error){
       log("Testing custom error message via prepare_v3()...");
-      let rc = capi.sqlite3_prepare_v3(db.pointer, [/*invalid*/], -1, 0, null, null);
+      let rc = capi.sqlite3_prepare_v3(db.pointer, {/*invalid*/}, -1, 0, null, null);
       T.assert(capi.SQLITE_MISUSE === rc)
         .assert(0 === capi.sqlite3_errmsg(db.pointer).indexOf("Invalid SQL"));
       log("errmsg =",capi.sqlite3_errmsg(db.pointer));
     const resultRows = [];
     db.exec({
       sql:new TextEncoder('utf-8').encode([
-        // ^^^ testing string-vs-typedarray handling in execMulti()
+        // ^^^ testing string-vs-typedarray handling in exec()
         "attach 'session' as foo;" /* name 'session' is magic for kvvfs! */,
         "create table foo.bar(a);",
         "insert into foo.bar(a) values(1),(2),(3);",
     T.assert(3===resultRows.length)
       .assert(2===resultRows[1]);
     T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a'));
+    let colCount = 0, rowCount = 0;
+    const execCallback = function(pVoid, nCols, aVals, aNames){
+      colCount = nCols;
+      ++rowCount;
+      T.assert(2===aVals.length)
+        .assert(2===aNames.length)
+        .assert(+(aVals[1]) === 2 * +(aVals[0]));
+    };
+    const capi = sqlite3.capi;
+    let rc = capi.sqlite3_exec(
+      db.pointer, "select a, a*2 from foo.bar", execCallback,
+      0, 0
+    );
+    T.assert(0===rc).assert(3===rowCount).assert(2===colCount);
+    rc = capi.sqlite3_exec(
+      db.pointer, "select a from foo.bar", ()=>{
+        toss("Testing throwing from exec() callback.");
+      }, 0, 0
+    );
+    T.assert(capi.SQLITE_ABORT === rc);
     db.exec("detach foo");
     T.mustThrow(()=>db.exec("select * from foo.bar"));
   };
index 986e683dea8f4c132377375574c7120c6cf37482..7163fe120430baca7dd7833f4948c11c6bf15556 100644 (file)
     runOneTest('close',{unlink:true},function(ev){
       ev = ev.result;
       T.assert(undefined === ev.filename);
+      logHtml('warning',"This is the final test.");
     });
+    logHtml('warning',"Finished posting tests. Waiting on async results.");
   };
 
   const runTests = function(){
index 3b4a64f8fd6f3ef6aff7a72156c5b384a3afc0f1..6f4fcd270a2bd6cbe3ac391f6e8a47e1cb99416b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\ssqlite3.version\sobject.\sAdd\smore\sstate\sto\sthe\sWorker\s#1\sconfig-get\sresponse,\sincluding\ssqlite3.version.
-D 2022-09-30T16:49:03.804
+C Add\sJS\swrapper\sfor\ssqlite3_exec()\swhich\sknows\show\sto\shandle\sa\sJS\scallback.\sAdd\ssome\sconsole.error()\sreporting\sof\smodule-load\sfailures,\sas\sthey\sotherwise\soften\sget\ssilently\sswallowed\sup\sby\sthe\sloader's\smechanisms.\sAdd\s'flexible-string'\sJS-to-WASM\sargument\sconverter\swhich\sperforms\smore\sX-to-string\sconversions\sthan\sthe\s'string'\sarg\sconverter\sdoes.
+D 2022-09-30T20:35:37.991
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -479,16 +479,16 @@ F ext/wasm/README.md 1e5b28158b74ab3ffc9d54fcbc020f0bbeb82c2ff8bbd904214c86c70e8
 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api c6b05641d733227a995cc05a2ba7ddc9ef2323081ae0cae5ed1d1f83d5b54b36
 F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
 F ext/wasm/api/README.md f54102d74cfde01ebe242fa1411e126a9cda8f19b3ac378afd1103b21abfad05
-F ext/wasm/api/extern-post-js.js b0df294159c290bec06cd67cce1a882d61944959ffe66a2f4ccbcb337e357781
+F ext/wasm/api/extern-post-js.js dc68cbf552d8ea085181400a6963907c32e0b088b03ffd8969b1869fea246629
 F ext/wasm/api/extern-pre-js.js 20143b16b672d0a576fbf768a786d12ee1f84e222126477072389b992542a5b2
 F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba81456260a713ed04900c
 F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
 F ext/wasm/api/pre-js.js 2db711eb637991b383fc6b5c0f3df65ec48a7201e5730e304beba8de2d3f9b0b
-F ext/wasm/api/sqlite3-api-cleanup.js 98905936119a555659b5cf43844211809ab9f436c52a569004e5585d2842b5c2
-F ext/wasm/api/sqlite3-api-glue.js 90206acd5cf556bd8a7a9275619aa680c9075ad8072ed1e18f47fc1d5cfbcf26
+F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb48c8bc4bbd463f05b021a99
+F ext/wasm/api/sqlite3-api-glue.js ead29e6008ba148e7c67ad2bd928819dc72313ad2dcd34510cc61e089ee01c4e
 F ext/wasm/api/sqlite3-api-oo1.js 9caed0757a5e039ed92467e827fd3ca347fa08f19fe086fcbdd14a4ebe9c2f01
 F ext/wasm/api/sqlite3-api-opfs.js 1b097808b7b081b0f0700cf97d49ef19760e401706168edff9cd45cf9169f541
-F ext/wasm/api/sqlite3-api-prologue.js 3a93497a9bc542c7202f32063cd070aa9c4cd03171a5e354cf99dd4357585b7a
+F ext/wasm/api/sqlite3-api-prologue.js cac3bc095171dca4aaf3611e0dd60a850c8e9fbeeeba8f21792ed1948d24dacc
 F ext/wasm/api/sqlite3-api-worker1.js 2e8a037a76d20c7653e5a392d9830f17a22ce6736ffd0597aa39b69d1c01ad2c
 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
 F ext/wasm/api/sqlite3-wasm.c 336389b23c9b83763177499e49a0967949c392b2f7d84fbbb52ad6678e159f18
@@ -530,9 +530,9 @@ F ext/wasm/test-opfs-vfs.js a59ff9210b17d46b0c6fbf6a0ba60143c033327865f2e556e14f
 F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893
 F ext/wasm/testing-worker1-promiser.js ee1ac4950720c07541e791b7f35bdf420e8ab81a74049cc65394371b0c53c480
 F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae
-F ext/wasm/testing1.js 06b9a439ada636c5478c581c86b2b968f799e0468eae54dc5a4565dfd7afbb88
+F ext/wasm/testing1.js 5584e9b68f797dbc0f6161360f2c6840169533813d92c74d355a3e78dd5bb539
 F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
-F ext/wasm/testing2.js 34737da985c4cbd4812b2e7f200942662cae991c5a58ffa5d0350be089d0d410
+F ext/wasm/testing2.js 88f40ef3cd8201bdadd120a711c36bbf0ce56cc0eab1d5e7debb71fed7822494
 F ext/wasm/wasmfs.make 3cce1820006196de140f90f2da4b4ea657083fb5bfee7d125be43f7a85748c8f
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
@@ -2029,8 +2029,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 1e09efe7fa15b8908f8b8353164a8361de778e27ea6c0b11c402bf4e1c56333d
-R 4c776ad1a7aec6f0bcde0b14554ad6b2
+P 711f458d188a0dbe6612069c856ade29323ab426dfa4f80e7b82757ccc474cb8
+R 84d8e08f60a70faceba1089503bc1c19
 U stephan
-Z 125edfcbc5b4725eac67cee184f7f0b1
+Z f9cd8bd536b2dd8409558133f7a063eb
 # Remove this line to create a well-formed Fossil manifest.
index 3f354628d9134bae4a8f8a2ceab8eef5d8eb6348..255400f97e351452fd18ee139f8aa5a8bba483f5 100644 (file)
@@ -1 +1 @@
-711f458d188a0dbe6612069c856ade29323ab426dfa4f80e7b82757ccc474cb8
\ No newline at end of file
+96818aa83f4ccc574f558231249ecbdd39763b4351cf4cf6d33f53774a3ee5e6
\ No newline at end of file