Refactor the internal JS routines for converting UDF results and errors to JS into public APIs.
FossilOrigin-Name: 35d1d63c7d60119b64341c561294890812837d5432d1d7bed3ed88d6212fbfa0
This commit is contained in:
parent
8ccef8f27f
commit
5c99d91e53
@ -324,102 +324,31 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
"*"/*xInverse*/, "*"/*xDestroy*/]
|
"*"/*xInverse*/, "*"/*xDestroy*/]
|
||||||
);
|
);
|
||||||
|
|
||||||
const __udfSetResult = function(pCtx, val){
|
|
||||||
//console.warn("udfSetResult",typeof val, val);
|
|
||||||
switch(typeof val) {
|
|
||||||
case 'undefined':
|
|
||||||
/* Assume that the client already called sqlite3_result_xxx(). */
|
|
||||||
break;
|
|
||||||
case 'boolean':
|
|
||||||
capi.sqlite3_result_int(pCtx, val ? 1 : 0);
|
|
||||||
break;
|
|
||||||
case 'bigint':
|
|
||||||
if(wasm.bigIntEnabled){
|
|
||||||
if(util.bigIntFits64(val)) capi.sqlite3_result_int64(pCtx, val);
|
|
||||||
else toss3("BigInt value",val.toString(),"is too BigInt for int64.");
|
|
||||||
}else if(util.bigIntFits32(val)){
|
|
||||||
capi.sqlite3_result_int(pCtx, Number(val));
|
|
||||||
}else if(util.bigIntFitsDouble(val)){
|
|
||||||
capi.sqlite3_result_double(pCtx, Number(val));
|
|
||||||
}else{
|
|
||||||
toss3("BigInt value",val.toString(),"is too BigInt.");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'number': {
|
|
||||||
(util.isInt32(val)
|
|
||||||
? capi.sqlite3_result_int
|
|
||||||
: capi.sqlite3_result_double)(pCtx, val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'string':
|
|
||||||
capi.sqlite3_result_text(pCtx, val, -1, capi.SQLITE_TRANSIENT);
|
|
||||||
break;
|
|
||||||
case 'object':
|
|
||||||
if(null===val/*yes, typeof null === 'object'*/) {
|
|
||||||
capi.sqlite3_result_null(pCtx);
|
|
||||||
break;
|
|
||||||
}else if(util.isBindableTypedArray(val)){
|
|
||||||
const pBlob = wasm.allocFromTypedArray(val);
|
|
||||||
capi.sqlite3_result_blob(
|
|
||||||
pCtx, pBlob, val.byteLength,
|
|
||||||
wasm.exports[sqlite3.config.deallocExportName]
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// else fall through
|
|
||||||
default:
|
|
||||||
toss3("Don't not how to handle this UDF result value:",(typeof val), val);
|
|
||||||
};
|
|
||||||
}/*__udfSetResult()*/;
|
|
||||||
|
|
||||||
const __udfConvertArgs = function(argc, pArgv){
|
|
||||||
let i;
|
|
||||||
const tgt = [];
|
|
||||||
for(i = 0; i < argc; ++i){
|
|
||||||
/**
|
|
||||||
Curiously: despite ostensibly requiring 8-byte
|
|
||||||
alignment, the pArgv array is parcelled into chunks of
|
|
||||||
4 bytes (1 pointer each). The values those point to
|
|
||||||
have 8-byte alignment but the individual argv entries
|
|
||||||
do not.
|
|
||||||
*/
|
|
||||||
tgt.push(capi.sqlite3_value_to_js(
|
|
||||||
wasm.peekPtr(pArgv + (wasm.ptrSizeof * i))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return tgt;
|
|
||||||
}/*__udfConvertArgs()*/;
|
|
||||||
|
|
||||||
const __udfSetError = (pCtx, e)=>{
|
|
||||||
if(e instanceof sqlite3.WasmAllocError){
|
|
||||||
capi.sqlite3_result_error_nomem(pCtx);
|
|
||||||
}else{
|
|
||||||
const msg = ('string'===typeof e) ? e : e.message;
|
|
||||||
capi.sqlite3_result_error(pCtx, msg, -1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const __xFunc = function(callback){
|
const __xFunc = function(callback){
|
||||||
return function(pCtx, argc, pArgv){
|
return function(pCtx, argc, pArgv){
|
||||||
try{ __udfSetResult(pCtx, callback(pCtx, ...__udfConvertArgs(argc, pArgv))) }
|
try{
|
||||||
catch(e){
|
capi.sqlite3_result_js(
|
||||||
|
pCtx,
|
||||||
|
callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv))
|
||||||
|
);
|
||||||
|
}catch(e){
|
||||||
//console.error('xFunc() caught:',e);
|
//console.error('xFunc() caught:',e);
|
||||||
__udfSetError(pCtx, e);
|
capi.sqlite3_result_error_js(pCtx, e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const __xInverseAndStep = function(callback){
|
const __xInverseAndStep = function(callback){
|
||||||
return function(pCtx, argc, pArgv){
|
return function(pCtx, argc, pArgv){
|
||||||
try{ callback(pCtx, ...__udfConvertArgs(argc, pArgv)) }
|
try{ callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv)) }
|
||||||
catch(e){ __udfSetError(pCtx, e) }
|
catch(e){ capi.sqlite3_result_error_js(pCtx, e) }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const __xFinalAndValue = function(callback){
|
const __xFinalAndValue = function(callback){
|
||||||
return function(pCtx){
|
return function(pCtx){
|
||||||
try{ __udfSetResult(pCtx, callback(pCtx)) }
|
try{ capi.sqlite3_result_js(pCtx, callback(pCtx)) }
|
||||||
catch(e){ __udfSetError(pCtx, e) }
|
catch(e){ capi.sqlite3_result_error_js(pCtx, e) }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -525,61 +454,28 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
return rc;
|
return rc;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
A helper for UDFs implemented in JS and bound to WASM by the
|
A _deprecated_ alias for capi.sqlite3_result_js() which
|
||||||
client. Given a JS value, udfSetResult(pCtx,X) calls one of the
|
predates the addition of that function in the public API.
|
||||||
sqlite3_result_xyz(pCtx,...) routines, depending on X's data
|
|
||||||
type:
|
|
||||||
|
|
||||||
- `null`: sqlite3_result_null()
|
|
||||||
- `boolean`: sqlite3_result_int()
|
|
||||||
- `number`: sqlite3_result_int() or sqlite3_result_double()
|
|
||||||
- `string`: sqlite3_result_text()
|
|
||||||
- Uint8Array or Int8Array: sqlite3_result_blob()
|
|
||||||
- `undefined`: indicates that the UDF called one of the
|
|
||||||
`sqlite3_result_xyz()` routines on its own, making this
|
|
||||||
function a no-op. Results are _undefined_ if this function is
|
|
||||||
passed the `undefined` value but did _not_ call one of the
|
|
||||||
`sqlite3_result_xyz()` routines.
|
|
||||||
|
|
||||||
Anything else triggers sqlite3_result_error().
|
|
||||||
*/
|
*/
|
||||||
capi.sqlite3_create_function_v2.udfSetResult =
|
capi.sqlite3_create_function_v2.udfSetResult =
|
||||||
capi.sqlite3_create_function.udfSetResult =
|
capi.sqlite3_create_function.udfSetResult =
|
||||||
capi.sqlite3_create_window_function.udfSetResult = __udfSetResult;
|
capi.sqlite3_create_window_function.udfSetResult = capi.sqlite3_result_js;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A helper for UDFs implemented in JS and bound to WASM by the
|
A _deprecated_ alias for capi.sqlite3_values_to_js() which
|
||||||
client. When passed the
|
predates the addition of that function in the public API.
|
||||||
(argc,argv) values from the UDF-related functions which receive
|
|
||||||
them (xFunc, xStep, xInverse), it creates a JS array
|
|
||||||
representing those arguments, converting each to JS in a manner
|
|
||||||
appropriate to its data type: numeric, text, blob
|
|
||||||
(Uint8Array), or null.
|
|
||||||
|
|
||||||
Results are undefined if it's passed anything other than those
|
|
||||||
two arguments from those specific contexts.
|
|
||||||
|
|
||||||
Thus an argc of 4 will result in a length-4 array containing
|
|
||||||
the converted values from the corresponding argv.
|
|
||||||
|
|
||||||
The conversion will throw only on allocation error or an internal
|
|
||||||
error.
|
|
||||||
*/
|
*/
|
||||||
capi.sqlite3_create_function_v2.udfConvertArgs =
|
capi.sqlite3_create_function_v2.udfConvertArgs =
|
||||||
capi.sqlite3_create_function.udfConvertArgs =
|
capi.sqlite3_create_function.udfConvertArgs =
|
||||||
capi.sqlite3_create_window_function.udfConvertArgs = __udfConvertArgs;
|
capi.sqlite3_create_window_function.udfConvertArgs = capi.sqlite3_values_to_js;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A helper for UDFs implemented in JS and bound to WASM by the
|
A _deprecated_ alias for capi.sqlite3_result_error_js() which
|
||||||
client. It expects to be a passed `(sqlite3_context*, Error)`
|
predates the addition of that function in the public API.
|
||||||
(an exception object or message string). And it sets the
|
|
||||||
current UDF's result to sqlite3_result_error_nomem() or
|
|
||||||
sqlite3_result_error(), depending on whether the 2nd argument
|
|
||||||
is a sqlite3.WasmAllocError object or not.
|
|
||||||
*/
|
*/
|
||||||
capi.sqlite3_create_function_v2.udfSetError =
|
capi.sqlite3_create_function_v2.udfSetError =
|
||||||
capi.sqlite3_create_function.udfSetError =
|
capi.sqlite3_create_function.udfSetError =
|
||||||
capi.sqlite3_create_window_function.udfSetError = __udfSetError;
|
capi.sqlite3_create_window_function.udfSetError = capi.sqlite3_result_error_js;
|
||||||
|
|
||||||
}/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/;
|
}/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/;
|
||||||
|
|
||||||
|
@ -1672,9 +1672,11 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
|
|
||||||
By default it throws if it cannot determine any sensible
|
By default it throws if it cannot determine any sensible
|
||||||
conversion. If passed a falsy second argument, it instead returns
|
conversion. If passed a falsy second argument, it instead returns
|
||||||
`undefined` if no suitable conversion is found. Note that there
|
`undefined` if no suitable conversion is found. Note that there
|
||||||
is no conversion from SQL to JS which results in the `undefined`
|
is no conversion from SQL to JS which results in the `undefined`
|
||||||
value, so `undefined` has an unambiguous meaning here.
|
value, so `undefined` has an unambiguous meaning here. It will
|
||||||
|
always throw a WasmAllocError if allocating memory for a
|
||||||
|
conversion fails.
|
||||||
|
|
||||||
Caveats:
|
Caveats:
|
||||||
|
|
||||||
@ -1723,6 +1725,141 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
return arg;
|
return arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Requires a C-style array of `sqlite3_value*` objects and the
|
||||||
|
number of entries in that array. Returns a JS array containing
|
||||||
|
the results of passing each C array entry to
|
||||||
|
sqlite3_value_to_js(). The 3rd argument to this function is
|
||||||
|
passed on as the 2nd argument to that one.
|
||||||
|
*/
|
||||||
|
capi.sqlite3_values_to_js = function(argc,pArgv,throwIfCannotConvert=true){
|
||||||
|
let i;
|
||||||
|
const tgt = [];
|
||||||
|
for(i = 0; i < argc; ++i){
|
||||||
|
/**
|
||||||
|
Curiously: despite ostensibly requiring 8-byte
|
||||||
|
alignment, the pArgv array is parcelled into chunks of
|
||||||
|
4 bytes (1 pointer each). The values those point to
|
||||||
|
have 8-byte alignment but the individual argv entries
|
||||||
|
do not.
|
||||||
|
*/
|
||||||
|
tgt.push(capi.sqlite3_value_to_js(
|
||||||
|
wasm.peekPtr(pArgv + (wasm.ptrSizeof * i))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return tgt;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calls either sqlite3_result_error_nomem(), if e is-a
|
||||||
|
WasmAllocError, or sqlite3_result_error(). In the latter case,
|
||||||
|
the second arugment is coerced to a string to create the error
|
||||||
|
message.
|
||||||
|
|
||||||
|
The first argument is a (sqlite3_context*). Returns void.
|
||||||
|
Does not throw.
|
||||||
|
*/
|
||||||
|
capi.sqlite3_result_error_js = function(pCtx,e){
|
||||||
|
if(e instanceof WasmAllocError){
|
||||||
|
capi.sqlite3_result_error_nomem(pCtx);
|
||||||
|
}else{
|
||||||
|
/* Maintenance reminder: ''+e, rather than e.message,
|
||||||
|
will prefix e.message with e.name, so it includes
|
||||||
|
the exception's type name in the result. */;
|
||||||
|
capi.sqlite3_result_error(pCtx, ''+e, -1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function passes its 2nd argument to one of the
|
||||||
|
sqlite3_result_xyz() routines, depending on the type of that
|
||||||
|
argument:
|
||||||
|
|
||||||
|
- If (val instanceof Error), this function passes it to
|
||||||
|
sqlite3_result_error_js().
|
||||||
|
- `null`: `sqlite3_result_null()`
|
||||||
|
- `boolean`: `sqlite3_result_int()` with a value of 0 or 1.
|
||||||
|
- `number`: `sqlite3_result_int()`, `sqlite3_result_int64()`, or
|
||||||
|
`sqlite3_result_double()`, depending on the range of the number
|
||||||
|
and whether or not int64 support is enabled.
|
||||||
|
- `bigint`: similar to `number` but will trigger an error if the
|
||||||
|
value is too big to store in an int64.
|
||||||
|
- `string`: `sqlite3_result_text()`
|
||||||
|
- Uint8Array or Int8Array: `sqlite3_result_blob()`
|
||||||
|
- `undefined`: is a no-op provided to simplify certain use cases.
|
||||||
|
|
||||||
|
Anything else triggers `sqlite3_result_error()` with a
|
||||||
|
description of the problem.
|
||||||
|
|
||||||
|
The first argument to this function is a `(sqlite3_context*)`.
|
||||||
|
Returns void. Does not throw.
|
||||||
|
*/
|
||||||
|
capi.sqlite3_result_js = function(pCtx,val){
|
||||||
|
if(val instanceof Error){
|
||||||
|
capi.sqlite3_result_error_js(pCtx, val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
switch(typeof val) {
|
||||||
|
case 'undefined':
|
||||||
|
/* This is a no-op. This routine originated in the create_function()
|
||||||
|
family of APIs and in that context, passing in undefined indicated
|
||||||
|
that the caller was responsible for calling sqlite3_result_xxx()
|
||||||
|
(if needed). */
|
||||||
|
break;
|
||||||
|
case 'boolean':
|
||||||
|
capi.sqlite3_result_int(pCtx, val ? 1 : 0);
|
||||||
|
break;
|
||||||
|
case 'bigint':
|
||||||
|
if(util.bigIntFits32(val)){
|
||||||
|
capi.sqlite3_result_int(pCtx, Number(val));
|
||||||
|
}else if(util.bigIntFitsDouble(val)){
|
||||||
|
capi.sqlite3_result_double(pCtx, Number(val));
|
||||||
|
}else if(wasm.bigIntEnabled){
|
||||||
|
if(util.bigIntFits64(val)) capi.sqlite3_result_int64(pCtx, val);
|
||||||
|
else toss3("BigInt value",val.toString(),"is too BigInt for int64.");
|
||||||
|
}else{
|
||||||
|
toss3("BigInt value",val.toString(),"is too BigInt.");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'number': {
|
||||||
|
let f;
|
||||||
|
if(util.isInt32(val)){
|
||||||
|
f = capi.sqlite3_result_int;
|
||||||
|
}else if(wasm.bigIntEnabled
|
||||||
|
&& Number.isInteger(val)
|
||||||
|
&& util.bigIntFits64(BigInt(val))){
|
||||||
|
f = capi.sqlite3_result_int64;
|
||||||
|
}else{
|
||||||
|
f = capi.sqlite3_result_double;
|
||||||
|
}
|
||||||
|
f(pCtx, val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'string':
|
||||||
|
capi.sqlite3_result_text(pCtx, val, -1, capi.SQLITE_TRANSIENT);
|
||||||
|
break;
|
||||||
|
case 'object':
|
||||||
|
if(null===val/*yes, typeof null === 'object'*/) {
|
||||||
|
capi.sqlite3_result_null(pCtx);
|
||||||
|
break;
|
||||||
|
}else if(util.isBindableTypedArray(val)){
|
||||||
|
const pBlob = wasm.allocFromTypedArray(val);
|
||||||
|
capi.sqlite3_result_blob(
|
||||||
|
pCtx, pBlob, val.byteLength,
|
||||||
|
wasm.exports[sqlite3.config.deallocExportName]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// else fall through
|
||||||
|
default:
|
||||||
|
toss3("Don't not how to handle this UDF result value:",(typeof val), val);
|
||||||
|
}
|
||||||
|
}catch(e){
|
||||||
|
capi.sqlite3_result_error_js(pCtx, e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* The remainder of the API will be set up in later steps. */
|
/* The remainder of the API will be set up in later steps. */
|
||||||
const sqlite3 = {
|
const sqlite3 = {
|
||||||
WasmAllocError: WasmAllocError,
|
WasmAllocError: WasmAllocError,
|
||||||
|
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
|||||||
C Export\ssqlite3_result_subtype()\sand\ssqlite3_value_dup/free/subtype()\sto\sWASM.
|
C Refactor\sthe\sinternal\sJS\sroutines\sfor\sconverting\sUDF\sresults\sand\serrors\sto\sJS\sinto\spublic\sAPIs.
|
||||||
D 2022-12-09T15:26:58.074
|
D 2022-12-10T10:24:46.478
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
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/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
|
||||||
F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
|
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-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
|
||||||
F ext/wasm/api/sqlite3-api-glue.js 88e62a380b39a924728d9ed4f74f5424f0ea36e8d124df7da9268cc01ad0b191
|
F ext/wasm/api/sqlite3-api-glue.js fc2b58b3309fa404d3e58499609e5c5b17177687f53f1a6703c50067904d7f72
|
||||||
F ext/wasm/api/sqlite3-api-oo1.js 6d10849609231ccd46fa11b1d3fbbe0f45d9fe84c66a0b054601036540844300
|
F ext/wasm/api/sqlite3-api-oo1.js 6d10849609231ccd46fa11b1d3fbbe0f45d9fe84c66a0b054601036540844300
|
||||||
F ext/wasm/api/sqlite3-api-prologue.js 2582c5a983e6213687153125a12e7f7496a1cd474ee24d777675b104028b0a61
|
F ext/wasm/api/sqlite3-api-prologue.js 5173cf1f434410c40fa7c6c6c77aca2a969ef7750f9e099175439d6f9c381407
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
|
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
|
||||||
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
|
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
|
||||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
|
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
|
||||||
@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P de8fc4bf34f80f320012a0e506ed8e3e24806daf67845d5dabb00b916108f6ef
|
P 4600a7bbdc4cbe14591d48ea19fe5f7de3a0c10a14cdd97fd51e263a13163d10
|
||||||
R cd32a70b8175f1ae6d43525e76cb6794
|
R 87bf3540e42b9fcd39b8a805ab39f0fe
|
||||||
U stephan
|
U stephan
|
||||||
Z 75119f06284b4ae77a74934eba10a318
|
Z e910f830b2b784709a3d3c5d3fc7fb9d
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
4600a7bbdc4cbe14591d48ea19fe5f7de3a0c10a14cdd97fd51e263a13163d10
|
35d1d63c7d60119b64341c561294890812837d5432d1d7bed3ed88d6212fbfa0
|
Loading…
x
Reference in New Issue
Block a user