1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Experimentally add sqlite3.oo1.DB/Stmt.wrapHandle(), which allow DB/Stmt instances to wrap a (sqlite3*)/(sqlite3_stmt*) optionally with or without taking ownership of it. The intent is to enable mix-and-match use of the C API, the oo1 API, and any other hypothetical API which exposes those pointers. oo1.Stmt.parameterCount is now a property access interceptor like Stmt.columnCount is, but that doesn't change how it's used.

FossilOrigin-Name: 1227543b87c3320d6b80e0f61b88ea53b68779966a0295c4d6a1db6369c48207
This commit is contained in:
stephan
2025-07-06 15:01:44 +00:00
parent 27408ab9c9
commit 4d453cc2ed
4 changed files with 346 additions and 84 deletions

View File

@ -37,6 +37,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
it. it.
*/ */
const __ptrMap = new WeakMap(); const __ptrMap = new WeakMap();
/**
A Set of oo1.DB objects which are proxies for (A) (sqlite3*) or
another oo1.DB object or (B) oo1.Stmt objects which are proxies
for (sqlite3_stmt*) pointers. Such objects do not own their
underlying handle and that handle must be guaranteed (by the
client) to outlive the proxy. These proxies are primarily
intended as a way to briefly wrap an (sqlite3[_stmt]*) object as
an oo1.DB/Stmt without taking over ownership.
*/
const __doesNotOwnHandle = new Set();
/** /**
Map of DB instances to objects, each object being a map of Stmt Map of DB instances to objects, each object being a map of Stmt
wasm pointers to Stmt objects. wasm pointers to Stmt objects.
@ -234,73 +244,89 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}; };
} }
const opt = ctor.normalizeArgs(...args); const opt = ctor.normalizeArgs(...args);
let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags; //sqlite3.config.debug("DB ctor",opt);
if(('string'!==typeof fn && 'number'!==typeof fn) let pDb;
|| 'string'!==typeof flagsStr if( (pDb = opt['sqlite3*']) ){
|| (vfsName && ('string'!==typeof vfsName && 'number'!==typeof vfsName))){ /* This property ^^^^^ is very specifically NOT DOCUMENTED and
sqlite3.config.error("Invalid DB ctor args",opt,arguments); NOT part of the public API. This is a back door for functions
toss3("Invalid arguments for DB constructor."); like DB.wrapDbHandle(). */
} //sqlite3.config.debug("creating proxy db from",opt);
let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn; if( !opt['sqlite3*:takeOwnership'] ){
const vfsCheck = ctor._name2vfs[fnJs]; /* This is object does not own its handle. */
if(vfsCheck){ __doesNotOwnHandle.add(this);
vfsName = vfsCheck.vfs;
fn = fnJs = vfsCheck.filename(fnJs);
}
let pDb, oflags = 0;
if( flagsStr.indexOf('c')>=0 ){
oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
}
if( flagsStr.indexOf('w')>=0 ) oflags |= capi.SQLITE_OPEN_READWRITE;
if( 0===oflags ) oflags |= capi.SQLITE_OPEN_READONLY;
oflags |= capi.SQLITE_OPEN_EXRESCODE;
const stack = wasm.pstack.pointer;
try {
const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */;
let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || 0);
pDb = wasm.peekPtr(pPtr);
checkSqlite3Rc(pDb, rc);
capi.sqlite3_extended_result_codes(pDb, 1);
if(flagsStr.indexOf('t')>=0){
capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
__dbTraceToConsole, pDb);
} }
}catch( e ){ this.filename = capi.sqlite3_db_filename(pDb,'main');
if( pDb ) capi.sqlite3_close_v2(pDb); }else{
throw e; let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags;
}finally{ if(('string'!==typeof fn && 'number'!==typeof fn)
wasm.pstack.restore(stack); || 'string'!==typeof flagsStr
|| (vfsName && ('string'!==typeof vfsName && 'number'!==typeof vfsName))){
sqlite3.config.error("Invalid DB ctor args",opt,arguments);
toss3("Invalid arguments for DB constructor.");
}
let fnJs = ('number'===typeof fn) ? wasm.cstrToJs(fn) : fn;
const vfsCheck = ctor._name2vfs[fnJs];
if(vfsCheck){
vfsName = vfsCheck.vfs;
fn = fnJs = vfsCheck.filename(fnJs);
}
let oflags = 0;
if( flagsStr.indexOf('c')>=0 ){
oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
}
if( flagsStr.indexOf('w')>=0 ) oflags |= capi.SQLITE_OPEN_READWRITE;
if( 0===oflags ) oflags |= capi.SQLITE_OPEN_READONLY;
oflags |= capi.SQLITE_OPEN_EXRESCODE;
const stack = wasm.pstack.pointer;
try {
const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */;
let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || 0);
pDb = wasm.peekPtr(pPtr);
checkSqlite3Rc(pDb, rc);
capi.sqlite3_extended_result_codes(pDb, 1);
if(flagsStr.indexOf('t')>=0){
capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
__dbTraceToConsole, pDb);
}
}catch( e ){
if( pDb ) capi.sqlite3_close_v2(pDb);
throw e;
}finally{
wasm.pstack.restore(stack);
}
this.filename = fnJs;
} }
this.filename = fnJs;
__ptrMap.set(this, pDb); __ptrMap.set(this, pDb);
__stmtMap.set(this, Object.create(null)); __stmtMap.set(this, Object.create(null));
try{ if( !opt['sqlite3*'] ){
try{
//#if enable-see //#if enable-see
dbCtorApplySEEKey(this,opt); dbCtorApplySEEKey(this,opt);
//#endif //#endif
// Check for per-VFS post-open SQL/callback... // Check for per-VFS post-open SQL/callback...
const pVfs = capi.sqlite3_js_db_vfs(pDb) const pVfs = capi.sqlite3_js_db_vfs(pDb)
|| toss3("Internal error: cannot get VFS for new db handle."); || toss3("Internal error: cannot get VFS for new db handle.");
const postInitSql = __vfsPostOpenCallback[pVfs]; const postInitSql = __vfsPostOpenCallback[pVfs];
if(postInitSql){ if(postInitSql){
/** /**
Reminder: if this db is encrypted and the client did _not_ pass Reminder: if this db is encrypted and the client did _not_ pass
in the key, any init code will fail, causing the ctor to throw. in the key, any init code will fail, causing the ctor to throw.
We don't actually know whether the db is encrypted, so we cannot We don't actually know whether the db is encrypted, so we cannot
sensibly apply any heuristics which skip the init code only for sensibly apply any heuristics which skip the init code only for
encrypted databases for which no key has yet been supplied. encrypted databases for which no key has yet been supplied.
*/ */
if(postInitSql instanceof Function){ if(postInitSql instanceof Function){
postInitSql(this, sqlite3); postInitSql(this, sqlite3);
}else{ }else{
checkSqlite3Rc( checkSqlite3Rc(
pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0) pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0)
); );
}
} }
}catch(e){
this.close();
throw e;
} }
}catch(e){
this.close();
throw e;
} }
}; };
@ -486,26 +512,30 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
- `db`: the DB object which created the statement. - `db`: the DB object which created the statement.
- `columnCount`: the number of result columns in the query, or 0 - `columnCount`: the number of result columns in the query, or 0
for queries which cannot return results. This property is a proxy for queries which cannot return results. This property is a
for sqlite3_column_count() and its use in loops should be avoided read-only proxy for sqlite3_column_count() and its use in loops
because of the call overhead associated with that. The should be avoided because of the call overhead associated with
`columnCount` is not cached when the Stmt is created because a that. The `columnCount` is not cached when the Stmt is created
schema change made via a separate db connection between this because a schema change made between this statement's preparation
statement's preparation and when it is stepped may invalidate it. and when it is stepped may invalidate it.
- `parameterCount`: the number of bindable parameters in the query. - `parameterCount`: the number of bindable parameters in the
query. Like `columnCount`, this property is ready-only and is a
proxy for a C API call.
As a general rule, most methods of this class will throw if As a general rule, most methods of this class will throw if
called on an instance which has been finalized. For brevity's called on an instance which has been finalized. For brevity's
sake, the method docs do not all repeat this warning. sake, the method docs do not all repeat this warning.
*/ */
const Stmt = function(){ const Stmt = function(/*oo1db, stmtPtr, BindTypes [,takeOwnership=true] */){
if(BindTypes!==arguments[2]){ if(BindTypes!==arguments[2]){
toss3(capi.SQLITE_MISUSE, "Do not call the Stmt constructor directly. Use DB.prepare()."); toss3(capi.SQLITE_MISUSE, "Do not call the Stmt constructor directly. Use DB.prepare().");
} }
this.db = arguments[0]; this.db = arguments[0];
__ptrMap.set(this, arguments[1]); __ptrMap.set(this, arguments[1]);
this.parameterCount = capi.sqlite3_bind_parameter_count(this.pointer); if( arguments.length>3 && false===arguments[3] ){
__doesNotOwnHandle.add(this);
}
}; };
/** Throws if the given DB has been closed, else it is returned. */ /** Throws if the given DB has been closed, else it is returned. */
@ -723,12 +753,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
a db. a db.
*/ */
close: function(){ close: function(){
if(this.pointer){ const pDb = this.pointer;
if(pDb){
if(this.onclose && (this.onclose.before instanceof Function)){ if(this.onclose && (this.onclose.before instanceof Function)){
try{this.onclose.before(this)} try{this.onclose.before(this)}
catch(e){/*ignore*/} catch(e){/*ignore*/}
} }
const pDb = this.pointer;
Object.keys(__stmtMap.get(this)).forEach((k,s)=>{ Object.keys(__stmtMap.get(this)).forEach((k,s)=>{
if(s && s.pointer){ if(s && s.pointer){
try{s.finalize()} try{s.finalize()}
@ -737,7 +767,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}); });
__ptrMap.delete(this); __ptrMap.delete(this);
__stmtMap.delete(this); __stmtMap.delete(this);
capi.sqlite3_close_v2(pDb); if( !__doesNotOwnHandle.delete(this) ){
capi.sqlite3_close_v2(pDb);
}
if(this.onclose && (this.onclose.after instanceof Function)){ if(this.onclose && (this.onclose.after instanceof Function)){
try{this.onclose.after(this)} try{this.onclose.after(this)}
catch(e){/*ignore*/} catch(e){/*ignore*/}
@ -1450,9 +1482,87 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/ */
checkRc: function(resultCode){ checkRc: function(resultCode){
return checkSqlite3Rc(this, resultCode); return checkSqlite3Rc(this, resultCode);
} },
}/*DB.prototype*/; }/*DB.prototype*/;
/**
Returns a new oo1.DB instance which wraps the given db.
The first argument must be either a non-NULL (sqlite3*) WASM
pointer or a non-close()d instance of oo1.DB.
The second argument only applies if the first argument is a
(sqlite3*). If it is, the returned object will pass that pointer
to sqlite3_close() when its close() method is called, otherwise
it will not.
If the first argument is a oo1.DB object, the second argument is
disregarded and the returned object will be created as a
sqlite3.oo1.DB object (as opposed to the concrete derived DB
subclass from the first argument), so will not include any
derived-type behaviors,
e.g. JsStorageDb.prototype.clearStorage().
Throws if db cannot be resolved to one of the legal options.
The caller MUST GUARANTEE that the passed-in handle will outlive
the returned object, i.e. that it will not be closed. If it is closed,
this object will hold a stale pointer and results are undefined.
Aside from its lifetime, the proxy is to be treated as any other
DB instance, including the requirement of calling close() on
it. close() will free up internal resources owned by the proxy,
and disassociate the proxy from that handle, but will not
actually close the proxied db handle.
The following quirks and requirements apply when proxying another
DB instance, as opposed to a (sqlite3*):
- DO NOT call close() on the being-proxied instance while a proxy
is active.
- ALWAYS eventually call close() on the returned object BEFORE
the being-proxied handle is closed.
- For historical reasons, the filename property of the returned
object is captured at the time of this call, as opposed to being
dynamically proxied. e.g., if the filename property of the
being-proxied object is changed, this object will not reflect
that change. There is no good reason to ever modify that
property, so this distinction is not truly significant but it's
noted here because it's a client-visible discrepancy between the
proxy and its partner. (Sidebar: the filename property _should_
be a property access interceptor for sqlite3_db_filename(),
but making it so now may break existing code.)
*/
DB.wrapHandle = function(db, takeOwnership=false){
let ptr, ctor = DB;
const oo1db = (db instanceof DB) ? db : undefined;
if( wasm.isPtr(db) ){
ptr = db;
}else if( oo1db ){
takeOwnership = false;
ptr = db.pointer;
//ctor = db.constructor;
// ^^^ that doesn't work, resulting in an Object-type value
}
//sqlite3.config.debug("wrapHandle()",'db',db,'ctor',ctor,
//'arguments',arguments,'db.constructor',db.constructor);
if( !ptr ){
throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE,
"Argument must be a WASM sqlite3 "+
"pointer or an sqlite3.oo1.DB instance");
}
const dc = new ctor({
"sqlite3*": ptr,
"sqlite3*:takeOwnership": !!takeOwnership
});
if( oo1db ){
dc.filename = oo1db.filename;
}//else dc.filename was captured by the ctor for legacy consistency
//sqlite3.config.debug("wrapHandle() dc",dc);
return dc;
}/*DB.wrapHandle()*/;
/** Throws if the given Stmt has been finalized, else stmt is /** Throws if the given Stmt has been finalized, else stmt is
returned. */ returned. */
@ -1641,12 +1751,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
This method always throws if called when it is illegal to do This method always throws if called when it is illegal to do
so. Namely, when triggered via a per-row callback handler of a so. Namely, when triggered via a per-row callback handler of a
DB.exec() call. DB.exec() call.
If Stmt does not own its underlying (sqlite3_stmt*) (see
Stmt.wrapHandle()) then this function will not pass it to
sqlite3_finalize().
*/ */
finalize: function(){ finalize: function(){
if(this.pointer){ const ptr = this.pointer;
if(ptr){
affirmNotLockedByExec(this,'finalize()'); affirmNotLockedByExec(this,'finalize()');
const rc = capi.sqlite3_finalize(this.pointer); const rc = (__doesNotOwnHandle.delete(this)
delete __stmtMap.get(this.db)[this.pointer]; ? 0
: capi.sqlite3_finalize(ptr));
delete __stmtMap.get(this.db)[ptr];
__ptrMap.delete(this); __ptrMap.delete(this);
__execLock.delete(this); __execLock.delete(this);
__stmtMayGet.delete(this); __stmtMayGet.delete(this);
@ -2134,6 +2251,60 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
set: ()=>toss3("The columnCount property is read-only.") set: ()=>toss3("The columnCount property is read-only.")
}); });
Object.defineProperty(Stmt.prototype, 'parameterCount', {
enumerable: false,
get: function(){return capi.sqlite3_bind_parameter_count(this.pointer)},
set: ()=>toss3("The parameterCount property is read-only.")
});
/**
The Stmt counterpart of oo1.DB.wrapHandle(), this creates a Stmt
instance which wraps a WASM (sqlite3_stmt*) in the oo1 API with
or without taking over ownership of that pointer.
The first argument must be an oo1.DB instance[^1].
The second argument must be a valid WASM (sqlite3_stmt*), as
produced by sqlite3_prepare_v2() and sqlite3_prepare_v3().
The third argument specifies whether the returned Stmt object
takes over ownership of the underlying (sqlite3_stmt*). If true,
the returned object's finalize() method will finalize that
handle, else it will not. If it is false, ownership of stmtPtr is
unchanged and stmtPtr MUST outlive the returned object or results
are undefined.
This function throws if the arguments are invalid. On success it
returns a new Stmt object which wraps the given statement
pointer.
Like all Stmt objects, the finalize() method must eventually be
called on the returned object to free up internal resources,
regardless of whether this function's third argument is true or
not.
[^1]: The first argument cannot be a (sqlite3*) because the
resulting Stmt object requires a parent DB object. It is not yet
determined whether it would be of general benefit to refactor the
DB/Stmt pair internals to communicate in terms of the underlying
(sqlite3*) rather than a DB object. If so, we could laxen the
first argument's requirement and allow an (sqlite3*).
*/
Stmt.wrapHandle = function(oo1db, stmtPtr, takeOwnership=false){
let ctor = Stmt;
if( !(oo1db instanceof DB) || !oo1db.pointer ){
throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE,
"First argument must be an opened "+
"sqlite3.oo1.DB instance");
}
if( !stmtPtr || !wasm.isPtr(stmtPtr) ){
throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE,
"Second argument must be a WASM "+
"sqlite3_stmt pointer");
}
return new Stmt(oo1db, stmtPtr, BindTypes, !!takeOwnership);
}
/** The OO API's public namespace. */ /** The OO API's public namespace. */
sqlite3.oo1 = { sqlite3.oo1 = {
DB, DB,

View File

@ -41,7 +41,7 @@
ES6 worker module build: ES6 worker module build:
./c-pp -f tester1.c-pp.js -o tester1-esm.js -Dtarget=es6-module ./c-pp -f tester1.c-pp.js -o tester1-esm.mjs -Dtarget=es6-module
*/ */
//#if target=es6-module //#if target=es6-module
import {default as sqlite3InitModule} from './jswasm/sqlite3.mjs'; import {default as sqlite3InitModule} from './jswasm/sqlite3.mjs';
@ -1209,6 +1209,94 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
} }
} }
}) })
////////////////////////////////////////////////////////////////////
.t({
name: "oo1.DB/Stmt.wrapDbHandle()",
test: function(sqlite3){
/* Maintenance reminder: this function is early in the list to
demonstrate that the wrappers for this.db created by this
function do not interfere with downstream tests, e.g. by
closing this.db.pointer. */
sqlite3.config.debug("Proxying",this.db);
let dw = sqlite3.oo1.DB.wrapHandle(this.db);
sqlite3.config.debug('dw',dw);
T.assert( dw, '!!dw' )
.assert( dw instanceof sqlite3.oo1.DB, 'dw is-a oo1.DB' )
.assert( dw.pointer, 'dw.pointer' )
.assert( dw.pointer === this.db.pointer, 'dw.pointer===db.pointer' )
.assert( dw.filename === this.db.filename, 'dw.filename===db.filename' );
T.assert( dw === dw.exec("select 1") );
let q;
try {
q = dw.prepare("select 1");
T.assert( q.step() )
.assert( !q.step() );
}finally{
if( q ) q.finalize();
}
dw.close();
T.assert( !dw.pointer )
.assert( this.db === this.db.exec("select 1") );
dw = undefined;
let pDb = 0, pStmt = 0;
const stack = wasm.pstack.pointer;
try {
const ppOut = wasm.pstack.allocPtr();
T.assert( 0===wasm.peekPtr(ppOut) );
let rc = capi.sqlite3_open_v2( ":memory:", ppOut,
capi.SQLITE_OPEN_CREATE
| capi.SQLITE_OPEN_READWRITE,
0);
T.assert( 0===rc, 'open_v2()' );
pDb = wasm.peekPtr(ppOut);
wasm.pokePtr(ppOut, 0);
T.assert( pDb>0, 'pDb>0' );
const pTmp = pDb;
dw = sqlite3.oo1.DB.wrapHandle(pDb, true);
pDb = 0;
//sqlite3.config.debug("dw",dw);
T.assert( pTmp===dw.pointer, 'pDb===dw.pointer' );
T.assert( dw.filename === "", "dw.filename == "+dw.filename );
let q = dw.prepare("select 1");
try {
T.assert( q.step(), "step()" );
T.assert( !q.step(), "!step()" );
}finally{
q.finalize();
q = undefined;
}
T.assert( dw===dw.exec("select 1") );
dw.affirmOpen();
rc = capi.sqlite3_prepare_v2( dw, "select 1", -1, ppOut, 0 );
T.assert( 0===rc, 'prepare_v2() rc='+rc );
pStmt = wasm.peekPtr(ppOut);
try {
q = sqlite3.oo1.Stmt.wrapHandle(dw, pStmt, false);
T.assert( q.step(), "step()" )
.assert( !q.step(), "!step()" );
q.finalize();
q = undefined;
q = sqlite3.oo1.Stmt.wrapHandle(dw, pStmt, true);
pStmt = 0;
q.reset();
T.assert( q.step(), "step()" )
.assert( !q.step(), "!step()" );
}finally{
if( pStmt ) capi.sqlite3_finalize(pStmt)
if( q ) q.finalize();
}
}finally{
wasm.pstack.restore(stack);
if( pDb ){ capi.sqlite3_close_v2(pDb); }
else if( dw ){ dw.close(); }
}
}
})/*oo1.DB/Stmt.wrapHandle()*/
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
.t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){ .t('sqlite3_db_config() and sqlite3_db_status()', function(sqlite3){
let rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, 0, 0); let rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, 0, 0);

View File

@ -1,5 +1,5 @@
C Add\s'reconfigure'\starget\sto\sMakefile.in\sto\sre-run\sthe\sconfigure\sscript\swith\sthe\ssame\sflags\sit\swas\sgenerated\swith. C Experimentally\sadd\ssqlite3.oo1.DB/Stmt.wrapHandle(),\swhich\sallow\sDB/Stmt\sinstances\sto\swrap\sa\s(sqlite3*)/(sqlite3_stmt*)\soptionally\swith\sor\swithout\staking\sownership\sof\sit.\sThe\sintent\sis\sto\senable\smix-and-match\suse\sof\sthe\sC\sAPI,\sthe\soo1\sAPI,\sand\sany\sother\shypothetical\sAPI\swhich\sexposes\sthose\spointers.\soo1.Stmt.parameterCount\sis\snow\sa\sproperty\saccess\sinterceptor\slike\sStmt.columnCount\sis,\sbut\sthat\sdoesn't\schange\show\sit's\sused.
D 2025-07-04T18:32:18.912 D 2025-07-06T15:01:44.333
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@ -641,7 +641,7 @@ F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea
F ext/wasm/api/pre-js.c-pp.js a614a2c82b12c4d96d8e3ba77330329efc53c4d56a8a7e60ade900f341866cfb F ext/wasm/api/pre-js.c-pp.js a614a2c82b12c4d96d8e3ba77330329efc53c4d56a8a7e60ade900f341866cfb
F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359 F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
F ext/wasm/api/sqlite3-api-glue.c-pp.js 0b76510f3650053bac67ca8947cb6ab9d050ad2218118a2e7796dd37be832ffa F ext/wasm/api/sqlite3-api-glue.c-pp.js 0b76510f3650053bac67ca8947cb6ab9d050ad2218118a2e7796dd37be832ffa
F ext/wasm/api/sqlite3-api-oo1.c-pp.js c68d6da0088c2527156fca9163a721abe08e7bd077b15404fd8d292f4612adc1 F ext/wasm/api/sqlite3-api-oo1.c-pp.js 44d122b6d22ba9caa644193357a03bf5d2678a7815f1e2bbbdb086b14db11b7e
F ext/wasm/api/sqlite3-api-prologue.js 8708570165f5b4bce9a78ccd91bc9ddf8735970ac1c4d659e36c9a7d9a644bb4 F ext/wasm/api/sqlite3-api-prologue.js 8708570165f5b4bce9a78ccd91bc9ddf8735970ac1c4d659e36c9a7d9a644bb4
F ext/wasm/api/sqlite3-api-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644f23e64b126e7ae113570587c0ab F ext/wasm/api/sqlite3-api-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644f23e64b126e7ae113570587c0ab
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
@ -698,7 +698,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2 F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
F ext/wasm/tester1.c-pp.js 766a2ba51a2619d41a49be7c6a1ad014c1d23fc97b67496e4f103038203eb17d F ext/wasm/tester1.c-pp.js e7176b2bc1228cf9a87833be7e53e20cb82dec2f104525f5cdd6cb1a53998ad6
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88 F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@ -2208,8 +2208,11 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 64f5f14322349b47451b8cac03bf8cd6f1ae45a8822e7f1ddee3d0b265047501 P c60907e77b32824aaaf024d299cdaf161b5f64fc927ffe5d5455eeb5754e6b01
R 2e84b390408477c8e70efdd22e84c169 R 23984087c5c98e4f1ed7d33ca211546f
T *branch * oo1-unowned-handles
T *sym-oo1-unowned-handles *
T -sym-trunk * Cancelled\sby\sbranch.
U stephan U stephan
Z a6be9728f4a0aec0de70108286e76b7e Z 3bad3f183e619bbd50d1bebd9118b331
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
c60907e77b32824aaaf024d299cdaf161b5f64fc927ffe5d5455eeb5754e6b01 1227543b87c3320d6b80e0f61b88ea53b68779966a0295c4d6a1db6369c48207