Various build- and code-reorg cleanups for ext/wasm. No functional changes.

FossilOrigin-Name: 835bd4a11e56ede378235379604ac01350ee92433f952a23c761f7be492fd475
This commit is contained in:
stephan 2024-01-16 14:24:35 +00:00
commit 6f30cac209
15 changed files with 496 additions and 509 deletions

View File

@ -43,8 +43,9 @@
# which generates the makefile code, rather than using $(call) and
# $(eval), or at least centralize the setup of the numerous vars
# related to each build variant $(JS_BUILD_MODES). (Update: an
# external script was attempted but it's even less legible than the
# $(eval) indirection going on in this file.
# external script was attempted but generating properly-escaped
# makefile code from within a shell script is even less legible
# than the $(eval) indirection going on in this file.)
#
default: all
#default: quick
@ -432,8 +433,10 @@ sqlite3-api.jses += $(sqlite3-api-build-version.js)
sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.js
# sqlite3-api-worker.js = the Worker1 API:
sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.js
# sqlite3-v-helper = helper APIs for VFSes and VTABLEs:
sqlite3-api.jses += $(dir.api)/sqlite3-v-helper.js
# sqlite3-vfs-helper = helper APIs for VFSes:
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-helper.c-pp.js
# sqlite3-vtab-helper = helper APIs for VTABLEs:
sqlite3-api.jses += $(dir.api)/sqlite3-vtab-helper.c-pp.js
# sqlite3-vfs-opfs.c-pp.js = the first OPFS VFS:
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
# sqlite3-vfs-opfs-sahpool.c-pp.js = the second OPFS VFS:
@ -652,6 +655,9 @@ $(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
########################################################################
# $(sqlite3-license-version.js) contains the license header and
# in-comment build version info.
#
# Maintenance reminder: there are awk binaries out there which do not
# support -e SCRIPT.
$(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \
$(MAKEFILE)
@echo "Making $@..."; { \
@ -659,8 +665,8 @@ $(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js)
echo '/*'; \
echo '** This code was built from sqlite3 version...'; \
echo "**"; \
awk -e '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' \
-e '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
awk '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' $(sqlite3.h); \
awk '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
echo "**"; \
echo "** Using the Emscripten SDK version $(emcc.version)."; \
echo '*/'; \

View File

@ -78,10 +78,12 @@ browser client:
a Promise-based interface into the Worker #1 API. This is
a far user-friendlier way to interface with databases running
in a Worker thread.
- **`sqlite3-v-helper.js`**\
Installs `sqlite3.vfs` and `sqlite3.vtab`, namespaces which contain
helpers for use by downstream code which creates `sqlite3_vfs`
and `sqlite3_module` implementations.
- **`sqlite3-vfs-helper.js`**\
Installs the `sqlite3.vfs` namespace, which contain helpers for use
by downstream code which creates `sqlite3_vfs` implementations.
- **`sqlite3-vtab-helper.js`**\
Installs the `sqlite3.vtab` namespace, which contain helpers for use
by downstream code which creates `sqlite3_module` implementations.
- **`sqlite3-vfs-opfs.c-pp.js`**\
is an sqlite3 VFS implementation which supports the Origin-Private
FileSystem (OPFS) as a storage layer to provide persistent storage

View File

@ -19,8 +19,10 @@ Module.postRun.push(function(Module/*the Emscripten-style module object*/){
- sqlite3-api-glue.js => glues previous parts together
- sqlite3-api-oo.js => SQLite3 OO API #1
- sqlite3-api-worker1.js => Worker-based API
- sqlite3-vfs-helper.js => Internal-use utilities for...
- sqlite3-vfs-opfs.js => OPFS VFS
- sqlite3-vfs-helper.c-pp.js => Utilities for VFS impls
- sqlite3-vtab-helper.c-pp.js => Utilities for virtual table impls
- sqlite3-vfs-opfs.c-pp.js => OPFS VFS
- sqlite3-vfs-opfs-sahpool.c-pp.js => OPFS SAHPool VFS
- sqlite3-api-cleanup.js => final API cleanup
- post-js-footer.js => closes this postRun() function
*/

View File

@ -14,7 +14,8 @@
previous steps of the sqlite3-api.js bootstrapping process:
sqlite3-api-prologue.js, whwasmutil.js, and jaccwabyt.js. It
initializes the main API pieces so that the downstream components
(e.g. sqlite3-api-oo1.js) have all that they need.
(e.g. sqlite3-api-oo1.js) have all of the infrastructure that they
need.
*/
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
'use strict';
@ -329,6 +330,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
if(wasm.exports.sqlite3_activate_see instanceof Function){
/**
This code is capable of using an SEE build but note that an SEE
WASM build is generally incompatible with SEE's license
conditions. It is permitted for use internally in organizations
which have licensed SEE, but not for public sites because
exposing an SEE build of sqlite3.wasm effectively provides all
clients with a working copy of the commercial SEE code.
*/
wasm.bindingSignatures.push(
["sqlite3_key", "int", "sqlite3*", "string", "int"],
["sqlite3_key_v2","int","sqlite3*","string","*","int"],
@ -341,6 +350,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
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.
(That said: we never actually build without BigInt support,
and such builds are untested.)
Note that not all of these functions directly require int64
but are only for use with APIs which require int64. For example,
@ -359,7 +370,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
/* 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_malloc(), sqlite3_free(), and its 64-bit variants. Because
of this, the canonical builds of sqlite3.wasm/js guarantee that
sqlite3.wasm.alloc() and friends use those allocators. Custom builds
may not guarantee that, however. */,
["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
["sqlite3_malloc64", "*","i64"],
@ -422,8 +436,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
// Add session/changeset APIs...
if(wasm.bigIntEnabled && !!wasm.exports.sqlite3changegroup_add){
/* ACHTUNG: 2022-12-23: the session/changeset API bindings are
COMPLETELY UNTESTED. */
/**
FuncPtrAdapter options for session-related callbacks with the
native signature "i(ps)". This proxy converts the 2nd argument
@ -601,16 +613,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
/**
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_...().
sqlite3.util. Some of them get exposed to clients via variants
in sqlite3_js_...().
2024-01-11: these were renamed, with two underscores in the
prefix, to ensure that clients do not accidentally depend on
them. They have always been documented as internal-use-only, so
no clients "should" be depending on the old names.
*/
wasm.bindingSignatures.wasm = [
["sqlite3_wasm_db_reset", "int", "sqlite3*"],
["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
["sqlite3_wasm_vfs_create_file", "int",
wasm.bindingSignatures.wasmInternal = [
["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_posix_create_file", "int", "string","*", "int"],
["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
];
/**
@ -652,7 +669,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Use case: sqlite3_bind_pointer() and sqlite3_result_pointer()
call for "a static string and preferably a string
literal". This converter is used to ensure that the string
literal." This converter is used to ensure that the string
value seen by those functions is long-lived and behaves as they
need it to.
*/
@ -674,14 +691,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
`sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
*/
const __xArgPtr = wasm.xWrap.argAdapter('*');
const nilType = function(){}/*a class no value can ever be an instance of*/;
const nilType = function(){
/*a class which 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)=>
__xArgPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType))
@ -742,8 +760,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
for(const e of wasm.bindingSignatures){
capi[e[0]] = wasm.xWrap.apply(null, e);
}
for(const e of wasm.bindingSignatures.wasm){
wasm[e[0]] = wasm.xWrap.apply(null, e);
for(const e of wasm.bindingSignatures.wasmInternal){
util[e[0]] = wasm.xWrap.apply(null, e);
}
/* For C API functions which cannot work properly unless
@ -765,9 +783,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
implicitly making it part of the public interface. */
delete wasm.bindingSignatures;
if(wasm.exports.sqlite3_wasm_db_error){
if(wasm.exports.sqlite3__wasm_db_error){
const __db_err = wasm.xWrap(
'sqlite3_wasm_db_error', 'int', 'sqlite3*', 'int', 'string'
'sqlite3__wasm_db_error', 'int', 'sqlite3*', 'int', 'string'
);
/**
Sets the given db's error state. Accepts:
@ -785,7 +803,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Returns the resulting code. Pass (pDb,0,0) to clear the error
state.
*/
util.sqlite3_wasm_db_error = function(pDb, resultCode, message){
util.sqlite3__wasm_db_error = function(pDb, resultCode, message){
if(resultCode instanceof sqlite3.WasmAllocError){
resultCode = capi.SQLITE_NOMEM;
message = 0 /*avoid allocating message string*/;
@ -796,17 +814,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return pDb ? __db_err(pDb, resultCode, message) : resultCode;
};
}else{
util.sqlite3_wasm_db_error = function(pDb,errCode,msg){
console.warn("sqlite3_wasm_db_error() is not exported.",arguments);
util.sqlite3__wasm_db_error = function(pDb,errCode,msg){
console.warn("sqlite3__wasm_db_error() is not exported.",arguments);
return errCode;
};
}
}/*xWrap() bindings*/
{/* Import C-level constants and structs... */
const cJson = wasm.xCall('sqlite3_wasm_enum_json');
const cJson = wasm.xCall('sqlite3__wasm_enum_json');
if(!cJson){
toss("Maintenance required: increase sqlite3_wasm_enum_json()'s",
toss("Maintenance required: increase sqlite3__wasm_enum_json()'s",
"static buffer size!");
}
//console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
@ -877,7 +895,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
delete capi[k];
}
capi.sqlite3_vtab_config = wasm.xWrap(
'sqlite3_wasm_vtab_config','int',[
'sqlite3__wasm_vtab_config','int',[
'sqlite3*', 'int', 'int']
);
}/* end vtab-related setup */
@ -889,7 +907,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
consistency with non-special-case wrappings.
*/
const __dbArgcMismatch = (pDb,f,n)=>{
return util.sqlite3_wasm_db_error(pDb, capi.SQLITE_MISUSE,
return util.sqlite3__wasm_db_error(pDb, capi.SQLITE_MISUSE,
f+"() requires "+n+" argument"+
(1===n?"":'s')+".");
};
@ -898,7 +916,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
argument and require SQLITE_UTF8. Sets the db error code to
SQLITE_FORMAT and returns that code. */
const __errEncoding = (pDb)=>{
return util.sqlite3_wasm_db_error(
return util.sqlite3__wasm_db_error(
pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding."
);
};
@ -1128,7 +1146,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
return rc;
}catch(e){
return util.sqlite3_wasm_db_error(pDb, e);
return util.sqlite3__wasm_db_error(pDb, e);
}
};
@ -1254,7 +1272,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return rc;
}catch(e){
console.error("sqlite3_create_function_v2() setup threw:",e);
return util.sqlite3_wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
}
};
@ -1299,7 +1317,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return rc;
}catch(e){
console.error("sqlite3_create_window_function() setup threw:",e);
return util.sqlite3_wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e);
}
};
/**
@ -1394,7 +1412,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
case 'string': return __prepare.basic(pDb, xSql, xSqlLen, prepFlags, ppStmt, null);
case 'number': return __prepare.full(pDb, xSql, xSqlLen, prepFlags, ppStmt, pzTail);
default:
return util.sqlite3_wasm_db_error(
return util.sqlite3__wasm_db_error(
pDb, capi.SQLITE_MISUSE,
"Invalid SQL argument type for sqlite3_prepare_v2/v3()."
);
@ -1438,7 +1456,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}else if('string'===typeof text){
[p, n] = wasm.allocCString(text);
}else{
return util.sqlite3_wasm_db_error(
return util.sqlite3__wasm_db_error(
capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
"Invalid 3rd argument type for sqlite3_bind_text()."
);
@ -1446,7 +1464,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return __bindText(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
}catch(e){
wasm.dealloc(p);
return util.sqlite3_wasm_db_error(
return util.sqlite3__wasm_db_error(
capi.sqlite3_db_handle(pStmt), e
);
}
@ -1472,7 +1490,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}else if('string'===typeof pMem){
[p, n] = wasm.allocCString(pMem);
}else{
return util.sqlite3_wasm_db_error(
return util.sqlite3__wasm_db_error(
capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE,
"Invalid 3rd argument type for sqlite3_bind_blob()."
);
@ -1480,7 +1498,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
}catch(e){
wasm.dealloc(p);
return util.sqlite3_wasm_db_error(
return util.sqlite3__wasm_db_error(
capi.sqlite3_db_handle(pStmt), e
);
}
@ -1504,11 +1522,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
case capi.SQLITE_CONFIG_SORTERREF_SIZE: // 28 /* int nByte */
case capi.SQLITE_CONFIG_STMTJRNL_SPILL: // 26 /* int nByte */
case capi.SQLITE_CONFIG_URI:// 17 /* int */
return wasm.exports.sqlite3_wasm_config_i(op, args[0]);
return wasm.exports.sqlite3__wasm_config_i(op, args[0]);
case capi.SQLITE_CONFIG_LOOKASIDE: // 13 /* int int */
return wasm.exports.sqlite3_wasm_config_ii(op, args[0], args[1]);
return wasm.exports.sqlite3__wasm_config_ii(op, args[0], args[1]);
case capi.SQLITE_CONFIG_MEMDB_MAXSIZE: // 29 /* sqlite3_int64 */
return wasm.exports.sqlite3_wasm_config_j(op, args[0]);
return wasm.exports.sqlite3__wasm_config_j(op, args[0]);
case capi.SQLITE_CONFIG_GETMALLOC: // 5 /* sqlite3_mem_methods* */
case capi.SQLITE_CONFIG_GETMUTEX: // 11 /* sqlite3_mutex_methods* */
case capi.SQLITE_CONFIG_GETPCACHE2: // 19 /* sqlite3_pcache_methods2* */
@ -1574,11 +1592,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
if( pKvvfs ){/* kvvfs-specific glue */
if(util.isUIThread()){
const kvvfsMethods = new capi.sqlite3_kvvfs_methods(
wasm.exports.sqlite3_wasm_kvvfs_methods()
wasm.exports.sqlite3__wasm_kvvfs_methods()
);
delete capi.sqlite3_kvvfs_methods;
const kvvfsMakeKey = wasm.exports.sqlite3_wasm_kvvfsMakeKeyOnPstack,
const kvvfsMakeKey = wasm.exports.sqlite3__wasm_kvvfsMakeKeyOnPstack,
pstack = wasm.pstack;
const kvvfsStorage = (zClass)=>
@ -1587,7 +1605,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
/**
Implementations for members of the object referred to by
sqlite3_wasm_kvvfs_methods(). We swap out the native
sqlite3__wasm_kvvfs_methods(). We swap out the native
implementations with these, which use localStorage or
sessionStorage for their backing store.
*/
@ -1667,5 +1685,181 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
}/*pKvvfs*/
/* Warn if client-level code makes use of FuncPtrAdapter. */
wasm.xWrap.FuncPtrAdapter.warnOnUse = true;
const StructBinder = sqlite3.StructBinder
/* we require a local alias b/c StructBinder is removed from the sqlite3
object during the final steps of the API cleanup. */;
/**
Installs a StructBinder-bound function pointer member of the
given name and function in the given StructBinder.StructType
target object.
It creates a WASM proxy for the given function and arranges for
that proxy to be cleaned up when tgt.dispose() is called. Throws
on the slightest hint of error, e.g. tgt is-not-a StructType,
name does not map to a struct-bound member, etc.
As a special case, if the given function is a pointer, then
`wasm.functionEntry()` is used to validate that it is a known
function. If so, it is used as-is with no extra level of proxying
or cleanup, else an exception is thrown. It is legal to pass a
value of 0, indicating a NULL pointer, with the caveat that 0
_is_ a legal function pointer in WASM but it will not be accepted
as such _here_. (Justification: the function at address zero must
be one which initially came from the WASM module, not a method we
want to bind to a virtual table or VFS.)
This function returns a proxy for itself which is bound to tgt
and takes 2 args (name,func). That function returns the same
thing as this one, permitting calls to be chained.
If called with only 1 arg, it has no side effects but returns a
func with the same signature as described above.
ACHTUNG: because we cannot generically know how to transform JS
exceptions into result codes, the installed functions do no
automatic catching of exceptions. It is critical, to avoid
undefined behavior in the C layer, that methods mapped via
this function do not throw. The exception, as it were, to that
rule is...
If applyArgcCheck is true then each JS function (as opposed to
function pointers) gets wrapped in a proxy which asserts that it
is passed the expected number of arguments, throwing if the
argument count does not match expectations. That is only intended
for dev-time usage for sanity checking, and may leave the C
environment in an undefined state.
*/
const installMethod = function callee(
tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck
){
if(!(tgt instanceof StructBinder.StructType)){
toss("Usage error: target object is-not-a StructType.");
}else if(!(func instanceof Function) && !wasm.isPtr(func)){
toss("Usage errror: expecting a Function or WASM pointer to one.");
}
if(1===arguments.length){
return (n,f)=>callee(tgt, n, f, applyArgcCheck);
}
if(!callee.argcProxy){
callee.argcProxy = function(tgt, funcName, func,sig){
return function(...args){
if(func.length!==arguments.length){
toss("Argument mismatch for",
tgt.structInfo.name+"::"+funcName
+": Native signature is:",sig);
}
return func.apply(this, args);
}
};
/* An ondispose() callback for use with
StructBinder-created types. */
callee.removeFuncList = function(){
if(this.ondispose.__removeFuncList){
this.ondispose.__removeFuncList.forEach(
(v,ndx)=>{
if('number'===typeof v){
try{wasm.uninstallFunction(v)}
catch(e){/*ignore*/}
}
/* else it's a descriptive label for the next number in
the list. */
}
);
delete this.ondispose.__removeFuncList;
}
};
}/*static init*/
const sigN = tgt.memberSignature(name);
if(sigN.length<2){
toss("Member",name,"does not have a function pointer signature:",sigN);
}
const memKey = tgt.memberKey(name);
const fProxy = (applyArgcCheck && !wasm.isPtr(func))
/** This middle-man proxy is only for use during development, to
confirm that we always pass the proper number of
arguments. We know that the C-level code will always use the
correct argument count. */
? callee.argcProxy(tgt, memKey, func, sigN)
: func;
if(wasm.isPtr(fProxy)){
if(fProxy && !wasm.functionEntry(fProxy)){
toss("Pointer",fProxy,"is not a WASM function table entry.");
}
tgt[memKey] = fProxy;
}else{
const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name, true));
tgt[memKey] = pFunc;
if(!tgt.ondispose || !tgt.ondispose.__removeFuncList){
tgt.addOnDispose('ondispose.__removeFuncList handler',
callee.removeFuncList);
tgt.ondispose.__removeFuncList = [];
}
tgt.ondispose.__removeFuncList.push(memKey, pFunc);
}
return (n,f)=>callee(tgt, n, f, applyArgcCheck);
}/*installMethod*/;
installMethod.installMethodArgcCheck = false;
/**
Installs methods into the given StructBinder.StructType-type
instance. Each entry in the given methods object must map to a
known member of the given StructType, else an exception will be
triggered. See installMethod() for more details, including the
semantics of the 3rd argument.
As an exception to the above, if any two or more methods in the
2nd argument are the exact same function, installMethod() is
_not_ called for the 2nd and subsequent instances, and instead
those instances get assigned the same method pointer which is
created for the first instance. This optimization is primarily to
accommodate special handling of sqlite3_module::xConnect and
xCreate methods.
On success, returns its first argument. Throws on error.
*/
const installMethods = function(
structInstance, methods, applyArgcCheck = installMethod.installMethodArgcCheck
){
const seen = new Map /* map of <Function, memberName> */;
for(const k of Object.keys(methods)){
const m = methods[k];
const prior = seen.get(m);
if(prior){
const mkey = structInstance.memberKey(k);
structInstance[mkey] = structInstance[structInstance.memberKey(prior)];
}else{
installMethod(structInstance, k, m, applyArgcCheck);
seen.set(m, k);
}
}
return structInstance;
};
/**
Equivalent to calling installMethod(this,...arguments) with a
first argument of this object. If called with 1 or 2 arguments
and the first is an object, it's instead equivalent to calling
installMethods(this,...arguments).
*/
StructBinder.StructType.prototype.installMethod = function callee(
name, func, applyArgcCheck = installMethod.installMethodArgcCheck
){
return (arguments.length < 3 && name && 'object'===typeof name)
? installMethods(this, ...arguments)
: installMethod(this, ...arguments);
};
/**
Equivalent to calling installMethods() with a first argument
of this object.
*/
StructBinder.StructType.prototype.installMethods = function(
methods, applyArgcCheck = installMethod.installMethodArgcCheck
){
return installMethods(this, methods, applyArgcCheck);
};
});

View File

@ -1061,7 +1061,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
are undefined if the passed-in value did not come from
this.pointer.
*/
restore: wasm.exports.sqlite3_wasm_pstack_restore,
restore: wasm.exports.sqlite3__wasm_pstack_restore,
/**
Attempts to allocate the given number of bytes from the
pstack. On success, it zeroes out a block of memory of the
@ -1083,7 +1083,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
if('string'===typeof n && !(n = wasm.sizeofIR(n))){
WasmAllocError.toss("Invalid value for pstack.alloc(",arguments[0],")");
}
return wasm.exports.sqlite3_wasm_pstack_alloc(n)
return wasm.exports.sqlite3__wasm_pstack_alloc(n)
|| WasmAllocError.toss("Could not allocate",n,
"bytes from the pstack.");
},
@ -1163,10 +1163,10 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
*/
pointer: {
configurable: false, iterable: true, writeable: false,
get: wasm.exports.sqlite3_wasm_pstack_ptr
get: wasm.exports.sqlite3__wasm_pstack_ptr
//Whether or not a setter as an alternative to restore() is
//clearer or would just lead to confusion is unclear.
//set: wasm.exports.sqlite3_wasm_pstack_restore
//set: wasm.exports.sqlite3__wasm_pstack_restore
},
/**
sqlite3.wasm.pstack.quota to the total number of bytes
@ -1175,7 +1175,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
*/
quota: {
configurable: false, iterable: true, writeable: false,
get: wasm.exports.sqlite3_wasm_pstack_quota
get: wasm.exports.sqlite3__wasm_pstack_quota
},
/**
sqlite3.wasm.pstack.remaining resolves to the amount of space
@ -1183,7 +1183,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
*/
remaining: {
configurable: false, iterable: true, writeable: false,
get: wasm.exports.sqlite3_wasm_pstack_remaining
get: wasm.exports.sqlite3__wasm_pstack_remaining
}
})/*wasm.pstack properties*/;
@ -1256,14 +1256,14 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
}
try{
if(pdir && 0===wasm.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
'sqlite3__wasm_init_wasmfs', 'i32', ['string'], pdir
)){
return __wasmfsOpfsDir = pdir;
}else{
return __wasmfsOpfsDir = "";
}
}catch(e){
// sqlite3_wasm_init_wasmfs() is not available
// sqlite3__wasm_init_wasmfs() is not available
return __wasmfsOpfsDir = "";
}
};
@ -1365,7 +1365,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
const zSchema = schema
? (wasm.isPtr(schema) ? schema : wasm.scopedAllocCString(''+schema))
: 0;
let rc = wasm.exports.sqlite3_wasm_db_serialize(
let rc = wasm.exports.sqlite3__wasm_db_serialize(
pDb, zSchema, ppOut, pSize, 0
);
if(rc){
@ -1391,7 +1391,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
or not provided, then "main" is assumed.
*/
capi.sqlite3_js_db_vfs =
(dbPointer, dbName=0)=>wasm.sqlite3_wasm_db_vfs(dbPointer, dbName);
(dbPointer, dbName=0)=>util.sqlite3__wasm_db_vfs(dbPointer, dbName);
/**
A thin wrapper around capi.sqlite3_aggregate_context() which
@ -1449,7 +1449,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
if(!util.isInt32(dataLen) || dataLen<0){
SQLite3Error.toss("Invalid 3rd argument for sqlite3_js_posix_create_file().");
}
const rc = wasm.sqlite3_wasm_posix_create_file(filename, pData, dataLen);
const rc = util.sqlite3__wasm_posix_create_file(filename, pData, dataLen);
if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
capi.sqlite3_js_rc_str(rc));
}finally{
@ -1551,7 +1551,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
SQLite3Error.toss("Invalid 4th argument for sqlite3_js_vfs_create_file().");
}
try{
const rc = wasm.sqlite3_wasm_vfs_create_file(vfs, filename, pData, dataLen);
const rc = util.sqlite3__wasm_vfs_create_file(vfs, filename, pData, dataLen);
if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code",
capi.sqlite3_js_rc_str(rc));
}finally{
@ -1672,12 +1672,12 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
*/
capi.sqlite3_db_config = function(pDb, op, ...args){
if(!this.s){
this.s = wasm.xWrap('sqlite3_wasm_db_config_s','int',
this.s = wasm.xWrap('sqlite3__wasm_db_config_s','int',
['sqlite3*', 'int', 'string:static']
/* MAINDBNAME requires a static string */);
this.pii = wasm.xWrap('sqlite3_wasm_db_config_pii', 'int',
this.pii = wasm.xWrap('sqlite3__wasm_db_config_pii', 'int',
['sqlite3*', 'int', '*','int', 'int']);
this.ip = wasm.xWrap('sqlite3_wasm_db_config_ip','int',
this.ip = wasm.xWrap('sqlite3__wasm_db_config_ip','int',
['sqlite3*', 'int', 'int','*']);
}
switch(op){

View File

@ -359,6 +359,7 @@
*/
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const util = sqlite3.util;
sqlite3.initWorker1API = function(){
'use strict';
const toss = (...args)=>{throw new Error(args.join(' '))};
@ -409,12 +410,12 @@ sqlite3.initWorker1API = function(){
if(db){
delete this.dbs[getDbId(db)];
const filename = db.filename;
const pVfs = sqlite3.wasm.sqlite3_wasm_db_vfs(db.pointer, 0);
const pVfs = util.sqlite3__wasm_db_vfs(db.pointer, 0);
db.close();
const ddNdx = this.dbList.indexOf(db);
if(ddNdx>=0) this.dbList.splice(ddNdx, 1);
if(alsoUnlink && filename && pVfs){
sqlite3.wasm.sqlite3_wasm_vfs_unlink(pVfs, filename);
util.sqlite3__wasm_vfs_unlink(pVfs, filename);
}
}
},
@ -495,12 +496,12 @@ sqlite3.initWorker1API = function(){
}
if(pVfs){
/* 2022-11-02: this feature is as-yet untested except that
sqlite3_wasm_vfs_create_file() has been tested from the
sqlite3__wasm_vfs_create_file() has been tested from the
browser dev console. */
let pMem;
try{
pMem = sqlite3.wasm.allocFromTypedArray(byteArray);
const rc = sqlite3.wasm.sqlite3_wasm_vfs_create_file(
const rc = util.sqlite3__wasm_vfs_create_file(
pVfs, oargs.filename, pMem, byteArray.byteLength
);
if(rc) sqlite3.SQLite3Error.toss(rc);

View File

@ -0,0 +1,103 @@
/*
** 2022-11-30
**
** The author disclaims copyright to this source code. In place of a
** legal notice, here is a blessing:
**
** * May you do good and not evil.
** * May you find forgiveness for yourself and forgive others.
** * May you share freely, never taking more than you give.
*/
/**
This file installs sqlite3.vfs, a namespace of helpers for use in
the creation of JavaScript implementations of sqlite3_vfs.
*/
'use strict';
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss3;
const vfs = Object.create(null);
sqlite3.vfs = vfs;
/**
Uses sqlite3_vfs_register() to register this
sqlite3.capi.sqlite3_vfs instance. This object must have already
been filled out properly. If the first argument is truthy, the
VFS is registered as the default VFS, else it is not.
On success, returns this object. Throws on error.
*/
capi.sqlite3_vfs.prototype.registerVfs = function(asDefault=false){
if(!(this instanceof sqlite3.capi.sqlite3_vfs)){
toss("Expecting a sqlite3_vfs-type argument.");
}
const rc = capi.sqlite3_vfs_register(this, asDefault ? 1 : 0);
if(rc){
toss("sqlite3_vfs_register(",this,") failed with rc",rc);
}
if(this.pointer !== capi.sqlite3_vfs_find(this.$zName)){
toss("BUG: sqlite3_vfs_find(vfs.$zName) failed for just-installed VFS",
this);
}
return this;
};
/**
A wrapper for
sqlite3.StructBinder.StructType.prototype.installMethods() or
registerVfs() to reduce installation of a VFS and/or its I/O
methods to a single call.
Accepts an object which contains the properties "io" and/or
"vfs", each of which is itself an object with following properties:
- `struct`: an sqlite3.StructBinder.StructType-type struct. This
must be a populated (except for the methods) object of type
sqlite3_io_methods (for the "io" entry) or sqlite3_vfs (for the
"vfs" entry).
- `methods`: an object mapping sqlite3_io_methods method names
(e.g. 'xClose') to JS implementations of those methods. The JS
implementations must be call-compatible with their native
counterparts.
For each of those object, this function passes its (`struct`,
`methods`, (optional) `applyArgcCheck`) properties to
installMethods().
If the `vfs` entry is set then:
- Its `struct` property's registerVfs() is called. The
`vfs` entry may optionally have an `asDefault` property, which
gets passed as the argument to registerVfs().
- If `struct.$zName` is falsy and the entry has a string-type
`name` property, `struct.$zName` is set to the C-string form of
that `name` value before registerVfs() is called. That string
gets added to the on-dispose state of the struct.
On success returns this object. Throws on error.
*/
vfs.installVfs = function(opt){
let count = 0;
const propList = ['io','vfs'];
for(const key of propList){
const o = opt[key];
if(o){
++count;
o.struct.installMethods(o.methods, !!o.applyArgcCheck);
if('vfs'===key){
if(!o.struct.$zName && 'string'===typeof o.name){
o.struct.addOnDispose(
o.struct.$zName = wasm.allocCString(o.name)
);
}
o.struct.registerVfs(!!o.asDefault);
}
}
}
if(!count) toss("Misuse: installVfs() options object requires at least",
"one of:", propList);
return this;
};
}/*sqlite3ApiBootstrap.initializers.push()*/);

View File

@ -245,7 +245,8 @@ const installOpfsVfs = function callee(options){
opfsIoMethods.$iVersion = 1;
opfsVfs.$iVersion = 2/*yes, two*/;
opfsVfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof;
opfsVfs.$mxPathname = 1024/*sure, why not?*/;
opfsVfs.$mxPathname = 1024/* sure, why not? The OPFS name length limit
is undocumented/unspecified. */;
opfsVfs.$zName = wasm.allocCString("opfs");
// All C-side memory of opfsVfs is zeroed out, but just to be explicit:
opfsVfs.$xDlOpen = opfsVfs.$xDlError = opfsVfs.$xDlSym = opfsVfs.$xDlClose = null;
@ -993,27 +994,6 @@ const installOpfsVfs = function callee(options){
*/
opfsUtil.randomFilename = randomFilename;
/**
Re-registers the OPFS VFS. This is intended only for odd use
cases which have to call sqlite3_shutdown() as part of their
initialization process, which will unregister the VFS
registered by installOpfsVfs(). If passed a truthy value, the
OPFS VFS is registered as the default VFS, else it is not made
the default. Returns the result of the the
sqlite3_vfs_register() call.
Design note: the problem of having to re-register things after
a shutdown/initialize pair is more general. How to best plug
that in to the library is unclear. In particular, we cannot
hook in to any C-side calls to sqlite3_initialize(), so we
cannot add an after-initialize callback mechanism.
*/
opfsUtil.registerVfs = (asDefault=false)=>{
return wasm.exports.sqlite3_vfs_register(
opfsVfs.pointer, asDefault ? 1 : 0
);
};
/**
Returns a promise which resolves to an object which represents
all files and directories in the OPFS tree. The top-most object

View File

@ -10,19 +10,13 @@
*/
/**
This file installs sqlite3.vfs, and object which exists to assist
in the creation of JavaScript implementations of sqlite3_vfs, along
with its virtual table counterpart, sqlite3.vtab.
This file installs sqlite3.vtab, a namespace of helpers for use in
the creation of JavaScript implementations virtual tables.
*/
'use strict';
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss3;
const vfs = Object.create(null), vtab = Object.create(null);
const StructBinder = sqlite3.StructBinder
/* we require a local alias b/c StructBinder is removed from the sqlite3
object during the final steps of the API cleanup. */;
sqlite3.vfs = vfs;
const vtab = Object.create(null);
sqlite3.vtab = vtab;
const sii = capi.sqlite3_index_info;
@ -72,257 +66,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return asPtr ? ptr : new sii.sqlite3_index_orderby(ptr);
};
/**
Installs a StructBinder-bound function pointer member of the
given name and function in the given StructType target object.
It creates a WASM proxy for the given function and arranges for
that proxy to be cleaned up when tgt.dispose() is called. Throws
on the slightest hint of error, e.g. tgt is-not-a StructType,
name does not map to a struct-bound member, etc.
As a special case, if the given function is a pointer, then
`wasm.functionEntry()` is used to validate that it is a known
function. If so, it is used as-is with no extra level of proxying
or cleanup, else an exception is thrown. It is legal to pass a
value of 0, indicating a NULL pointer, with the caveat that 0
_is_ a legal function pointer in WASM but it will not be accepted
as such _here_. (Justification: the function at address zero must
be one which initially came from the WASM module, not a method we
want to bind to a virtual table or VFS.)
This function returns a proxy for itself which is bound to tgt
and takes 2 args (name,func). That function returns the same
thing as this one, permitting calls to be chained.
If called with only 1 arg, it has no side effects but returns a
func with the same signature as described above.
ACHTUNG: because we cannot generically know how to transform JS
exceptions into result codes, the installed functions do no
automatic catching of exceptions. It is critical, to avoid
undefined behavior in the C layer, that methods mapped via
this function do not throw. The exception, as it were, to that
rule is...
If applyArgcCheck is true then each JS function (as opposed to
function pointers) gets wrapped in a proxy which asserts that it
is passed the expected number of arguments, throwing if the
argument count does not match expectations. That is only intended
for dev-time usage for sanity checking, and will leave the C
environment in an undefined state.
*/
const installMethod = function callee(
tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck
){
if(!(tgt instanceof StructBinder.StructType)){
toss("Usage error: target object is-not-a StructType.");
}else if(!(func instanceof Function) && !wasm.isPtr(func)){
toss("Usage errror: expecting a Function or WASM pointer to one.");
}
if(1===arguments.length){
return (n,f)=>callee(tgt, n, f, applyArgcCheck);
}
if(!callee.argcProxy){
callee.argcProxy = function(tgt, funcName, func,sig){
return function(...args){
if(func.length!==arguments.length){
toss("Argument mismatch for",
tgt.structInfo.name+"::"+funcName
+": Native signature is:",sig);
}
return func.apply(this, args);
}
};
/* An ondispose() callback for use with
StructBinder-created types. */
callee.removeFuncList = function(){
if(this.ondispose.__removeFuncList){
this.ondispose.__removeFuncList.forEach(
(v,ndx)=>{
if('number'===typeof v){
try{wasm.uninstallFunction(v)}
catch(e){/*ignore*/}
}
/* else it's a descriptive label for the next number in
the list. */
}
);
delete this.ondispose.__removeFuncList;
}
};
}/*static init*/
const sigN = tgt.memberSignature(name);
if(sigN.length<2){
toss("Member",name,"does not have a function pointer signature:",sigN);
}
const memKey = tgt.memberKey(name);
const fProxy = (applyArgcCheck && !wasm.isPtr(func))
/** This middle-man proxy is only for use during development, to
confirm that we always pass the proper number of
arguments. We know that the C-level code will always use the
correct argument count. */
? callee.argcProxy(tgt, memKey, func, sigN)
: func;
if(wasm.isPtr(fProxy)){
if(fProxy && !wasm.functionEntry(fProxy)){
toss("Pointer",fProxy,"is not a WASM function table entry.");
}
tgt[memKey] = fProxy;
}else{
const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name, true));
tgt[memKey] = pFunc;
if(!tgt.ondispose || !tgt.ondispose.__removeFuncList){
tgt.addOnDispose('ondispose.__removeFuncList handler',
callee.removeFuncList);
tgt.ondispose.__removeFuncList = [];
}
tgt.ondispose.__removeFuncList.push(memKey, pFunc);
}
return (n,f)=>callee(tgt, n, f, applyArgcCheck);
}/*installMethod*/;
installMethod.installMethodArgcCheck = false;
/**
Installs methods into the given StructType-type instance. Each
entry in the given methods object must map to a known member of
the given StructType, else an exception will be triggered. See
installMethod() for more details, including the semantics of the
3rd argument.
As an exception to the above, if any two or more methods in the
2nd argument are the exact same function, installMethod() is
_not_ called for the 2nd and subsequent instances, and instead
those instances get assigned the same method pointer which is
created for the first instance. This optimization is primarily to
accommodate special handling of sqlite3_module::xConnect and
xCreate methods.
On success, returns its first argument. Throws on error.
*/
const installMethods = function(
structInstance, methods, applyArgcCheck = installMethod.installMethodArgcCheck
){
const seen = new Map /* map of <Function, memberName> */;
for(const k of Object.keys(methods)){
const m = methods[k];
const prior = seen.get(m);
if(prior){
const mkey = structInstance.memberKey(k);
structInstance[mkey] = structInstance[structInstance.memberKey(prior)];
}else{
installMethod(structInstance, k, m, applyArgcCheck);
seen.set(m, k);
}
}
return structInstance;
};
/**
Equivalent to calling installMethod(this,...arguments) with a
first argument of this object. If called with 1 or 2 arguments
and the first is an object, it's instead equivalent to calling
installMethods(this,...arguments).
*/
StructBinder.StructType.prototype.installMethod = function callee(
name, func, applyArgcCheck = installMethod.installMethodArgcCheck
){
return (arguments.length < 3 && name && 'object'===typeof name)
? installMethods(this, ...arguments)
: installMethod(this, ...arguments);
};
/**
Equivalent to calling installMethods() with a first argument
of this object.
*/
StructBinder.StructType.prototype.installMethods = function(
methods, applyArgcCheck = installMethod.installMethodArgcCheck
){
return installMethods(this, methods, applyArgcCheck);
};
/**
Uses sqlite3_vfs_register() to register this
sqlite3.capi.sqlite3_vfs. This object must have already been
filled out properly. If the first argument is truthy, the VFS is
registered as the default VFS, else it is not.
On success, returns this object. Throws on error.
*/
capi.sqlite3_vfs.prototype.registerVfs = function(asDefault=false){
if(!(this instanceof sqlite3.capi.sqlite3_vfs)){
toss("Expecting a sqlite3_vfs-type argument.");
}
const rc = capi.sqlite3_vfs_register(this, asDefault ? 1 : 0);
if(rc){
toss("sqlite3_vfs_register(",this,") failed with rc",rc);
}
if(this.pointer !== capi.sqlite3_vfs_find(this.$zName)){
toss("BUG: sqlite3_vfs_find(vfs.$zName) failed for just-installed VFS",
this);
}
return this;
};
/**
A wrapper for installMethods() or registerVfs() to reduce
installation of a VFS and/or its I/O methods to a single
call.
Accepts an object which contains the properties "io" and/or
"vfs", each of which is itself an object with following properties:
- `struct`: an sqlite3.StructType-type struct. This must be a
populated (except for the methods) object of type
sqlite3_io_methods (for the "io" entry) or sqlite3_vfs (for the
"vfs" entry).
- `methods`: an object mapping sqlite3_io_methods method names
(e.g. 'xClose') to JS implementations of those methods. The JS
implementations must be call-compatible with their native
counterparts.
For each of those object, this function passes its (`struct`,
`methods`, (optional) `applyArgcCheck`) properties to
installMethods().
If the `vfs` entry is set then:
- Its `struct` property's registerVfs() is called. The
`vfs` entry may optionally have an `asDefault` property, which
gets passed as the argument to registerVfs().
- If `struct.$zName` is falsy and the entry has a string-type
`name` property, `struct.$zName` is set to the C-string form of
that `name` value before registerVfs() is called. That string
gets added to the on-dispose state of the struct.
On success returns this object. Throws on error.
*/
vfs.installVfs = function(opt){
let count = 0;
const propList = ['io','vfs'];
for(const key of propList){
const o = opt[key];
if(o){
++count;
installMethods(o.struct, o.methods, !!o.applyArgcCheck);
if('vfs'===key){
if(!o.struct.$zName && 'string'===typeof o.name){
o.struct.addOnDispose(
o.struct.$zName = wasm.allocCString(o.name)
);
}
o.struct.registerVfs(!!o.asDefault);
}
}
}
if(!count) toss("Misuse: installVfs() options object requires at least",
"one of:", propList);
return this;
};
/**
Internal factory function for xVtab and xCursor impls.
*/
@ -456,30 +199,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/
vtab.xIndexInfo = (pIdxInfo)=>new capi.sqlite3_index_info(pIdxInfo);
/**
Given an error object, this function returns
sqlite3.capi.SQLITE_NOMEM if (e instanceof
sqlite3.WasmAllocError), else it returns its
second argument. Its intended usage is in the methods
of a sqlite3_vfs or sqlite3_module:
```
try{
let rc = ...
return rc;
}catch(e){
return sqlite3.vtab.exceptionToRc(e, sqlite3.capi.SQLITE_XYZ);
// where SQLITE_XYZ is some call-appropriate result code.
}
```
*/
/**vfs.exceptionToRc = vtab.exceptionToRc =
(e, defaultRc=capi.SQLITE_ERROR)=>(
(e instanceof sqlite3.WasmAllocError)
? capi.SQLITE_NOMEM
: defaultRc
);*/
/**
Given an sqlite3_module method name and error object, this
function returns sqlite3.capi.SQLITE_NOMEM if (e instanceof
@ -525,20 +244,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
};
vtab.xError.errorReporter = 1 ? console.error.bind(console) : false;
/**
"The problem" with this is that it introduces an outer function with
a different arity than the passed-in method callback. That means we
cannot do argc validation on these. Additionally, some methods (namely
xConnect) may have call-specific error handling. It would be a shame to
hard-coded that per-method support in this function.
*/
/** vtab.methodCatcher = function(methodName, method, defaultErrRc=capi.SQLITE_ERROR){
return function(...args){
try { method(...args); }
}catch(e){ return vtab.xError(methodName, e, defaultRc) }
};
*/
/**
A helper for sqlite3_vtab::xRowid() and xUpdate()
implementations. It must be passed the final argument to one of
@ -685,12 +390,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
remethods[k] = fwrap(k, m);
}
}
installMethods(mod, remethods, false);
mod.installMethods(remethods, false);
}else{
// No automatic exception handling. Trust the client
// to not throw.
installMethods(
mod, methods, !!opt.applyArgcCheck/*undocumented option*/
mod.installMethods(
methods, !!opt.applyArgcCheck/*undocumented option*/
);
}
if(0===mod.$iVersion){

View File

@ -238,28 +238,28 @@
** Another option is to malloc() a chunk of our own and call that our
** "stack".
*/
SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_end(void){
SQLITE_WASM_EXPORT void * sqlite3__wasm_stack_end(void){
extern void __heap_base
/* see https://stackoverflow.com/questions/10038964 */;
return &__heap_base;
}
SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_begin(void){
SQLITE_WASM_EXPORT void * sqlite3__wasm_stack_begin(void){
extern void __data_end;
return &__data_end;
}
static void * pWasmStackPtr = 0;
SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_ptr(void){
if(!pWasmStackPtr) pWasmStackPtr = sqlite3_wasm_stack_end();
SQLITE_WASM_EXPORT void * sqlite3__wasm_stack_ptr(void){
if(!pWasmStackPtr) pWasmStackPtr = sqlite3__wasm_stack_end();
return pWasmStackPtr;
}
SQLITE_WASM_EXPORT void sqlite3_wasm_stack_restore(void * p){
SQLITE_WASM_EXPORT void sqlite3__wasm_stack_restore(void * p){
pWasmStackPtr = p;
}
SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_alloc(int n){
SQLITE_WASM_EXPORT void * sqlite3__wasm_stack_alloc(int n){
if(n<=0) return 0;
n = (n + 7) & ~7 /* align to 8-byte boundary */;
unsigned char * const p = (unsigned char *)sqlite3_wasm_stack_ptr();
unsigned const char * const b = (unsigned const char *)sqlite3_wasm_stack_begin();
unsigned char * const p = (unsigned char *)sqlite3__wasm_stack_ptr();
unsigned const char * const b = (unsigned const char *)sqlite3__wasm_stack_begin();
if(b + n >= p || b + n < b/*overflow*/) return 0;
return pWasmStackPtr = p - n;
}
@ -267,7 +267,7 @@ SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_alloc(int n){
/*
** State for the "pseudo-stack" allocator implemented in
** sqlite3_wasm_pstack_xyz(). In order to avoid colliding with
** sqlite3__wasm_pstack_xyz(). In order to avoid colliding with
** Emscripten-controled stack space, it carves out a bit of stack
** memory to use for that purpose. This memory ends up in the
** WASM-managed memory, such that routines which manipulate the wasm
@ -291,14 +291,14 @@ static struct {
/*
** Returns the current pstack position.
*/
SQLITE_WASM_EXPORT void * sqlite3_wasm_pstack_ptr(void){
SQLITE_WASM_EXPORT void * sqlite3__wasm_pstack_ptr(void){
return PStack.pPos;
}
/*
** Sets the pstack position poitner to p. Results are undefined if the
** given value did not come from sqlite3_wasm_pstack_ptr().
** given value did not come from sqlite3__wasm_pstack_ptr().
*/
SQLITE_WASM_EXPORT void sqlite3_wasm_pstack_restore(unsigned char * p){
SQLITE_WASM_EXPORT void sqlite3__wasm_pstack_restore(unsigned char * p){
assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos);
assert(0==((unsigned long long)p & 0x7));
if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){
@ -313,7 +313,7 @@ SQLITE_WASM_EXPORT void sqlite3_wasm_pstack_restore(unsigned char * p){
** JS code from having to do so, and most uses of the pstack will
** call for doing so).
*/
SQLITE_WASM_EXPORT void * sqlite3_wasm_pstack_alloc(int n){
SQLITE_WASM_EXPORT void * sqlite3__wasm_pstack_alloc(int n){
if( n<=0 ) return 0;
//if( n & 0x7 ) n += 8 - (n & 0x7) /* align to 8-byte boundary */;
n = (n + 7) & ~7 /* align to 8-byte boundary */;
@ -324,9 +324,9 @@ SQLITE_WASM_EXPORT void * sqlite3_wasm_pstack_alloc(int n){
}
/*
** Return the number of bytes left which can be
** sqlite3_wasm_pstack_alloc()'d.
** sqlite3__wasm_pstack_alloc()'d.
*/
SQLITE_WASM_EXPORT int sqlite3_wasm_pstack_remaining(void){
SQLITE_WASM_EXPORT int sqlite3__wasm_pstack_remaining(void){
assert(PStack.pPos >= PStack.pBegin);
assert(PStack.pPos <= PStack.pEnd);
return (int)(PStack.pPos - PStack.pBegin);
@ -337,7 +337,7 @@ SQLITE_WASM_EXPORT int sqlite3_wasm_pstack_remaining(void){
** any space which is currently allocated. This value is a
** compile-time constant.
*/
SQLITE_WASM_EXPORT int sqlite3_wasm_pstack_quota(void){
SQLITE_WASM_EXPORT int sqlite3__wasm_pstack_quota(void){
return (int)(PStack.pEnd - PStack.pBegin);
}
@ -356,7 +356,7 @@ SQLITE_WASM_EXPORT int sqlite3_wasm_pstack_quota(void){
** Returns err_code.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_db_error(sqlite3*db, int err_code, const char *zMsg){
int sqlite3__wasm_db_error(sqlite3*db, int err_code, const char *zMsg){
if( db!=0 ){
if( 0!=zMsg ){
const int nMsg = sqlite3Strlen30(zMsg);
@ -380,7 +380,7 @@ struct WasmTestStruct {
};
typedef struct WasmTestStruct WasmTestStruct;
SQLITE_WASM_EXPORT
void sqlite3_wasm_test_struct(WasmTestStruct * s){
void sqlite3__wasm_test_struct(WasmTestStruct * s){
if(s){
s->v4 *= 2;
s->v8 = s->v4 * 2;
@ -408,7 +408,7 @@ void sqlite3_wasm_test_struct(WasmTestStruct * s){
** increased. In debug builds that will trigger an assert().
*/
SQLITE_WASM_EXPORT
const char * sqlite3_wasm_enum_json(void){
const char * sqlite3__wasm_enum_json(void){
static char aBuffer[1024 * 20] = {0} /* where the JSON goes */;
int n = 0, nChildren = 0, nStruct = 0
/* output counters for figuring out where commas go */;
@ -425,7 +425,7 @@ const char * sqlite3_wasm_enum_json(void){
/* Core output macros... */
#define lenCheck assert(zPos < zEnd - 128 \
&& "sqlite3_wasm_enum_json() buffer is too small."); \
&& "sqlite3__wasm_enum_json() buffer is too small."); \
if( zPos >= zEnd - 128 ) return 0
#define outf(format,...) \
zPos += snprintf(zPos, ((size_t)(zEnd - zPos)), format, __VA_ARGS__); \
@ -1220,7 +1220,7 @@ const char * sqlite3_wasm_enum_json(void){
** call is returned.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_vfs_unlink(sqlite3_vfs *pVfs, const char *zName){
int sqlite3__wasm_vfs_unlink(sqlite3_vfs *pVfs, const char *zName){
int rc = SQLITE_MISUSE /* ??? */;
if( 0==pVfs && 0!=zName ) pVfs = sqlite3_vfs_find(0);
if( zName && pVfs && pVfs->xDelete ){
@ -1238,7 +1238,7 @@ int sqlite3_wasm_vfs_unlink(sqlite3_vfs *pVfs, const char *zName){
** given name is open.
*/
SQLITE_WASM_EXPORT
sqlite3_vfs * sqlite3_wasm_db_vfs(sqlite3 *pDb, const char *zDbName){
sqlite3_vfs * sqlite3__wasm_db_vfs(sqlite3 *pDb, const char *zDbName){
sqlite3_vfs * pVfs = 0;
sqlite3_file_control(pDb, zDbName ? zDbName : "main",
SQLITE_FCNTL_VFS_POINTER, &pVfs);
@ -1261,7 +1261,7 @@ sqlite3_vfs * sqlite3_wasm_db_vfs(sqlite3 *pDb, const char *zDbName){
** SQLITE_MISUSE if pDb is NULL.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_db_reset(sqlite3 *pDb){
int sqlite3__wasm_db_reset(sqlite3 *pDb){
int rc = SQLITE_MISUSE;
if( pDb ){
sqlite3_table_column_metadata(pDb, "main", 0, 0, 0, 0, 0, 0, 0);
@ -1288,11 +1288,11 @@ int sqlite3_wasm_db_reset(sqlite3 *pDb){
** takes no measures to ensure that is the case.
**
** This implementation appears to work fine, but
** sqlite3_wasm_db_serialize() is arguably the better way to achieve
** sqlite3__wasm_db_serialize() is arguably the better way to achieve
** this.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_db_export_chunked( sqlite3* pDb,
int sqlite3__wasm_db_export_chunked( sqlite3* pDb,
int (*xCallback)(unsigned const char *zOut, int n) ){
sqlite3_int64 nSize = 0;
sqlite3_int64 nPos = 0;
@ -1343,7 +1343,7 @@ int sqlite3_wasm_db_export_chunked( sqlite3* pDb,
** sqlite3_free() to free it.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_db_serialize( sqlite3 *pDb, const char *zSchema,
int sqlite3__wasm_db_serialize( sqlite3 *pDb, const char *zSchema,
unsigned char **pOut,
sqlite3_int64 *nOut, unsigned int mFlags ){
unsigned char * z;
@ -1366,7 +1366,7 @@ int sqlite3_wasm_db_serialize( sqlite3 *pDb, const char *zSchema,
** this function's out-of-scope use of the sqlite3_vfs/file/io_methods
** APIs leads to triggering of assertions in the core library. Its use
** is now deprecated and VFS-specific APIs for importing files need to
** be found to replace it. sqlite3_wasm_posix_create_file() is
** be found to replace it. sqlite3__wasm_posix_create_file() is
** suitable for the "unix" family of VFSes.
**
** Creates a new file using the I/O API of the given VFS, containing
@ -1407,7 +1407,7 @@ int sqlite3_wasm_db_serialize( sqlite3 *pDb, const char *zSchema,
** support is disabled or unavailable.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs,
int sqlite3__wasm_vfs_create_file( sqlite3_vfs *pVfs,
const char *zFilename,
const unsigned char * pData,
int nData ){
@ -1497,7 +1497,7 @@ int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs,
** SQLITE_IOERR on error.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_posix_create_file( const char *zFilename,
int sqlite3__wasm_posix_create_file( const char *zFilename,
const unsigned char * pData,
int nData ){
int rc;
@ -1520,17 +1520,17 @@ int sqlite3_wasm_posix_create_file( const char *zFilename,
** for use by the sqlite project's own JS/WASM bindings.
**
** Allocates sqlite3KvvfsMethods.nKeySize bytes from
** sqlite3_wasm_pstack_alloc() and returns 0 if that allocation fails,
** sqlite3__wasm_pstack_alloc() and returns 0 if that allocation fails,
** else it passes that string to kvstorageMakeKey() and returns a
** NUL-terminated pointer to that string. It is up to the caller to
** use sqlite3_wasm_pstack_restore() to free the returned pointer.
** use sqlite3__wasm_pstack_restore() to free the returned pointer.
*/
SQLITE_WASM_EXPORT
char * sqlite3_wasm_kvvfsMakeKeyOnPstack(const char *zClass,
char * sqlite3__wasm_kvvfsMakeKeyOnPstack(const char *zClass,
const char *zKeyIn){
assert(sqlite3KvvfsMethods.nKeySize>24);
char *zKeyOut =
(char *)sqlite3_wasm_pstack_alloc(sqlite3KvvfsMethods.nKeySize);
(char *)sqlite3__wasm_pstack_alloc(sqlite3KvvfsMethods.nKeySize);
if(zKeyOut){
kvstorageMakeKey(zClass, zKeyIn, zKeyOut);
}
@ -1545,7 +1545,7 @@ char * sqlite3_wasm_kvvfsMakeKeyOnPstack(const char *zClass,
** I/O methods and associated state.
*/
SQLITE_WASM_EXPORT
sqlite3_kvvfs_methods * sqlite3_wasm_kvvfs_methods(void){
sqlite3_kvvfs_methods * sqlite3__wasm_kvvfs_methods(void){
return &sqlite3KvvfsMethods;
}
@ -1560,7 +1560,7 @@ sqlite3_kvvfs_methods * sqlite3_wasm_kvvfs_methods(void){
** valid value.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_vtab_config(sqlite3 *pDb, int op, int arg){
int sqlite3__wasm_vtab_config(sqlite3 *pDb, int op, int arg){
switch(op){
case SQLITE_VTAB_DIRECTONLY:
case SQLITE_VTAB_INNOCUOUS:
@ -1580,7 +1580,7 @@ int sqlite3_wasm_vtab_config(sqlite3 *pDb, int op, int arg){
** (int,int*) variadic args.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_db_config_ip(sqlite3 *pDb, int op, int arg1, int* pArg2){
int sqlite3__wasm_db_config_ip(sqlite3 *pDb, int op, int arg1, int* pArg2){
switch(op){
case SQLITE_DBCONFIG_ENABLE_FKEY:
case SQLITE_DBCONFIG_ENABLE_TRIGGER:
@ -1613,7 +1613,7 @@ int sqlite3_wasm_db_config_ip(sqlite3 *pDb, int op, int arg1, int* pArg2){
** (void*,int,int) variadic args.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_db_config_pii(sqlite3 *pDb, int op, void * pArg1, int arg2, int arg3){
int sqlite3__wasm_db_config_pii(sqlite3 *pDb, int op, void * pArg1, int arg2, int arg3){
switch(op){
case SQLITE_DBCONFIG_LOOKASIDE:
return sqlite3_db_config(pDb, op, pArg1, arg2, arg3);
@ -1629,7 +1629,7 @@ int sqlite3_wasm_db_config_pii(sqlite3 *pDb, int op, void * pArg1, int arg2, int
** (const char *) variadic args.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_db_config_s(sqlite3 *pDb, int op, const char *zArg){
int sqlite3__wasm_db_config_s(sqlite3 *pDb, int op, const char *zArg){
switch(op){
case SQLITE_DBCONFIG_MAINDBNAME:
return sqlite3_db_config(pDb, op, zArg);
@ -1646,7 +1646,7 @@ int sqlite3_wasm_db_config_s(sqlite3 *pDb, int op, const char *zArg){
** a single integer argument.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_config_i(int op, int arg){
int sqlite3__wasm_config_i(int op, int arg){
return sqlite3_config(op, arg);
}
@ -1658,7 +1658,7 @@ int sqlite3_wasm_config_i(int op, int arg){
** two int arguments.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_config_ii(int op, int arg1, int arg2){
int sqlite3__wasm_config_ii(int op, int arg1, int arg2){
return sqlite3_config(op, arg1, arg2);
}
@ -1670,7 +1670,7 @@ int sqlite3_wasm_config_ii(int op, int arg1, int arg2){
** a single i64 argument.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_config_j(int op, sqlite3_int64 arg){
int sqlite3__wasm_config_j(int op, sqlite3_int64 arg){
return sqlite3_config(op, arg);
}
@ -1689,17 +1689,17 @@ int sqlite3_wasm_config_j(int op, sqlite3_int64 arg){
**
** ```
** sqlite3.wasm.functionEntry(
** sqlite3.wasm.exports.sqlite3_wasm_ptr_to_sqlite3_free()
** sqlite3.wasm.exports.sqlite3__wasm_ptr_to_sqlite3_free()
** ) === sqlite3.wasm.exports.sqlite3_free
** ```
**
** Using a function to return this pointer, as opposed to exporting it
** via sqlite3_wasm_enum_json(), is an attempt to work around a
** via sqlite3__wasm_enum_json(), is an attempt to work around a
** Safari-specific quirk covered at
** https://sqlite.org/forum/info/e5b20e1feb37a19a.
**/
SQLITE_WASM_EXPORT
void * sqlite3_wasm_ptr_to_sqlite3_free(void){
void * sqlite3__wasm_ptr_to_sqlite3_free(void){
return (void*)sqlite3_free;
}
#endif
@ -1729,7 +1729,7 @@ void * sqlite3_wasm_ptr_to_sqlite3_free(void){
** defined, SQLITE_NOTFOUND is returned without side effects.
*/
SQLITE_WASM_EXPORT
int sqlite3_wasm_init_wasmfs(const char *zMountPoint){
int sqlite3__wasm_init_wasmfs(const char *zMountPoint){
static backend_t pOpfs = 0;
if( !zMountPoint || !*zMountPoint ) zMountPoint = "/opfs";
if( !pOpfs ){
@ -1749,7 +1749,7 @@ int sqlite3_wasm_init_wasmfs(const char *zMountPoint){
}
#else
SQLITE_WASM_EXPORT
int sqlite3_wasm_init_wasmfs(const char *zUnused){
int sqlite3__wasm_init_wasmfs(const char *zUnused){
//emscripten_console_warn("WASMFS OPFS is not compiled in.");
if(zUnused){/*unused*/}
return SQLITE_NOTFOUND;
@ -1759,51 +1759,51 @@ int sqlite3_wasm_init_wasmfs(const char *zUnused){
#if SQLITE_WASM_TESTS
SQLITE_WASM_EXPORT
int sqlite3_wasm_test_intptr(int * p){
int sqlite3__wasm_test_intptr(int * p){
return *p = *p * 2;
}
SQLITE_WASM_EXPORT
void * sqlite3_wasm_test_voidptr(void * p){
void * sqlite3__wasm_test_voidptr(void * p){
return p;
}
SQLITE_WASM_EXPORT
int64_t sqlite3_wasm_test_int64_max(void){
int64_t sqlite3__wasm_test_int64_max(void){
return (int64_t)0x7fffffffffffffff;
}
SQLITE_WASM_EXPORT
int64_t sqlite3_wasm_test_int64_min(void){
return ~sqlite3_wasm_test_int64_max();
int64_t sqlite3__wasm_test_int64_min(void){
return ~sqlite3__wasm_test_int64_max();
}
SQLITE_WASM_EXPORT
int64_t sqlite3_wasm_test_int64_times2(int64_t x){
int64_t sqlite3__wasm_test_int64_times2(int64_t x){
return x * 2;
}
SQLITE_WASM_EXPORT
void sqlite3_wasm_test_int64_minmax(int64_t * min, int64_t *max){
*max = sqlite3_wasm_test_int64_max();
*min = sqlite3_wasm_test_int64_min();
void sqlite3__wasm_test_int64_minmax(int64_t * min, int64_t *max){
*max = sqlite3__wasm_test_int64_max();
*min = sqlite3__wasm_test_int64_min();
/*printf("minmax: min=%lld, max=%lld\n", *min, *max);*/
}
SQLITE_WASM_EXPORT
int64_t sqlite3_wasm_test_int64ptr(int64_t * p){
/*printf("sqlite3_wasm_test_int64ptr( @%lld = 0x%llx )\n", (int64_t)p, *p);*/
int64_t sqlite3__wasm_test_int64ptr(int64_t * p){
/*printf("sqlite3__wasm_test_int64ptr( @%lld = 0x%llx )\n", (int64_t)p, *p);*/
return *p = *p * 2;
}
SQLITE_WASM_EXPORT
void sqlite3_wasm_test_stack_overflow(int recurse){
if(recurse) sqlite3_wasm_test_stack_overflow(recurse);
void sqlite3__wasm_test_stack_overflow(int recurse){
if(recurse) sqlite3__wasm_test_stack_overflow(recurse);
}
/* For testing the 'string:dealloc' whwasmutil.xWrap() conversion. */
SQLITE_WASM_EXPORT
char * sqlite3_wasm_test_str_hello(int fail){
char * sqlite3__wasm_test_str_hello(int fail){
char * s = fail ? 0 : (char *)sqlite3_malloc(6);
if(s){
memcpy(s, "hello", 5);
@ -1838,12 +1838,12 @@ char * sqlite3_wasm_test_str_hello(int fail){
** optional + or - sign in front, or a hexadecimal
** literal of the form 0x...
*/
static int sqlite3_wasm_SQLTester_strnotglob(const char *zGlob, const char *z){
static int sqlite3__wasm_SQLTester_strnotglob(const char *zGlob, const char *z){
int c, c2;
int invert;
int seen;
typedef int (*recurse_f)(const char *,const char *);
static const recurse_f recurse = sqlite3_wasm_SQLTester_strnotglob;
static const recurse_f recurse = sqlite3__wasm_SQLTester_strnotglob;
while( (c = (*(zGlob++)))!=0 ){
if( c=='*' ){
@ -1918,11 +1918,10 @@ static int sqlite3_wasm_SQLTester_strnotglob(const char *zGlob, const char *z){
}
SQLITE_WASM_EXPORT
int sqlite3_wasm_SQLTester_strglob(const char *zGlob, const char *z){
return !sqlite3_wasm_SQLTester_strnotglob(zGlob, z);
int sqlite3__wasm_SQLTester_strglob(const char *zGlob, const char *z){
return !sqlite3__wasm_SQLTester_strnotglob(zGlob, z);
}
#endif /* SQLITE_WASM_TESTS */
#undef SQLITE_WASM_EXPORT

View File

@ -374,9 +374,7 @@
"for use in the dev console.", sqlite3);
globalThis.sqlite3 = sqlite3;
const dbVfs = sqlite3.wasm.xWrap('fiddle_db_vfs', "*", ['string']);
fiddleModule.fsUnlink = (fn)=>{
return sqlite3.wasm.sqlite3_wasm_vfs_unlink(dbVfs(0), fn);
};
fiddleModule.fsUnlink = (fn)=>fiddleModule.FS.unlink(fn);
wMsg('fiddle-ready');
}).catch(e=>{
console.error("Fiddle worker init failed:",e);

View File

@ -111,10 +111,6 @@
self.sqlite3InitModule(EmscriptenModule).then(async (sqlite3)=>{
const S = globalThis.S = App.sqlite3 = sqlite3;
log("Loaded speedtest1 module. Setting up...");
App.vfsUnlink = function(pDb, fname){
const pVfs = S.wasm.sqlite3_wasm_db_vfs(pDb, 0);
if(pVfs) S.wasm.sqlite3_wasm_vfs_unlink(pVfs, fname||0);
};
App.pDir = wasmfsDir(S.wasm);
App.wasm = S.wasm;
//if(App.pDir) log("Persistent storage:",pDir);

View File

@ -63,7 +63,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
/* Predicate for tests/groups. */
const testIsTodo = ()=>false;
const haveWasmCTests = ()=>{
return !!wasm.exports.sqlite3_wasm_test_intptr;
return !!wasm.exports.sqlite3__wasm_test_intptr;
};
const hasOpfs = ()=>{
return globalThis.FileSystemHandle
@ -722,7 +722,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
//log("xCall()...");
{
const pJson = w.xCall('sqlite3_wasm_enum_json');
const pJson = w.xCall('sqlite3__wasm_enum_json');
T.assert(Number.isFinite(pJson)).assert(w.cstrlen(pJson)>300);
}
@ -736,9 +736,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.mustThrowMatching(()=>fw(1), /requires 0 arg/);
let rc = fw();
T.assert('string'===typeof rc).assert(rc.length>5);
rc = w.xCallWrapped('sqlite3_wasm_enum_json','*');
rc = w.xCallWrapped('sqlite3__wasm_enum_json','*');
T.assert(rc>0 && Number.isFinite(rc));
rc = w.xCallWrapped('sqlite3_wasm_enum_json','utf8');
rc = w.xCallWrapped('sqlite3__wasm_enum_json','utf8');
T.assert('string'===typeof rc).assert(rc.length>300);
@ -821,7 +821,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
if(haveWasmCTests()){
if(!sqlite3.config.useStdAlloc){
fw = w.xWrap('sqlite3_wasm_test_str_hello', 'utf8:dealloc',['i32']);
fw = w.xWrap('sqlite3__wasm_test_str_hello', 'utf8:dealloc',['i32']);
rc = fw(0);
T.assert('hello'===rc);
rc = fw(1);
@ -831,14 +831,14 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
if(w.bigIntEnabled){
w.xWrap.resultAdapter('thrice', (v)=>3n*BigInt(v));
w.xWrap.argAdapter('twice', (v)=>2n*BigInt(v));
fw = w.xWrap('sqlite3_wasm_test_int64_times2','thrice','twice');
fw = w.xWrap('sqlite3__wasm_test_int64_times2','thrice','twice');
rc = fw(1);
T.assert(12n===rc);
w.scopedAllocCall(function(){
const pI1 = w.scopedAlloc(8), pI2 = pI1+4;
w.pokePtr([pI1, pI2], 0);
const f = w.xWrap('sqlite3_wasm_test_int64_minmax',undefined,['i64*','i64*']);
const f = w.xWrap('sqlite3__wasm_test_int64_minmax',undefined,['i64*','i64*']);
const [r1, r2] = w.peek64([pI1, pI2]);
T.assert(!Number.isSafeInteger(r1)).assert(!Number.isSafeInteger(r2));
});
@ -942,7 +942,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
assert(wts.pointer>0).assert(0===wts.$v4).assert(0n===wts.$v8).
assert(0===wts.$ppV).assert(0===wts.$xFunc);
const testFunc =
W.xGet('sqlite3_wasm_test_struct'/*name gets mangled in -O3 builds!*/);
W.xGet('sqlite3__wasm_test_struct'/*name gets mangled in -O3 builds!*/);
let counter = 0;
//log("wts.pointer =",wts.pointer);
const wtsFunc = function(arg){
@ -1128,7 +1128,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.g('sqlite3.oo1')
.t('Create db', function(sqlite3){
const dbFile = '/tester1.db';
wasm.sqlite3_wasm_vfs_unlink(0, dbFile);
sqlite3.util.sqlite3__wasm_vfs_unlink(0, dbFile);
const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c');
db.onclose = {
disposeAfter: [],
@ -1459,7 +1459,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
rv = db.exec("SELECT 1 WHERE 0",{rowMode: 0});
T.assert(Array.isArray(rv)).assert(0===rv.length);
if(wasm.bigIntEnabled && haveWasmCTests()){
const mI = wasm.xCall('sqlite3_wasm_test_int64_max');
const mI = wasm.xCall('sqlite3__wasm_test_int64_max');
const b = BigInt(Number.MAX_SAFE_INTEGER * 2);
T.assert(b === db.selectValue("SELECT "+b)).
assert(b === db.selectValue("SELECT ?", b)).
@ -1685,7 +1685,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert(n>0 && db2.selectValue(sql) === n);
}finally{
db2.close();
wasm.sqlite3_wasm_vfs_unlink(0, filename);
sqlite3.util.sqlite3__wasm_vfs_unlink(0, filename);
}
}
}/*sqlite3_js_posix_create_file()*/)
@ -2075,7 +2075,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
try{
ptrInt = w.scopedAlloc(4);
w.poke32(ptrInt,origValue);
const cf = w.xGet('sqlite3_wasm_test_intptr');
const cf = w.xGet('sqlite3__wasm_test_intptr');
const oldPtrInt = ptrInt;
T.assert(origValue === w.peek32(ptrInt));
const rc = cf(ptrInt);
@ -2090,13 +2090,13 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
const v64 = ()=>w.peek64(pi64)
T.assert(v64() == o64);
//T.assert(o64 === w.peek64(pi64));
const cf64w = w.xGet('sqlite3_wasm_test_int64ptr');
const cf64w = w.xGet('sqlite3__wasm_test_int64ptr');
cf64w(pi64);
T.assert(v64() == BigInt(2 * o64));
cf64w(pi64);
T.assert(v64() == BigInt(4 * o64));
const biTimes2 = w.xGet('sqlite3_wasm_test_int64_times2');
const biTimes2 = w.xGet('sqlite3__wasm_test_int64_times2');
T.assert(BigInt(2 * o64) ===
biTimes2(BigInt(o64)/*explicit conv. required to avoid TypeError
in the call :/ */));
@ -2106,13 +2106,13 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
const g64 = (p)=>w.peek64(p);
w.poke64([pMin, pMax], 0);
const minMaxI64 = [
w.xCall('sqlite3_wasm_test_int64_min'),
w.xCall('sqlite3_wasm_test_int64_max')
w.xCall('sqlite3__wasm_test_int64_min'),
w.xCall('sqlite3__wasm_test_int64_max')
];
T.assert(minMaxI64[0] < BigInt(Number.MIN_SAFE_INTEGER)).
assert(minMaxI64[1] > BigInt(Number.MAX_SAFE_INTEGER));
//log("int64_min/max() =",minMaxI64, typeof minMaxI64[0]);
w.xCall('sqlite3_wasm_test_int64_minmax', pMin, pMax);
w.xCall('sqlite3__wasm_test_int64_minmax', pMin, pMax);
T.assert(g64(pMin) === minMaxI64[0], "int64 mismatch").
assert(g64(pMax) === minMaxI64[1], "int64 mismatch");
//log("pMin",g64(pMin), "pMax",g64(pMax));
@ -2560,7 +2560,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
////////////////////////////////////////////////////////////////////////
.t('Close db', function(){
T.assert(this.db).assert(wasm.isPtr(this.db.pointer));
//wasm.sqlite3_wasm_db_reset(this.db); // will leak virtual tables!
//wasm.sqlite3__wasm_db_reset(this.db); // will leak virtual tables!
this.db.close();
T.assert(!this.db.pointer);
})
@ -2892,7 +2892,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs');
T.assert(pVfs);
const unlink = this.opfsUnlink =
(fn=filename)=>{wasm.sqlite3_wasm_vfs_unlink(pVfs,fn)};
(fn=filename)=>{sqlite3.util.sqlite3__wasm_vfs_unlink(pVfs,fn)};
unlink();
let db = new sqlite3.oo1.OpfsDb(filename);
try {
@ -3209,6 +3209,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
print: log,
printErr: error
}).then(async function(sqlite3){
TestUtil.assert(!!sqlite3.util);
log("Done initializing WASM/JS bits. Running tests...");
sqlite3.config.warn("Installing sqlite3 bits as global S for local dev/test purposes.");
globalThis.S = sqlite3;
@ -3227,9 +3228,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
logClass('warning',"BigInt/int64 support is disabled.");
}
if(haveWasmCTests()){
log("sqlite3_wasm_test_...() APIs are available.");
log("sqlite3__wasm_test_...() APIs are available.");
}else{
logClass('warning',"sqlite3_wasm_test_...() APIs unavailable.");
logClass('warning',"sqlite3__wasm_test_...() APIs unavailable.");
}
log("registered vfs list =",capi.sqlite3_js_vfs_list().join(', '));
TestUtil.runTests(sqlite3);

View File

@ -1,5 +1,5 @@
C Version\s3.45.0
D 2024-01-15T17:01:13.164
C Various\sbuild-\sand\scode-reorg\scleanups\sfor\sext/wasm.\sNo\sfunctional\schanges.
D 2024-01-16T14:24:35.067
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -575,7 +575,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile 99aad6d6a28c43573f80825e986427c1a024a3298aaf0c69c56a0c6b336f12c8
F ext/wasm/GNUmakefile 867c903a27fa0d53a3bf1b01d8c7bb713456f87e0939c3cac9f07faa68f58734
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@ -586,23 +586,24 @@ F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f30
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api f442460ed9a109e637dd3ea1caa4489553ad9414e8988118b208bb7a4bbece6b
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md 5eb44fa02e9c693a1884a3692428647894b0380b24bca120866b7a24c8786134
F ext/wasm/api/README.md 34fe11466f9c1d81b10a0469e1114e5f1c5a6365c73d80a1a6ca639a1a358b73
F ext/wasm/api/extern-post-js.c-pp.js c4154a7f90c2d7e51fd6738273908152036c3457fdc0b6523f1be3ef51105aac
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08902f15c34720ee4a1
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
F ext/wasm/api/post-js-header.js 04dc12c3edd666b64a1b4ef3b6690c88dcc653f26451fd4734472d8e29c1c122
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
F ext/wasm/api/sqlite3-api-glue.js 119b91c8a7ce6648679eb66fcdd1ed07ef7fd892eb501d658fbfefcc962012d9
F ext/wasm/api/sqlite3-api-glue.js 587dc6db2d69329a5f4cb9635c377f516cf4a8e30f443f33380e5044889ec71b
F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb8a1757c50a91e506c0
F ext/wasm/api/sqlite3-api-prologue.js 9aeba7b45cf41b3a26d34d7fb2525633cd1adfc544888c1ea8dbb077496f4ce9
F ext/wasm/api/sqlite3-api-worker1.js fd46628ef147dd5856c88f63a9a279a40f744f1fdfddd55251ad8fbc3d8200ae
F ext/wasm/api/sqlite3-api-prologue.js fffcee629bf020a8ccf5c367fbe6a169f5d5d73dfce1707a75c9fbf4aa21c7da
F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d w ext/wasm/api/sqlite3-v-helper.js
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 595953994aa3ae2287c889c4da39ab3d6f17b6461ecf4bec334b7a3faafddb02
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 46c4afa6c50d7369252c104f274ad977a97e91ccfafc38b400fe36e90bdda88e
F ext/wasm/api/sqlite3-wasm.c dfd1f1a225b267e8fd641dcd6c7d579fbe2b731aeaa123324135efac830a2bcf
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js ebf6c7e997cd8948b35b3afc550b0503dd53febd9d2b56354efd11d985e5f0f2
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js a2fcbc3fecdd0eea229283584ebc122f29d98194083675dbe5cb2cf3a17fe309
F ext/wasm/api/sqlite3-wasm.c d33a16495ca871781e78812d3a18fed78b797468fffee657b8d7199b277ff359
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js f234191fe6bf41a5a1e59c9f43ed816e74a522b3d60d3f556f66c3085c448503
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
@ -627,7 +628,7 @@ F ext/wasm/dist.make 3a851858aad72e246a5d9c5aaf6b6a144305f1bf898ac1846760ea7bab9
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
F ext/wasm/fiddle.make fa2ba6e90457ba2a71cb745f200d409caf773076df75ae5b177cc225d7627a11
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/fiddle/fiddle-worker.js e0153f9af6500805c6f09c0b3cfdb7d857e9d6863dbee9d50d1628fccf5f4b4d
F ext/wasm/fiddle/fiddle-worker.js 9be57887756c6854dbdcb5e7d8b7a26935d565491333a2f91dc4113598c659b5
F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/index-dist.html e91d76e4581185238fd3d42ed86ec600f7023ed3e3a944c5c356f25304bf1263
@ -640,7 +641,7 @@ F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd84223150
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe
F ext/wasm/speedtest1-worker.html 864b65ed78ce24847a348c180e7f267621a02ca027068a1863ec1c90187c1852
F ext/wasm/speedtest1-worker.js 4d2ea70a3c24e05bdca78025202841f33d298c4fa9541a0070c3228661f89ecd
F ext/wasm/speedtest1-worker.js 95e549e13a4d35863a9a7fc66122b5f546c0130d3be7b06dfcc556eb66d24bde
F ext/wasm/speedtest1.html ff048b4a623aa192e83e143e48f1ce2a899846dd42c023fdedc8772b6e3f07da
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
@ -649,7 +650,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
F ext/wasm/tester1.c-pp.js a92dc256738dbd1b50f142d1fd0c835294ba09b7bb6526650360e942f88cb63f
F ext/wasm/tester1.c-pp.js 7c51d19f3644904156a154ddedd7024539ffba1a4e2df5e1efe10333e5b91b8f
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@ -2157,10 +2158,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P f47a5f4e0ce078e6cc1183e6cbb3c4013af379b496efae94863a42e5c39928ed
R ab5a4296dc153e787688d4ab18626d94
T +sym-release *
T +sym-version-3.45.0 *
U drh
Z fb1ecde834264212c972e5b30790a005
P 1066602b2b1976fe58b5150777cced894af17c803e068f5918390d6915b46e1d 5836657929d7d6d3f0d5865c9f6de4e4c00edd53d15a246802b375fa15d0f255
R 59b52c4e344f8871547dae1c84cd4afc
T +closed 5836657929d7d6d3f0d5865c9f6de4e4c00edd53d15a246802b375fa15d0f255 Closed\sby\sintegrate-merge.
U stephan
Z 3deb67a608c540b8c97149e595f2800e
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
1066602b2b1976fe58b5150777cced894af17c803e068f5918390d6915b46e1d
835bd4a11e56ede378235379604ac01350ee92433f952a23c761f7be492fd475