]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Reimplement JS's sqlite3_bind_text/blob() with hand-written bindings to permit more...
authorstephan <stephan@noemail.net>
Fri, 23 Dec 2022 23:46:33 +0000 (23:46 +0000)
committerstephan <stephan@noemail.net>
Fri, 23 Dec 2022 23:46:33 +0000 (23:46 +0000)
FossilOrigin-Name: 96ba44946b3e88b6aa305c4363cbbfeab0d9120b3d8c4d2587d68b9293ea7cc6

ext/wasm/api/sqlite3-api-glue.js
ext/wasm/api/sqlite3-api-oo1.js
ext/wasm/api/sqlite3-api-prologue.js
ext/wasm/common/whwasmutil.js
manifest
manifest.uuid

index a760e921fe94c58adc17d2e1912a6cc9267409c4..dd80963f3e68e0a9172b2b7f39756faf269e93c5 100644 (file)
@@ -42,10 +42,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
   wasm.bindingSignatures = [
     // Please keep these sorted by function name!
     ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
-    ["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*"
-     /* TODO: we should arguably write a custom wrapper which knows
-        how to handle Blob, TypedArrays, and JS strings. */
-    ],
+    /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written
+       bindings to permit more flexible inputs. */
     ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
     ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
     ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
@@ -53,16 +51,14 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
     ["sqlite3_bind_pointer", "int",
      "sqlite3_stmt*", "int", "*", "string:static", "*"],
-    ["sqlite3_bind_text","int", "sqlite3_stmt*", "int", "string", "int", "*"
-     /* We should arguably create a hand-written binding of
-        bind_text() which does more flexible text conversion, along
-        the lines of sqlite3_prepare_v3(). The slightly problematic
-        part is the final argument (text destructor). */
-    ],
-    //["sqlite3_busy_handler","int", "sqlite3*", "*", "*"],
-    // ^^^^ TODO: custom binding which auto-converts JS function arg
-    // to a WASM function, noting that calling it multiple times
-    // would introduce a leak.
+    ["sqlite3_busy_handler","int", [
+      "sqlite3*",
+      new wasm.xWrap.FuncPtrAdapter({
+        signature: 'i(pi)',
+        contextKey: (argIndex,argv)=>'sqlite3@'+argv[0]
+      }),
+      "*"
+    ]],
     ["sqlite3_busy_timeout","int", "sqlite3*", "int"],
     ["sqlite3_close_v2", "int", "sqlite3*"],
     ["sqlite3_changes", "int", "sqlite3*"],
@@ -779,6 +775,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
 
   if(1){/* Special-case handling of sqlite3_prepare_v2() and
            sqlite3_prepare_v3() */
+
     /**
        Helper for string:flexible conversions which require a
        byte-length counterpart argument. Passed a value and its
@@ -802,32 +799,33 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     /**
        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",
-                                        "**", "**"]);
+    const __prepare = {
+      /**
+         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.
+      */
+      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.
+      */
+      full: wasm.xWrap('sqlite3_prepare_v3',
+                       "int", ["sqlite3*", "*", "int", "int",
+                               "**", "**"])
+    };
 
     /* Documented in the capi object's initializer. */
     capi.sqlite3_prepare_v3 = function f(pDb, sql, sqlLen, prepFlags, ppStmt, pzTail){
@@ -852,7 +850,80 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
         ? capi.sqlite3_prepare_v3(pDb, sql, sqlLen, 0, ppStmt, pzTail)
         : __dbArgcMismatch(pDb,"sqlite3_prepare_v2",f.length);
     };
-  }/*sqlite3_prepare_v2/v3()*/;
+
+  }/*sqlite3_prepare_v2/v3()*/
+
+  {/*sqlite3_bind_text/blob()*/
+    const __bindText = wasm.xWrap("sqlite3_bind_text", "int", [
+      "sqlite3_stmt*", "int", "string", "int", "*"
+    ]);
+    const __bindBlob = wasm.xWrap("sqlite3_bind_blob", "int", [
+      "sqlite3_stmt*", "int", "*", "int", "*"
+    ]);
+
+    /** Documented in the capi object's initializer. */
+    capi.sqlite3_bind_text = function f(pStmt, iCol, text, nText, xDestroy){
+      if(f.length!==arguments.length){
+        return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt),
+                                "sqlite3_bind_text", f.length);
+      }else if(wasm.isPtr(text) || null===text){
+        return __bindText(pStmt, iCol, text, nText, xDestroy);
+      }else if(text instanceof ArrayBuffer){
+        text = new Uint8Array(text);
+      }else if(Array.isArray(pMem)){
+        text = pMem.join('');
+      }
+      let p, n;
+      try {
+        if(util.isSQLableTypedArray(text)){
+          p = wasm.allocFromTypedArray(text);
+          n = text.byteLength;
+        }else if('string'===typeof text){
+          [p, n] = wasm.allocCString(text);
+        }else{
+          return util.sqlite3_wasm_db_error(
+            capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
+            "Invalid 3rd argument type for sqlite3_bind_text()."
+          );
+        }
+        return __bindText(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
+      }finally{
+        wasm.dealloc(p);
+      }
+    }/*sqlite3_bind_text()*/;
+
+    /** Documented in the capi object's initializer. */
+    capi.sqlite3_bind_blob = function f(pStmt, iCol, pMem, nMem, xDestroy){
+      if(f.length!==arguments.length){
+        return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt),
+                                "sqlite3_bind_blob", f.length);
+      }else if(wasm.isPtr(pMem) || null===pMem){
+        return __bindBlob(pStmt, iCol, pMem, nMem, xDestroy);
+      }else if(pMem instanceof ArrayBuffer){
+        pMem = new Uint8Array(pMem);
+      }else if(Array.isArray(pMem)){
+        pMem = pMem.join('');
+      }
+      let p, n;
+      try{
+        if(util.isBindableTypedArray(pMem)){
+          p = wasm.allocFromTypedArray(pMem);
+          n = nMem>=0 ? nMem : pMem.byteLength;
+        }else if('string'===typeof pMem){
+          [p, n] = wasm.allocCString(pMem);
+        }else{
+          return util.sqlite3_wasm_db_error(
+            capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
+            "Invalid 3rd argument type for sqlite3_bind_blob()."
+          );
+        }
+        return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
+      }finally{
+        wasm.dealloc(p);
+      }
+    }/*sqlite3_bind_blob()*/;
+
+  }/*sqlite3_bind_text/blob()*/
 
   {/* sqlite3_set_authorizer() */
     const __ssa = wasm.xWrap("sqlite3_set_authorizer", 'int', [
index 1776cb327efb0a5387f280f770e121b30140ea4e..ddb346e5457ee5d52a4181b761a0d493f3301849 100644 (file)
@@ -1332,8 +1332,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
           }else if(!util.isBindableTypedArray(val)){
             toss3("Binding a value as a blob requires",
                   "that it be a string, Uint8Array, or Int8Array.");
-          }else if(1){
-            /* _Hypothetically_ more efficient than the impl in the 'else' block. */
+          }else{
             const stack = wasm.scopedAllocPush();
             try{
               const pBlob = wasm.scopedAlloc(val.byteLength || 1);
@@ -1343,14 +1342,6 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
             }finally{
               wasm.scopedAllocPop(stack);
             }
-          }else{
-            const pBlob = wasm.allocFromTypedArray(val);
-            try{
-              rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
-                                         capi.SQLITE_TRANSIENT);
-            }finally{
-              wasm.dealloc(pBlob);
-            }
           }
           break;
         }
