mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Move JS-to-C binding signatures from sqlite3-api-prologue.js to sqlite3-api-glue.js to allow for use of the new/experimental sqlite3.wasm.xWrap() feature which automatically binds JS functions to WASM/C as needed, which simplifies creation of bindings which take C function pointers. Reimplement sqlite3_exec(), sqlite3_create_collation(), sqlite3_progress_handler() to use this new feature.
FossilOrigin-Name: 9386d6f634680b4e0fa5487c34c63acb29f0b7a6ae738b8f6164ad084a229b62
This commit is contained in:
@ -24,6 +24,251 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
self.WhWasmUtilInstaller(wasm);
|
self.WhWasmUtilInstaller(wasm);
|
||||||
delete self.WhWasmUtilInstaller;
|
delete self.WhWasmUtilInstaller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Signatures for the WASM-exported C-side functions. Each entry
|
||||||
|
is an array with 2+ elements:
|
||||||
|
|
||||||
|
[ "c-side name",
|
||||||
|
"result type" (wasm.xWrap() syntax),
|
||||||
|
[arg types in xWrap() syntax]
|
||||||
|
// ^^^ this needn't strictly be an array: it can be subsequent
|
||||||
|
// elements instead: [x,y,z] is equivalent to x,y,z
|
||||||
|
]
|
||||||
|
|
||||||
|
Note that support for the API-specific data types in the
|
||||||
|
result/argument type strings gets plugged in at a later phase in
|
||||||
|
the API initialization process.
|
||||||
|
*/
|
||||||
|
wasm.bindingSignatures = [
|
||||||
|
// Please keep these sorted by function name!
|
||||||
|
["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
|
||||||
|
["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*"
|
||||||
|
/* TODO: we should arguably write a custom wrapper which knows
|
||||||
|
how to handle Blob, TypedArrays, and JS strings. */
|
||||||
|
],
|
||||||
|
["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
|
||||||
|
["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
|
||||||
|
["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
|
||||||
|
["sqlite3_bind_pointer", "int",
|
||||||
|
"sqlite3_stmt*", "int", "*", "string:static", "*"],
|
||||||
|
["sqlite3_bind_text","int", "sqlite3_stmt*", "int", "string", "int", "int"
|
||||||
|
/* We should arguably create a hand-written binding of
|
||||||
|
bind_text() which does more flexible text conversion, along
|
||||||
|
the lines of sqlite3_prepare_v3(). The slightly problematic
|
||||||
|
part is the final argument (text destructor). */
|
||||||
|
],
|
||||||
|
//["sqlite3_busy_handler","int", "sqlite3*", "*", "*"],
|
||||||
|
// ^^^^ TODO: custom binding which auto-converts JS function arg
|
||||||
|
// to a WASM function, noting that calling it multiple times
|
||||||
|
// would introduce a leak.
|
||||||
|
["sqlite3_busy_timeout","int", "sqlite3*", "int"],
|
||||||
|
["sqlite3_close_v2", "int", "sqlite3*"],
|
||||||
|
["sqlite3_changes", "int", "sqlite3*"],
|
||||||
|
["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
|
||||||
|
["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_column_count", "int", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
|
||||||
|
["sqlite3_compileoption_get", "string", "int"],
|
||||||
|
["sqlite3_compileoption_used", "int", "string"],
|
||||||
|
["sqlite3_complete", "int", "string:flexible"],
|
||||||
|
/* sqlite3_create_function(), sqlite3_create_function_v2(), and
|
||||||
|
sqlite3_create_window_function() use hand-written bindings to
|
||||||
|
simplify handling of their function-type arguments. */
|
||||||
|
/* sqlite3_create_collation() and sqlite3_create_collation_v2()
|
||||||
|
use hand-written bindings to simplify passing of the callback
|
||||||
|
function.
|
||||||
|
["sqlite3_create_collation", "int",
|
||||||
|
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
|
||||||
|
"*", "*"],
|
||||||
|
["sqlite3_create_collation_v2", "int",
|
||||||
|
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
|
||||||
|
"*", "*", "*"],
|
||||||
|
*/
|
||||||
|
["sqlite3_data_count", "int", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_db_filename", "string", "sqlite3*", "string"],
|
||||||
|
["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_db_name", "string", "sqlite3*", "int"],
|
||||||
|
["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"],
|
||||||
|
["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
|
||||||
|
/* Careful! Short version: de/serialize() are problematic because they
|
||||||
|
might use a different allocator than the user for managing the
|
||||||
|
deserialized block. de/serialize() are ONLY safe to use with
|
||||||
|
sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. */,
|
||||||
|
["sqlite3_errcode", "int", "sqlite3*"],
|
||||||
|
["sqlite3_errmsg", "string", "sqlite3*"],
|
||||||
|
["sqlite3_error_offset", "int", "sqlite3*"],
|
||||||
|
["sqlite3_errstr", "string", "int"],
|
||||||
|
/*["sqlite3_exec", "int", "sqlite3*", "string", "*", "*", "**"
|
||||||
|
Handled seperately to perform translation of the callback
|
||||||
|
into a WASM-usable one. ],*/
|
||||||
|
["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_extended_errcode", "int", "sqlite3*"],
|
||||||
|
["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
|
||||||
|
["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
|
||||||
|
["sqlite3_finalize", "int", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_free", undefined,"*"],
|
||||||
|
["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
|
||||||
|
["sqlite3_initialize", undefined],
|
||||||
|
/*["sqlite3_interrupt", undefined, "sqlite3*"
|
||||||
|
^^^ we cannot actually currently support this because JS is
|
||||||
|
single-threaded and we don't have a portable way to access a DB
|
||||||
|
from 2 SharedWorkers concurrently. ],*/
|
||||||
|
["sqlite3_keyword_count", "int"],
|
||||||
|
["sqlite3_keyword_name", "int", ["int", "**", "*"]],
|
||||||
|
["sqlite3_keyword_check", "int", ["string", "int"]],
|
||||||
|
["sqlite3_libversion", "string"],
|
||||||
|
["sqlite3_libversion_number", "int"],
|
||||||
|
["sqlite3_limit", "int", ["sqlite3*", "int", "int"]],
|
||||||
|
["sqlite3_malloc", "*","int"],
|
||||||
|
["sqlite3_open", "int", "string", "*"],
|
||||||
|
["sqlite3_open_v2", "int", "string", "*", "int", "string"],
|
||||||
|
/* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
|
||||||
|
separately due to us requiring two different sets of semantics
|
||||||
|
for those, depending on how their SQL argument is provided. */
|
||||||
|
/* sqlite3_randomness() uses a hand-written wrapper to extend
|
||||||
|
the range of supported argument types. */
|
||||||
|
[
|
||||||
|
"sqlite3_progress_handler", undefined, [
|
||||||
|
"sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({
|
||||||
|
name: 'xProgressHandler',
|
||||||
|
signature: 'i(p)',
|
||||||
|
bindMode: 'singleton'
|
||||||
|
}), "*"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
["sqlite3_realloc", "*","*","int"],
|
||||||
|
["sqlite3_reset", "int", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
|
||||||
|
["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
|
||||||
|
["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
|
||||||
|
["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"],
|
||||||
|
["sqlite3_result_error_nomem", undefined, "sqlite3_context*"],
|
||||||
|
["sqlite3_result_error_toobig", undefined, "sqlite3_context*"],
|
||||||
|
["sqlite3_result_int", undefined, "sqlite3_context*", "int"],
|
||||||
|
["sqlite3_result_null", undefined, "sqlite3_context*"],
|
||||||
|
["sqlite3_result_pointer", undefined,
|
||||||
|
"sqlite3_context*", "*", "string:static", "*"],
|
||||||
|
["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
|
||||||
|
["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
|
||||||
|
["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
|
||||||
|
["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
|
||||||
|
["sqlite3_set_auxdata", undefined, "sqlite3_context*", "int", "*", "*"/* => v(*) */],
|
||||||
|
["sqlite3_shutdown", undefined],
|
||||||
|
["sqlite3_sourceid", "string"],
|
||||||
|
["sqlite3_sql", "string", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_status", "int", "int", "*", "*", "int"],
|
||||||
|
["sqlite3_step", "int", "sqlite3_stmt*"],
|
||||||
|
["sqlite3_stmt_isexplain", "int", ["sqlite3_stmt*"]],
|
||||||
|
["sqlite3_stmt_readonly", "int", ["sqlite3_stmt*"]],
|
||||||
|
["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"],
|
||||||
|
["sqlite3_strglob", "int", "string","string"],
|
||||||
|
["sqlite3_stricmp", "int", "string", "string"],
|
||||||
|
["sqlite3_strlike", "int", "string", "string","int"],
|
||||||
|
["sqlite3_strnicmp", "int", "string", "string", "int"],
|
||||||
|
["sqlite3_table_column_metadata", "int",
|
||||||
|
"sqlite3*", "string", "string", "string",
|
||||||
|
"**", "**", "*", "*", "*"],
|
||||||
|
["sqlite3_total_changes", "int", "sqlite3*"],
|
||||||
|
["sqlite3_trace_v2", "int", "sqlite3*", "int", "*", "*"],
|
||||||
|
["sqlite3_txn_state", "int", ["sqlite3*","string"]],
|
||||||
|
/* Note that sqlite3_uri_...() have very specific requirements for
|
||||||
|
their first C-string arguments, so we cannot perform any value
|
||||||
|
conversion on those. */
|
||||||
|
["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
|
||||||
|
["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
|
||||||
|
["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
|
||||||
|
["sqlite3_user_data","void*", "sqlite3_context*"],
|
||||||
|
["sqlite3_value_blob", "*", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_bytes","int", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_double","f64", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_free", undefined, "sqlite3_value*"],
|
||||||
|
["sqlite3_value_frombind", "int", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_int","int", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_nochange", "int", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
|
||||||
|
["sqlite3_value_subtype", "int", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_text", "string", "sqlite3_value*"],
|
||||||
|
["sqlite3_value_type", "int", "sqlite3_value*"],
|
||||||
|
["sqlite3_vfs_find", "*", "string"],
|
||||||
|
["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
|
||||||
|
["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
|
||||||
|
]/*wasm.bindingSignatures*/;
|
||||||
|
|
||||||
|
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
|
||||||
|
/* ^^^ "the problem" is that this is an option feature and the
|
||||||
|
build-time function-export list does not currently take
|
||||||
|
optional features into account. */
|
||||||
|
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Functions which require BigInt (int64) support are separated from
|
||||||
|
the others because we need to conditionally bind them or apply
|
||||||
|
dummy impls, depending on the capabilities of the environment.
|
||||||
|
|
||||||
|
Note that not all of these functions directly require int64
|
||||||
|
but are only for use with APIs which require int64. For example,
|
||||||
|
the vtab-related functions.
|
||||||
|
*/
|
||||||
|
wasm.bindingSignatures.int64 = [
|
||||||
|
["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
|
||||||
|
["sqlite3_changes64","i64", ["sqlite3*"]],
|
||||||
|
["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
|
||||||
|
["sqlite3_create_module", "int",
|
||||||
|
["sqlite3*","string","sqlite3_module*","*"]],
|
||||||
|
["sqlite3_create_module_v2", "int",
|
||||||
|
["sqlite3*","string","sqlite3_module*","*","*"]],
|
||||||
|
["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
|
||||||
|
["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
|
||||||
|
["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
|
||||||
|
["sqlite3_malloc64", "*","i64"],
|
||||||
|
["sqlite3_msize", "i64", "*"],
|
||||||
|
["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
|
||||||
|
["sqlite3_realloc64", "*","*", "i64"],
|
||||||
|
["sqlite3_result_int64", undefined, "*", "i64"],
|
||||||
|
["sqlite3_result_zeroblob64", "int", "*", "i64"],
|
||||||
|
["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
|
||||||
|
["sqlite3_status64", "int", "int", "*", "*", "int"],
|
||||||
|
["sqlite3_total_changes64", "i64", ["sqlite3*"]],
|
||||||
|
["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
|
||||||
|
["sqlite3_value_int64","i64", "sqlite3_value*"],
|
||||||
|
["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
|
||||||
|
["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
|
||||||
|
["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
|
||||||
|
["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"],
|
||||||
|
["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"],
|
||||||
|
/*["sqlite3_vtab_config" is variadic and requires a hand-written
|
||||||
|
proxy.] */
|
||||||
|
["sqlite3_vtab_nochange","int", "sqlite3_context*"],
|
||||||
|
["sqlite3_vtab_on_conflict","int", "sqlite3*"],
|
||||||
|
["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
Functions which are intended solely for API-internal use by the
|
||||||
|
WASM components, not client code. These get installed into
|
||||||
|
sqlite3.wasm. Some of them get exposed to clients via variants
|
||||||
|
named sqlite3_js_...().
|
||||||
|
*/
|
||||||
|
wasm.bindingSignatures.wasm = [
|
||||||
|
["sqlite3_wasm_db_reset", "int", "sqlite3*"],
|
||||||
|
["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
|
||||||
|
["sqlite3_wasm_vfs_create_file", "int",
|
||||||
|
"sqlite3_vfs*","string","*", "int"],
|
||||||
|
["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install JS<->C struct bindings for the non-opaque struct types we
|
Install JS<->C struct bindings for the non-opaque struct types we
|
||||||
need... */
|
need... */
|
||||||
@ -166,7 +411,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
Sets the given db's error state. Accepts:
|
Sets the given db's error state. Accepts:
|
||||||
|
|
||||||
- (sqlite3*, int code, string msg)
|
- (sqlite3*, int code, string msg)
|
||||||
- (sqlite3*, Error [,string msg])
|
- (sqlite3*, Error e [,string msg = ''+e])
|
||||||
|
|
||||||
If passed a WasmAllocError, the message is ingored and the
|
If passed a WasmAllocError, the message is ingored and the
|
||||||
result code is SQLITE_NOMEM. If passed any other Error type,
|
result code is SQLITE_NOMEM. If passed any other Error type,
|
||||||
@ -183,7 +428,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
resultCode = capi.SQLITE_NOMEM;
|
resultCode = capi.SQLITE_NOMEM;
|
||||||
message = 0 /*avoid allocating message string*/;
|
message = 0 /*avoid allocating message string*/;
|
||||||
}else if(resultCode instanceof Error){
|
}else if(resultCode instanceof Error){
|
||||||
message = message || resultCode.message;
|
message = message || ''+resultCode;
|
||||||
resultCode = (resultCode.resultCode || capi.SQLITE_ERROR);
|
resultCode = (resultCode.resultCode || capi.SQLITE_ERROR);
|
||||||
}
|
}
|
||||||
return __db_err(pDb, resultCode, message);
|
return __db_err(pDb, resultCode, message);
|
||||||
@ -211,15 +456,29 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
|
|
||||||
const __ccv2 = wasm.xWrap(
|
const __ccv2 = wasm.xWrap(
|
||||||
'sqlite3_create_collation_v2', 'int',
|
'sqlite3_create_collation_v2', 'int',
|
||||||
'sqlite3*','string','int','*','*','*'
|
'sqlite3*','string','int','*',
|
||||||
/* int(*xCompare)(void*,int,const void*,int,const void*) */
|
new wasm.xWrap.FuncPtrAdapter({
|
||||||
/* void(*xDestroy(void*) */);
|
/* int(*xCompare)(void*,int,const void*,int,const void*) */
|
||||||
|
name: 'xCompare',
|
||||||
|
signature: 'i(pipip)',
|
||||||
|
bindMode: 'static'
|
||||||
|
}),
|
||||||
|
new wasm.xWrap.FuncPtrAdapter({
|
||||||
|
/* void(*xDestroy(void*) */
|
||||||
|
name: 'xDestroy',
|
||||||
|
signature: 'v(p)',
|
||||||
|
bindMode: 'static'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Works exactly like C's sqlite3_create_collation_v2() except that:
|
Works exactly like C's sqlite3_create_collation_v2() except that:
|
||||||
|
|
||||||
1) It permits its two function arguments to be JS functions,
|
1) It permits its two function arguments to be JS functions,
|
||||||
for which it will install WASM-bound proxies.
|
for which it will install WASM-bound proxies. The bindings
|
||||||
|
are "permanent," in that they will stay in the WASM environment
|
||||||
|
until it shuts down unless the client somehow finds and removes
|
||||||
|
them.
|
||||||
|
|
||||||
2) It returns capi.SQLITE_FORMAT if the 3rd argument is not
|
2) It returns capi.SQLITE_FORMAT if the 3rd argument is not
|
||||||
capi.SQLITE_UTF8. No other encodings are supported.
|
capi.SQLITE_UTF8. No other encodings are supported.
|
||||||
@ -235,19 +494,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding."
|
pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let rc, pfCompare, pfDestroy;
|
let rc;
|
||||||
try{
|
try{
|
||||||
if(xCompare instanceof Function){
|
rc = __ccv2(pDb, zName, eTextRep, pArg, xCompare, xDestroy);
|
||||||
pfCompare = wasm.installFunction(xCompare, 'i(pipip)');
|
|
||||||
}
|
|
||||||
if(xDestroy instanceof Function){
|
|
||||||
pfDestroy = wasm.installFunction(xDestroy, 'v(p)');
|
|
||||||
}
|
|
||||||
rc = __ccv2(pDb, zName, eTextRep, pArg,
|
|
||||||
pfCompare || xCompare, pfDestroy || xDestroy);
|
|
||||||
}catch(e){
|
}catch(e){
|
||||||
if(pfCompare) wasm.uninstallFunction(pfCompare);
|
|
||||||
if(pfDestroy) wasm.uninstallFunction(pfDestroy);
|
|
||||||
rc = util.sqlite3_wasm_db_error(pDb, e);
|
rc = util.sqlite3_wasm_db_error(pDb, e);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@ -259,17 +509,20 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
: __dbArgcMismatch(pDb, 'sqlite3_create_collation', 5);
|
: __dbArgcMismatch(pDb, 'sqlite3_create_collation', 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}/*sqlite3_create_collation() and friends*/
|
}/*sqlite3_create_collation() and friends*/
|
||||||
|
|
||||||
if(1){/* Special-case handling of sqlite3_exec() */
|
if(1){/* Special-case handling of sqlite3_exec() */
|
||||||
const __exec = wasm.xWrap("sqlite3_exec", "int",
|
const __exec = wasm.xWrap("sqlite3_exec", "int",
|
||||||
["sqlite3*", "string:flexible", "*", "*", "**"]);
|
["sqlite3*", "string:flexible",
|
||||||
|
new wasm.xWrap.FuncPtrAdapter({
|
||||||
|
signature: 'i(pipp)',
|
||||||
|
bindMode: 'transient'
|
||||||
|
}), "*", "**"]);
|
||||||
/* Documented in the api object's initializer. */
|
/* Documented in the api object's initializer. */
|
||||||
capi.sqlite3_exec = function f(pDb, sql, callback, pVoid, pErrMsg){
|
capi.sqlite3_exec = function f(pDb, sql, callback, pVoid, pErrMsg){
|
||||||
if(f.length!==arguments.length){
|
if(f.length!==arguments.length){
|
||||||
return __dbArgcMismatch(pDb,"sqlite3_exec",f.length);
|
return __dbArgcMismatch(pDb,"sqlite3_exec",f.length);
|
||||||
}else if('function' !== typeof callback){
|
}else if(!(callback instanceof Function)){
|
||||||
return __exec(pDb, sql, callback, pVoid, pErrMsg);
|
return __exec(pDb, sql, callback, pVoid, pErrMsg);
|
||||||
}
|
}
|
||||||
/* Wrap the callback in a WASM-bound function and convert the callback's
|
/* Wrap the callback in a WASM-bound function and convert the callback's
|
||||||
@ -294,15 +547,12 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
};
|
};
|
||||||
let pFunc, rc;
|
let rc;
|
||||||
try{
|
try{
|
||||||
pFunc = wasm.installFunction("ipipp", cbwrap);
|
rc = __exec(pDb, sql, cbwrap, pVoid, pErrMsg);
|
||||||
rc = __exec(pDb, sql, pFunc, pVoid, pErrMsg);
|
|
||||||
}catch(e){
|
}catch(e){
|
||||||
rc = util.sqlite3_wasm_db_error(pDb, capi.SQLITE_ERROR,
|
rc = util.sqlite3_wasm_db_error(pDb, capi.SQLITE_ERROR,
|
||||||
"Error running exec(): "+e.message);
|
"Error running exec(): "+e);
|
||||||
}finally{
|
|
||||||
if(pFunc) wasm.uninstallFunction(pFunc);
|
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
};
|
};
|
||||||
|
@ -878,250 +878,6 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
) ? !!capi.sqlite3_compileoption_used(optName) : false;
|
) ? !!capi.sqlite3_compileoption_used(optName) : false;
|
||||||
}/*compileOptionUsed()*/;
|
}/*compileOptionUsed()*/;
|
||||||
|
|
||||||
/**
|
|
||||||
Signatures for the WASM-exported C-side functions. Each entry
|
|
||||||
is an array with 2+ elements:
|
|
||||||
|
|
||||||
[ "c-side name",
|
|
||||||
"result type" (wasm.xWrap() syntax),
|
|
||||||
[arg types in xWrap() syntax]
|
|
||||||
// ^^^ this needn't strictly be an array: it can be subsequent
|
|
||||||
// elements instead: [x,y,z] is equivalent to x,y,z
|
|
||||||
]
|
|
||||||
|
|
||||||
Note that support for the API-specific data types in the
|
|
||||||
result/argument type strings gets plugged in at a later phase in
|
|
||||||
the API initialization process.
|
|
||||||
*/
|
|
||||||
wasm.bindingSignatures = [
|
|
||||||
// Please keep these sorted by function name!
|
|
||||||
["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
|
|
||||||
["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*"
|
|
||||||
/* TODO: we should arguably write a custom wrapper which knows
|
|
||||||
how to handle Blob, TypedArrays, and JS strings. */
|
|
||||||
],
|
|
||||||
["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
|
|
||||||
["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
|
|
||||||
["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
|
|
||||||
["sqlite3_bind_pointer", "int",
|
|
||||||
"sqlite3_stmt*", "int", "*", "string:static", "*"],
|
|
||||||
["sqlite3_bind_text","int", "sqlite3_stmt*", "int", "string", "int", "int"
|
|
||||||
/* We should arguably create a hand-written binding of
|
|
||||||
bind_text() which does more flexible text conversion, along
|
|
||||||
the lines of sqlite3_prepare_v3(). The slightly problematic
|
|
||||||
part is the final argument (text destructor). */
|
|
||||||
],
|
|
||||||
//["sqlite3_busy_handler","int", "sqlite3*", "*", "*"],
|
|
||||||
// ^^^^ TODO: custom binding which auto-converts JS function arg
|
|
||||||
// to a WASM function, noting that calling it multiple times
|
|
||||||
// would introduce a leak.
|
|
||||||
["sqlite3_busy_timeout","int", "sqlite3*", "int"],
|
|
||||||
["sqlite3_close_v2", "int", "sqlite3*"],
|
|
||||||
["sqlite3_changes", "int", "sqlite3*"],
|
|
||||||
["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
|
|
||||||
["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_column_count", "int", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
|
|
||||||
["sqlite3_compileoption_get", "string", "int"],
|
|
||||||
["sqlite3_compileoption_used", "int", "string"],
|
|
||||||
["sqlite3_complete", "int", "string:flexible"],
|
|
||||||
/* sqlite3_create_function(), sqlite3_create_function_v2(), and
|
|
||||||
sqlite3_create_window_function() use hand-written bindings to
|
|
||||||
simplify handling of their function-type arguments. */
|
|
||||||
/* sqlite3_create_collation() and sqlite3_create_collation_v2()
|
|
||||||
use hand-written bindings to simplify passing of the callback
|
|
||||||
function.
|
|
||||||
["sqlite3_create_collation", "int",
|
|
||||||
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
|
|
||||||
"*", "*"],
|
|
||||||
["sqlite3_create_collation_v2", "int",
|
|
||||||
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
|
|
||||||
"*", "*", "*"],
|
|
||||||
*/
|
|
||||||
["sqlite3_data_count", "int", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_db_filename", "string", "sqlite3*", "string"],
|
|
||||||
["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_db_name", "string", "sqlite3*", "int"],
|
|
||||||
["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"],
|
|
||||||
["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
|
|
||||||
/* Careful! Short version: de/serialize() are problematic because they
|
|
||||||
might use a different allocator than the user for managing the
|
|
||||||
deserialized block. de/serialize() are ONLY safe to use with
|
|
||||||
sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. */,
|
|
||||||
["sqlite3_errcode", "int", "sqlite3*"],
|
|
||||||
["sqlite3_errmsg", "string", "sqlite3*"],
|
|
||||||
["sqlite3_error_offset", "int", "sqlite3*"],
|
|
||||||
["sqlite3_errstr", "string", "int"],
|
|
||||||
/*["sqlite3_exec", "int", "sqlite3*", "string", "*", "*", "**"
|
|
||||||
Handled seperately to perform translation of the callback
|
|
||||||
into a WASM-usable one. ],*/
|
|
||||||
["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_extended_errcode", "int", "sqlite3*"],
|
|
||||||
["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
|
|
||||||
["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
|
|
||||||
["sqlite3_finalize", "int", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_free", undefined,"*"],
|
|
||||||
["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
|
|
||||||
["sqlite3_initialize", undefined],
|
|
||||||
/*["sqlite3_interrupt", undefined, "sqlite3*"
|
|
||||||
^^^ we cannot actually currently support this because JS is
|
|
||||||
single-threaded and we don't have a portable way to access a DB
|
|
||||||
from 2 SharedWorkers concurrently. ],*/
|
|
||||||
["sqlite3_keyword_count", "int"],
|
|
||||||
["sqlite3_keyword_name", "int", ["int", "**", "*"]],
|
|
||||||
["sqlite3_keyword_check", "int", ["string", "int"]],
|
|
||||||
["sqlite3_libversion", "string"],
|
|
||||||
["sqlite3_libversion_number", "int"],
|
|
||||||
["sqlite3_limit", "int", ["sqlite3*", "int", "int"]],
|
|
||||||
["sqlite3_malloc", "*","int"],
|
|
||||||
["sqlite3_open", "int", "string", "*"],
|
|
||||||
["sqlite3_open_v2", "int", "string", "*", "int", "string"],
|
|
||||||
/* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
|
|
||||||
separately due to us requiring two different sets of semantics
|
|
||||||
for those, depending on how their SQL argument is provided. */
|
|
||||||
/* sqlite3_randomness() uses a hand-written wrapper to extend
|
|
||||||
the range of supported argument types. */
|
|
||||||
//TODO: hand-written wrapper to convert function-type arg:
|
|
||||||
//void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
|
||||||
//
|
|
||||||
//!TODO!: accept arg/result conversion descriptions which are objects
|
|
||||||
//following an interface and a FuncPtr impl which does that conversion.
|
|
||||||
//That would require moving these bindings int sqlite3-api-glue.js, after
|
|
||||||
//whwasmutil.js is loaded.
|
|
||||||
["sqlite3_progress_handler", undefined, ["sqlite3*","int", "*", "*"]],
|
|
||||||
["sqlite3_realloc", "*","*","int"],
|
|
||||||
["sqlite3_reset", "int", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
|
|
||||||
["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
|
|
||||||
["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
|
|
||||||
["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"],
|
|
||||||
["sqlite3_result_error_nomem", undefined, "sqlite3_context*"],
|
|
||||||
["sqlite3_result_error_toobig", undefined, "sqlite3_context*"],
|
|
||||||
["sqlite3_result_int", undefined, "sqlite3_context*", "int"],
|
|
||||||
["sqlite3_result_null", undefined, "sqlite3_context*"],
|
|
||||||
["sqlite3_result_pointer", undefined,
|
|
||||||
"sqlite3_context*", "*", "string:static", "*"],
|
|
||||||
["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
|
|
||||||
["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
|
|
||||||
["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
|
|
||||||
["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
|
|
||||||
["sqlite3_set_auxdata", undefined, "sqlite3_context*", "int", "*", "*"/* => v(*) */],
|
|
||||||
["sqlite3_shutdown", undefined],
|
|
||||||
["sqlite3_sourceid", "string"],
|
|
||||||
["sqlite3_sql", "string", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_status", "int", "int", "*", "*", "int"],
|
|
||||||
["sqlite3_step", "int", "sqlite3_stmt*"],
|
|
||||||
["sqlite3_stmt_isexplain", "int", ["sqlite3_stmt*"]],
|
|
||||||
["sqlite3_stmt_readonly", "int", ["sqlite3_stmt*"]],
|
|
||||||
["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"],
|
|
||||||
["sqlite3_strglob", "int", "string","string"],
|
|
||||||
["sqlite3_stricmp", "int", "string", "string"],
|
|
||||||
["sqlite3_strlike", "int", "string", "string","int"],
|
|
||||||
["sqlite3_strnicmp", "int", "string", "string", "int"],
|
|
||||||
["sqlite3_table_column_metadata", "int",
|
|
||||||
"sqlite3*", "string", "string", "string",
|
|
||||||
"**", "**", "*", "*", "*"],
|
|
||||||
["sqlite3_total_changes", "int", "sqlite3*"],
|
|
||||||
["sqlite3_trace_v2", "int", "sqlite3*", "int", "*", "*"],
|
|
||||||
["sqlite3_txn_state", "int", ["sqlite3*","string"]],
|
|
||||||
/* Note that sqlite3_uri_...() have very specific requirements for
|
|
||||||
their first C-string arguments, so we cannot perform any value
|
|
||||||
conversion on those. */
|
|
||||||
["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
|
|
||||||
["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
|
|
||||||
["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
|
|
||||||
["sqlite3_user_data","void*", "sqlite3_context*"],
|
|
||||||
["sqlite3_value_blob", "*", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_bytes","int", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_double","f64", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_free", undefined, "sqlite3_value*"],
|
|
||||||
["sqlite3_value_frombind", "int", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_int","int", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_nochange", "int", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
|
|
||||||
["sqlite3_value_subtype", "int", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_text", "string", "sqlite3_value*"],
|
|
||||||
["sqlite3_value_type", "int", "sqlite3_value*"],
|
|
||||||
["sqlite3_vfs_find", "*", "string"],
|
|
||||||
["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
|
|
||||||
["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
|
|
||||||
]/*wasm.bindingSignatures*/;
|
|
||||||
|
|
||||||
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
|
|
||||||
/* ^^^ "the problem" is that this is an option feature and the
|
|
||||||
build-time function-export list does not currently take
|
|
||||||
optional features into account. */
|
|
||||||
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Functions which require BigInt (int64) support are separated from
|
|
||||||
the others because we need to conditionally bind them or apply
|
|
||||||
dummy impls, depending on the capabilities of the environment.
|
|
||||||
|
|
||||||
Note that not all of these functions directly require int64
|
|
||||||
but are only for use with APIs which require int64. For example,
|
|
||||||
the vtab-related functions.
|
|
||||||
*/
|
|
||||||
wasm.bindingSignatures.int64 = [
|
|
||||||
["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
|
|
||||||
["sqlite3_changes64","i64", ["sqlite3*"]],
|
|
||||||
["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
|
|
||||||
["sqlite3_create_module", "int",
|
|
||||||
["sqlite3*","string","sqlite3_module*","*"]],
|
|
||||||
["sqlite3_create_module_v2", "int",
|
|
||||||
["sqlite3*","string","sqlite3_module*","*","*"]],
|
|
||||||
["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
|
|
||||||
["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
|
|
||||||
["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
|
|
||||||
["sqlite3_malloc64", "*","i64"],
|
|
||||||
["sqlite3_msize", "i64", "*"],
|
|
||||||
["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
|
|
||||||
["sqlite3_realloc64", "*","*", "i64"],
|
|
||||||
["sqlite3_result_int64", undefined, "*", "i64"],
|
|
||||||
["sqlite3_result_zeroblob64", "int", "*", "i64"],
|
|
||||||
["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
|
|
||||||
["sqlite3_status64", "int", "int", "*", "*", "int"],
|
|
||||||
["sqlite3_total_changes64", "i64", ["sqlite3*"]],
|
|
||||||
["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
|
|
||||||
["sqlite3_value_int64","i64", "sqlite3_value*"],
|
|
||||||
["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
|
|
||||||
["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
|
|
||||||
["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
|
|
||||||
["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"],
|
|
||||||
["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"],
|
|
||||||
/*["sqlite3_vtab_config" is variadic and requires a hand-written
|
|
||||||
proxy.] */
|
|
||||||
["sqlite3_vtab_nochange","int", "sqlite3_context*"],
|
|
||||||
["sqlite3_vtab_on_conflict","int", "sqlite3*"],
|
|
||||||
["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
Functions which are intended solely for API-internal use by the
|
|
||||||
WASM components, not client code. These get installed into
|
|
||||||
sqlite3.wasm. Some of them get exposed to clients via variants
|
|
||||||
named sqlite3_js_...().
|
|
||||||
*/
|
|
||||||
wasm.bindingSignatures.wasm = [
|
|
||||||
["sqlite3_wasm_db_reset", "int", "sqlite3*"],
|
|
||||||
["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
|
|
||||||
["sqlite3_wasm_vfs_create_file", "int",
|
|
||||||
"sqlite3_vfs*","string","*", "int"],
|
|
||||||
["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
sqlite3.wasm.pstack (pseudo-stack) holds a special-case
|
sqlite3.wasm.pstack (pseudo-stack) holds a special-case
|
||||||
stack-style allocator intended only for use with _small_ data of
|
stack-style allocator intended only for use with _small_ data of
|
||||||
|
@ -495,6 +495,70 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
})).exports['f'];
|
})).exports['f'];
|
||||||
}/*jsFuncToWasm()*/;
|
}/*jsFuncToWasm()*/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Documented as target.installFunction() except for the 3rd
|
||||||
|
argument: if truthy, the newly-created function pointer
|
||||||
|
is stashed in the current scoped-alloc scope and will be
|
||||||
|
cleaned up at the matching scopedAllocPop(), else it
|
||||||
|
is not stashed there.
|
||||||
|
*/
|
||||||
|
const __installFunction = function f(func, sig, scoped){
|
||||||
|
if(scoped && !cache.scopedAlloc.length){
|
||||||
|
toss("No scopedAllocPush() scope is active.");
|
||||||
|
}
|
||||||
|
if('string'===typeof func){
|
||||||
|
const x = sig;
|
||||||
|
sig = func;
|
||||||
|
func = x;
|
||||||
|
}
|
||||||
|
if('string'!==typeof sig || !(func instanceof Function)){
|
||||||
|
toss("Invalid arguments: expecting (function,signature) "+
|
||||||
|
"or (signature,function).");
|
||||||
|
}
|
||||||
|
const ft = target.functionTable();
|
||||||
|
const oldLen = ft.length;
|
||||||
|
let ptr;
|
||||||
|
while(cache.freeFuncIndexes.length){
|
||||||
|
ptr = cache.freeFuncIndexes.pop();
|
||||||
|
if(ft.get(ptr)){ /* Table was modified via a different API */
|
||||||
|
ptr = null;
|
||||||
|
continue;
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!ptr){
|
||||||
|
ptr = oldLen;
|
||||||
|
ft.grow(1);
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
/*this will only work if func is a WASM-exported function*/
|
||||||
|
ft.set(ptr, func);
|
||||||
|
if(scoped){
|
||||||
|
cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}catch(e){
|
||||||
|
if(!(e instanceof TypeError)){
|
||||||
|
if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// It's not a WASM-exported function, so compile one...
|
||||||
|
try {
|
||||||
|
const fptr = target.jsFuncToWasm(func, sig);
|
||||||
|
ft.set(ptr, fptr);
|
||||||
|
if(scoped){
|
||||||
|
cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr);
|
||||||
|
}
|
||||||
|
}catch(e){
|
||||||
|
if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Expects a JS function and signature, exactly as for
|
Expects a JS function and signature, exactly as for
|
||||||
this.jsFuncToWasm(). It uses that function to create a
|
this.jsFuncToWasm(). It uses that function to create a
|
||||||
@ -526,50 +590,19 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
|
|
||||||
https://github.com/emscripten-core/emscripten/issues/17323
|
https://github.com/emscripten-core/emscripten/issues/17323
|
||||||
*/
|
*/
|
||||||
target.installFunction = function f(func, sig){
|
target.installFunction = (func, sig)=>__installFunction(func, sig, false);
|
||||||
if(2!==arguments.length){
|
|
||||||
toss("installFunction() requires exactly 2 arguments");
|
/**
|
||||||
}
|
EXPERIMENTAL! DO NOT USE IN CLIENT CODE!
|
||||||
if('string'===typeof func){
|
|
||||||
const x = sig;
|
Works exactly like installFunction() but requires that a
|
||||||
sig = func;
|
scopedAllocPush() is active and uninstalls the given function
|
||||||
func = x;
|
when that alloc scope is popped via scopedAllocPop().
|
||||||
}
|
This is used for implementing JS/WASM function bindings which
|
||||||
const ft = target.functionTable();
|
should only persist for the life of a call into a single
|
||||||
const oldLen = ft.length;
|
C-side function.
|
||||||
let ptr;
|
*/
|
||||||
while(cache.freeFuncIndexes.length){
|
target.scopedInstallFunction = (func, sig)=>__installFunction(func, sig, true);
|
||||||
ptr = cache.freeFuncIndexes.pop();
|
|
||||||
if(ft.get(ptr)){ /* Table was modified via a different API */
|
|
||||||
ptr = null;
|
|
||||||
continue;
|
|
||||||
}else{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!ptr){
|
|
||||||
ptr = oldLen;
|
|
||||||
ft.grow(1);
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
/*this will only work if func is a WASM-exported function*/
|
|
||||||
ft.set(ptr, func);
|
|
||||||
return ptr;
|
|
||||||
}catch(e){
|
|
||||||
if(!(e instanceof TypeError)){
|
|
||||||
if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// It's not a WASM-exported function, so compile one...
|
|
||||||
try {
|
|
||||||
ft.set(ptr, target.jsFuncToWasm(func, sig));
|
|
||||||
}catch(e){
|
|
||||||
if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Requires a pointer value previously returned from
|
Requires a pointer value previously returned from
|
||||||
@ -1083,7 +1116,13 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
if(n<0) toss("Invalid state object for scopedAllocPop().");
|
if(n<0) toss("Invalid state object for scopedAllocPop().");
|
||||||
if(0===arguments.length) state = cache.scopedAlloc[n];
|
if(0===arguments.length) state = cache.scopedAlloc[n];
|
||||||
cache.scopedAlloc.splice(n,1);
|
cache.scopedAlloc.splice(n,1);
|
||||||
for(let p; (p = state.pop()); ) target.dealloc(p);
|
for(let p; (p = state.pop()); ){
|
||||||
|
if(target.functionEntry(p)){
|
||||||
|
//console.warn("scopedAllocPop() uninstalling transient function",p);
|
||||||
|
target.uninstallFunction(p);
|
||||||
|
}
|
||||||
|
else target.dealloc(p);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1303,12 +1342,12 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
State for use with xWrap()
|
State for use with xWrap()
|
||||||
*/
|
*/
|
||||||
cache.xWrap = Object.create(null);
|
cache.xWrap = Object.create(null);
|
||||||
const xcv = cache.xWrap.convert = Object.create(null);
|
cache.xWrap.convert = Object.create(null);
|
||||||
/** Map of type names to argument conversion functions. */
|
/** Map of type names to argument conversion functions. */
|
||||||
cache.xWrap.convert.arg = new Map;
|
cache.xWrap.convert.arg = new Map;
|
||||||
/** Map of type names to return result conversion functions. */
|
/** Map of type names to return result conversion functions. */
|
||||||
cache.xWrap.convert.result = new Map;
|
cache.xWrap.convert.result = new Map;
|
||||||
const xArg = xcv.arg, xResult = xcv.result;
|
const xArg = cache.xWrap.convert.arg, xResult = cache.xWrap.convert.result;
|
||||||
|
|
||||||
if(target.bigIntEnabled){
|
if(target.bigIntEnabled){
|
||||||
xArg.set('i64', (i)=>BigInt(i));
|
xArg.set('i64', (i)=>BigInt(i));
|
||||||
@ -1395,6 +1434,87 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const __FuncPtrBindModes = ['transient','static','singleton'];
|
||||||
|
/**
|
||||||
|
EXPERIMENTAL.
|
||||||
|
|
||||||
|
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 permanently
|
||||||
|
or only for the duration of a a single call into the C layer.
|
||||||
|
*/
|
||||||
|
xArg.FuncPtrAdapter = class {
|
||||||
|
/**
|
||||||
|
Requires an options object with these properties:
|
||||||
|
|
||||||
|
- signature: an function signature compatible with
|
||||||
|
jsFuncToWasm().
|
||||||
|
|
||||||
|
- bindMode (string): one of ('transient', 'static',
|
||||||
|
'singleton'). If 'transient', it uses
|
||||||
|
scopedInstallFunction() for its function bindings, meaning
|
||||||
|
they're limited to the lifetime of a single xWrap()-induced
|
||||||
|
function call. If it's 'static', the binding is permanent,
|
||||||
|
lasting the life of the WASM environment. If it's 'singleton'
|
||||||
|
then this function remembers the last function it installed
|
||||||
|
and uninstalls it before installing any replacements on
|
||||||
|
subsequent calls. If it's passed the exact same JS function
|
||||||
|
to install later, it will re-use the existing binding.
|
||||||
|
|
||||||
|
- name (optional): string describing the function binding. This
|
||||||
|
is solely for debugging and error-reporting purposes. If not
|
||||||
|
provided, an empty string is assumed.
|
||||||
|
|
||||||
|
The constructor only saves the above state for later, and does
|
||||||
|
not actually bind any functions. Its convertArg() methor is
|
||||||
|
called via xWrap() to perform any bindings.
|
||||||
|
*/
|
||||||
|
constructor(opt){
|
||||||
|
this.signature = opt.signature;
|
||||||
|
if(__FuncPtrBindModes.indexOf(opt.bindMode)<0){
|
||||||
|
toss("Invalid options.bindMode ("+opt.bindMod+") for FuncPtrAdapter. "+
|
||||||
|
"Expecting one of: ("+__FuncPtrBindModes.join(', ')+')');
|
||||||
|
}
|
||||||
|
this.bindMode = opt.bindMode;
|
||||||
|
this.name = opt.name || '';
|
||||||
|
this.singleton = ('singleton'===this.bindMode) ? [] : undefined;
|
||||||
|
//console.warn("FuncPtrAdapter()",this.signature,this.transient);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
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, otherwise v must be a Function, for which
|
||||||
|
xit creates (if needed) a WASM function binding and returns the
|
||||||
|
WASM pointer to that binding. It throws if passed an invalid
|
||||||
|
type.
|
||||||
|
*/
|
||||||
|
convertArg(v){
|
||||||
|
//console.warn("FuncPtrAdapter.convertArg()",this.signature,this.transient,v);
|
||||||
|
if(v instanceof Function){
|
||||||
|
if(this.singleton && this.singleton[0]===v){
|
||||||
|
return this.singleton[1];
|
||||||
|
}
|
||||||
|
const fp = __installFunction(v, this.signature, 'transient'===this.bindMode);
|
||||||
|
if(this.singleton){
|
||||||
|
if(this.singleton[1]){
|
||||||
|
try{target.uninstallFunction(this.singleton[1])}
|
||||||
|
catch(e){/*ignored*/}
|
||||||
|
}
|
||||||
|
this.singleton[0] = v;
|
||||||
|
this.singleton[1] = fp;
|
||||||
|
}
|
||||||
|
return fp;
|
||||||
|
}else if(target.isPtr(v) || null===v || undefined===v){
|
||||||
|
return v || 0;
|
||||||
|
}else{
|
||||||
|
throw new TypeError("Invalid FuncPtrAdapter argument type. "+
|
||||||
|
"Expecting "+(this.name ? this.name+' ' : '')+
|
||||||
|
"function matching signature "+
|
||||||
|
this.signature+".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const __xArgAdapterCheck =
|
const __xArgAdapterCheck =
|
||||||
(t)=>xArg.get(t) || toss("Argument adapter not found:",t);
|
(t)=>xArg.get(t) || toss("Argument adapter not found:",t);
|
||||||
|
|
||||||
@ -1565,7 +1685,10 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
}
|
}
|
||||||
/*Verify the arg type conversions are valid...*/;
|
/*Verify the arg type conversions are valid...*/;
|
||||||
if(undefined!==resultType && null!==resultType) __xResultAdapterCheck(resultType);
|
if(undefined!==resultType && null!==resultType) __xResultAdapterCheck(resultType);
|
||||||
argTypes.forEach(__xArgAdapterCheck);
|
for(const t of argTypes){
|
||||||
|
if(t instanceof xArg.FuncPtrAdapter) xArg.set(t, (v)=>t.convertArg(v));
|
||||||
|
else __xArgAdapterCheck(t);
|
||||||
|
}
|
||||||
const cxw = cache.xWrap;
|
const cxw = cache.xWrap;
|
||||||
if(0===xf.length){
|
if(0===xf.length){
|
||||||
// No args to convert, so we can create a simpler wrapper...
|
// No args to convert, so we can create a simpler wrapper...
|
||||||
@ -1666,6 +1789,8 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
'argAdapter()', xArg);
|
'argAdapter()', xArg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
target.xWrap.FuncPtrAdapter = xArg.FuncPtrAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Functions like xCall() but performs argument and result type
|
Functions like xCall() but performs argument and result type
|
||||||
conversions as for xWrap(). The first argument is the name of the
|
conversions as for xWrap(). The first argument is the name of the
|
||||||
|
@ -1054,7 +1054,13 @@ self.sqlite3InitModule = sqlite3InitModule;
|
|||||||
.assert(ex.message.indexOf("Invalid SQL")>0);
|
.assert(ex.message.indexOf("Invalid SQL")>0);
|
||||||
T.assert(db === db.checkRc(0))
|
T.assert(db === db.checkRc(0))
|
||||||
.assert(db === sqlite3.oo1.DB.checkRc(db,0))
|
.assert(db === sqlite3.oo1.DB.checkRc(db,0))
|
||||||
.assert(null === sqlite3.oo1.DB.checkRc(null,0))
|
.assert(null === sqlite3.oo1.DB.checkRc(null,0));
|
||||||
|
|
||||||
|
this.progressHandlerCount = 0;
|
||||||
|
capi.sqlite3_progress_handler(db, 5, (p)=>{
|
||||||
|
++this.progressHandlerCount;
|
||||||
|
return 0;
|
||||||
|
}, 0);
|
||||||
})
|
})
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
.t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){
|
.t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){
|
||||||
@ -1107,6 +1113,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
|||||||
new TextEncoder('utf-8').encode("select 3 as a")
|
new TextEncoder('utf-8').encode("select 3 as a")
|
||||||
);
|
);
|
||||||
//debug("statement =",st);
|
//debug("statement =",st);
|
||||||
|
this.progressHandlerCount = 0;
|
||||||
try {
|
try {
|
||||||
T.assert(wasm.isPtr(st.pointer))
|
T.assert(wasm.isPtr(st.pointer))
|
||||||
.mustThrowMatching(()=>st.pointer=1, /read-only/)
|
.mustThrowMatching(()=>st.pointer=1, /read-only/)
|
||||||
@ -1145,7 +1152,9 @@ self.sqlite3InitModule = sqlite3InitModule;
|
|||||||
st, capi.SQLITE_STMTSTATUS_RUN, 0
|
st, capi.SQLITE_STMTSTATUS_RUN, 0
|
||||||
) > 0);
|
) > 0);
|
||||||
|
|
||||||
T.assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
|
T.assert(this.progressHandlerCount > 0,
|
||||||
|
"Expecting progress callback.").
|
||||||
|
assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
|
||||||
assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
|
assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
|
||||||
assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)).
|
assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)).
|
||||||
assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0));
|
assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0));
|
||||||
@ -1207,6 +1216,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
|||||||
.t('Table t', function(sqlite3){
|
.t('Table t', function(sqlite3){
|
||||||
const db = this.db;
|
const db = this.db;
|
||||||
let list = [];
|
let list = [];
|
||||||
|
this.progressHandlerCount = 0;
|
||||||
let rc = db.exec({
|
let rc = db.exec({
|
||||||
sql:['CREATE TABLE t(a,b);',
|
sql:['CREATE TABLE t(a,b);',
|
||||||
// ^^^ using TEMP TABLE breaks the db export test
|
// ^^^ using TEMP TABLE breaks the db export test
|
||||||
@ -1220,7 +1230,9 @@ self.sqlite3InitModule = sqlite3InitModule;
|
|||||||
T.assert(rc === db)
|
T.assert(rc === db)
|
||||||
.assert(2 === list.length)
|
.assert(2 === list.length)
|
||||||
.assert('string'===typeof list[1])
|
.assert('string'===typeof list[1])
|
||||||
.assert(4===db.changes());
|
.assert(4===db.changes())
|
||||||
|
.assert(this.progressHandlerCount > 0,
|
||||||
|
"Expecting progress callback.")
|
||||||
if(wasm.bigIntEnabled){
|
if(wasm.bigIntEnabled){
|
||||||
T.assert(4n===db.changes(false,true));
|
T.assert(4n===db.changes(false,true));
|
||||||
}
|
}
|
||||||
@ -1643,6 +1655,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
|||||||
T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a'));
|
T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a'));
|
||||||
let colCount = 0, rowCount = 0;
|
let colCount = 0, rowCount = 0;
|
||||||
const execCallback = function(pVoid, nCols, aVals, aNames){
|
const execCallback = function(pVoid, nCols, aVals, aNames){
|
||||||
|
//console.warn("execCallback(",arguments,")");
|
||||||
colCount = nCols;
|
colCount = nCols;
|
||||||
++rowCount;
|
++rowCount;
|
||||||
T.assert(2===aVals.length)
|
T.assert(2===aVals.length)
|
||||||
|
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
|||||||
C ext/wasm/module-symbols.html:\sfor\sC\sAPIs\swhich\shave\sextended\sJS-side\ssemantics,\slink\sto\sthe\sJS-side\sAPI\sdocs\sinstead\sof\sthe\sC\sdocs.
|
C Move\sJS-to-C\sbinding\ssignatures\sfrom\ssqlite3-api-prologue.js\sto\ssqlite3-api-glue.js\sto\sallow\sfor\suse\sof\sthe\snew/experimental\ssqlite3.wasm.xWrap()\sfeature\swhich\sautomatically\sbinds\sJS\sfunctions\sto\sWASM/C\sas\sneeded,\swhich\ssimplifies\screation\sof\sbindings\swhich\stake\sC\sfunction\spointers.\sReimplement\ssqlite3_exec(),\ssqlite3_create_collation(),\ssqlite3_progress_handler()\sto\suse\sthis\snew\sfeature.
|
||||||
D 2022-12-12T11:38:22.370
|
D 2022-12-12T14:31:38.581
|
||||||
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,9 +503,9 @@ 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 1d1c0542392a17e1ab9dc652c00091afefe8489108bb8da899b68eab50c3f813
|
F ext/wasm/api/sqlite3-api-glue.js 5c3854480b600195edd7a9c98a9ea4f07f59cc6abe7ab2f19d30cdaa62f24b78
|
||||||
F ext/wasm/api/sqlite3-api-oo1.js 6d10849609231ccd46fa11b1d3fbbe0f45d9fe84c66a0b054601036540844300
|
F ext/wasm/api/sqlite3-api-oo1.js 6d10849609231ccd46fa11b1d3fbbe0f45d9fe84c66a0b054601036540844300
|
||||||
F ext/wasm/api/sqlite3-api-prologue.js 979a469f329636e7345a1a720b0be6e93c7585231387ebdef2b4493ff9a2bf74
|
F ext/wasm/api/sqlite3-api-prologue.js 39fbca8f25219c218d631433828ede53be8d518aa9f0da480758a3ea8abc1be8
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
|
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
|
||||||
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
|
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
|
||||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
|
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
|
||||||
@ -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 399918a67a22cab80f3a3f4f1c39eb2f83226953ed19579f2761157532a5c036
|
F ext/wasm/common/whwasmutil.js 60531749126c3d505521b9e9a0adb468951e3a201ca65fdc8a37d20a6c1194e0
|
||||||
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
|
||||||
@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
|||||||
F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
|
F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
|
||||||
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
|
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
|
||||||
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
|
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
|
||||||
F ext/wasm/tester1.c-pp.js 49bee1aafa597ab1ac518a0d7cbe93b734867d6f48371b87a3346709de0069c2
|
F ext/wasm/tester1.c-pp.js 6f7fcaeedff2c94fd9ebfd37a665cc7797524868b70fce2854ecab60b3d74274
|
||||||
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
|
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
|
||||||
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
||||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||||
@ -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 01d3a9bba3120cfec3f752048281f18ce7ab48fa7584750c097233a9ce095a20
|
P d557015208f504c6d5d20ebf1e451b3f07b19590d76371b16a9f4b54e9645282
|
||||||
R 919e96e26165900597588955a230bf5e
|
R 5a61f05e144f2d7b8121b7e697a724d0
|
||||||
U stephan
|
U stephan
|
||||||
Z db12a0f20be16fdb93fc89d67734b367
|
Z 82382106256d8062d011dc4fe2d4d001
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
d557015208f504c6d5d20ebf1e451b3f07b19590d76371b16a9f4b54e9645282
|
9386d6f634680b4e0fa5487c34c63acb29f0b7a6ae738b8f6164ad084a229b62
|
Reference in New Issue
Block a user