aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2022-12-15 02:28:55 +0000
committerstephan <stephan@noemail.net>2022-12-15 02:28:55 +0000
commit73b471964b872eaa99a4f3d7243fbfa9497fbe0c (patch)
tree3f5b4368cd29e651abf71bce68764488fa2c9b39
parentd60061616fbec1deb0c0d22f31ef016a9a76a450 (diff)
downloadsqlite-73b471964b872eaa99a4f3d7243fbfa9497fbe0c.tar.gz
sqlite-73b471964b872eaa99a4f3d7243fbfa9497fbe0c.zip
Internal refactoring of how sqlite3.wasm.xWrap() handles JS-to-C function pointer conversions, to enable similar conversions to be added more easily.
FossilOrigin-Name: 10cfe3fae6f680d3ecc3b0afbbf628ce91e34e3757b19dd27c231f0daf44232a
-rw-r--r--ext/wasm/api/sqlite3-api-glue.js8
-rw-r--r--ext/wasm/common/whwasmutil.js152
-rw-r--r--manifest14
-rw-r--r--manifest.uuid2
4 files changed, 100 insertions, 76 deletions
diff --git a/ext/wasm/api/sqlite3-api-glue.js b/ext/wasm/api/sqlite3-api-glue.js
index 972b4a2e0..5488f26c9 100644
--- a/ext/wasm/api/sqlite3-api-glue.js
+++ b/ext/wasm/api/sqlite3-api-glue.js
@@ -138,7 +138,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
the range of supported argument types. */
[
"sqlite3_progress_handler", undefined, [
- "sqlite3*", "int", wasm.xWrap.FuncPtrAdapter({
+ "sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
name: 'xProgressHandler',
signature: 'i(p)',
bindScope: 'context',
@@ -180,7 +180,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
"**", "**", "*", "*", "*"],
["sqlite3_total_changes", "int", "sqlite3*"],
["sqlite3_trace_v2", "int", "sqlite3*", "int",
- wasm.xWrap.FuncPtrAdapter({
+ new wasm.xWrap.FuncPtrAdapter({
name: 'sqlite3_trace_v2::callback',
signature: 'i(ippp)',
contextKey: (argIndex, argv)=>'sqlite3@'+argv[0]
@@ -469,14 +469,14 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
'sqlite3*','string','int','*',
new wasm.xWrap.FuncPtrAdapter({
/* int(*xCompare)(void*,int,const void*,int,const void*) */
- name: 'xCompare',
+ name: 'sqlite3_create_collation_v2::xCompare',
signature: 'i(pipip)',
bindScope: 'context',
contextKey: __collationContextKey
}),
new wasm.xWrap.FuncPtrAdapter({
/* void(*xDestroy(void*) */
- name: 'xDestroy',
+ name: 'sqlite3_create_collation_v2::xDestroy',
signature: 'v(p)',
bindScope: 'context',
contextKey: __collationContextKey
diff --git a/ext/wasm/common/whwasmutil.js b/ext/wasm/common/whwasmutil.js
index a662d5a1e..82d10dff1 100644
--- a/ext/wasm/common/whwasmutil.js
+++ b/ext/wasm/common/whwasmutil.js
@@ -1473,8 +1473,40 @@ self.WhWasmUtilInstaller = function(target){
}
/**
- EXPERIMENTAL! DO NOT USE IN CLIENT CODE!
+ Internal-use-only base class for FuncPtrAdapter and potentially
+ additional stateful argument adapter classes.
+
+ Note that its main interface (convertArg()) is strictly
+ internal, not to be exposed to client code, as it may still
+ need re-shaping. Only the constructors of concrete subclasses
+ should be exposed to clients, and those in such a way that
+ does not hinder internal redesign of the convertArg()
+ interface.
+ */
+ const AbstractArgAdapter = class {
+ constructor(opt){
+ this.name = opt.name;
+ }
+ /**
+ Gets called via xWrap() to "convert" v to whatever type
+ this specific class supports.
+ argIndex is the argv index of _this_ argument in the
+ being-xWrap()'d call. argv is the current argument list
+ undergoing xWrap() argument conversion. argv entries to the
+ left of argIndex will have already undergone transformation and
+ those to the right will not have (they will have the values the
+ client-level code passed in, awaiting conversion). The RHS
+ indexes must never be relied upon for anything because their
+ types are indeterminate, whereas the LHS values will be
+ WASM-compatible values by the time this is called.
+ */
+ convertArg(v,argIndex,argv){
+ toss("AbstractArgAdapter must be subclassed.");
+ }
+ };
+
+ /**
An attempt at adding function pointer conversion support to
xWrap(). This type is recognized by xWrap() as a proxy for
converting a JS function to a C-side function, either
@@ -1482,7 +1514,7 @@ self.WhWasmUtilInstaller = function(target){
or semi-contextual, where it may keep track of a single binding
for a given context and uninstall the binding if it's replaced.
- Requires an options object with these properties:
+ The constructor requires an options object with these properties:
- name (optional): string describing the function binding. This
is solely for debugging and error-reporting purposes. If not
@@ -1514,17 +1546,18 @@ self.WhWasmUtilInstaller = function(target){
context. This mode is the default if bindScope is _not_ set
but a property named contextKey (described below) is.
- - contextKey (function): is only used if bindScope is not set or
- is 'context'. This function gets passed (argIndex,argv), where
- argIndex is the index of _this_ function pointer in its
- _wrapping_ function's arguments and argv is the _current_
- still-being-xWrap()-processed args array. All arguments to the
- left of argIndex will have been processed by xWrap() by the
- time this is called. argv[argIndex] will be the value the user
- passed in to the xWrap()'d function for the argument this
- FuncPtrAdapter is mapped to. Arguments to the right of
- argv[argIndex] will not yet have been converted before this is
- called. The function must return a key which uniquely
+ - contextKey (function): is only used if bindScope is 'context'
+ or if bindScope is not set and this function is, in which case
+ 'context' is assumed. This function gets passed
+ (argIndex,argv), where argIndex is the index of _this_ function
+ pointer in its _wrapping_ function's arguments and argv is the
+ _current_ still-being-xWrap()-processed args array. All
+ arguments to the left of argIndex will have been processed by
+ xWrap() by the time this is called. argv[argIndex] will be the
+ value the user passed in to the xWrap()'d function for the
+ argument this FuncPtrAdapter is mapped to. Arguments to the
+ right of 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_
FuncPtrAdapter instance (other instances are not considered),
taking into account that C functions often take some sort of
@@ -1547,74 +1580,65 @@ self.WhWasmUtilInstaller = function(target){
The constructor only saves the above state for later, and does
not actually bind any functions. Its convertArg() method is
called via xWrap() to perform any bindings.
-
- If this is called like a function, instead of a constructor,
- it behaves as if it were called like a constructor.
*/
- xArg.FuncPtrAdapter = function ctor(opt) {
- if(!(this instanceof xArg.FuncPtrAdapter)){
- return new xArg.FuncPtrAdapter(opt);
- }
- this.signature = opt.signature;
- if(!opt.bindScope && (opt.contextKey instanceof Function)){
- opt.bindScope = 'context';
- }else if(ctor.bindScopes.indexOf(opt.bindScope)<0){
- toss("Invalid options.bindScope ("+opt.bindMod+") for FuncPtrAdapter. "+
- "Expecting one of: ("+ctor.bindScopes.join(', ')+')');
+ xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter {
+ constructor(opt) {
+ super(opt);
+ this.signature = opt.signature;
+ if(!opt.bindScope && (opt.contextKey instanceof Function)){
+ opt.bindScope = 'context';
+ }else if(FuncPtrAdapter.bindScopes.indexOf(opt.bindScope)<0){
+ toss("Invalid options.bindScope ("+opt.bindMod+") for FuncPtrAdapter. "+
+ "Expecting one of: ("+FuncPtrAdapter.bindScopes.join(', ')+')');
+ }
+ this.bindScope = opt.bindScope;
+ if(opt.contextKey) this.contextKey = opt.contextKey /*else inherit one*/;
+ this.isTransient = 'transient'===this.bindScope;
+ this.isContext = 'context'===this.bindScope;
+ if( ('singleton'===this.bindScope) ) this.singleton = [];
+ else this.singleton = undefined;
+ //console.warn("FuncPtrAdapter()",opt,this);
}
- this.bindScope = opt.bindScope;
- this.name = opt.name || '';
- if(opt.contextKey) this.contextKey = opt.contextKey /*else inherit one*/;
- this.isTransient = 'transient'===this.bindScope;
- this.isContext = 'context'===this.bindScope;
- if( ('singleton'===this.bindScope) ) this.singleton = [];
- else this.singleton = undefined;
- //console.warn("FuncPtrAdapter()",opt,this);
- };
- xArg.FuncPtrAdapter.bindScopes = [
- 'transient', 'context', 'singleton'
- ];
- xArg.FuncPtrAdapter.prototype = {
+
+ static bindScopes = [
+ 'transient', 'context', 'singleton'
+ ];
+
/* Dummy impl. Overwritten per-instance as needed. */
- contextKey: function(argIndex,argv){
+ contextKey(argIndex,argv){
return this;
- },
+ }
+
/* Returns this objects mapping for the given context key, in the
form of an an array, creating the mapping if needed. The key
may be anything suitable for use in a Map. */
- contextMap: function(key){
+ contextMap(key){
const cm = (this.__cmap || (this.__cmap = new Map));
let rc = cm.get(key);
if(undefined===rc) cm.set(key, (rc = []));
return rc;
- },
+ }
+
/**
Gets called via xWrap() to "convert" v to a WASM-bound function
pointer. If v is one of (a pointer, null, undefined) then
(v||0) is returned and any earlier function installed by this
- mapping _might_, depending on how it's bound, be
- uninstalled. If v is not one of those types, it must be a
- Function, for which it creates (if needed) a WASM function
- binding and returns the WASM pointer to that binding. If this
- instance is not in 'transient' mode, it will remember the
- binding for at least the next call, to avoid recreating the
- function binding unnecessarily.
+ mapping _might_, depending on how it's bound, be uninstalled.
+ If v is not one of those types, it must be a Function, for
+ which it creates (if needed) a WASM function binding and
+ returns the WASM pointer to that binding. If this instance is
+ 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_
perform any function binding, so this object's bindMode is
irrelevant for such cases.
- argIndex is the argv index of _this_ argument in the
- being-xWrap()'d call. argv is the current argument list
- undergoing xWrap() argument conversion. argv entries to the
- left of argIndex will have already undergone transformation and
- those to the right will not have (they will have the values the
- client-level code passed in, awaiting conversion). The RHS
- indexes must never be relied upon for anything because their
- types are indeterminate, whereas the LHS values will be
- WASM-compatible values by the time this is called.
+ See the parent class's convertArg() docs for details on what
+ exactly the 2nd and 3rd arguments are.
*/
- convertArg: function(v,argIndex,argv){
+ convertArg(v,argIndex,argv){
//console.warn("FuncPtrAdapter.convertArg()",this.signature,this.transient,v);
let pair = this.singleton;
if(!pair && this.isContext){
@@ -1650,7 +1674,7 @@ self.WhWasmUtilInstaller = function(target){
this.signature+".");
}
}/*convertArg()*/
- }/*FuncPtrAdapter.prototype*/;
+ }/*FuncPtrAdapter*/;
const __xArgAdapterCheck =
(t)=>xArg.get(t) || toss("Argument adapter not found:",t);
@@ -1823,7 +1847,7 @@ self.WhWasmUtilInstaller = function(target){
/*Verify the arg type conversions are valid...*/;
if(undefined!==resultType && null!==resultType) __xResultAdapterCheck(resultType);
for(const t of argTypes){
- if(t instanceof xArg.FuncPtrAdapter) xArg.set(t, (...args)=>t.convertArg(...args));
+ if(t instanceof AbstractArgAdapter) xArg.set(t, (...args)=>t.convertArg(...args));
else __xArgAdapterCheck(t);
}
const cxw = cache.xWrap;
@@ -1842,9 +1866,9 @@ self.WhWasmUtilInstaller = function(target){
The public interface of argument adapters is that they take
ONE argument and return a (possibly) converted result for
it. The passing-on of arguments after the first is an
- internal impl. detail for the sake of FuncPtrAdapter, and
+ internal impl. detail for the sake of AbstractArgAdapter, and
not to be relied on or documented for other cases. The fact
- that this is how FuncPtrAdapter.convertArgs() gets its 2nd+
+ that this is how AbstractArgAdapter.convertArgs() gets its 2nd+
arguments, and how FuncPtrAdapter.contextKey() gets its
args, is also an implementation detail and subject to
change. i.e. the public interface of 1 argument is stable.
diff --git a/manifest b/manifest
index f082e7072..be0d20aa9 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\san\sunnecessary/obsolete\sEmscripten-specific\sexport.
-D 2022-12-15T02:26:13.244
+C Internal\srefactoring\sof\show\ssqlite3.wasm.xWrap()\shandles\sJS-to-C\sfunction\spointer\sconversions,\sto\senable\ssimilar\sconversions\sto\sbe\sadded\smore\seasily.
+D 2022-12-15T02:28:55.691
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
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/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
-F ext/wasm/api/sqlite3-api-glue.js a8010bf3fa184886d1e9e76b0d0d1e290b5fa25130510644a59e91a18f779ef4
+F ext/wasm/api/sqlite3-api-glue.js 2e1087b870290a3a613d59ed626bde1f6da7c9c211cd36e41df1ee8b2932b508
F ext/wasm/api/sqlite3-api-oo1.js c0c4ccc269cccee657ffd03f094da7e270e1367b7928926b3730d543555a12a6
F ext/wasm/api/sqlite3-api-prologue.js 86eb4488f2be85e68c23ebcfad0834c24b6075e1645c67890cc4163c462efac1
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/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
-F ext/wasm/common/whwasmutil.js 8bec2460dfb515986faf854c011b7ae4f2cc1b2a128d9afa74ca57ee6057bdaa
+F ext/wasm/common/whwasmutil.js e8934d24518f99a8995e2da5a4f308d36c13bea90d36a0396585e2debba94d57
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
@@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c1d5261b222bbf94c20e558089f3d2eae6a88b6d739225ee4f7d0338e0e59994
-R 918e16f92d23cc300804b300dc026e25
+P fa278022afd6dd6e499d26f74a8359f3e9973e1680772059ce331b64e77ec582
+R e784d3c7094c47f7ba465262d6340c12
U stephan
-Z e5f6c496f6861a48778111a469988478
+Z 0c197c6d7ed7bd2414c2cff61c07cad7
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index a6b0edf39..8b8fca451 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-fa278022afd6dd6e499d26f74a8359f3e9973e1680772059ce331b64e77ec582 \ No newline at end of file
+10cfe3fae6f680d3ecc3b0afbbf628ce91e34e3757b19dd27c231f0daf44232a \ No newline at end of file