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

Split the JS vfs/vtab helper code into discreet units as a step towards a build which optionally elides those pieces. This is an internal restructuring change and does not affect the API.

FossilOrigin-Name: ede945fd2360097d9961b8a4b8fb48fea57399cb9163534ed1c3c6b86588b0a5
This commit is contained in:
stephan
2024-01-11 12:31:58 +00:00
parent 6b36d0b461
commit 598328209f
7 changed files with 334 additions and 327 deletions

View File

@ -433,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:

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

@ -329,6 +329,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 +349,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 +369,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 +435,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
@ -602,7 +613,12 @@ 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.util. Some of them get exposed to clients via variants
in wasm.sqlite3_js_...().
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.wasmInternal = [
["sqlite3__wasm_db_reset", "int", "sqlite3*"],
@ -652,7 +668,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 +690,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))
@ -1667,5 +1684,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

@ -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, an object which exists to assist
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. 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

@ -10,19 +10,17 @@
*/
/**
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, an object which exists to assist
in the creation of JavaScript implementations virtual tables.
Maintenance note: 2024-01-11: this file requires that StructBinder
has been extended with the installMethod(s)() methods, which
currently happens in sqlite3-api-glue.js.
*/
'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 +70,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 +203,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 +248,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 +394,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

@ -1,5 +1,5 @@
C Make\sexplicit\swhich\sJS\sAPIs\sare\sfor\sinternal\suse\sonly\sby\smoving\sthe\sJS-bound\sinternal-use-only\sfunctions\sout\sof\sclient-visible\sreach\sand\srenaming\sthe\sWASM-exported\sones\sfrom\ssqlite3_wasm...\sto\ssqlite3__wasm...\s(with\stwo\sunderscores).\sThese\shave\salways\sbeen\sdocumented\sas\sinternal-use-only,\sso\sthis\sis\snot\sa\sbreaking\schange\sexcept\sfor\sclients\swhich\shave\signored\sthe\sdocs.
D 2024-01-08T07:52:47.965
C Split\sthe\sJS\svfs/vtab\shelper\scode\sinto\sdiscreet\sunits\sas\sa\sstep\stowards\sa\sbuild\swhich\soptionally\selides\sthose\spieces.\sThis\sis\san\sinternal\srestructuring\schange\sand\sdoes\snot\saffect\sthe\sAPI.
D 2024-01-11T12:31:58.929
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 0f4ccfd350a9b0ebe60183fb4ad3b41c670eec62c88279f22e2627887b524b3c
F ext/wasm/GNUmakefile 693ff54a2710751a34ef4419a63eb7ea957f7e730f837fc1ef1dc475bdc5a6c8
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@ -586,22 +586,23 @@ 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/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
F ext/wasm/api/sqlite3-api-glue.js 8f4478c927466245259478788c293810bc812ac8c49df38c62574966d836131a
F ext/wasm/api/sqlite3-api-glue.js 81ec1423e8c6dc8c26a3af470c993460d2f5137319ab1a00581203017e8b6b1f
F ext/wasm/api/sqlite3-api-oo1.js 7f3bcf0549ac44cde4b9da0b642d771916738d3f6781fb8a1757c50a91e506c0
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 6c02e969ad988e083415221e84445711730a321c748d8555bb61aebec6b4a37c 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-vtab-helper.c-pp.js ebbabbd33915904d3135680a0ea25f374adb60d6f39d664994bc48ac1673c280
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
@ -2156,11 +2157,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 40f0a29e6dd90fcb969d7c0e49728ba0ee8f31d9e8f502b9a21469620a8ad283
R 31be0596762218f8c1e89235c4c8d052
T *branch * wasm-post-3.45
T *sym-wasm-post-3.45 *
T -sym-trunk * Cancelled\sby\sbranch.
P 0eddc20f37988df6bce5f407b69e4a315e5cca4af104586e6fe942f0d656cccd
R 1d7e7db8e9c4453b4e333bcfcd1a037e
U stephan
Z 0af9fee02d812416e8b303fb5ea1a236
Z d03852f251d26d93c85f34544dbc6738
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
0eddc20f37988df6bce5f407b69e4a315e5cca4af104586e6fe942f0d656cccd
ede945fd2360097d9961b8a4b8fb48fea57399cb9163534ed1c3c6b86588b0a5