mirror of
https://github.com/sqlite/sqlite.git
synced 2025-10-21 11:13:54 +03:00
Wasm: (A) diverse internal doc updates. (B) when generating automated JS-to-WASM function proxies for converters which require an additional middle-man proxy, e.g. sqlite3_exec(), use the client-provided function, not the proxy function, as the cache key, to keep from re-generating the conversion in some common use patterns.
FossilOrigin-Name: 5e5139c2a162562cee0071d03954ebc0b8938da0b045ec3f5eba32dc8e19604d
This commit is contained in:
@@ -230,7 +230,8 @@
|
|||||||
** Which sqlite3.c we're using needs to be configurable to enable
|
** Which sqlite3.c we're using needs to be configurable to enable
|
||||||
** building against a custom copy, e.g. the SEE variant. We #include
|
** building against a custom copy, e.g. the SEE variant. We #include
|
||||||
** the .c file, rather than the header, so that the WASM extensions
|
** the .c file, rather than the header, so that the WASM extensions
|
||||||
** have access to private API internals.
|
** have access to private API internals (namely for kvvfs and
|
||||||
|
** SQLTester pieces).
|
||||||
**
|
**
|
||||||
** The caveat here is that custom variants need to account for
|
** The caveat here is that custom variants need to account for
|
||||||
** exporting any necessary symbols (e.g. sqlite3_activate_see()). We
|
** exporting any necessary symbols (e.g. sqlite3_activate_see()). We
|
||||||
@@ -1753,7 +1754,7 @@ int sqlite3__wasm_init_wasmfs(const char *zMountPoint){
|
|||||||
SQLITE_WASM_EXPORT
|
SQLITE_WASM_EXPORT
|
||||||
int sqlite3__wasm_init_wasmfs(const char *zUnused){
|
int sqlite3__wasm_init_wasmfs(const char *zUnused){
|
||||||
//emscripten_console_warn("WASMFS OPFS is not compiled in.");
|
//emscripten_console_warn("WASMFS OPFS is not compiled in.");
|
||||||
if(zUnused){/*unused*/}
|
(void)zUnused;
|
||||||
return SQLITE_NOTFOUND;
|
return SQLITE_NOTFOUND;
|
||||||
}
|
}
|
||||||
#endif /* __EMSCRIPTEN__ && SQLITE_ENABLE_WASMFS */
|
#endif /* __EMSCRIPTEN__ && SQLITE_ENABLE_WASMFS */
|
||||||
|
@@ -10,28 +10,18 @@
|
|||||||
|
|
||||||
***********************************************************************
|
***********************************************************************
|
||||||
|
|
||||||
The whwasmutil is developed in conjunction with the Jaccwabyt
|
This code is developed in conjunction with the Jaccwabyt project:
|
||||||
project:
|
|
||||||
|
|
||||||
https://fossil.wanderinghorse.net/r/jaccwabyt
|
https://fossil.wanderinghorse.net/r/jaccwabyt
|
||||||
|
|
||||||
and sqlite3:
|
and SQLite:
|
||||||
|
|
||||||
https://sqlite.org
|
https://sqlite.org
|
||||||
|
|
||||||
This file is kept in sync between both of those trees.
|
This file is kept in sync between both of those trees.
|
||||||
|
|
||||||
Maintenance reminder: If you're reading this in a tree other than
|
|
||||||
one of those listed above, note that this copy may be replaced with
|
|
||||||
upstream copies of that one from time to time. Thus the code
|
|
||||||
installed by this function "should not" be edited outside of those
|
|
||||||
projects, else it risks getting overwritten.
|
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
This function is intended to simplify porting around various bits
|
The primary goal of this function is to replace, where possible,
|
||||||
of WASM-related utility code from project to project.
|
|
||||||
|
|
||||||
The primary goal of this code is to replace, where possible,
|
|
||||||
Emscripten-generated glue code with equivalent utility code which
|
Emscripten-generated glue code with equivalent utility code which
|
||||||
can be used in arbitrary WASM environments built with toolchains
|
can be used in arbitrary WASM environments built with toolchains
|
||||||
other than Emscripten. As of this writing, this code is capable of
|
other than Emscripten. As of this writing, this code is capable of
|
||||||
@@ -40,18 +30,7 @@
|
|||||||
APIs such as its "FS" (virtual filesystem) API. Loading of such
|
APIs such as its "FS" (virtual filesystem) API. Loading of such
|
||||||
things still requires using Emscripten's glue, but the post-load
|
things still requires using Emscripten's glue, but the post-load
|
||||||
utility APIs provided by this code are still usable as replacements
|
utility APIs provided by this code are still usable as replacements
|
||||||
for their sub-optimally-documented Emscripten counterparts.
|
for their Emscripten counterparts.
|
||||||
|
|
||||||
Intended usage:
|
|
||||||
|
|
||||||
```
|
|
||||||
globalThis.WhWasmUtilInstaller(appObject);
|
|
||||||
delete globalThis.WhWasmUtilInstaller;
|
|
||||||
```
|
|
||||||
|
|
||||||
Its global-scope symbol is intended only to provide an easy way to
|
|
||||||
make it available to 3rd-party scripts and "should" be deleted
|
|
||||||
after calling it. That symbol is _not_ used within the library.
|
|
||||||
|
|
||||||
Forewarning: this API explicitly targets only browser
|
Forewarning: this API explicitly targets only browser
|
||||||
environments. If a given non-browser environment has the
|
environments. If a given non-browser environment has the
|
||||||
@@ -59,6 +38,22 @@
|
|||||||
but it does not go out of its way to account for them and does not
|
but it does not go out of its way to account for them and does not
|
||||||
provide compatibility crutches for them.
|
provide compatibility crutches for them.
|
||||||
|
|
||||||
|
Intended usage:
|
||||||
|
|
||||||
|
```
|
||||||
|
const target = {}; // ... some object ...
|
||||||
|
globalThis.WhWasmUtilInstaller(target);
|
||||||
|
delete globalThis.WhWasmUtilInstaller;
|
||||||
|
```
|
||||||
|
|
||||||
|
The `target` object then holds the APIs. It may have certain
|
||||||
|
properties set to configure it, as documented below.
|
||||||
|
|
||||||
|
The global-scope symbol for this function is intended only to
|
||||||
|
provide an easy way to make it available to 3rd-party scripts and
|
||||||
|
"should" be deleted after calling it. That symbol is _not_ used
|
||||||
|
within the library.
|
||||||
|
|
||||||
It currently offers alternatives to the following
|
It currently offers alternatives to the following
|
||||||
Emscripten-generated APIs:
|
Emscripten-generated APIs:
|
||||||
|
|
||||||
@@ -104,9 +99,9 @@
|
|||||||
symbol.
|
symbol.
|
||||||
|
|
||||||
This code requires that the target object have the following
|
This code requires that the target object have the following
|
||||||
properties, noting that they needn't be available until the first
|
properties, though they needn't be available until the first time
|
||||||
time one of the installed APIs is used (as opposed to when this
|
one of the installed APIs is used (as opposed to when this function
|
||||||
function is called) except where explicitly noted:
|
is called) except where explicitly noted:
|
||||||
|
|
||||||
- `exports` must be a property of the target object OR a property
|
- `exports` must be a property of the target object OR a property
|
||||||
of `target.instance` (a WebAssembly.Module instance) and it must
|
of `target.instance` (a WebAssembly.Module instance) and it must
|
||||||
@@ -140,11 +135,10 @@
|
|||||||
false. If it is false, certain BigInt-related features will trigger
|
false. If it is false, certain BigInt-related features will trigger
|
||||||
an exception if invoked. This property, if not set when this is
|
an exception if invoked. This property, if not set when this is
|
||||||
called, will get a default value of true only if the BigInt64Array
|
called, will get a default value of true only if the BigInt64Array
|
||||||
constructor is available, else it will default to false. Note that
|
constructor is available, else it will default to false. Having
|
||||||
having the BigInt type is not sufficient for full int64 integration
|
the BigInt type is not sufficient for full int64 integration with
|
||||||
with WASM: the target WASM file must also have been built with
|
WASM: the target WASM file must also have been built with that
|
||||||
that support. In Emscripten that's done using the `-sWASM_BIGINT`
|
support. In Emscripten that's done using the `-sWASM_BIGINT` flag.
|
||||||
flag.
|
|
||||||
|
|
||||||
Some optional APIs require that the target have the following
|
Some optional APIs require that the target have the following
|
||||||
methods:
|
methods:
|
||||||
@@ -163,6 +157,15 @@
|
|||||||
APIs which require allocation routines are explicitly documented as
|
APIs which require allocation routines are explicitly documented as
|
||||||
such and/or have "alloc" in their names.
|
such and/or have "alloc" in their names.
|
||||||
|
|
||||||
|
Optional configuration values which may be set on target before
|
||||||
|
calling this:
|
||||||
|
|
||||||
|
- `pointerIR`: an IR-format string for the WASM environment's
|
||||||
|
pointer size. If set it must be either 'i32' or 'i64'. If not
|
||||||
|
set, it defaults to whatever this code thinks the pointer size
|
||||||
|
is. Modifying it after this call has no effect.
|
||||||
|
|
||||||
|
|
||||||
This code is developed and maintained in conjunction with the
|
This code is developed and maintained in conjunction with the
|
||||||
Jaccwabyt project:
|
Jaccwabyt project:
|
||||||
|
|
||||||
@@ -240,10 +243,17 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
installFunction() extracts them. */
|
installFunction() extracts them. */
|
||||||
cache.freeFuncIndexes = [];
|
cache.freeFuncIndexes = [];
|
||||||
/**
|
/**
|
||||||
Used by scopedAlloc() and friends.
|
List-of-lists used by scopedAlloc() and friends.
|
||||||
*/
|
*/
|
||||||
cache.scopedAlloc = [];
|
cache.scopedAlloc = [];
|
||||||
|
|
||||||
|
/** Push the pointer ptr to the current cache.scopedAlloc list
|
||||||
|
(which must already exist) and return ptr. */
|
||||||
|
cache.scopedAlloc.pushPtr = (ptr)=>{
|
||||||
|
cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr);
|
||||||
|
return ptr;
|
||||||
|
};
|
||||||
|
|
||||||
cache.utf8Decoder = new TextDecoder();
|
cache.utf8Decoder = new TextDecoder();
|
||||||
cache.utf8Encoder = new TextEncoder('utf-8');
|
cache.utf8Encoder = new TextEncoder('utf-8');
|
||||||
|
|
||||||
@@ -320,25 +330,20 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
BigInt64Array/BigUint64Array, else it throws if passed 64 or one
|
BigInt64Array/BigUint64Array, else it throws if passed 64 or one
|
||||||
of those constructors.
|
of those constructors.
|
||||||
|
|
||||||
Returns an integer-based TypedArray view of the WASM heap
|
Returns an integer-based TypedArray view of the WASM heap memory
|
||||||
memory buffer associated with the given block size. If passed
|
buffer associated with the given block size. If passed an integer
|
||||||
an integer as the first argument and unsigned is truthy then
|
as the first argument and unsigned is truthy then the "U"
|
||||||
the "U" (unsigned) variant of that view is returned, else the
|
(unsigned) variant of that view is returned, else the signed
|
||||||
signed variant is returned. If passed a TypedArray value, the
|
variant is returned. If passed a TypedArray value, the 2nd
|
||||||
2nd argument is ignored. Note that Float32Array and
|
argument is ignored. Float32Array and Float64Array views are not
|
||||||
Float64Array views are not supported by this function.
|
supported by this function.
|
||||||
|
|
||||||
Note that growth of the heap will invalidate any references to
|
Growth of the heap will invalidate any references to this heap,
|
||||||
this heap, so do not hold a reference longer than needed and do
|
so do not hold a reference longer than needed and do not use a
|
||||||
not use a reference after any operation which may
|
reference after any operation which may allocate. Instead,
|
||||||
allocate. Instead, re-fetch the reference by calling this
|
re-fetch the reference by calling this function again.
|
||||||
function again.
|
|
||||||
|
|
||||||
Throws if passed an invalid n.
|
Throws if passed an invalid n.
|
||||||
|
|
||||||
Pedantic side note: the name "heap" is a bit of a misnomer. In a
|
|
||||||
WASM environment, the stack and heap memory are all accessed via
|
|
||||||
the same view(s) of the memory.
|
|
||||||
*/
|
*/
|
||||||
target.heapForSize = function(n,unsigned = true){
|
target.heapForSize = function(n,unsigned = true){
|
||||||
let ctor;
|
let ctor;
|
||||||
@@ -522,7 +527,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
is stashed in the current scoped-alloc scope and will be
|
is stashed in the current scoped-alloc scope and will be
|
||||||
cleaned up at the matching scopedAllocPop(), else it
|
cleaned up at the matching scopedAllocPop(), else it
|
||||||
is not stashed there.
|
is not stashed there.
|
||||||
*/
|
*/
|
||||||
const __installFunction = function f(func, sig, scoped){
|
const __installFunction = function f(func, sig, scoped){
|
||||||
if(scoped && !cache.scopedAlloc.length){
|
if(scoped && !cache.scopedAlloc.length){
|
||||||
toss("No scopedAllocPush() scope is active.");
|
toss("No scopedAllocPush() scope is active.");
|
||||||
@@ -556,7 +561,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
/*this will only work if func is a WASM-exported function*/
|
/*this will only work if func is a WASM-exported function*/
|
||||||
ft.set(ptr, func);
|
ft.set(ptr, func);
|
||||||
if(scoped){
|
if(scoped){
|
||||||
cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr);
|
cache.scopedAlloc.pushPtr(ptr);
|
||||||
}
|
}
|
||||||
return ptr;
|
return ptr;
|
||||||
}catch(e){
|
}catch(e){
|
||||||
@@ -570,7 +575,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
const fptr = target.jsFuncToWasm(func, sig);
|
const fptr = target.jsFuncToWasm(func, sig);
|
||||||
ft.set(ptr, fptr);
|
ft.set(ptr, fptr);
|
||||||
if(scoped){
|
if(scoped){
|
||||||
cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr);
|
cache.scopedAlloc.pushPtr(ptr);
|
||||||
}
|
}
|
||||||
}catch(e){
|
}catch(e){
|
||||||
if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
|
if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
|
||||||
@@ -649,8 +654,8 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
Given a WASM heap memory address and a data type name in the form
|
Given a WASM heap memory address and a data type name in the form
|
||||||
(i8, i16, i32, i64, float (or f32), double (or f64)), this
|
(i8, i16, i32, i64, float (or f32), double (or f64)), this
|
||||||
fetches the numeric value from that address and returns it as a
|
fetches the numeric value from that address and returns it as a
|
||||||
number or, for the case of type='i64', a BigInt (noting that that
|
number or, for the case of type='i64', a BigInt (with the caveat
|
||||||
type triggers an exception if this.bigIntEnabled is
|
BigInt will trigger an exception if this.bigIntEnabled is
|
||||||
falsy). Throws if given an invalid type.
|
falsy). Throws if given an invalid type.
|
||||||
|
|
||||||
If the first argument is an array, it is treated as an array of
|
If the first argument is an array, it is treated as an array of
|
||||||
@@ -660,7 +665,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
|
|
||||||
As a special case, if type ends with a `*`, it is considered to
|
As a special case, if type ends with a `*`, it is considered to
|
||||||
be a pointer type and is treated as the WASM numeric type
|
be a pointer type and is treated as the WASM numeric type
|
||||||
appropriate for the pointer size (`i32`).
|
appropriate for the pointer size (==this.pointerIR).
|
||||||
|
|
||||||
While likely not obvious, this routine and its poke()
|
While likely not obvious, this routine and its poke()
|
||||||
counterpart are how pointer-to-value _output_ parameters
|
counterpart are how pointer-to-value _output_ parameters
|
||||||
@@ -668,9 +673,9 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
|
|
||||||
```
|
```
|
||||||
const ptr = alloc(4);
|
const ptr = alloc(4);
|
||||||
poke(ptr, 0, 'i32'); // clear the ptr's value
|
poke32(ptr, 0); // clear the ptr's value
|
||||||
aCFuncWithOutputPtrToInt32Arg( ptr ); // e.g. void foo(int *x);
|
aCFuncWithOutputPtrToInt32Arg( ptr ); // e.g. void foo(int *x);
|
||||||
const result = peek(ptr, 'i32'); // fetch ptr's value
|
const result = peek32(ptr); // fetch ptr's value
|
||||||
dealloc(ptr);
|
dealloc(ptr);
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -682,23 +687,23 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
const scope = scopedAllocPush();
|
const scope = scopedAllocPush();
|
||||||
try{
|
try{
|
||||||
const ptr = scopedAlloc(4);
|
const ptr = scopedAlloc(4);
|
||||||
poke(ptr, 0, 'i32');
|
poke32(ptr, 0);
|
||||||
aCFuncWithOutputPtrArg( ptr );
|
aCFuncWithOutputPtrArg( ptr );
|
||||||
result = peek(ptr, 'i32');
|
result = peek32(ptr);
|
||||||
}finally{
|
}finally{
|
||||||
scopedAllocPop(scope);
|
scopedAllocPop(scope);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
As a rule poke() must be called to set (typically zero
|
As a rule poke() must be called to set (typically zero out) the
|
||||||
out) the pointer's value, else it will contain an essentially
|
pointer's value, else it will contain an essentially random
|
||||||
random value.
|
value.
|
||||||
|
|
||||||
ACHTUNG: calling this often, e.g. in a loop, can have a noticably
|
ACHTUNG: calling this often, e.g. in a loop, can have a noticably
|
||||||
painful impact on performance. Rather than doing so, use
|
painful impact on performance. Rather than doing so, use
|
||||||
heapForSize() to fetch the heap object and read directly from it.
|
heapForSize() to fetch the heap object and read directly from it.
|
||||||
|
|
||||||
See: poke()
|
See also: poke()
|
||||||
*/
|
*/
|
||||||
target.peek = function f(ptr, type='i8'){
|
target.peek = function f(ptr, type='i8'){
|
||||||
if(type.endsWith('*')) type = ptrIR;
|
if(type.endsWith('*')) type = ptrIR;
|
||||||
@@ -735,7 +740,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
bytes are written. Throws if given an invalid type. See peek()
|
bytes are written. Throws if given an invalid type. See peek()
|
||||||
for details about the `type` argument. If the 3rd argument ends
|
for details about the `type` argument. If the 3rd argument ends
|
||||||
with `*` then it is treated as a pointer type and this function
|
with `*` then it is treated as a pointer type and this function
|
||||||
behaves as if the 3rd argument were `i32`.
|
behaves as if the 3rd argument were this.pointerIR.
|
||||||
|
|
||||||
If the first argument is an array, it is treated like a list
|
If the first argument is an array, it is treated like a list
|
||||||
of pointers and the given value is written to each one.
|
of pointers and the given value is written to each one.
|
||||||
@@ -1151,11 +1156,13 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
Cleans up all allocations made using scopedAlloc() in the context
|
Cleans up all allocations made using scopedAlloc() in the context
|
||||||
of the given opaque state object, which must be a value returned
|
of the given opaque state object, which must be a value returned
|
||||||
by scopedAllocPush(). See that function for an example of how to
|
by scopedAllocPush(). See that function for an example of how to
|
||||||
use this function.
|
use this function. It also uninstalls any WASM functions
|
||||||
|
installed with scopedInstallFunction().
|
||||||
|
|
||||||
Though scoped allocations are managed like a stack, this API
|
Though scoped allocations are managed like a stack, this API
|
||||||
behaves properly if allocation scopes are popped in an order
|
behaves properly if allocation scopes are popped in an order
|
||||||
other than the order they were pushed.
|
other than the order they were pushed. The intent is that it
|
||||||
|
_always_ be used in a stack-like manner.
|
||||||
|
|
||||||
If called with no arguments, it pops the most recent
|
If called with no arguments, it pops the most recent
|
||||||
scopedAllocPush() result:
|
scopedAllocPush() result:
|
||||||
@@ -1181,8 +1188,9 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
if(target.functionEntry(p)){
|
if(target.functionEntry(p)){
|
||||||
//console.warn("scopedAllocPop() uninstalling function",p);
|
//console.warn("scopedAllocPop() uninstalling function",p);
|
||||||
target.uninstallFunction(p);
|
target.uninstallFunction(p);
|
||||||
|
}else{
|
||||||
|
target.dealloc(p);
|
||||||
}
|
}
|
||||||
else target.dealloc(p);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1206,9 +1214,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
if(!cache.scopedAlloc.length){
|
if(!cache.scopedAlloc.length){
|
||||||
toss("No scopedAllocPush() scope is active.");
|
toss("No scopedAllocPush() scope is active.");
|
||||||
}
|
}
|
||||||
const p = target.alloc(n);
|
return cache.scopedAlloc.pushPtr(target.alloc(n));
|
||||||
cache.scopedAlloc[cache.scopedAlloc.length-1].push(p);
|
|
||||||
return p;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.defineProperty(target.scopedAlloc, 'level', {
|
Object.defineProperty(target.scopedAlloc, 'level', {
|
||||||
@@ -1343,7 +1349,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
value to dealloc(). The others are part of the same memory chunk
|
value to dealloc(). The others are part of the same memory chunk
|
||||||
and must not be freed separately.
|
and must not be freed separately.
|
||||||
|
|
||||||
The reason for the 2nd argument is..
|
The reason for the 2nd argument is...
|
||||||
|
|
||||||
When one of the returned pointers will refer to a 64-bit value,
|
When one of the returned pointers will refer to a 64-bit value,
|
||||||
e.g. a double or int64, an that value must be written or fetched,
|
e.g. a double or int64, an that value must be written or fetched,
|
||||||
@@ -1404,7 +1410,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
State for use with xWrap()
|
State for use with xWrap().
|
||||||
*/
|
*/
|
||||||
cache.xWrap = Object.create(null);
|
cache.xWrap = Object.create(null);
|
||||||
cache.xWrap.convert = Object.create(null);
|
cache.xWrap.convert = Object.create(null);
|
||||||
@@ -1438,8 +1444,9 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
.set('null', (v)=>v)
|
.set('null', (v)=>v)
|
||||||
.set(null, xResult.get('null'));
|
.set(null, xResult.get('null'));
|
||||||
|
|
||||||
{ /* Copy certain xArg[...] handlers to xResult[...] and
|
{ /* Copy xArg[...] handlers to xResult[...] for cases which have
|
||||||
add pointer-style variants of them. */
|
identical semantics. Also add pointer-style variants of
|
||||||
|
them. */
|
||||||
const copyToResult = ['i8', 'i16', 'i32', 'int',
|
const copyToResult = ['i8', 'i16', 'i32', 'int',
|
||||||
'f32', 'float', 'f64', 'double'];
|
'f32', 'float', 'f64', 'double'];
|
||||||
if(target.bigIntEnabled) copyToResult.push('i64');
|
if(target.bigIntEnabled) copyToResult.push('i64');
|
||||||
@@ -1461,7 +1468,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
- If v is a string, scopeAlloc() a new C-string from it and return
|
- If v is a string, scopeAlloc() a new C-string from it and return
|
||||||
that temp string's pointer.
|
that temp string's pointer.
|
||||||
|
|
||||||
- Else return the value from the arg adapter defined for ptrIR.
|
- Else return the value from the arg adapter defined for `ptrIR`.
|
||||||
|
|
||||||
TODO? Permit an Int8Array/Uint8Array and convert it to a string?
|
TODO? Permit an Int8Array/Uint8Array and convert it to a string?
|
||||||
Would that be too much magic concentrated in one place, ready to
|
Would that be too much magic concentrated in one place, ready to
|
||||||
@@ -1494,12 +1501,11 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
Internal-use-only base class for FuncPtrAdapter and potentially
|
Internal-use-only base class for FuncPtrAdapter and potentially
|
||||||
additional stateful argument adapter classes.
|
additional stateful argument adapter classes.
|
||||||
|
|
||||||
Note that its main interface (convertArg()) is strictly
|
Its main interface (convertArg()) is strictly internal, not to be
|
||||||
internal, not to be exposed to client code, as it may still
|
exposed to client code, as it may still need re-shaping. Only the
|
||||||
need re-shaping. Only the constructors of concrete subclasses
|
constructors of concrete subclasses should be exposed to clients,
|
||||||
should be exposed to clients, and those in such a way that
|
and those in such a way that does not hinder internal redesign of
|
||||||
does not hinder internal redesign of the convertArg()
|
the convertArg() interface.
|
||||||
interface.
|
|
||||||
*/
|
*/
|
||||||
const AbstractArgAdapter = class {
|
const AbstractArgAdapter = class {
|
||||||
constructor(opt){
|
constructor(opt){
|
||||||
@@ -1518,6 +1524,11 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
indexes must never be relied upon for anything because their
|
indexes must never be relied upon for anything because their
|
||||||
types are indeterminate, whereas the LHS values will be
|
types are indeterminate, whereas the LHS values will be
|
||||||
WASM-compatible values by the time this is called.
|
WASM-compatible values by the time this is called.
|
||||||
|
|
||||||
|
The reason for the argv and argIndex arguments is that we
|
||||||
|
frequently need more context than v for a specific conversion,
|
||||||
|
and that context invariably lies in the LHS arguments of v.
|
||||||
|
Examples of how this is useful can be found in FuncPtrAdapter.
|
||||||
*/
|
*/
|
||||||
convertArg(v,argv,argIndex){
|
convertArg(v,argv,argIndex){
|
||||||
toss("AbstractArgAdapter must be subclassed.");
|
toss("AbstractArgAdapter must be subclassed.");
|
||||||
@@ -1525,12 +1536,11 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An attempt at adding function pointer conversion support to
|
This type is recognized by xWrap() as a proxy for converting a JS
|
||||||
xWrap(). This type is recognized by xWrap() as a proxy for
|
function to a C-side function, either permanently, for the
|
||||||
converting a JS function to a C-side function, either
|
duration of a single call into the C layer, or semi-contextual,
|
||||||
permanently, for the duration of a single call into the C layer,
|
where it may keep track of a single binding for a given context
|
||||||
or semi-contextual, where it may keep track of a single binding
|
and uninstall the binding if it's replaced.
|
||||||
for a given context and uninstall the binding if it's replaced.
|
|
||||||
|
|
||||||
The constructor requires an options object with these properties:
|
The constructor requires an options object with these properties:
|
||||||
|
|
||||||
@@ -1566,7 +1576,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
|
|
||||||
- 'permanent': the function is installed and left there
|
- 'permanent': the function is installed and left there
|
||||||
forever. There is no way to recover its pointer address
|
forever. There is no way to recover its pointer address
|
||||||
later on.
|
later on for cleanup purposes. i.e. it effectively leaks.
|
||||||
|
|
||||||
- callProxy (function): if set, this must be a function which
|
- callProxy (function): if set, this must be a function which
|
||||||
will act as a proxy for any "converted" JS function. It is
|
will act as a proxy for any "converted" JS function. It is
|
||||||
@@ -1574,12 +1584,12 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
either that function or a function which acts on its
|
either that function or a function which acts on its
|
||||||
behalf. The returned function will be the one which gets
|
behalf. The returned function will be the one which gets
|
||||||
installed into the WASM function table. The proxy must perform
|
installed into the WASM function table. The proxy must perform
|
||||||
any required argument conversion (noting that it will be called
|
any required argument conversion (it will be called from C
|
||||||
from C code, so will receive C-format arguments) before passing
|
code, so will receive C-format arguments) before passing them
|
||||||
them on to the being-converted function. Whether or not the
|
on to the being-converted function. Whether or not the proxy
|
||||||
proxy itself must return a value depends on the context. If it
|
itself must return a value depends on the context. If it does,
|
||||||
does, it must be a WASM-friendly value, as it will be returning
|
it must be a WASM-friendly value, as it will be returning from
|
||||||
from a call made from native code.
|
a call made from WASM code.
|
||||||
|
|
||||||
- contextKey (function): is only used if bindScope is 'context'
|
- contextKey (function): is only used if bindScope is 'context'
|
||||||
or if bindScope is not set and this function is, in which case
|
or if bindScope is not set and this function is, in which case
|
||||||
@@ -1598,10 +1608,10 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
FuncPtrAdapter instance (other instances are not considered),
|
FuncPtrAdapter instance (other instances are not considered),
|
||||||
taking into account that C functions often take some sort of
|
taking into account that C functions often take some sort of
|
||||||
state object as one or more of their arguments. As an example,
|
state object as one or more of their arguments. As an example,
|
||||||
if the xWrap()'d function takes `(int,T*,functionPtr,X*)` and
|
if the xWrap()'d function takes `(int,T*,functionPtr,X*)` then
|
||||||
this FuncPtrAdapter is the argv[2]nd arg, contextKey(argv,2)
|
this FuncPtrAdapter instance is argv[2], and contextKey(argv,2)
|
||||||
might return 'T@'+argv[1], or even just argv[1]. Note,
|
might return 'T@'+argv[1], or even just argv[1]. Note,
|
||||||
however, that the (X*) argument will not yet have been
|
however, that the (`X*`) argument will not yet have been
|
||||||
processed by the time this is called and should not be used as
|
processed by the time this is called and should not be used as
|
||||||
part of that key because its pre-conversion data type might be
|
part of that key because its pre-conversion data type might be
|
||||||
unpredictable. Similarly, care must be taken with C-string-type
|
unpredictable. Similarly, care must be taken with C-string-type
|
||||||
@@ -1609,13 +1619,17 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
be WASM pointers, whereas those to the right might (and likely
|
be WASM pointers, whereas those to the right might (and likely
|
||||||
do) have another data type. When using C-strings in keys, never
|
do) have another data type. When using C-strings in keys, never
|
||||||
use their pointers in the key because most C-strings in this
|
use their pointers in the key because most C-strings in this
|
||||||
constellation are transient.
|
constellation are transient. Conversely, the pointer address
|
||||||
|
makes an ideal key for longer-lived native pointer types.
|
||||||
|
|
||||||
Yes, that ^^^ is quite awkward, but it's what we have.
|
Yes, that ^^^ is quite awkward, but it's what we have. In
|
||||||
|
context, as it were, it actually makes some sense, but one must
|
||||||
|
look under its hook a bit to understand why it's shaped the
|
||||||
|
way it is.
|
||||||
|
|
||||||
The constructor only saves the above state for later, and does
|
The constructor only saves the above state for later, and does
|
||||||
not actually bind any functions. Its convertArg() method is
|
not actually bind any functions. The conversion, if any, is
|
||||||
called via xWrap() to perform any bindings.
|
performed when its convertArg() method is called via xWrap().
|
||||||
|
|
||||||
Shortcomings:
|
Shortcomings:
|
||||||
|
|
||||||
@@ -1627,10 +1641,9 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
- Function pointers which include C-string arguments may still
|
- Function pointers which include C-string arguments may still
|
||||||
need a level of hand-written wrappers around them, depending on
|
need a level of hand-written wrappers around them, depending on
|
||||||
how they're used, in order to provide the client with JS
|
how they're used, in order to provide the client with JS
|
||||||
strings. Alternately, clients will need to perform such conversions
|
strings. Alternately, clients will need to perform such
|
||||||
on their own, e.g. using cstrToJs(). Or maybe we can find a way
|
conversions on their own, e.g. using cstrToJs(). The purpose of
|
||||||
to perform such conversions here, via addition of an xWrap()-style
|
the callProxy() method is to account for such cases.
|
||||||
function signature to the options argument.
|
|
||||||
*/
|
*/
|
||||||
xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter {
|
xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter {
|
||||||
constructor(opt) {
|
constructor(opt) {
|
||||||
@@ -1662,9 +1675,9 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Note that static class members are defined outside of the class
|
The static class members are defined outside of the class to
|
||||||
to work around an emcc toolchain build problem: one of the
|
work around an emcc toolchain build problem: one of the tools
|
||||||
tools in emsdk v3.1.42 does not support the static keyword.
|
in emsdk v3.1.42 does not support the static keyword.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Dummy impl. Overwritten per-instance as needed. */
|
/* Dummy impl. Overwritten per-instance as needed. */
|
||||||
@@ -1672,9 +1685,15 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns this objects mapping for the given context key, in the
|
/**
|
||||||
|
Returns this object's mapping for the given context key, in the
|
||||||
form of an an array, creating the mapping if needed. The key
|
form of an an array, creating the mapping if needed. The key
|
||||||
may be anything suitable for use in a Map. */
|
may be anything suitable for use in a Map.
|
||||||
|
|
||||||
|
The returned array is intended to be used as a pair of
|
||||||
|
[JSValue, WasmFuncPtr], where the first element is one passed
|
||||||
|
to this.convertArg() and the second is its WASM form.
|
||||||
|
*/
|
||||||
contextMap(key){
|
contextMap(key){
|
||||||
const cm = (this.__cmap || (this.__cmap = new Map));
|
const cm = (this.__cmap || (this.__cmap = new Map));
|
||||||
let rc = cm.get(key);
|
let rc = cm.get(key);
|
||||||
@@ -1684,19 +1703,21 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Gets called via xWrap() to "convert" v to a WASM-bound function
|
Gets called via xWrap() to "convert" v to a WASM-bound function
|
||||||
pointer. If v is one of (a pointer, null, undefined) then
|
pointer. If v is one of (a WASM pointer, null, undefined) then
|
||||||
(v||0) is returned and any earlier function installed by this
|
(v||0) is returned and any earlier function installed by this
|
||||||
mapping _might_, depending on how it's bound, be uninstalled.
|
mapping _might_, depending on how it's bound, be uninstalled.
|
||||||
If v is not one of those types, it must be a Function, for
|
If v is not one of those types, it must be a Function, for
|
||||||
which it creates (if needed) a WASM function binding and
|
which this method creates (if needed) a WASM function binding
|
||||||
returns the WASM pointer to that binding. If this instance is
|
and returns the WASM pointer to that binding.
|
||||||
not in 'transient' mode, it will remember the binding for at
|
|
||||||
least the next call, to avoid recreating the function binding
|
|
||||||
unnecessarily.
|
|
||||||
|
|
||||||
If it's passed a pointer(ish) value for v, it does _not_
|
If this instance is not in 'transient' mode, it will remember
|
||||||
perform any function binding, so this object's bindMode is
|
the binding for at least the next call, to avoid recreating the
|
||||||
irrelevant for such cases.
|
function binding unnecessarily.
|
||||||
|
|
||||||
|
If it's passed a pointer(ish) value for v, it assumes it's a
|
||||||
|
WASM function pointer and does _not_ perform any function
|
||||||
|
binding, so this object's bindMode is irrelevant/ignored for
|
||||||
|
such cases.
|
||||||
|
|
||||||
See the parent class's convertArg() docs for details on what
|
See the parent class's convertArg() docs for details on what
|
||||||
exactly the 2nd and 3rd arguments are.
|
exactly the 2nd and 3rd arguments are.
|
||||||
@@ -1708,11 +1729,16 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
pair = this.contextMap(this.contextKey(argv,argIndex));
|
pair = this.contextMap(this.contextKey(argv,argIndex));
|
||||||
//FuncPtrAdapter.debugOut(this.name, this.signature, "contextKey() =",this.contextKey(argv,argIndex), pair);
|
//FuncPtrAdapter.debugOut(this.name, this.signature, "contextKey() =",this.contextKey(argv,argIndex), pair);
|
||||||
}
|
}
|
||||||
if(pair && pair[0]===v) return pair[1];
|
if(pair && pair[0]===v){
|
||||||
|
/* We have already handled this function. */
|
||||||
|
return pair[1];
|
||||||
|
}
|
||||||
if(v instanceof Function){
|
if(v instanceof Function){
|
||||||
/* Install a WASM binding and return its pointer. */
|
/* Install a WASM binding and return its pointer. */
|
||||||
//FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.name,this.signature,this.transient,v,pair);
|
//FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.name,this.signature,this.transient,v,pair);
|
||||||
if(this.callProxy) v = this.callProxy(v);
|
if(this.callProxy){
|
||||||
|
v = this.callProxy(v);
|
||||||
|
}
|
||||||
const fp = __installFunction(v, this.signature, this.isTransient);
|
const fp = __installFunction(v, this.signature, this.isTransient);
|
||||||
if(FuncPtrAdapter.debugFuncInstall){
|
if(FuncPtrAdapter.debugFuncInstall){
|
||||||
FuncPtrAdapter.debugOut("FuncPtrAdapter installed", this,
|
FuncPtrAdapter.debugOut("FuncPtrAdapter installed", this,
|
||||||
@@ -1735,11 +1761,11 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
function. We're relying very much here on xWrap()
|
function. We're relying very much here on xWrap()
|
||||||
having pushed an alloc scope.
|
having pushed an alloc scope.
|
||||||
*/
|
*/
|
||||||
cache.scopedAlloc[cache.scopedAlloc.length-1].push(pair[1]);
|
cache.scopedAlloc.pushPtr(pair[1]);
|
||||||
}
|
}
|
||||||
catch(e){/*ignored*/}
|
catch(e){/*ignored*/}
|
||||||
}
|
}
|
||||||
pair[0] = v;
|
pair[0] = arguments[0]/*the original v*/;
|
||||||
pair[1] = fp;
|
pair[1] = fp;
|
||||||
}
|
}
|
||||||
return fp;
|
return fp;
|
||||||
@@ -1751,7 +1777,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this,
|
FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this,
|
||||||
this.contextKey(argv,argIndex), '@'+pair[1], v);
|
this.contextKey(argv,argIndex), '@'+pair[1], v);
|
||||||
}
|
}
|
||||||
try{ cache.scopedAlloc[cache.scopedAlloc.length-1].push(pair[1]) }
|
try{ cache.scopedAlloc.pushPtr(pair[1]); }
|
||||||
catch(e){/*ignored*/}
|
catch(e){/*ignored*/}
|
||||||
pair[0] = pair[1] = (v | 0);
|
pair[0] = pair[1] = (v | 0);
|
||||||
}
|
}
|
||||||
@@ -1782,13 +1808,19 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
/** Function used for debug output. */
|
/** Function used for debug output. */
|
||||||
xArg.FuncPtrAdapter.debugOut = console.debug.bind(console);
|
xArg.FuncPtrAdapter.debugOut = console.debug.bind(console);
|
||||||
|
|
||||||
|
/**
|
||||||
|
List of legal values for the FuncPtrAdapter bindScope config
|
||||||
|
option.
|
||||||
|
*/
|
||||||
xArg.FuncPtrAdapter.bindScopes = [
|
xArg.FuncPtrAdapter.bindScopes = [
|
||||||
'transient', 'context', 'singleton', 'permanent'
|
'transient', 'context', 'singleton', 'permanent'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** Throws if xArg.get(t) returns falsy. */
|
||||||
const __xArgAdapterCheck =
|
const __xArgAdapterCheck =
|
||||||
(t)=>xArg.get(t) || toss("Argument adapter not found:",t);
|
(t)=>xArg.get(t) || toss("Argument adapter not found:",t);
|
||||||
|
|
||||||
|
/** Throws if xResult.get(t) returns falsy. */
|
||||||
const __xResultAdapterCheck =
|
const __xResultAdapterCheck =
|
||||||
(t)=>xResult.get(t) || toss("Result adapter not found:",t);
|
(t)=>xResult.get(t) || toss("Result adapter not found:",t);
|
||||||
|
|
||||||
@@ -1942,8 +1974,8 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
target.xWrap.resultAdapter('string:my_free',(i)=>{
|
target.xWrap.resultAdapter('string:my_free',(i)=>{
|
||||||
try { return i ? target.cstrToJs(i) : null }
|
try { return i ? target.cstrToJs(i) : null; }
|
||||||
finally{ target.exports.my_free(i) }
|
finally{ target.exports.my_free(i); }
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -2003,8 +2035,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
if(fIsFunc) fArg = xf.name || 'unnamed function';
|
if(fIsFunc) fArg = xf.name || 'unnamed function';
|
||||||
if(argTypes.length!==xf.length) __argcMismatch(fArg, xf.length);
|
if(argTypes.length!==xf.length) __argcMismatch(fArg, xf.length);
|
||||||
if((null===resultType) && 0===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;
|
return xf;
|
||||||
}
|
}
|
||||||
/*Verify the arg type conversions are valid...*/;
|
/*Verify the arg type conversions are valid...*/;
|
||||||
@@ -2041,7 +2072,9 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
_not_ stable.
|
_not_ stable.
|
||||||
|
|
||||||
Maintenance reminder: the Ember framework modifies the core
|
Maintenance reminder: the Ember framework modifies the core
|
||||||
Array type, breaking for-in loops.
|
Array type, breaking for-in loops:
|
||||||
|
|
||||||
|
https://sqlite.org/forum/forumpost/b549992634b55104
|
||||||
*/
|
*/
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for(; i < args.length; ++i) args[i] = cxw.convertArgNoCheck(
|
for(; i < args.length; ++i) args[i] = cxw.convertArgNoCheck(
|
||||||
@@ -2054,7 +2087,28 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
};
|
};
|
||||||
}/*xWrap()*/;
|
}/*xWrap()*/;
|
||||||
|
|
||||||
/** Internal impl for xWrap.resultAdapter() and argAdapter(). */
|
/**
|
||||||
|
Internal impl for xWrap.resultAdapter() and argAdapter().
|
||||||
|
|
||||||
|
func = one of xWrap.resultAdapter or xWrap.argAdapter.
|
||||||
|
|
||||||
|
argc = the number of args in the wrapping call to this
|
||||||
|
function.
|
||||||
|
|
||||||
|
typeName = the first arg to the wrapping function.
|
||||||
|
|
||||||
|
adapter = the second arg to the wrapping function.
|
||||||
|
|
||||||
|
modeName = a descriptive name of the wrapping function for
|
||||||
|
error-reporting purposes.
|
||||||
|
|
||||||
|
xcvPart = one of xResult or xArg.
|
||||||
|
|
||||||
|
This acts as either a getter (if 1===argc) or setter (if
|
||||||
|
2===argc) for the given adapter. Returns func on success or
|
||||||
|
throws if (A) called with 2 args but adapter is-not-a Function or
|
||||||
|
(B) typeName is not a string or (C) argc is not one of (1, 2).
|
||||||
|
*/
|
||||||
const __xAdapter = function(func, argc, typeName, adapter, modeName, xcvPart){
|
const __xAdapter = function(func, argc, typeName, adapter, modeName, xcvPart){
|
||||||
if('string'===typeof typeName){
|
if('string'===typeof typeName){
|
||||||
if(1===argc) return xcvPart.get(typeName);
|
if(1===argc) return xcvPart.get(typeName);
|
||||||
@@ -2089,16 +2143,16 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
xWrap.resultAdapter('twice',(v)=>v+v);
|
xWrap.resultAdapter('twice',(v)=>v+v);
|
||||||
```
|
```
|
||||||
|
|
||||||
xWrap.resultAdapter() MUST NOT use the scopedAlloc() family of
|
Result adapters MUST NOT use the scopedAlloc() family of APIs to
|
||||||
APIs to allocate a result value. xWrap()-generated wrappers run
|
allocate a result value. xWrap()-generated wrappers run in the
|
||||||
in the context of scopedAllocPush() so that argument adapters can
|
context of scopedAllocPush() so that argument adapters can easily
|
||||||
easily convert, e.g., to C-strings, and have them cleaned up
|
convert, e.g., to C-strings, and have them cleaned up
|
||||||
automatically before the wrapper returns to the caller. Likewise,
|
automatically before the wrapper returns to the caller. Likewise,
|
||||||
if a _result_ adapter uses scoped allocation, the result will be
|
if a _result_ adapter uses scoped allocation, the result will be
|
||||||
freed before the wrapper returns, leading to chaos and undefined
|
freed before the wrapper returns, leading to chaos and undefined
|
||||||
behavior.
|
behavior.
|
||||||
|
|
||||||
Except when called as a getter, this function returns itself.
|
When called as a setter, this function returns itself.
|
||||||
*/
|
*/
|
||||||
target.xWrap.resultAdapter = function f(typeName, adapter){
|
target.xWrap.resultAdapter = function f(typeName, adapter){
|
||||||
return __xAdapter(f, arguments.length, typeName, adapter,
|
return __xAdapter(f, arguments.length, typeName, adapter,
|
||||||
@@ -2122,13 +2176,13 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Contrariwise, xWrap.resultAdapter() must _not_ use scopedAlloc()
|
Contrariwise, _result_ adapters _must not_ use scopedAlloc() to
|
||||||
to allocate its results because they would be freed before the
|
allocate results because they would be freed before the
|
||||||
xWrap()-created wrapper returns.
|
xWrap()-created wrapper returns.
|
||||||
|
|
||||||
Note that it is perfectly legitimate to use these adapters to
|
It is perfectly legitimate to use these adapters to perform
|
||||||
perform argument validation, as opposed (or in addition) to
|
argument validation, as opposed (or in addition) to conversion.
|
||||||
conversion.
|
When used that way, they should throw for invalid arguments.
|
||||||
*/
|
*/
|
||||||
target.xWrap.argAdapter = function f(typeName, adapter){
|
target.xWrap.argAdapter = function f(typeName, adapter){
|
||||||
return __xAdapter(f, arguments.length, typeName, adapter,
|
return __xAdapter(f, arguments.length, typeName, adapter,
|
||||||
@@ -2151,8 +2205,7 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
is to be called more than once, it's more efficient to use
|
is to be called more than once, it's more efficient to use
|
||||||
xWrap() to create a wrapper, then to call that wrapper as many
|
xWrap() to create a wrapper, then to call that wrapper as many
|
||||||
times as needed. For one-shot calls, however, this variant is
|
times as needed. For one-shot calls, however, this variant is
|
||||||
arguably more efficient because it will hypothetically free the
|
simpler.
|
||||||
wrapper function quickly.
|
|
||||||
*/
|
*/
|
||||||
target.xCallWrapped = function(fArg, resultType, argTypes, ...args){
|
target.xCallWrapped = function(fArg, resultType, argTypes, ...args){
|
||||||
if(Array.isArray(arguments[3])) args = arguments[3];
|
if(Array.isArray(arguments[3])) args = arguments[3];
|
||||||
@@ -2239,8 +2292,9 @@ globalThis.WhWasmUtilInstaller = function(target){
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Note that the initial `then()` attached to the promise gets only
|
(The initial `then()` attached to the promise gets only that
|
||||||
that object, and not the `config` one.)
|
object, and not the `config` object, thus the potential need for a
|
||||||
|
`config.onload` handler.)
|
||||||
|
|
||||||
Error handling is up to the caller, who may attach a `catch()` call
|
Error handling is up to the caller, who may attach a `catch()` call
|
||||||
to the promise.
|
to the promise.
|
||||||
|
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\stypo\sin\sthe\sname\sof\sthe\sCursorHints\soptimization\sin\sthe\sCLI.
|
C Wasm:\s(A)\sdiverse\sinternal\sdoc\supdates.\s(B)\swhen\sgenerating\sautomated\sJS-to-WASM\sfunction\sproxies\sfor\sconverters\swhich\srequire\san\sadditional\smiddle-man\sproxy,\se.g.\ssqlite3_exec(),\suse\sthe\sclient-provided\sfunction,\snot\sthe\sproxy\sfunction,\sas\sthe\scache\skey,\sto\skeep\sfrom\sre-generating\sthe\sconversion\sin\ssome\scommon\suse\spatterns.
|
||||||
D 2025-09-19T09:18:22.076
|
D 2025-09-19T14:21:09.961
|
||||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
@@ -607,7 +607,7 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
|
|||||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 0f68a64e508598910e7c01214ae27d603dfc8baec6a184506fafac603a901931
|
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 0f68a64e508598910e7c01214ae27d603dfc8baec6a184506fafac603a901931
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4ab0704ee198de7d1059eccedc7703c931510b588d10af0ee36ea5b3ebbac284
|
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4ab0704ee198de7d1059eccedc7703c931510b588d10af0ee36ea5b3ebbac284
|
||||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
|
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
|
||||||
F ext/wasm/api/sqlite3-wasm.c 7b207c10c6b4019cf667c4e332bdd33c98afc08c943f8cc0aea7693ad8635f7c
|
F ext/wasm/api/sqlite3-wasm.c 404cc1f0f5c307210a8d7c3a7dda57834e0e8b3d406ba51977a97a6d14a74734
|
||||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 4ad256b4ff7f839ad18931ed35d46cced544207bd2209665ec552e193f7f4544
|
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 4ad256b4ff7f839ad18931ed35d46cced544207bd2209665ec552e193f7f4544
|
||||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||||
@@ -618,7 +618,7 @@ F ext/wasm/c-pp.c cca55c5b55ebd8d29916adbedb0e40baa12caa9a2e8429f812683c308f9b0e
|
|||||||
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
|
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
|
||||||
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
|
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
|
||||||
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
|
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
|
||||||
F ext/wasm/common/whwasmutil.js ea50e847cf08c2a96694f87d00b49fb97ee5fe62c15439cc269c8e1d9ab74c0a
|
F ext/wasm/common/whwasmutil.js 4ea5a413016d9a561a26976c699a2670f2385b93be04cd2d463dd6c1955bd175
|
||||||
F ext/wasm/config.make.in c424ae1cc3c89274520ad312509d36c4daa34a3fce5d0c688e5f8f4365e1049a
|
F ext/wasm/config.make.in c424ae1cc3c89274520ad312509d36c4daa34a3fce5d0c688e5f8f4365e1049a
|
||||||
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
|
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
|
||||||
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
|
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
|
||||||
@@ -2175,8 +2175,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
|
|||||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||||
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P 42c225a2ed7fc95f9b01467c64ba2bf97bca216fdcd6ab1ba3fb49c068650de9
|
P 468a11fd415710042b23880772f6c2c7771008208823fe3b554227a9244dbf92
|
||||||
R fec5e9cf9c4aa5198306438cd736e135
|
R 45b30de6d5f1d826a12d811876f55290
|
||||||
U drh
|
U stephan
|
||||||
Z 1e7399cfaf854450b90c6eb04c4097ba
|
Z 31a53fb96f385e882a14f4d3fa47d2d3
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@@ -1 +1 @@
|
|||||||
468a11fd415710042b23880772f6c2c7771008208823fe3b554227a9244dbf92
|
5e5139c2a162562cee0071d03954ebc0b8938da0b045ec3f5eba32dc8e19604d
|
||||||
|
Reference in New Issue
Block a user