index 6c50e99b0a3c1e1ee96c84db5dc82415c0b6dd4e..c3533a4767f0cd62cb5e3f9cc461b18e0658f5c4 100644 (file)
@@ -417,6 +417,92 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
   };
 
   Object.assign(capi, {
+    /**
+       sqlite3_bind_blob() works exactly like its C counterpart unless
+       its 3rd argument is one of:
+
+       - JS string: the 3rd argument is converted to a C string, the
+         4th argument is ignored, and the C-string's length is used
+         in its place.
+
+       - Array: converted to a string as defined for "flexible
+         strings" and then it's treated as a JS string.
+
+       - Int8Array or Uint8Array: wasm.allocFromTypedArray() is used to
+         conver the memory to the WASM heap. If the 4th argument is
+         0 or greater, it is used as-is, otherwise the array's byteLength
+         value is used. This is an exception to the C API's undefined
+         behavior for a negative 4th argument, but results are undefined
+         if the given 4th argument value is greater than the byteLength
+         of the input array.
+
+       - If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
+         treated as that type.
+
+       In all of those cases, the final argument (text destructor) is
+       ignored and capi.SQLITE_TRANSIENT is assumed.
+
+       A 3rd argument of `null` is treated as if it were a WASM pointer
+       of 0.
+
+       If the 3rd argument is neither a WASM pointer nor one of the
+       above-described types, capi.SQLITE_MISUSE is returned.
+
+       The first argument may be either an `sqlite3_stmt*` WASM
+       pointer or an sqlite3.oo1.Stmt instance.
+
+       For consistency with the C API, it requires the same number of
+       arguments. It returns capi.SQLITE_MISUSE if passed any other
+       argument count.
+    */
+    sqlite3_bind_blob: undefined/*installed later*/,
+
+    /**
+       sqlite3_bind_text() works exactly like its C counterpart unless
+       its 3rd argument is one of:
+
+       - JS string: the 3rd argument is converted to a C string, the
+         4th argument is ignored, and the C-string's length is used
+         in its place.
+
+       - Array: converted to a string as defined for "flexible
+         strings". The 4th argument is ignored and a value of -1
+         is assumed.
+
+       - Int8Array or Uint8Array: is assumed to contain UTF-8 text, is
+         converted to a string. The 4th argument is ignored, replaced
+         by the array's byteLength value.
+
+       - If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
+         treated as that type.
+
+       In each of those cases, the final argument (text destructor) is
+       ignored and capi.SQLITE_TRANSIENT is assumed.
+
+       A 3rd argument of `null` is treated as if it were a WASM pointer
+       of 0.
+
+       If the 3rd argument is neither a WASM pointer nor one of the
+       above-described types, capi.SQLITE_MISUSE is returned.
+
+       The first argument may be either an `sqlite3_stmt*` WASM
+       pointer or an sqlite3.oo1.Stmt instance.
+
+       For consistency with the C API, it requires the same number of
+       arguments. It returns capi.SQLITE_MISUSE if passed any other
+       argument count.
+
+       If client code needs to bind partial strings, it needs to
+       either parcel the string up before passing it in here or it
+       must pass in a WASM pointer for the 3rd argument and a valid
+       4th-argument value, taking care not to pass a value which
+       truncates a multi-byte UTF-8 character. When passing
+       WASM-format strings, it is important that the final argument be
+       valid or unexpected content can result can result, or even a
+       crash if the application reads past the WASM heap bounds.
+    */
+    sqlite3_bind_text: undefined/*installed later*/,
+
     /**
        sqlite3_create_function_v2() differs from its native
        counterpart only in the following ways:
@@ -525,18 +611,18 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        WASM build is compiled with emcc's `-sALLOW_TABLE_GROWTH`
        flag.
     */
-    sqlite3_create_function_v2: function(
+    sqlite3_create_function_v2: (
       pDb, funcName, nArg, eTextRep, pApp,
       xFunc, xStep, xFinal, xDestroy
-    ){/*installed later*/},
+    )=>{/*installed later*/},
     /**
        Equivalent to passing the same arguments to
        sqlite3_create_function_v2(), with 0 as the final argument.
     */
-    sqlite3_create_function:function(
+    sqlite3_create_function: (
       pDb, funcName, nArg, eTextRep, pApp,
       xFunc, xStep, xFinal
-    ){/*installed later*/},
+    )=>{/*installed later*/},
     /**
        The sqlite3_create_window_function() JS wrapper differs from
        its native implementation in the exact same way that
@@ -544,10 +630,10 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        xInverse(), is treated identically to xStep() by the wrapping
        layer.
     */
-    sqlite3_create_window_function: function(
+    sqlite3_create_window_function: (
       pDb, funcName, nArg, eTextRep, pApp,
       xStep, xFinal, xValue, xInverse, xDestroy
-    ){/*installed later*/},
+    )=>{/*installed later*/},
     /**
        The sqlite3_prepare_v3() binding handles two different uses
        with differing JS/WASM semantics:
@@ -669,7 +755,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     toss3,
     typedArrayPart
   };
-    
+
   Object.assign(wasm, {
     /**
        Emscripten APIs have a deep-seated assumption that all pointers
index 880ef4ab4e094462e958f44ffd5cbf15387e02ea..de7500a0205ad8978f3e8295a8557ed711808c11 100644 (file)
@@ -1406,7 +1406,8 @@ self.WhWasmUtilInstaller = function(target){
     .set('int', xArg.get('i32'))
     .set('null', (i)=>i)
     .set(null, xArg.get('null'))
-    .set('**', __xArgPtr);
+    .set('**', __xArgPtr)
+    .set('*', __xArgPtr);
   xResult.set('*', __xArgPtr)
     .set('pointer', __xArgPtr)
     .set('number', (v)=>Number(v))
@@ -1448,23 +1449,23 @@ self.WhWasmUtilInstaller = function(target){
     if('string'===typeof v) return target.scopedAllocCString(v);
     return v ? __xArgPtr(v) : null;
   };
-  xArg.set('string', __xArgString);
-  xArg.set('utf8', __xArgString);
-  xArg.set('pointer', __xArgString);
-  xArg.set('*', __xArgString);
-
-  xResult.set('string', (i)=>target.cstrToJs(i));
-  xResult.set('utf8', xResult.get('string'));
-  xResult.set('string:dealloc', (i)=>{
-    try { return i ? target.cstrToJs(i) : null }
-    finally{ target.dealloc(i) }
-  });
-  xResult.set('utf8:dealloc', xResult.get('string:dealloc'));
-  xResult.set('json', (i)=>JSON.parse(target.cstrToJs(i)));
-  xResult.set('json:dealloc', (i)=>{
-    try{ return i ? JSON.parse(target.cstrToJs(i)) : null }
-    finally{ target.dealloc(i) }
-  });
+  xArg.set('string', __xArgString)
+    .set('utf8', __xArgString)
+    .set('pointer', __xArgString);
+  //xArg.set('*', __xArgString);
+
+  xResult.set('string', (i)=>target.cstrToJs(i))
+    .set('utf8', xResult.get('string'))
+    .set('string:dealloc', (i)=>{
+      try { return i ? target.cstrToJs(i) : null }
+      finally{ target.dealloc(i) }
+    })
+    .set('utf8:dealloc', xResult.get('string:dealloc'))
+    .set('json', (i)=>JSON.parse(target.cstrToJs(i)))
+    .set('json:dealloc', (i)=>{
+      try{ return i ? JSON.parse(target.cstrToJs(i)) : null }
+      finally{ target.dealloc(i) }
+    });
 
   /**
      Internal-use-only base class for FuncPtrAdapter and potentially
@@ -1748,10 +1749,13 @@ self.WhWasmUtilInstaller = function(target){
      - `N*` (args): a type name in the form `N*`, where N is a numeric
        type name, is treated the same as WASM pointer.
 
-     - `*` and `pointer` (args): have multple semantics. They
-       behave exactly as described below for `string` args.
+     - `*` and `pointer` (args): are assumed to be WASM pointer values
+       and are returned coerced to an appropriately-sized pointer
+       value (i32 or i64). Non-numeric values will coerce to 0 and
+       out-of-range values will have undefined results (just as with
+       any pointer misuse).
 
-     - `*` and `pointer` (results): are aliases for the current
+     - `*` and `pointer` (results): aliases for the current
        WASM pointer numeric type.
 
      - `**` (args): is simply a descriptive alias for the WASM pointer
index 0476b9ecedf852053da0a0038719c50e71eb8233..9fa7ef3ea993e70d8e18f44df5ecfd98628d8e8c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Internal\sJS\scleanups.\sCorrect\spart\sof\s[ac136925a645]\sto\saccount\sfor\sthe\seTextRep\sflag\sbeing\sable\sto\shold\sflags\sother\sthan\sthe\sencoding.
-D 2022-12-23T21:10:49.493
+C Reimplement\sJS's\ssqlite3_bind_text/blob()\swith\shand-written\sbindings\sto\spermit\smore\sflexible\sinputs.\sAdd\sautomated\sJS-to-C\sfunction\sconversion\sto\ssqlite3_busy_handler().\ssqlite3.wasm.xWrap()'s\s'*'\sargument\sconversion\sno\slonger\streats\sJS\sstrings\sas\sC-strings:\sthose\sconversions\srequire\sexplicit\sopt-in\svia\sthe\s'string'\sconverter\s(or\sequivalent).
+D 2022-12-23T23:46:33.608
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -503,9 +503,9 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
 F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
 F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
 F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
-F ext/wasm/api/sqlite3-api-glue.js f50211dc11f1debf972cdaea87cb4df9772022828072e7100cf5025d1dca2a78
-F ext/wasm/api/sqlite3-api-oo1.js 4cce9671e8a31ac9b76bd8559e7827ccc2b121734e460fa9c7d243735a771ec8
-F ext/wasm/api/sqlite3-api-prologue.js 789639d256e3134563c5c9be25ade28b40e06e783885d26cccc01cd1ed4b820d
+F ext/wasm/api/sqlite3-api-glue.js f0651048a2601bf79f7f39c2c855f6417e65548417f5019ac9ac2ffb2463f2b9
+F ext/wasm/api/sqlite3-api-oo1.js c2a3e310f993a632b6c5da0c49b0635863a73df60c4f9fc0a30648f25e4ec32a
+F ext/wasm/api/sqlite3-api-prologue.js 683956ea6ab5e0132db48bb693a6bb9dd92f36c8c0902af36572e9b29006ac6d
 F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
 F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
 F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
@@ -521,7 +521,7 @@ F ext/wasm/c-pp.c 92285f7bce67ed7b7020b40fde8ed0982c442b63dc33df9dfd4b658d4a6c07
 F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b
 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
 F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
-F ext/wasm/common/whwasmutil.js 97807770ec452fdcaa48509c5decd3a2c1e3001164a62a3223a347f66967533e
+F ext/wasm/common/whwasmutil.js 700fb1b702986522d2177fe8247bfbab3040e82cb4f6c35e929c4c85fbd7ffc5
 F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
 F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
 F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
@@ -2067,8 +2067,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 deffe6fb211410fa1a1fbca824a52b4e09b54d4b4f4a4e12d71c9e4b7e8606fb
-R 537077e8e7a576993086a957d5c52d05
+P 1dfc03ab1e0269807beef27bf884ab9ead7553d4a5f6ed213f812d7fa052045f
+R 0557f08bf576b7be78ec588d2742348d
 U stephan
-Z 379d99233453fc912eb71dcbaf16b8ce
+Z 4e12d5aedea06f895991428eb871a6d7
 # Remove this line to create a well-formed Fossil manifest.
index a091b64a433a572014fe05f745596a18b7b887ee..83020f5c61a6816dde5d491fb665175c7f795a06 100644 (file)
@@ -1 +1 @@
-1dfc03ab1e0269807beef27bf884ab9ead7553d4a5f6ed213f812d7fa052045f
\ No newline at end of file
+96ba44946b3e88b6aa305c4363cbbfeab0d9120b3d8c4d2587d68b9293ea7cc6
\ No newline at end of file