mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Expose the auto-extension API to JS and reorganize some nearby code.
FossilOrigin-Name: 52b229d11d82bfb81c8b63e252c51c57a34dc50498dd685451588c185873c628
This commit is contained in:
@ -69,6 +69,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
wasm.bindingSignatures = [
|
||||
// Please keep these sorted by function name!
|
||||
["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
|
||||
/* sqlite3_auto_extension() has a hand-written binding. */
|
||||
/* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written
|
||||
bindings to permit more flexible inputs. */
|
||||
["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
|
||||
@ -87,8 +88,9 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
"*"
|
||||
]],
|
||||
["sqlite3_busy_timeout","int", "sqlite3*", "int"],
|
||||
/*[sqlite3_close_v2() is implemented by hand to perform some
|
||||
extra work. "sqlite3_close_v2", "int", "sqlite3*"],*/
|
||||
/* sqlite3_cancel_auto_extension() has a hand-written binding. */
|
||||
/* sqlite3_close_v2() is implemented by hand to perform some
|
||||
extra work. */
|
||||
["sqlite3_changes", "int", "sqlite3*"],
|
||||
["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
|
||||
["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
|
||||
@ -190,6 +192,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
]],
|
||||
["sqlite3_realloc", "*","*","int"],
|
||||
["sqlite3_reset", "int", "sqlite3_stmt*"],
|
||||
/* sqlite3_reset_auto_extension() has a hand-written binding. */
|
||||
["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
|
||||
["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
|
||||
["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
|
||||
@ -543,8 +546,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
});
|
||||
delete self.Jaccwabyt;
|
||||
|
||||
{/* Convert Arrays and certain TypedArrays to strings for
|
||||
'string:flexible'-type arguments */
|
||||
{// wasm.xWrap() bindings...
|
||||
|
||||
/* Convert Arrays and certain TypedArrays to strings for
|
||||
'string:flexible'-type arguments */
|
||||
const __xString = wasm.xWrap.argAdapter('string');
|
||||
wasm.xWrap.argAdapter(
|
||||
'string:flexible', (v)=>__xString(util.flexibleString(v))
|
||||
@ -580,9 +585,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
return rc || (this[v] = wasm.allocCString(v));
|
||||
}.bind(Object.create(null))
|
||||
);
|
||||
}/* special-case string-type argument conversions */
|
||||
|
||||
if(1){// wasm.xWrap() bindings...
|
||||
/**
|
||||
Add some descriptive xWrap() aliases for '*' intended to (A)
|
||||
initially improve readability/correctness of
|
||||
@ -590,27 +593,27 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
from higher-level representations, e.g. capi.sqlite3_vfs to
|
||||
`sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
|
||||
*/
|
||||
const aPtr = wasm.xWrap.argAdapter('*');
|
||||
const nilType = function(){};
|
||||
wasm.xWrap.argAdapter('sqlite3_filename', aPtr)
|
||||
('sqlite3_context*', aPtr)
|
||||
('sqlite3_value*', aPtr)
|
||||
('void*', aPtr)
|
||||
('sqlite3_changegroup*', aPtr)
|
||||
('sqlite3_changeset_iter*', aPtr)
|
||||
//('sqlite3_rebaser*', aPtr)
|
||||
('sqlite3_session*', aPtr)
|
||||
const __xArgPtr = wasm.xWrap.argAdapter('*');
|
||||
const nilType = function(){}/*a class no value can ever be an instance of*/;
|
||||
wasm.xWrap.argAdapter('sqlite3_filename', __xArgPtr)
|
||||
('sqlite3_context*', __xArgPtr)
|
||||
('sqlite3_value*', __xArgPtr)
|
||||
('void*', __xArgPtr)
|
||||
('sqlite3_changegroup*', __xArgPtr)
|
||||
('sqlite3_changeset_iter*', __xArgPtr)
|
||||
//('sqlite3_rebaser*', __xArgPtr)
|
||||
('sqlite3_session*', __xArgPtr)
|
||||
('sqlite3_stmt*', (v)=>
|
||||
aPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType))
|
||||
__xArgPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType))
|
||||
? v.pointer : v))
|
||||
('sqlite3*', (v)=>
|
||||
aPtr((v instanceof (sqlite3?.oo1?.DB || nilType))
|
||||
__xArgPtr((v instanceof (sqlite3?.oo1?.DB || nilType))
|
||||
? v.pointer : v))
|
||||
('sqlite3_index_info*', (v)=>
|
||||
aPtr((v instanceof (capi.sqlite3_index_info || nilType))
|
||||
__xArgPtr((v instanceof (capi.sqlite3_index_info || nilType))
|
||||
? v.pointer : v))
|
||||
('sqlite3_module*', (v)=>
|
||||
aPtr((v instanceof (capi.sqlite3_module || nilType))
|
||||
__xArgPtr((v instanceof (capi.sqlite3_module || nilType))
|
||||
? v.pointer : v))
|
||||
/**
|
||||
`sqlite3_vfs*`:
|
||||
@ -631,8 +634,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
"Unknown sqlite3_vfs name:", v
|
||||
);
|
||||
}
|
||||
return aPtr((v instanceof (capi.sqlite3_vfs || nilType))
|
||||
? v.pointer : v);
|
||||
return __xArgPtr((v instanceof (capi.sqlite3_vfs || nilType))
|
||||
? v.pointer : v);
|
||||
});
|
||||
|
||||
const __xRcPtr = wasm.xWrap.resultAdapter('*');
|
||||
@ -709,7 +712,83 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
return errCode;
|
||||
};
|
||||
}
|
||||
}/*xWrap() bindings*/;
|
||||
}/*xWrap() bindings*/
|
||||
|
||||
{/* Import C-level constants and structs... */
|
||||
const cJson = wasm.xCall('sqlite3_wasm_enum_json');
|
||||
if(!cJson){
|
||||
toss("Maintenance required: increase sqlite3_wasm_enum_json()'s",
|
||||
"static buffer size!");
|
||||
}
|
||||
//console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
|
||||
wasm.ctype = JSON.parse(wasm.cstrToJs(cJson));
|
||||
// Groups of SQLITE_xyz macros...
|
||||
const defineGroups = ['access', 'authorizer',
|
||||
'blobFinalizers', 'changeset',
|
||||
'config', 'dataTypes',
|
||||
'dbConfig', 'dbStatus',
|
||||
'encodings', 'fcntl', 'flock', 'ioCap',
|
||||
'limits', 'openFlags',
|
||||
'prepareFlags', 'resultCodes',
|
||||
'sqlite3Status',
|
||||
'stmtStatus', 'syncFlags',
|
||||
'trace', 'txnState', 'udfFlags',
|
||||
'version' ];
|
||||
if(wasm.bigIntEnabled){
|
||||
defineGroups.push('serialize', 'session', 'vtab');
|
||||
}
|
||||
for(const t of defineGroups){
|
||||
for(const e of Object.entries(wasm.ctype[t])){
|
||||
// ^^^ [k,v] there triggers a buggy code transformation via
|
||||
// one of the Emscripten-driven optimizers.
|
||||
capi[e[0]] = e[1];
|
||||
}
|
||||
}
|
||||
const __rcMap = Object.create(null);
|
||||
for(const t of ['resultCodes']){
|
||||
for(const e of Object.entries(wasm.ctype[t])){
|
||||
__rcMap[e[1]] = e[0];
|
||||
}
|
||||
}
|
||||
/**
|
||||
For the given integer, returns the SQLITE_xxx result code as a
|
||||
string, or undefined if no such mapping is found.
|
||||
*/
|
||||
capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc];
|
||||
/* Bind all registered C-side structs... */
|
||||
const notThese = Object.assign(Object.create(null),{
|
||||
// For each struct to NOT register, map its name to true:
|
||||
WasmTestStruct: true,
|
||||
/* We unregister the kvvfs VFS from Worker threads below. */
|
||||
sqlite3_kvvfs_methods: !util.isUIThread(),
|
||||
/* sqlite3_index_info and friends require int64: */
|
||||
sqlite3_index_info: !wasm.bigIntEnabled,
|
||||
sqlite3_index_constraint: !wasm.bigIntEnabled,
|
||||
sqlite3_index_orderby: !wasm.bigIntEnabled,
|
||||
sqlite3_index_constraint_usage: !wasm.bigIntEnabled
|
||||
});
|
||||
for(const s of wasm.ctype.structs){
|
||||
if(!notThese[s.name]){
|
||||
capi[s.name] = sqlite3.StructBinder(s);
|
||||
}
|
||||
}
|
||||
if(capi.sqlite3_index_info){
|
||||
/* Move these inner structs into sqlite3_index_info. Binding
|
||||
** them to WASM requires that we create global-scope structs to
|
||||
** model them with, but those are no longer needed after we've
|
||||
** passed them to StructBinder. */
|
||||
for(const k of ['sqlite3_index_constraint',
|
||||
'sqlite3_index_orderby',
|
||||
'sqlite3_index_constraint_usage']){
|
||||
capi.sqlite3_index_info[k] = capi[k];
|
||||
delete capi[k];
|
||||
}
|
||||
capi.sqlite3_vtab_config = wasm.xWrap(
|
||||
'sqlite3_wasm_vtab_config','int',[
|
||||
'sqlite3*', 'int', 'int']
|
||||
);
|
||||
}/* end vtab-related setup */
|
||||
}/*end C constant and struct imports*/
|
||||
|
||||
/**
|
||||
Internal helper to assist in validating call argument counts in
|
||||
@ -803,7 +882,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
*/
|
||||
__dbCleanupMap.cleanup = function(pDb){
|
||||
pDb = __argPDb(pDb);
|
||||
wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
|
||||
wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
|
||||
/**
|
||||
Installing NULL functions in the C API will remove those
|
||||
bindings. The FuncPtrAdapter which sits between us and the C
|
||||
@ -1140,8 +1219,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
}/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/;
|
||||
|
||||
if(1){/* Special-case handling of sqlite3_prepare_v2() and
|
||||
sqlite3_prepare_v3() */
|
||||
{/* Special-case handling of sqlite3_prepare_v2() and
|
||||
sqlite3_prepare_v3() */
|
||||
|
||||
/**
|
||||
Helper for string:flexible conversions which require a
|
||||
@ -1346,81 +1425,41 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
};
|
||||
}/* sqlite3_config() */
|
||||
|
||||
{/* Import C-level constants and structs... */
|
||||
const cJson = wasm.xCall('sqlite3_wasm_enum_json');
|
||||
if(!cJson){
|
||||
toss("Maintenance required: increase sqlite3_wasm_enum_json()'s",
|
||||
"static buffer size!");
|
||||
}
|
||||
//console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
|
||||
wasm.ctype = JSON.parse(wasm.cstrToJs(cJson));
|
||||
// Groups of SQLITE_xyz macros...
|
||||
const defineGroups = ['access', 'authorizer',
|
||||
'blobFinalizers', 'changeset',
|
||||
'config', 'dataTypes',
|
||||
'dbConfig', 'dbStatus',
|
||||
'encodings', 'fcntl', 'flock', 'ioCap',
|
||||
'limits', 'openFlags',
|
||||
'prepareFlags', 'resultCodes',
|
||||
'sqlite3Status',
|
||||
'stmtStatus', 'syncFlags',
|
||||
'trace', 'txnState', 'udfFlags',
|
||||
'version' ];
|
||||
if(wasm.bigIntEnabled){
|
||||
defineGroups.push('serialize', 'session', 'vtab');
|
||||
}
|
||||
for(const t of defineGroups){
|
||||
for(const e of Object.entries(wasm.ctype[t])){
|
||||
// ^^^ [k,v] there triggers a buggy code transformation via
|
||||
// one of the Emscripten-driven optimizers.
|
||||
capi[e[0]] = e[1];
|
||||
{/*auto-extension bindings.*/
|
||||
const __autoExtFptr = new Set;
|
||||
|
||||
capi.sqlite3_auto_extension = function(fPtr){
|
||||
if( fPtr instanceof Function ){
|
||||
fPtr = wasm.installFunction('i(ppp)', fPtr);
|
||||
}else if( 1!==arguments.length || !wasm.isPtr(fPtr) ){
|
||||
return capi.SQLITE_MISUSE;
|
||||
}
|
||||
}
|
||||
const __rcMap = Object.create(null);
|
||||
for(const t of ['resultCodes']){
|
||||
for(const e of Object.entries(wasm.ctype[t])){
|
||||
__rcMap[e[1]] = e[0];
|
||||
const rc = wasm.exports.sqlite3_auto_extension(fPtr);
|
||||
if( fPtr!==arguments[0] ){
|
||||
if(0===rc) __autoExtFptr.add(fPtr);
|
||||
else wasm.uninstallFunction(fPtr);
|
||||
}
|
||||
}
|
||||
/**
|
||||
For the given integer, returns the SQLITE_xxx result code as a
|
||||
string, or undefined if no such mapping is found.
|
||||
*/
|
||||
capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc];
|
||||
/* Bind all registered C-side structs... */
|
||||
const notThese = Object.assign(Object.create(null),{
|
||||
// For each struct to NOT register, map its name to true:
|
||||
WasmTestStruct: true,
|
||||
/* We unregister the kvvfs VFS from Worker threads below. */
|
||||
sqlite3_kvvfs_methods: !util.isUIThread(),
|
||||
/* sqlite3_index_info and friends require int64: */
|
||||
sqlite3_index_info: !wasm.bigIntEnabled,
|
||||
sqlite3_index_constraint: !wasm.bigIntEnabled,
|
||||
sqlite3_index_orderby: !wasm.bigIntEnabled,
|
||||
sqlite3_index_constraint_usage: !wasm.bigIntEnabled
|
||||
});
|
||||
for(const s of wasm.ctype.structs){
|
||||
if(!notThese[s.name]){
|
||||
capi[s.name] = sqlite3.StructBinder(s);
|
||||
}
|
||||
}
|
||||
if(capi.sqlite3_index_info){
|
||||
/* Move these inner structs into sqlite3_index_info. Binding
|
||||
** them to WASM requires that we create global-scope structs to
|
||||
** model them with, but those are no longer needed after we've
|
||||
** passed them to StructBinder. */
|
||||
for(const k of ['sqlite3_index_constraint',
|
||||
'sqlite3_index_orderby',
|
||||
'sqlite3_index_constraint_usage']){
|
||||
capi.sqlite3_index_info[k] = capi[k];
|
||||
delete capi[k];
|
||||
}
|
||||
capi.sqlite3_vtab_config = wasm.xWrap(
|
||||
'sqlite3_wasm_vtab_config','int',[
|
||||
'sqlite3*', 'int', 'int']
|
||||
);
|
||||
}/* end vtab-related setup */
|
||||
}/*end C constant and struct imports*/
|
||||
return rc;
|
||||
};
|
||||
|
||||
capi.sqlite3_cancel_auto_extension = function(fPtr){
|
||||
/* We do not do an automatic JS-to-WASM function conversion here
|
||||
because it would be senseless: the converted pointer would
|
||||
never possibly match an already-installed one. */;
|
||||
if(!fPtr || 1!==arguments.length || !wasm.isPtr(fPtr)) return 0;
|
||||
return wasm.exports.sqlite3_cancel_auto_extension(fPtr);
|
||||
/* Note that it "cannot happen" that a client passes a pointer which
|
||||
is in __autoExtFptr because __autoExtFptr only contains automatic
|
||||
conversions created inside sqlite3_auto_extension() and
|
||||
never exposed to the client. */
|
||||
};
|
||||
|
||||
capi.sqlite3_reset_auto_extension = function(){
|
||||
wasm.exports.sqlite3_reset_auto_extension();
|
||||
for(const fp of __autoExtFptr) wasm.uninstallFunction(fp);
|
||||
__autoExtFptr.clear();
|
||||
};
|
||||
}/* auto-extension */
|
||||
|
||||
const pKvvfs = capi.sqlite3_vfs_find("kvvfs");
|
||||
if( pKvvfs ){/* kvvfs-specific glue */
|
||||
|
Reference in New Issue
Block a user