Cherry-pick [c4dab53b8ea3401abd] for sqlite3.wasm.xWrap() optimizations.
FossilOrigin-Name: 9b97412d3aa791870016ab3c6f565b6a6afa1764f98e969833aec093b9b29919
This commit is contained in:
parent
3547e4997f
commit
a9e1d96cd8
@ -359,7 +359,8 @@ self.WhWasmUtilInstaller = function(target){
|
||||
|
||||
/**
|
||||
Given a function pointer, returns the WASM function table entry
|
||||
if found, else returns a falsy value.
|
||||
if found, else returns a falsy value: undefined if fptr is out of
|
||||
range or null if it's in range but the table entry is empty.
|
||||
*/
|
||||
target.functionEntry = function(fptr){
|
||||
const ft = target.functionTable();
|
||||
@ -552,13 +553,12 @@ self.WhWasmUtilInstaller = function(target){
|
||||
cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr);
|
||||
}
|
||||
}catch(e){
|
||||
if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
|
||||
throw e;
|
||||
if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
|
||||
throw e;
|
||||
}
|
||||
return ptr;
|
||||
return ptr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Expects a JS function and signature, exactly as for
|
||||
this.jsFuncToWasm(). It uses that function to create a
|
||||
@ -612,8 +612,13 @@ self.WhWasmUtilInstaller = function(target){
|
||||
installFunction() has been called and results are undefined if
|
||||
ptr was not returned by that function. The returned function
|
||||
may be passed back to installFunction() to reinstall it.
|
||||
|
||||
To simplify certain use cases, if passed a falsy non-0 value
|
||||
(noting that 0 is a valid function table index), this function
|
||||
has no side effects and returns undefined.
|
||||
*/
|
||||
target.uninstallFunction = function(ptr){
|
||||
if(!ptr && 0!==ptr) return undefined;
|
||||
const fi = cache.freeFuncIndexes;
|
||||
const ft = target.functionTable();
|
||||
fi.push(ptr);
|
||||
@ -730,7 +735,7 @@ self.WhWasmUtilInstaller = function(target){
|
||||
? cache : heapWrappers();
|
||||
for(const p of (Array.isArray(ptr) ? ptr : [ptr])){
|
||||
switch (type) {
|
||||
case 'i1':
|
||||
case 'i1':
|
||||
case 'i8': c.HEAP8[p>>0] = value; continue;
|
||||
case 'i16': c.HEAP16[p>>1] = value; continue;
|
||||
case 'i32': c.HEAP32[p>>2] = value; continue;
|
||||
@ -803,7 +808,6 @@ self.WhWasmUtilInstaller = function(target){
|
||||
/** f64 variant of poke8(). */
|
||||
target.poke64f = (ptr, value)=>target.poke(ptr, value, 'f64');
|
||||
|
||||
|
||||
/** Deprecated alias for getMemValue() */
|
||||
target.getMemValue = target.peek;
|
||||
/** Deprecated alias for peekPtr() */
|
||||
@ -1351,7 +1355,7 @@ self.WhWasmUtilInstaller = function(target){
|
||||
|
||||
const __argcMismatch =
|
||||
(f,n)=>toss(f+"() requires",n,"argument(s).");
|
||||
|
||||
|
||||
/**
|
||||
Looks up a WASM-exported function named fname from
|
||||
target.exports. If found, it is called, passed all remaining
|
||||
@ -1390,18 +1394,25 @@ self.WhWasmUtilInstaller = function(target){
|
||||
if(target.bigIntEnabled){
|
||||
xArg.set('i64', (i)=>BigInt(i));
|
||||
}
|
||||
xArg.set('i32', (i)=>(i | 0));
|
||||
xArg.set('i16', (i)=>((i | 0) & 0xFFFF));
|
||||
xArg.set('i8', (i)=>((i | 0) & 0xFF));
|
||||
xArg.set('f32', (i)=>Number(i).valueOf());
|
||||
xArg.set('float', xArg.get('f32'));
|
||||
xArg.set('f64', xArg.get('f32'));
|
||||
xArg.set('double', xArg.get('f64'));
|
||||
xArg.set('int', xArg.get('i32'));
|
||||
xResult.set('*', xArg.get(ptrIR));
|
||||
xResult.set('pointer', xArg.get(ptrIR));
|
||||
xArg.set('**', xArg.get(ptrIR));
|
||||
xResult.set('number', (v)=>Number(v));
|
||||
const __xArgPtr = 'i32' === ptrIR
|
||||
? ((i)=>(i | 0)) : ((i)=>(BigInt(i) | BigInt(0)));
|
||||
xArg.set('i32', __xArgPtr )
|
||||
.set('i16', (i)=>((i | 0) & 0xFFFF))
|
||||
.set('i8', (i)=>((i | 0) & 0xFF))
|
||||
.set('f32', (i)=>Number(i).valueOf())
|
||||
.set('float', xArg.get('f32'))
|
||||
.set('f64', xArg.get('f32'))
|
||||
.set('double', xArg.get('f64'))
|
||||
.set('int', xArg.get('i32'))
|
||||
.set('null', (i)=>i)
|
||||
.set(null, xArg.get('null'))
|
||||
.set('**', __xArgPtr);
|
||||
xResult.set('*', __xArgPtr)
|
||||
.set('pointer', __xArgPtr)
|
||||
.set('number', (v)=>Number(v))
|
||||
.set('void', (v)=>undefined)
|
||||
.set('null', (v)=>v)
|
||||
.set(null, xResult.get('null'));
|
||||
|
||||
{ /* Copy certain xArg[...] handlers to xResult[...] and
|
||||
add pointer-style variants of them. */
|
||||
@ -1430,15 +1441,17 @@ self.WhWasmUtilInstaller = function(target){
|
||||
|
||||
TODO? Permit an Int8Array/Uint8Array and convert it to a string?
|
||||
Would that be too much magic concentrated in one place, ready to
|
||||
backfire?
|
||||
backfire? We handle that at the client level in sqlite3 with a
|
||||
custom argument converter.
|
||||
*/
|
||||
xArg.set('string', function(v){
|
||||
const __xArgString = function(v){
|
||||
if('string'===typeof v) return target.scopedAllocCString(v);
|
||||
return v ? xArg.get(ptrIR)(v) : null;
|
||||
});
|
||||
xArg.set('utf8', xArg.get('string'));
|
||||
xArg.set('pointer', xArg.get('string'));
|
||||
xArg.set('*', xArg.get('string'));
|
||||
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'));
|
||||
@ -1452,25 +1465,6 @@ self.WhWasmUtilInstaller = function(target){
|
||||
try{ return i ? JSON.parse(target.cstrToJs(i)) : null }
|
||||
finally{ target.dealloc(i) }
|
||||
});
|
||||
xResult.set('void', (v)=>undefined);
|
||||
xResult.set('null', (v)=>v);
|
||||
|
||||
if(0){
|
||||
/***
|
||||
This idea can't currently work because we don't know the
|
||||
signature for the func and don't have a way for the user to
|
||||
convey it. To do this we likely need to be able to match
|
||||
arg/result handlers by a regex, but that would incur an O(N)
|
||||
cost as we check the regex one at a time. Another use case for
|
||||
such a thing would be pseudotypes like "int:-1" to say that
|
||||
the value will always be treated like -1 (which has a useful
|
||||
case in the sqlite3 bindings).
|
||||
*/
|
||||
xArg.set('func-ptr', function(v){
|
||||
if(!(v instanceof Function)) return xArg.get(ptrIR);
|
||||
const f = target.jsFuncToWasm(v, WHAT_SIGNATURE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
Internal-use-only base class for FuncPtrAdapter and potentially
|
||||
@ -1537,8 +1531,8 @@ self.WhWasmUtilInstaller = function(target){
|
||||
value. This is only useful for use with "global" functions
|
||||
which do not rely on any state other than this function
|
||||
pointer. If the being-converted function pointer is intended
|
||||
to be mapped to some sort of state object (e.g. an sqlite3*)
|
||||
then "context" (see below) is the proper mode.
|
||||
to be mapped to some sort of state object (e.g. an
|
||||
`sqlite3*`) then "context" (see below) is the proper mode.
|
||||
|
||||
- 'context': similar to singleton mode but for a given
|
||||
"context", where the context is a key provided by the user
|
||||
@ -1688,35 +1682,41 @@ self.WhWasmUtilInstaller = function(target){
|
||||
(t)=>xResult.get(t) || toss("Result adapter not found:",t);
|
||||
|
||||
cache.xWrap.convertArg = (t,...args)=>__xArgAdapterCheck(t)(...args);
|
||||
cache.xWrap.convertArgNoCheck = (t,...args)=>xArg.get(t)(...args);
|
||||
|
||||
cache.xWrap.convertResult =
|
||||
(t,v)=>(null===t ? v : (t ? __xResultAdapterCheck(t)(v) : undefined));
|
||||
cache.xWrap.convertResultNoCheck =
|
||||
(t,v)=>(null===t ? v : (t ? xResult.get(t)(v) : undefined));
|
||||
|
||||
/**
|
||||
Creates a wrapper for the WASM-exported function fname. Uses
|
||||
xGet() to fetch the exported function (which throws on
|
||||
error) and returns either that function or a wrapper for that
|
||||
Creates a wrapper for another function which converts the arguments
|
||||
of the wrapper to argument types accepted by the wrapped function,
|
||||
then converts the wrapped function's result to another form
|
||||
for the wrapper.
|
||||
|
||||
The first argument must be one of:
|
||||
|
||||
- A JavaScript function.
|
||||
- The name of a WASM-exported function. In the latter case xGet()
|
||||
is used to fetch the exported function, which throws if it's not
|
||||
found.
|
||||
- A pointer into the indirect function table. e.g. a pointer
|
||||
returned from target.installFunction().
|
||||
|
||||
It returns either the passed-in function or a wrapper for that
|
||||
function which converts the JS-side argument types into WASM-side
|
||||
types and converts the result type. If the function takes no
|
||||
arguments and resultType is `null` then the function is returned
|
||||
as-is, else a wrapper is created for it to adapt its arguments
|
||||
and result value, as described below.
|
||||
types and converts the result type.
|
||||
|
||||
(If you're familiar with Emscripten's ccall() and cwrap(), this
|
||||
function is essentially cwrap() on steroids.)
|
||||
|
||||
This function's arguments are:
|
||||
|
||||
- fname: the exported function's name. xGet() is used to fetch
|
||||
this, so will throw if no exported function is found with that
|
||||
name.
|
||||
|
||||
- resultType: the name of the result type. A literal `null` means
|
||||
to return the original function's value as-is (mnemonic: there
|
||||
is "null" conversion going on). Literal `undefined` or the
|
||||
string `"void"` mean to ignore the function's result and return
|
||||
`undefined`. Aside from those two special cases, it may be one
|
||||
of the values described below or any mapping installed by the
|
||||
client using xWrap.resultAdapter().
|
||||
The second argument, `resultType`, describes the conversion for
|
||||
the wrapped functions result. A literal `null` or the string
|
||||
`'null'` both mean to return the original function's value as-is
|
||||
(mnemonic: there is "null" conversion going on). Literal
|
||||
`undefined` or the string `"void"` both mean to ignore the
|
||||
function's result and return `undefined`. Aside from those two
|
||||
special cases, the `resultType` value may be one of the values
|
||||
described below or any mapping installed by the client using
|
||||
xWrap.resultAdapter().
|
||||
|
||||
If passed 3 arguments and the final one is an array, that array
|
||||
must contain a list of type names (see below) for adapting the
|
||||
@ -1730,6 +1730,12 @@ self.WhWasmUtilInstaller = function(target){
|
||||
xWrap('funcname', 'i32', ['string', 'f64']);
|
||||
```
|
||||
|
||||
This function enforces that the given list of arguments has the
|
||||
same arity as the being-wrapped function (as defined by its
|
||||
`length` property) and it will throw if that is not the case.
|
||||
Similarly, the created wrapper will throw if passed a differing
|
||||
argument count.
|
||||
|
||||
Type names are symbolic names which map the arguments to an
|
||||
adapter function to convert, if needed, the value before passing
|
||||
it on to WASM or to convert a return result from WASM. The list
|
||||
@ -1766,6 +1772,10 @@ self.WhWasmUtilInstaller = function(target){
|
||||
|
||||
Non-numeric conversions include:
|
||||
|
||||
- `null` literal or `"null"` string (args and results): perform
|
||||
no translation and pass the arg on as-is. This is primarily
|
||||
useful for results but may have a use or two for arguments.
|
||||
|
||||
- `string` or `utf8` (args): has two different semantics in order
|
||||
to accommodate various uses of certain C APIs
|
||||
(e.g. output-style strings)...
|
||||
@ -1780,9 +1790,9 @@ self.WhWasmUtilInstaller = function(target){
|
||||
client has already allocated and it's passed on as
|
||||
a WASM pointer.
|
||||
|
||||
- `string` or `utf8` (results): treats the result value as a
|
||||
const C-string, encoded as UTF-8, copies it to a JS string,
|
||||
and returns that JS string.
|
||||
- `string` or `utf8` (results): treats the result value as a
|
||||
const C-string, encoded as UTF-8, copies it to a JS string,
|
||||
and returns that JS string.
|
||||
|
||||
- `string:dealloc` or `utf8:dealloc) (results): treats the result value
|
||||
as a non-const UTF-8 C-string, ownership of which has just been
|
||||
@ -1819,6 +1829,11 @@ self.WhWasmUtilInstaller = function(target){
|
||||
type conversions are valid for both arguments _and_ result types
|
||||
as they often have different memory ownership requirements.
|
||||
|
||||
Design note: the ability to pass in a JS function as the first
|
||||
argument is of relatively limited use, primarily for testing
|
||||
argument and result converters. JS functions, by and large, will
|
||||
not want to deal with C-type arguments.
|
||||
|
||||
TODOs:
|
||||
|
||||
- Figure out how/whether we can (semi-)transparently handle
|
||||
@ -1839,14 +1854,21 @@ self.WhWasmUtilInstaller = function(target){
|
||||
abstracting it into this API (and taking on the associated
|
||||
costs) may well not make good sense.
|
||||
*/
|
||||
target.xWrap = function(fname, resultType, ...argTypes){
|
||||
target.xWrap = function(fArg, resultType, ...argTypes){
|
||||
if(3===arguments.length && Array.isArray(arguments[2])){
|
||||
argTypes = arguments[2];
|
||||
}
|
||||
const xf = target.xGet(fname);
|
||||
if(argTypes.length!==xf.length) __argcMismatch(fname, xf.length);
|
||||
if(target.isPtr(fArg)){
|
||||
fArg = target.functionEntry(fArg)
|
||||
|| toss("Function pointer not found in WASM function table.");
|
||||
}
|
||||
const fIsFunc = (fArg instanceof Function);
|
||||
const xf = fIsFunc ? fArg : target.xGet(fArg);
|
||||
if(fIsFunc) fArg = xf.name || 'unnamed function';
|
||||
if(argTypes.length!==xf.length) __argcMismatch(fArg, xf.length);
|
||||
if((null===resultType) && 0===xf.length){
|
||||
/* Func taking no args with an as-is return. We don't need a wrapper. */
|
||||
/* Func taking no args with an as-is return. We don't need a wrapper.
|
||||
We forego the argc check here, though. */
|
||||
return xf;
|
||||
}
|
||||
/*Verify the arg type conversions are valid...*/;
|
||||
@ -1859,11 +1881,11 @@ self.WhWasmUtilInstaller = function(target){
|
||||
if(0===xf.length){
|
||||
// No args to convert, so we can create a simpler wrapper...
|
||||
return (...args)=>(args.length
|
||||
? __argcMismatch(fname, xf.length)
|
||||
? __argcMismatch(fArg, xf.length)
|
||||
: cxw.convertResult(resultType, xf.call(null)));
|
||||
}
|
||||
return function(...args){
|
||||
if(args.length!==xf.length) __argcMismatch(fname, xf.length);
|
||||
if(args.length!==xf.length) __argcMismatch(fArg, xf.length);
|
||||
const scope = target.scopedAllocPush();
|
||||
try{
|
||||
/*
|
||||
@ -1881,8 +1903,8 @@ self.WhWasmUtilInstaller = function(target){
|
||||
and what those arguments are, is _not_ part of the public
|
||||
interface and is _not_ stable.
|
||||
*/
|
||||
for(const i in args) args[i] = cxw.convertArg(argTypes[i], args[i], i, args);
|
||||
return cxw.convertResult(resultType, xf.apply(null,args));
|
||||
for(const i in args) args[i] = cxw.convertArgNoCheck(argTypes[i], args[i], i, args);
|
||||
return cxw.convertResultNoCheck(resultType, xf.apply(null,args));
|
||||
}finally{
|
||||
target.scopedAllocPop(scope);
|
||||
}
|
||||
@ -1974,14 +1996,13 @@ self.WhWasmUtilInstaller = function(target){
|
||||
|
||||
/**
|
||||
Functions like xCall() but performs argument and result type
|
||||
conversions as for xWrap(). The first argument is the name of the
|
||||
exported function to call. The 2nd its the name of its result
|
||||
type, as documented for xWrap(). The 3rd is an array of argument
|
||||
type name, as documented for xWrap() (use a falsy value or an
|
||||
empty array for nullary functions). The 4th+ arguments are
|
||||
arguments for the call, with the special case that if the 4th
|
||||
argument is an array, it is used as the arguments for the
|
||||
call. Returns the converted result of the call.
|
||||
conversions as for xWrap(). The first, second, and third
|
||||
arguments are as documented for xWrap(), except that the 3rd
|
||||
argument may be either a falsy value or empty array to represent
|
||||
nullary functions. The 4th+ arguments are arguments for the call,
|
||||
with the special case that if the 4th argument is an array, it is
|
||||
used as the arguments for the call. Returns the converted result
|
||||
of the call.
|
||||
|
||||
This is just a thin wrapper around xWrap(). If the given function
|
||||
is to be called more than once, it's more efficient to use
|
||||
@ -1990,9 +2011,9 @@ self.WhWasmUtilInstaller = function(target){
|
||||
arguably more efficient because it will hypothetically free the
|
||||
wrapper function quickly.
|
||||
*/
|
||||
target.xCallWrapped = function(fname, resultType, argTypes, ...args){
|
||||
target.xCallWrapped = function(fArg, resultType, argTypes, ...args){
|
||||
if(Array.isArray(arguments[3])) args = arguments[3];
|
||||
return target.xWrap(fname, resultType, argTypes||[]).apply(null, args||[]);
|
||||
return target.xWrap(fArg, resultType, argTypes||[]).apply(null, args||[]);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -539,7 +539,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
}
|
||||
w.dealloc(m);
|
||||
}
|
||||
|
||||
|
||||
// isPtr32()
|
||||
{
|
||||
const ip = w.isPtr32;
|
||||
@ -743,6 +743,65 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
.assert('HI' === cj(new Uint8Array([72, 73])));
|
||||
});
|
||||
|
||||
// jsFuncToWasm()
|
||||
{
|
||||
const fsum3 = (x,y,z)=>x+y+z;
|
||||
fw = w.jsFuncToWasm('i(iii)', fsum3);
|
||||
T.assert(fw instanceof Function)
|
||||
.assert( fsum3 !== fw )
|
||||
.assert( 3 === fw.length )
|
||||
.assert( 6 === fw(1,2,3) );
|
||||
T.mustThrowMatching( ()=>w.jsFuncToWasm('x()', function(){}),
|
||||
'Invalid signature letter: x');
|
||||
}
|
||||
|
||||
// xWrap(Function,...)
|
||||
{
|
||||
let fp;
|
||||
try {
|
||||
const fmy = function fmy(i,s,d){
|
||||
if(fmy.debug) log("fmy(",...arguments,")");
|
||||
T.assert( 3 === i )
|
||||
.assert( w.isPtr(s) )
|
||||
.assert( w.cstrToJs(s) === 'a string' )
|
||||
.assert( T.eqApprox(1.2, d) );
|
||||
return w.allocCString("hi");
|
||||
};
|
||||
fmy.debug = false;
|
||||
const xwArgs = ['string:dealloc', ['i32', 'string', 'f64']];
|
||||
fw = w.xWrap(fmy, ...xwArgs);
|
||||
const fmyArgs = [3, 'a string', 1.2];
|
||||
let rc = fw(...fmyArgs);
|
||||
T.assert( 'hi' === rc );
|
||||
if(0){
|
||||
/* Retain this as a "reminder to self"...
|
||||
|
||||
This extra level of indirection does not work: the
|
||||
string argument is ending up as a null in fmy() but
|
||||
the numeric arguments are making their ways through
|
||||
|
||||
What's happening is: installFunction() is creating a
|
||||
WASM-compatible function instance. When we pass a JS string
|
||||
into there it's getting coerced into `null` before being passed
|
||||
on to the lower-level wrapper.
|
||||
*/
|
||||
fmy.debug = true;
|
||||
fp = wasm.installFunction('i(isd)', fw);
|
||||
fw = w.functionEntry(fp);
|
||||
rc = fw(...fmyArgs);
|
||||
log("rc =",rc);
|
||||
T.assert( 'hi' === rc );
|
||||
// Similarly, this does not work:
|
||||
//let fpw = w.xWrap(fp, null, [null,null,null]);
|
||||
//rc = fpw(...fmyArgs);
|
||||
//log("rc =",rc);
|
||||
//T.assert( 'hi' === rc );
|
||||
}
|
||||
}finally{
|
||||
wasm.uninstallFunction(fp);
|
||||
}
|
||||
}
|
||||
|
||||
if(haveWasmCTests()){
|
||||
if(!sqlite3.config.useStdAlloc){
|
||||
fw = w.xWrap('sqlite3_wasm_test_str_hello', 'utf8:dealloc',['i32']);
|
||||
@ -768,7 +827,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}/*xWrap()*/
|
||||
}/*WhWasmUtil*/)
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -997,7 +1056,6 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
P.restore(stack);
|
||||
}
|
||||
}/*pstack tests*/)
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
;/*end of C/WASM utils checks*/
|
||||
|
||||
|
17
manifest
17
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\slots\sof\sharmless,\snuisance\scompiler\swarnings,\smostly\sunused\sparameter\nwarnings\sin\sextensions.
|
||||
D 2022-12-23T14:49:24.143
|
||||
C Cherry-pick\s[c4dab53b8ea3401abd]\sfor\ssqlite3.wasm.xWrap()\soptimizations.
|
||||
D 2022-12-23T18:19:28.093
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -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 ba1a8db1f32124e43e24b3d890102b6552b2c0b5a202185041a55887692df328
|
||||
F ext/wasm/common/whwasmutil.js ff43d28d04e60068ecb3e9a2550581f36be5867ad5ffc00d8479580a12cf9b0f
|
||||
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
|
||||
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
|
||||
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
|
||||
@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
|
||||
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
|
||||
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
|
||||
F ext/wasm/tester1.c-pp.js c45c46cdae1949d426ee12a736087ab180beacc2a20cd829f9052b957adf9ac9
|
||||
F ext/wasm/tester1.c-pp.js 4202e7ec525445386f29612ddf1365348edd1f6002b8b21721c954b9569b756a
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
|
||||
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
@ -2067,8 +2067,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 7d3772f0bd0e2602fe919573b49001da4e2b9f3874cb0183dea675204afa7abd
|
||||
R 16338e89b5ec3a31b67202fe13704742
|
||||
U drh
|
||||
Z 80509b64f86f8701ef91d19f5ff36290
|
||||
P c14bbe1606c1450b709970f922b94a641dfc8f9bd09126501d7dc4db99ea4772
|
||||
Q +c4dab53b8ea3401abd57671b8f3cb39fa4431b864d4c4e14ae24592f8d4cba0a
|
||||
R 584560ad77984d30d6316ac32176cf60
|
||||
U stephan
|
||||
Z ff71cfe8de9cd6a3b2f8b5e767f940f3
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
c14bbe1606c1450b709970f922b94a641dfc8f9bd09126501d7dc4db99ea4772
|
||||
9b97412d3aa791870016ab3c6f565b6a6afa1764f98e969833aec093b9b29919
|
Loading…
Reference in New Issue
Block a user