1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Enhance sqlite3.wasm.xWrap.FuncPtrAdapter to be able to handle sqlite3_create_function() and friends and reimplement those bindings to use this feature (this will also simplify certain session API bindings). Interal API changes only with no client-side breakage.

FossilOrigin-Name: 7f9ace1b11a6703031790af9cf08ab25df25850a86e6ca2a7aeaefd8aa395e6d
This commit is contained in:
stephan
2022-12-25 12:51:53 +00:00
parent 75c04ba89c
commit 485229e147
4 changed files with 169 additions and 165 deletions

View File

@ -82,7 +82,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
"sqlite3*", "sqlite3*",
new wasm.xWrap.FuncPtrAdapter({ new wasm.xWrap.FuncPtrAdapter({
signature: 'i(pi)', signature: 'i(pi)',
contextKey: (argIndex,argv)=>'sqlite3@'+argv[0] contextKey: (argv,argIndex)=>'sqlite3@'+argv[0]
}), }),
"*" "*"
]], ]],
@ -160,7 +160,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
name: 'xProgressHandler', name: 'xProgressHandler',
signature: 'i(p)', signature: 'i(p)',
bindScope: 'context', bindScope: 'context',
contextKey: (argIndex,argv)=>'sqlite3@'+argv[0] contextKey: (argv,argIndex)=>'sqlite3@'+argv[0]
}), "*" }), "*"
] ]
], ],
@ -200,7 +200,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
new wasm.xWrap.FuncPtrAdapter({ new wasm.xWrap.FuncPtrAdapter({
name: 'sqlite3_trace_v2::callback', name: 'sqlite3_trace_v2::callback',
signature: 'i(ippp)', signature: 'i(ippp)',
contextKey: (argIndex, argv)=>'sqlite3@'+argv[0] contextKey: (argv,argIndex)=>'sqlite3@'+argv[0]
}), "*"], }), "*"],
["sqlite3_txn_state", "int", ["sqlite3*","string"]], ["sqlite3_txn_state", "int", ["sqlite3*","string"]],
/* Note that sqlite3_uri_...() have very specific requirements for /* Note that sqlite3_uri_...() have very specific requirements for
@ -497,28 +497,24 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
); );
}; };
if(1){/* Bindings for sqlite3_create_collation[_v2]() */ {/* Bindings for sqlite3_create_collation[_v2]() */
const __collationContextKey = (argIndex,argv)=>{ // contextKey() impl for wasm.xWrap.FuncPtrAdapter
const contextKey = (argv,argIndex)=>{
return 'argv['+argIndex+']:sqlite3@'+argv[0]+ return 'argv['+argIndex+']:sqlite3@'+argv[0]+
':'+wasm.cstrToJs(argv[1]).toLowerCase() ':'+wasm.cstrToJs(argv[1]).toLowerCase()
}; };
const __ccv2 = wasm.xWrap( const __sqlite3CreateCollationV2 = wasm.xWrap(
'sqlite3_create_collation_v2', 'int', 'sqlite3_create_collation_v2', 'int', [
'sqlite3*','string','int','*', 'sqlite3*', 'string', 'int', '*',
new wasm.xWrap.FuncPtrAdapter({ new wasm.xWrap.FuncPtrAdapter({
/* int(*xCompare)(void*,int,const void*,int,const void*) */ /* int(*xCompare)(void*,int,const void*,int,const void*) */
name: 'sqlite3_create_collation_v2::xCompare', name: 'xCompare', signature: 'i(pipip)', contextKey
signature: 'i(pipip)', }),
bindScope: 'context', new wasm.xWrap.FuncPtrAdapter({
contextKey: __collationContextKey /* void(*xDestroy(void*) */
}), name: 'xDestroy', signature: 'v(p)', contextKey
new wasm.xWrap.FuncPtrAdapter({ })
/* void(*xDestroy(void*) */ ]
name: 'sqlite3_create_collation_v2::xDestroy',
signature: 'v(p)',
bindScope: 'context',
contextKey: __collationContextKey
})
); );
/** /**
@ -552,13 +548,11 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){ }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
return __errEncoding(pDb); return __errEncoding(pDb);
} }
let rc, pfCompare, pfDestroy; try{
try{ return __sqlite3CreateCollationV2(pDb, zName, eTextRep, pArg, xCompare, xDestroy);
rc = __ccv2(pDb, zName, eTextRep, pArg, xCompare, xDestroy);
}catch(e){ }catch(e){
rc = util.sqlite3_wasm_db_error(pDb, e); return util.sqlite3_wasm_db_error(pDb, e);
} }
return rc;
}; };
capi.sqlite3_create_collation = (pDb,zName,eTextRep,pArg,xCompare)=>{ capi.sqlite3_create_collation = (pDb,zName,eTextRep,pArg,xCompare)=>{
@ -617,82 +611,91 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}/*sqlite3_exec() proxy*/; }/*sqlite3_exec() proxy*/;
{/* Special-case handling of sqlite3_create_function_v2() {/* Special-case handling of sqlite3_create_function_v2()
and sqlite3_create_window_function() */ and sqlite3_create_window_function(). */
/* Maintenance reminder: FuncPtrAdapter is not expressive enough /**
to be able to perform these mappings. */ FuncPtrAdapter for contextKey() for sqlite3_create_function().
const sqlite3CreateFunction = wasm.xWrap( */
"sqlite3_create_function_v2", "int", const contextKey = function(argv,argIndex){
["sqlite3*", "string"/*funcName*/, "int"/*nArg*/, return (
"int"/*eTextRep*/, "*"/*pApp*/, 'sqlite3@'+argv[0]
"*"/*xStep*/,"*"/*xFinal*/, "*"/*xValue*/, "*"/*xDestroy*/] +':'+argIndex
); +':'+wasm.cstrToJs(argv[1]).toLowerCase()
)
};
const sqlite3CreateWindowFunction = wasm.xWrap( /**
"sqlite3_create_window_function", "int", JS proxies for the various sqlite3_create[_window]_function()
["sqlite3*", "string"/*funcName*/, "int"/*nArg*/, callbacks, structured in a form usable by wasm.xWrap.FuncPtrAdapter.
"int"/*eTextRep*/, "*"/*pApp*/, */
"*"/*xStep*/,"*"/*xFinal*/, "*"/*xValue*/, const __cfProxy = Object.assign(Object.create(null), {
"*"/*xInverse*/, "*"/*xDestroy*/] xInverseAndStep: {
); signature:'v(pip)', contextKey,
callProxy: (callback)=>{
const __xFunc = function(callback){ return (pCtx, argc, pArgv)=>{
return function(pCtx, argc, pArgv){ try{ callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv)) }
try{ catch(e){ capi.sqlite3_result_error_js(pCtx, e) }
capi.sqlite3_result_js( };
pCtx,
callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv))
);
}catch(e){
//console.error('xFunc() caught:',e);
capi.sqlite3_result_error_js(pCtx, e);
} }
}; },
}; xFinalAndValue: {
signature:'v(p)', contextKey,
const __xInverseAndStep = function(callback){ callProxy: (callback)=>{
return function(pCtx, argc, pArgv){ return (pCtx)=>{
try{ callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv)) } try{ capi.sqlite3_result_js(pCtx, callback(pCtx)) }
catch(e){ capi.sqlite3_result_error_js(pCtx, e) } catch(e){ capi.sqlite3_result_error_js(pCtx, e) }
}; };
}; }
},
const __xFinalAndValue = function(callback){ xFunc: {
return function(pCtx){ signature:'v(pip)', contextKey,
try{ capi.sqlite3_result_js(pCtx, callback(pCtx)) } callProxy: (callback)=>{
catch(e){ capi.sqlite3_result_error_js(pCtx, e) } return (pCtx, argc, pArgv)=>{
}; try{
}; capi.sqlite3_result_js(
pCtx,
const __xDestroy = function(callback){ callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv))
return function(pVoid){ );
try{ callback(pVoid) } }catch(e){
catch(e){ console.error("UDF xDestroy method threw:",e) } //console.error('xFunc() caught:',e);
}; capi.sqlite3_result_error_js(pCtx, e);
}; }
};
const __xMap = Object.assign(Object.create(null), { }
xFunc: {sig:'v(pip)', f:__xFunc}, },
xStep: {sig:'v(pip)', f:__xInverseAndStep}, xDestroy: {
xInverse: {sig:'v(pip)', f:__xInverseAndStep}, signature:'v(p)', contextKey,
xFinal: {sig:'v(p)', f:__xFinalAndValue}, //Arguable: a well-behaved destructor doesn't require a proxy.
xValue: {sig:'v(p)', f:__xFinalAndValue}, callProxy: (callback)=>{
xDestroy: {sig:'v(p)', f:__xDestroy} return (pVoid)=>{
}); try{ callback(pVoid) }
catch(e){ console.error("UDF xDestroy method threw:",e) }
/* Internal helper for sqlite3_create_function() and friends. */ };
const __xWrapFuncs = function(theKeys, theFuncs, tgtUninst){
const rc = []
for(const k of theKeys){
let fArg = theFuncs[k];
if('function'===typeof fArg){
const w = __xMap[k] || toss3("Internal error in __xWrapFuncs: invalid key:",k);
fArg = wasm.installFunction(w.sig, w.f(fArg));
tgtUninst.push(fArg);
} }
rc.push(fArg);
} }
return rc; })/*__cfProxy*/;
};
const __sqlite3CreateFunction = wasm.xWrap(
"sqlite3_create_function_v2", "int", [
"sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
"int"/*eTextRep*/, "*"/*pApp*/,
new wasm.xWrap.FuncPtrAdapter({name: 'xFunc', ...__cfProxy.xFunc}),
new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
]
);
const __sqlite3CreateWindowFunction = wasm.xWrap(
"sqlite3_create_window_function", "int", [
"sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
"int"/*eTextRep*/, "*"/*pApp*/,
new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}),
new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}),
new wasm.xWrap.FuncPtrAdapter({name: 'xValue', ...__cfProxy.xFinalAndValue}),
new wasm.xWrap.FuncPtrAdapter({name: 'xInverse', ...__cfProxy.xInverseAndStep}),
new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy})
]
);
/* Documented in the api object's initializer. */ /* Documented in the api object's initializer. */
capi.sqlite3_create_function_v2 = function f( capi.sqlite3_create_function_v2 = function f(
@ -709,26 +712,16 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){ }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
return __errEncoding(pDb); return __errEncoding(pDb);
} }
/* Wrap the callbacks in a WASM-bound functions... */
const uninstall = [/*funcs to uninstall on error*/];
let rc;
try{ try{
const funcArgs = __xWrapFuncs(['xFunc','xStep','xFinal','xDestroy'], return __sqlite3CreateFunction(pDb, funcName, nArg, eTextRep,
{xFunc, xStep, xFinal, xDestroy}, pApp, xFunc, xStep, xFinal, xDestroy);
uninstall);
rc = sqlite3CreateFunction(pDb, funcName, nArg, eTextRep,
pApp, ...funcArgs);
}catch(e){ }catch(e){
console.error("sqlite3_create_function_v2() setup threw:",e); console.error("sqlite3_create_function_v2() setup threw:",e);
for(let v of uninstall){ return util.sqlite3_wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
wasm.uninstallFunction(v);
}
rc = util.sqlite3_wasm_db_error(pDb, capi.SQLITE_ERROR,
"Creation of UDF threw: "+e.message);
} }
return rc;
}; };
/* Documented in the api object's initializer. */
capi.sqlite3_create_function = function f( capi.sqlite3_create_function = function f(
pDb, funcName, nArg, eTextRep, pApp, pDb, funcName, nArg, eTextRep, pApp,
xFunc, xStep, xFinal xFunc, xStep, xFinal
@ -744,8 +737,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
pDb, funcName, nArg, eTextRep, pApp, pDb, funcName, nArg, eTextRep, pApp,
xStep, //void (*xStep)(sqlite3_context*,int,sqlite3_value**) xStep, //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
xFinal, //void (*xFinal)(sqlite3_context*) xFinal, //void (*xFinal)(sqlite3_context*)
xValue, //void (*xFinal)(sqlite3_context*) xValue, //void (*xValue)(sqlite3_context*)
xInverse,//void (*xStep)(sqlite3_context*,int,sqlite3_value**) xInverse,//void (*xInverse)(sqlite3_context*,int,sqlite3_value**)
xDestroy //void (*xDestroy)(void*) xDestroy //void (*xDestroy)(void*)
){ ){
if( f.length!==arguments.length ){ if( f.length!==arguments.length ){
@ -755,24 +748,14 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){ }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){
return __errEncoding(pDb); return __errEncoding(pDb);
} }
/* Wrap the callbacks in a WASM-bound functions... */
const uninstall = [/*funcs to uninstall on error*/];
let rc;
try{ try{
const funcArgs = __xWrapFuncs(['xStep','xFinal','xValue','xInverse','xDestroy'], return __sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
{xStep, xFinal, xValue, xInverse, xDestroy}, pApp, xStep, xFinal, xValue,
uninstall); xInverse, xDestroy);
rc = sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
pApp, ...funcArgs);
}catch(e){ }catch(e){
console.error("sqlite3_create_window_function() setup threw:",e); console.error("sqlite3_create_window_function() setup threw:",e);
for(let v of uninstall){ return util.sqlite3_wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
wasm.uninstallFunction(v);
}
rc = util.sqlite3_wasm_db_error(pDb, capi.SQLITE_ERROR,
"Creation of UDF threw: "+e.message);
} }
return rc;
}; };
/** /**
A _deprecated_ alias for capi.sqlite3_result_js() which A _deprecated_ alias for capi.sqlite3_result_js() which

View File

@ -1496,7 +1496,7 @@ self.WhWasmUtilInstaller = function(target){
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.
*/ */
convertArg(v,argIndex,argv){ convertArg(v,argv,argIndex){
toss("AbstractArgAdapter must be subclassed."); toss("AbstractArgAdapter must be subclassed.");
} }
}; };
@ -1541,24 +1541,38 @@ self.WhWasmUtilInstaller = function(target){
context. This mode is the default if bindScope is _not_ set context. This mode is the default if bindScope is _not_ set
but a property named contextKey (described below) is. but a property named contextKey (described below) is.
- callProxy (function): if set, this must be a function which
will act as a proxy for any "converted" JS function. It is
passed the being-converted function value and must return
either that function or a function which acts on its
behalf. The returned function will be the one which gets
installed into the WASM function table. The proxy must perform
any required argument conversion (noting that it will be called
from C code, so will receive C-format arguments) before passing
them on to the being-converted function. Whether or not the
proxy itself must return a value depends on the context. If it
does, it must be a WASM-friendly value, as it will be returning
from a call made from native 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
'context' is assumed. This function gets passed 'context' is assumed. This function gets bound to this object,
(argIndex,argv), where argIndex is the index of _this_ function so its "this" is this object. It gets passed (argv,argIndex),
pointer in its _wrapping_ function's arguments and argv is the where argIndex is the index of _this_ function pointer in its
_current_ still-being-xWrap()-processed args array. All _wrapping_ function's arguments and argv is the _current_
arguments to the left of argIndex will have been processed by still-being-xWrap()-processed args array. All arguments to the
xWrap() by the time this is called. argv[argIndex] will be the left of argIndex will have been processed by xWrap() by the
value the user passed in to the xWrap()'d function for the time this is called. argv[argIndex] will be the value the user
argument this FuncPtrAdapter is mapped to. Arguments to the passed in to the xWrap()'d function for the argument this
right of argv[argIndex] will not yet have been converted before FuncPtrAdapter is mapped to. Arguments to the right of
this is called. The function must return a key which uniquely argv[argIndex] will not yet have been converted before this is
called. The function must return a key which uniquely
identifies this function mapping context for _this_ identifies this function mapping context for _this_
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*)` and
this FuncPtrAdapter is the argv[2]nd arg, contextKey(2,argv) this FuncPtrAdapter is the argv[2]nd arg, 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
@ -1570,7 +1584,7 @@ self.WhWasmUtilInstaller = function(target){
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.
Yes, that ^^^ is a bit awkward, but it's what we have. Yes, that ^^^ is quite awkward, but it's what we have.
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. Its convertArg() method is
@ -1598,6 +1612,8 @@ self.WhWasmUtilInstaller = function(target){
if( ('singleton'===this.bindScope) ) this.singleton = []; if( ('singleton'===this.bindScope) ) this.singleton = [];
else this.singleton = undefined; else this.singleton = undefined;
//console.warn("FuncPtrAdapter()",opt,this); //console.warn("FuncPtrAdapter()",opt,this);
this.callProxy = (opt.callProxy instanceof Function)
? opt.callProxy : undefined;
} }
static bindScopes = [ static bindScopes = [
@ -1605,7 +1621,7 @@ self.WhWasmUtilInstaller = function(target){
]; ];
/* Dummy impl. Overwritten per-instance as needed. */ /* Dummy impl. Overwritten per-instance as needed. */
contextKey(argIndex,argv){ contextKey(argv,argIndex){
return this; return this;
} }
@ -1638,14 +1654,16 @@ self.WhWasmUtilInstaller = function(target){
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.
*/ */
convertArg(v,argIndex,argv){ convertArg(v,argv,argIndex){
//console.warn("FuncPtrAdapter.convertArg()",this.signature,this.transient,v); //console.warn("FuncPtrAdapter.convertArg()",this.signature,this.transient,v);
let pair = this.singleton; let pair = this.singleton;
if(!pair && this.isContext){ if(!pair && this.isContext){
pair = this.contextMap(this.contextKey(argIndex, argv)); pair = this.contextMap(this.contextKey(argv,argIndex));
} }
if(pair && pair[0]===v) return pair[1]; if(pair && pair[0]===v) return pair[1];
if(v instanceof Function){ if(v instanceof Function){
/* Install a WASM binding and return its pointer. */
if(this.callProxy) v = this.callProxy(v);
const fp = __installFunction(v, this.signature, this.isTransient); const fp = __installFunction(v, this.signature, this.isTransient);
if(pair){ if(pair){
/* Replace existing stashed mapping */ /* Replace existing stashed mapping */
@ -1660,10 +1678,10 @@ self.WhWasmUtilInstaller = function(target){
}else if(target.isPtr(v) || null===v || undefined===v){ }else if(target.isPtr(v) || null===v || undefined===v){
if(pair && pair[1] && pair[1]!==v){ if(pair && pair[1] && pair[1]!==v){
/* uninstall stashed mapping and replace stashed mapping with v. */ /* uninstall stashed mapping and replace stashed mapping with v. */
//console.warn("FuncPtrAdapter is uninstalling function", this.contextKey(argIndex,argv),v); //console.warn("FuncPtrAdapter is uninstalling function", this.contextKey(argv,argIndex),v);
try{target.uninstallFunction(pair[1])} try{target.uninstallFunction(pair[1])}
catch(e){/*ignored*/} catch(e){/*ignored*/}
pair[0] = pair[1] = (v || 0); pair[0] = pair[1] = (v | 0);
} }
return v || 0; return v || 0;
}else{ }else{
@ -1897,17 +1915,20 @@ self.WhWasmUtilInstaller = function(target){
The public interface of argument adapters is that they take The public interface of argument adapters is that they take
ONE argument and return a (possibly) converted result for ONE argument and return a (possibly) converted result for
it. The passing-on of arguments after the first is an it. The passing-on of arguments after the first is an
internal impl. detail for the sake of AbstractArgAdapter, and internal implementation detail for the sake of
not to be relied on or documented for other cases. The fact AbstractArgAdapter, and not to be relied on or documented
that this is how AbstractArgAdapter.convertArgs() gets its 2nd+ for other cases. The fact that this is how
arguments, and how FuncPtrAdapter.contextKey() gets its AbstractArgAdapter.convertArgs() gets its 2nd+ arguments,
args, is also an implementation detail and subject to and how FuncPtrAdapter.contextKey() gets its args, is also
change. i.e. the public interface of 1 argument is stable. an implementation detail and subject to change. i.e. the
The fact that any arguments may be passed in after that one, public interface of 1 argument is stable. The fact that any
and what those arguments are, is _not_ part of the public arguments may be passed in after that one, and what those
interface and is _not_ stable. arguments are, is _not_ part of the public interface and is
_not_ stable.
*/ */
for(const i in args) args[i] = cxw.convertArgNoCheck(argTypes[i], args[i], i, args); for(const i in args) args[i] = cxw.convertArgNoCheck(
argTypes[i], args[i], args, i
);
return cxw.convertResultNoCheck(resultType, xf.apply(null,args)); return cxw.convertResultNoCheck(resultType, xf.apply(null,args));
}finally{ }finally{
target.scopedAllocPop(scope); target.scopedAllocPop(scope);

View File

@ -1,5 +1,5 @@
C Simplify\sthe\ssignature\sfor\sJS\sfunctions,\sas\sopposed\sto\sfunction\spointers,\spassed\sto\ssqlite3_exec(),\seliminating\sthe\ssuperfluous\sinitial\stwo\sarguments.\sUpdate\srelated\stests\sto\sdemonstrate\sboth\sfunction-passing\sapproaches. C Enhance\ssqlite3.wasm.xWrap.FuncPtrAdapter\sto\sbe\sable\sto\shandle\ssqlite3_create_function()\sand\sfriends\sand\sreimplement\sthose\sbindings\sto\suse\sthis\sfeature\s(this\swill\salso\ssimplify\scertain\ssession\sAPI\sbindings).\sInteral\sAPI\schanges\sonly\swith\sno\sclient-side\sbreakage.
D 2022-12-25T10:22:27.506 D 2022-12-25T12:51:53.541
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,7 +503,7 @@ 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 72f1ed1d60db62e18cf752c5871bc7c21cfef9258d9c81e61c830914c3f7da91 F ext/wasm/api/sqlite3-api-glue.js 4114cbd92818eda90bffb9cf3f181a4c1eb50521c95a3ea6d4e0bbc552901ffb
F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b
F ext/wasm/api/sqlite3-api-prologue.js a27762fd1ed2576897026f28a748a69edcdcc53ef79f46cead5e4446dc949763 F ext/wasm/api/sqlite3-api-prologue.js a27762fd1ed2576897026f28a748a69edcdcc53ef79f46cead5e4446dc949763
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
@ -521,7 +521,7 @@ F ext/wasm/c-pp.c 92285f7bce67ed7b7020b40fde8ed0982c442b63dc33df9dfd4b658d4a6c07
F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
F ext/wasm/common/whwasmutil.js 700fb1b702986522d2177fe8247bfbab3040e82cb4f6c35e929c4c85fbd7ffc5 F ext/wasm/common/whwasmutil.js 46e1ae432eda14ade6c84318c257917dd86755cb0bfa329d989522e057adff6e
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
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6 F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.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 ffe2999a91a7dec129a38afb675fe9e539d7c347886bfea85cba55f6367d54d1 P e7cc70cdda426863f82ebe1305f4c3053824c5a605b1516b0b7f205f1203178b
R 57b44198d665feb79b35a3b3cc62df00 R 942325294903c7f082d03ed59c06bba6
U stephan U stephan
Z fa52e396693ed4ebb322eeecdf80849b Z 9f06406b1eaa13fb27bb0e5cf658bbb6
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
e7cc70cdda426863f82ebe1305f4c3053824c5a605b1516b0b7f205f1203178b 7f9ace1b11a6703031790af9cf08ab25df25850a86e6ca2a7aeaefd8aa395e6d