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:
@ -37,6 +37,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
it.
|
||||
*/
|
||||
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
|
||||
wasm pointers to Stmt objects.
|
||||
@ -234,6 +244,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
};
|
||||
}
|
||||
const opt = ctor.normalizeArgs(...args);
|
||||
//sqlite3.config.debug("DB ctor",opt);
|
||||
let pDb;
|
||||
if( (pDb = opt['sqlite3*']) ){
|
||||
/* This property ^^^^^ is very specifically NOT DOCUMENTED and
|
||||
NOT part of the public API. This is a back door for functions
|
||||
like DB.wrapDbHandle(). */
|
||||
//sqlite3.config.debug("creating proxy db from",opt);
|
||||
if( !opt['sqlite3*:takeOwnership'] ){
|
||||
/* This is object does not own its handle. */
|
||||
__doesNotOwnHandle.add(this);
|
||||
}
|
||||
this.filename = capi.sqlite3_db_filename(pDb,'main');
|
||||
}else{
|
||||
let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags;
|
||||
if(('string'!==typeof fn && 'number'!==typeof fn)
|
||||
|| 'string'!==typeof flagsStr
|
||||
@ -247,7 +270,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
vfsName = vfsCheck.vfs;
|
||||
fn = fnJs = vfsCheck.filename(fnJs);
|
||||
}
|
||||
let pDb, oflags = 0;
|
||||
let oflags = 0;
|
||||
if( flagsStr.indexOf('c')>=0 ){
|
||||
oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
|
||||
}
|
||||
@ -272,8 +295,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
wasm.pstack.restore(stack);
|
||||
}
|
||||
this.filename = fnJs;
|
||||
}
|
||||
__ptrMap.set(this, pDb);
|
||||
__stmtMap.set(this, Object.create(null));
|
||||
if( !opt['sqlite3*'] ){
|
||||
try{
|
||||
//#if enable-see
|
||||
dbCtorApplySEEKey(this,opt);
|
||||
@ -302,6 +327,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
this.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -486,26 +512,30 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
- `db`: the DB object which created the statement.
|
||||
|
||||
- `columnCount`: the number of result columns in the query, or 0
|
||||
for queries which cannot return results. This property is a proxy
|
||||
for sqlite3_column_count() and its use in loops should be avoided
|
||||
because of the call overhead associated with that. The
|
||||
`columnCount` is not cached when the Stmt is created because a
|
||||
schema change made via a separate db connection between this
|
||||
statement's preparation and when it is stepped may invalidate it.
|
||||
for queries which cannot return results. This property is a
|
||||
read-only proxy for sqlite3_column_count() and its use in loops
|
||||
should be avoided because of the call overhead associated with
|
||||
that. The `columnCount` is not cached when the Stmt is created
|
||||
because a schema change made between this statement's preparation
|
||||
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
|
||||
called on an instance which has been finalized. For brevity's
|
||||
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]){
|
||||
toss3(capi.SQLITE_MISUSE, "Do not call the Stmt constructor directly. Use DB.prepare().");
|
||||
}
|
||||
this.db = arguments[0];
|
||||
__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. */
|
||||
@ -723,12 +753,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
a db.
|
||||
*/
|
||||
close: function(){
|
||||
if(this.pointer){
|
||||
const pDb = this.pointer;
|
||||
if(pDb){
|
||||
if(this.onclose && (this.onclose.before instanceof Function)){
|
||||
try{this.onclose.before(this)}
|
||||
catch(e){/*ignore*/}
|
||||
}
|
||||
const pDb = this.pointer;
|
||||
Object.keys(__stmtMap.get(this)).forEach((k,s)=>{
|
||||
if(s && s.pointer){
|
||||
try{s.finalize()}
|
||||
@ -737,7 +767,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
});
|
||||
__ptrMap.delete(this);
|
||||
__stmtMap.delete(this);
|
||||
if( !__doesNotOwnHandle.delete(this) ){
|
||||
capi.sqlite3_close_v2(pDb);
|
||||
}
|
||||
if(this.onclose && (this.onclose.after instanceof Function)){
|
||||
try{this.onclose.after(this)}
|
||||
catch(e){/*ignore*/}
|
||||
@ -1450,9 +1482,87 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
*/
|
||||
checkRc: function(resultCode){
|
||||
return checkSqlite3Rc(this, resultCode);
|
||||
}
|
||||
},
|
||||
}/*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
|
||||
returned. */
|
||||
@ -1641,12 +1751,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
This method always throws if called when it is illegal to do
|
||||
so. Namely, when triggered via a per-row callback handler of a
|
||||
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(){
|
||||
if(this.pointer){
|
||||
const ptr = this.pointer;
|
||||
if(ptr){
|
||||
affirmNotLockedByExec(this,'finalize()');
|
||||
const rc = capi.sqlite3_finalize(this.pointer);
|
||||
delete __stmtMap.get(this.db)[this.pointer];
|
||||
const rc = (__doesNotOwnHandle.delete(this)
|
||||
? 0
|
||||
: capi.sqlite3_finalize(ptr));
|
||||
delete __stmtMap.get(this.db)[ptr];
|
||||
__ptrMap.delete(this);
|
||||
__execLock.delete(this);
|
||||
__stmtMayGet.delete(this);
|
||||
@ -2134,6 +2251,60 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
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. */
|
||||
sqlite3.oo1 = {
|
||||
DB,
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
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
|
||||
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){
|
||||
let rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, 0, 0);
|
||||
|
17
manifest
17
manifest
@ -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.
|
||||
D 2025-07-04T18:32:18.912
|
||||
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-06T15:01:44.333
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
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/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
|
||||
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-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644f23e64b126e7ae113570587c0ab
|
||||
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/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||
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/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
|
||||
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.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 64f5f14322349b47451b8cac03bf8cd6f1ae45a8822e7f1ddee3d0b265047501
|
||||
R 2e84b390408477c8e70efdd22e84c169
|
||||
P c60907e77b32824aaaf024d299cdaf161b5f64fc927ffe5d5455eeb5754e6b01
|
||||
R 23984087c5c98e4f1ed7d33ca211546f
|
||||
T *branch * oo1-unowned-handles
|
||||
T *sym-oo1-unowned-handles *
|
||||
T -sym-trunk * Cancelled\sby\sbranch.
|
||||
U stephan
|
||||
Z a6be9728f4a0aec0de70108286e76b7e
|
||||
Z 3bad3f183e619bbd50d1bebd9118b331
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
c60907e77b32824aaaf024d299cdaf161b5f64fc927ffe5d5455eeb5754e6b01
|
||||
1227543b87c3320d6b80e0f61b88ea53b68779966a0295c4d6a1db6369c48207
|
||||
|
Reference in New Issue
Block a user