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

Extend the JS/WASM SEE build support by (A) filtering SEE-related bits out of the JS when not building with SEE and (B) accepting an optional key/textkey/hexkey option to the sqlite3.oo1.DB and subclass constructors to create/open SEE-encrypted databases with. Demonstrate SEE in the test app using the kvvfs. This obviates the changes made in [5c505ee8a7].

FossilOrigin-Name: 8fbda563d2f56f8dd3f695a5711e4356de79035f332270db45d4b33ed52fdfd2
This commit is contained in:
stephan
2024-04-22 16:46:37 +00:00
parent 4f2f6c74ca
commit 0a42e9913b
7 changed files with 226 additions and 42 deletions

View File

@ -335,19 +335,26 @@ DISTCLEAN_FILES += $(bin.stripccomments)
# #
# Note that the SQLITE_... build flags used here have NO EFFECT on the # Note that the SQLITE_... build flags used here have NO EFFECT on the
# JS/WASM build. They are solely for use with $(bin.c-pp) itself. # JS/WASM build. They are solely for use with $(bin.c-pp) itself.
#
# -D... flags which should be included in all invocations should be
# appended to $(C-PP.FILTER.global).
bin.c-pp := ./c-pp bin.c-pp := ./c-pp
$(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE) $(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \ $(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \ -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \
-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \ -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
-DSQLITE_TEMP_STORE=3 -DSQLITE_TEMP_STORE=3
C-PP.FILTER.global ?=
ifeq (1,$(SQLITE_C_IS_SEE))
C-PP.FILTER.global += -Denable-see
endif
define C-PP.FILTER define C-PP.FILTER
# Create $2 from $1 using $(bin.c-pp) # Create $2 from $1 using $(bin.c-pp)
# $1 = Input file: c-pp -f $(1).js # $1 = Input file: c-pp -f $(1).js
# $2 = Output file: c-pp -o $(2).js # $2 = Output file: c-pp -o $(2).js
# $3 = optional c-pp -D... flags # $3 = optional c-pp -D... flags
$(2): $(1) $$(MAKEFILE) $$(bin.c-pp) $(2): $(1) $$(MAKEFILE) $$(bin.c-pp)
$$(bin.c-pp) -f $(1) -o $$@ $(3) $$(bin.c-pp) -f $(1) -o $$@ $(3) $(C-PP.FILTER.global)
CLEAN_FILES += $(2) CLEAN_FILES += $(2)
endef endef
# /end C-PP.FILTER # /end C-PP.FILTER

View File

@ -329,7 +329,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
} }
if(wasm.exports.sqlite3_activate_see instanceof Function){ //#if enable-see
if(wasm.exports.sqlite3_key_v2 instanceof Function){
/** /**
This code is capable of using an SEE build but note that an SEE This code is capable of using an SEE build but note that an SEE
WASM build is generally incompatible with SEE's license WASM build is generally incompatible with SEE's license
@ -346,6 +347,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3_activate_see", undefined, "string"] ["sqlite3_activate_see", undefined, "string"]
); );
} }
//#endif enable-see
/** /**
Functions which require BigInt (int64) support are separated from Functions which require BigInt (int64) support are separated from
the others because we need to conditionally bind them or apply the others because we need to conditionally bind them or apply
@ -627,7 +630,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3__wasm_vfs_create_file", "int", ["sqlite3__wasm_vfs_create_file", "int",
"sqlite3_vfs*","string","*", "int"], "sqlite3_vfs*","string","*", "int"],
["sqlite3__wasm_posix_create_file", "int", "string","*", "int"], ["sqlite3__wasm_posix_create_file", "int", "string","*", "int"],
["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"] ["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"],
["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"]
]; ];
/** /**

View File

@ -87,6 +87,94 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/ */
const __vfsPostOpenSql = Object.create(null); const __vfsPostOpenSql = Object.create(null);
/**
Converts ArrayBuffer or Uint8Array ba into a string of hex
digits.
*/
const byteArrayToHex = function(ba){
if( ba instanceof ArrayBuffer ){
ba = new Uint8Array(ba);
}
const li = [];
const digits = "0123456789abcdef";
for( const d of ba ){
li.push( digits[(d & 0xf0) >> 4], digits[d & 0x0f] );
}
return li.join('');
};
//#if enable-see
/**
Internal helper to apply an SEE key to a just-opened
database. Requires that db be-a DB object which has just been
opened, opt be the options object processed by its ctor, and opt
must have either the key, hexkey, or textkey properties, either
as a string, an ArrayBuffer, or a Uint8Array.
This is a no-op in non-SEE builds. It throws on error and returns
without side effects if its key/textkey options are not of valid
types.
Returns true if it applies the key, else a falsy value.
*/
const dbCtorApplySEEKey = function(db,opt){
if( !capi.sqlite3_key_v2 ) return;
let keytype;
let key;
const check = (opt.key ? 1 : 0) + (opt.hexkey ? 1 : 0) + (opt.textkey ? 1 : 0);
if( !check ) return;
else if( check>1 ) toss3("Only ONE of (key, hexkey, textkey) may be provided.");
if( opt.key ){
/* It is not legal to bind an argument to PRAGMA key=?, so we
convert it to a hexkey... */
keytype = 'key';
key = opt.key;
if('string'===typeof key){
key = new TextEncoder('utf-8').encode(key);
}
if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
key = byteArrayToHex(key);
keytype = 'hexkey';
}else{
toss3("Invalid value for the 'key' option. Expecting a string, ArrayBuffer, or Uint8Array.");
return;
}
}else if( opt.textkey ){
/* For textkey we need it to be in string form, so convert it to
a string if it's a byte array... */
keytype = 'textkey';
key = opt.textkey;
if(key instanceof ArrayBuffer){
key = new Uint8Array(key);
}
if(key instanceof Uint8Array){
key = new TextDecoder('utf-8').decode(key);
}else if('string'!==typeof key){
toss3("Invalid value for the 'textkey' option. Expecting a string, ArrayBuffer, or Uint8Array.");
}
}else if( opt.hexkey ){
keytype = 'hexkey';
key = opt.hexkey;
if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){
key = byteArrayToHex(key);
}else if('string'!==typeof key){
toss3("Invalid value for the 'hexkey' option. Expecting a string, ArrayBuffer, or Uint8Array.");
}
/* else assume it's valid hex codes */;
}else{
return;
}
let stmt;
try{
stmt = db.prepare("PRAGMA "+keytype+"="+util.sqlite3__wasm_qfmt_token(key, 1));
stmt.step();
}finally{
if(stmt) stmt.finalize();
}
return true;
};
//#endif enable-see
/** /**
A proxy for DB class constructors. It must be called with the A proxy for DB class constructors. It must be called with the
being-construct DB object as its "this". See the DB constructor being-construct DB object as its "this". See the DB constructor
@ -175,28 +263,22 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
__ptrMap.set(this, pDb); __ptrMap.set(this, pDb);
__stmtMap.set(this, Object.create(null)); __stmtMap.set(this, Object.create(null));
try{ try{
//#if enable-see
dbCtorApplySEEKey(this,opt);
//#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)
if(!pVfs) toss3("Internal error: cannot get VFS for new db handle."); || toss3("Internal error: cannot get VFS for new db handle.");
const postInitSql = __vfsPostOpenSql[pVfs]; const postInitSql = __vfsPostOpenSql[pVfs];
if(postInitSql){ if(postInitSql){
if(capi.sqlite3_activate_see){
/** /**
In SEE-capable builds we have to avoid running any db Reminder: if this db is encrypted and the client did _not_ pass
code before the client has an opportunity to apply their in the key, any init code will fail, causing the ctor to throw.
decryption key. If we first run any db code, e.g. pragma We don't actually know whether the db is encrypted, so we cannot
journal_mode=..., then it will fail with SQLITE_NOTADB sensibly apply any heuristics which skip the init code only for
and the db handle will be left in an unusuable encrypted databases for which no key has yet been supplied.
state. Note that at this point we do not actually know
whether the db is encrypted, but if a client has gone out
of their way to create an SEE build, it seems safe to
assume that they are using the encryption.
*/ */
sqlite3.config.warn( if(postInitSql instanceof Function){
"Disabling execution of on-open() db code "+
"because this is an SEE build. DB: "+fnJs
);
}else if(postInitSql instanceof Function){
postInitSql(this, sqlite3); postInitSql(this, sqlite3);
}else{ }else{
checkSqlite3Rc( checkSqlite3Rc(
@ -298,6 +380,20 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
- `flags`: open-mode flags - `flags`: open-mode flags
- `vfs`: the VFS fname - `vfs`: the VFS fname
//#if enable-see
And, for SEE-capable builds, optionally ONE of the following:
- `key`, `hexkey`, or `textkey`: encryption key as a string,
ArrayBuffer, or Uint8Array. These flags function as documented
for the SEE pragmas of the same names.
In non-SEE builds, these options are ignored. In SEE builds,
`PRAGMA key/textkey/hexkey=X` is executed immediately after
opening the db. If more than one of the options is provided,
or any option has an invalid argument type, an exception is
thrown.
//#endif enable-see
The `filename` and `vfs` arguments may be either JS strings or The `filename` and `vfs` arguments may be either JS strings or
C-strings allocated via WASM. `flags` is required to be a JS C-strings allocated via WASM. `flags` is required to be a JS
string (because it's specific to this API, which is specific string (because it's specific to this API, which is specific
@ -1562,7 +1658,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
they are larger than 32 bits, else double or int32, depending they are larger than 32 bits, else double or int32, depending
on whether they have a fractional part. Booleans are bound as on whether they have a fractional part. Booleans are bound as
integer 0 or 1. It is not expected the distinction of binding integer 0 or 1. It is not expected the distinction of binding
doubles which have no fractional parts is integers is doubles which have no fractional parts and integers is
significant for the majority of clients due to sqlite3's data significant for the majority of clients due to sqlite3's data
typing model. If [BigInt] support is enabled then this typing model. If [BigInt] support is enabled then this
routine will bind BigInt values as 64-bit integers if they'll routine will bind BigInt values as 64-bit integers if they'll
@ -1946,16 +2042,26 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Functionally equivalent to DB(storageName,'c','kvvfs') except Functionally equivalent to DB(storageName,'c','kvvfs') except
that it throws if the given storage name is not one of 'local' that it throws if the given storage name is not one of 'local'
or 'session'. or 'session'.
As of version 3.46, the argument may optionally be an options
object in the form:
{
filename: 'session'|'local',
... etc. (all options supported by the DB ctor)
}
noting that the 'vfs' option supported by main DB
constructor is ignored here: the vfs is always 'kvvfs'.
*/ */
sqlite3.oo1.JsStorageDb = function(storageName='session'){ sqlite3.oo1.JsStorageDb = function(storageName='session'){
const opt = dbCtorHelper.normalizeArgs(...arguments);
storageName = opt.filename;
if('session'!==storageName && 'local'!==storageName){ if('session'!==storageName && 'local'!==storageName){
toss3("JsStorageDb db name must be one of 'session' or 'local'."); toss3("JsStorageDb db name must be one of 'session' or 'local'.");
} }
dbCtorHelper.call(this, { opt.vfs = 'kvvfs';
filename: storageName, dbCtorHelper.call(this, opt);
flags: 'c',
vfs: "kvvfs"
});
}; };
const jdb = sqlite3.oo1.JsStorageDb; const jdb = sqlite3.oo1.JsStorageDb;
jdb.prototype = Object.create(DB.prototype); jdb.prototype = Object.create(DB.prototype);

View File

@ -1678,6 +1678,25 @@ int sqlite3__wasm_config_j(int op, sqlite3_int64 arg){
return sqlite3_config(op, arg); return sqlite3_config(op, arg);
} }
/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** If z is not NULL, returns the result of passing z to
** sqlite3_mprintf()'s %Q modifier (if addQuotes is true) or %q (if
** addQuotes is 0). Returns NULL if z is NULL or on OOM.
*/
SQLITE_WASM_EXPORT
char * sqlite3__wasm_qfmt_token(char *z, int addQuotes){
char * rc = 0;
if( z ){
rc = addQuotes
? sqlite3_mprintf("%Q", z)
: sqlite3_mprintf("%q", z);
}
return rc;
}
#if 0 #if 0
// Pending removal after verification of a workaround discussed in the // Pending removal after verification of a workaround discussed in the
// forum post linked to below. // forum post linked to below.

View File

@ -2587,7 +2587,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
const pVfs = capi.sqlite3_vfs_find('kvvfs'); const pVfs = capi.sqlite3_vfs_find('kvvfs');
T.assert(pVfs); T.assert(pVfs);
const JDb = this.JDb = sqlite3.oo1.JsStorageDb; const JDb = this.JDb = sqlite3.oo1.JsStorageDb;
const unlink = this.kvvfsUnlink = ()=>{JDb.clearStorage(filename)}; const unlink = this.kvvfsUnlink = ()=>JDb.clearStorage(this.kvvfsDbFile);
unlink(); unlink();
let db = new JDb(filename); let db = new JDb(filename);
try { try {
@ -2605,6 +2605,54 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
} }
} }
}/*kvvfs sanity checks*/) }/*kvvfs sanity checks*/)
//#if enable-see
.t({
name: 'kvvfs with SEE encryption',
predicate: ()=>(isUIThread()
|| "Only available in main thread."),
test: function(sqlite3){
this.kvvfsUnlink();
let db;
try{
db = new this.JDb({
filename: this.kvvfsDbFile,
key: 'foo'
});
db.exec([
"create table t(a,b);",
"insert into t(a,b) values(1,2),(3,4)"
]);
db.close();
let err;
try{
db = new this.JDb({
filename: this.kvvfsDbFile,
flags: 'ct'
});
T.assert(db) /* opening is fine, but... */;
db.exec("select 1 from sqlite_schema");
console.warn("sessionStorage =",sessionStorage);
}catch(e){
err = e;
}finally{
db.close();
}
T.assert(err,"Expecting an exception")
.assert(sqlite3.capi.SQLITE_NOTADB==err.resultCode,
"Expecting NOTADB");
db = new sqlite3.oo1.DB({
filename: this.kvvfsDbFile,
vfs: 'kvvfs',
hexkey: new Uint8Array([0x66,0x6f,0x6f]) // equivalent: '666f6f'
});
T.assert( 4===db.selectValue('select sum(a) from t') );
}finally{
if( db ) db.close();
this.kvvfsUnlink();
}
}
})/*kvvfs with SEE*/
//#endif enable-see
;/* end kvvfs tests */ ;/* end kvvfs tests */
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,5 @@
C Extra\srobustness\sin\sthe\scode\sthat\scauses\scursors\sto\sreturn\sNULL\swhen\sthey\nare\sparticipating\sin\san\sOUTER\sJOIN. C Extend\sthe\sJS/WASM\sSEE\sbuild\ssupport\sby\s(A)\sfiltering\sSEE-related\sbits\sout\sof\sthe\sJS\swhen\snot\sbuilding\swith\sSEE\sand\s(B)\saccepting\san\soptional\skey/textkey/hexkey\soption\sto\sthe\ssqlite3.oo1.DB\sand\ssubclass\sconstructors\sto\screate/open\sSEE-encrypted\sdatabases\swith.\sDemonstrate\sSEE\sin\sthe\stest\sapp\susing\sthe\skvvfs.\sThis\sobviates\sthe\schanges\smade\sin\s[5c505ee8a7].
D 2024-04-22T13:31:24.188 D 2024-04-22T16:46:37.381
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -587,7 +587,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile 4bb4cf70a8153dd5b5fee17d724075c54174da630b424bbcf48c744633396f62 F ext/wasm/GNUmakefile 0d5ccc8a4814716c1c789bb3069dd4d71d5ef0a97bbea074ac182fbfb85a3ca8
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576 F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193 F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@ -605,8 +605,8 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
F ext/wasm/api/post-js-header.js 04dc12c3edd666b64a1b4ef3b6690c88dcc653f26451fd4734472d8e29c1c122 F ext/wasm/api/post-js-header.js 04dc12c3edd666b64a1b4ef3b6690c88dcc653f26451fd4734472d8e29c1c122
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219 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-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
F ext/wasm/api/sqlite3-api-glue.js 2d35660c52dcb4bb16d00c56553d34e7caa6ad30083938b515e6f9aa0b312fbb F ext/wasm/api/sqlite3-api-glue.js c744f4b919e1254c898b467573858671a1c8797c2490d0eca2fdbadf2d0ac74b
F ext/wasm/api/sqlite3-api-oo1.js 5b61a9ea9465d75a6086f89273778cad0c3c1794a59c23cce3363e06a1f78bfb F ext/wasm/api/sqlite3-api-oo1.js 708934dd9919863bb67e2a54ba6604b05835ba3779d4dc4486218c8512eb0771
F ext/wasm/api/sqlite3-api-prologue.js 93a72b07b2a5d964d2edc76a90b439ece49298bd7ba60a1c6ae5d4878213701e F ext/wasm/api/sqlite3-api-prologue.js 93a72b07b2a5d964d2edc76a90b439ece49298bd7ba60a1c6ae5d4878213701e
F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf F ext/wasm/api/sqlite3-api-worker1.js 8d9c0562831f62218170a3373468d8a0b7a6503b5985e309b69bf71187b525cf
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
@ -615,7 +615,7 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 8433ee332d5f5e39fb19427fccb7bad7f44aa99b5504daad3343fc128c311e78 F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 8433ee332d5f5e39fb19427fccb7bad7f44aa99b5504daad3343fc128c311e78
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3c72f1a0e6a7343c8c882d29d01bb440f10be12c844651605b486e76f3d6cc8c
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js a2fcbc3fecdd0eea229283584ebc122f29d98194083675dbe5cb2cf3a17fe309 F ext/wasm/api/sqlite3-vtab-helper.c-pp.js a2fcbc3fecdd0eea229283584ebc122f29d98194083675dbe5cb2cf3a17fe309
F ext/wasm/api/sqlite3-wasm.c afba6827a49151b564af5cf588a6bbd0401b16ef5cbe3269c66f676fee9ca92c F ext/wasm/api/sqlite3-wasm.c 3f744dc45ac4be8125d58364448bdc9c082f332a88cec211bfd0143ad0acb373
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bd89edfe42a4d7122a6d6d405c5423cf00aabba1f76f6ea8e2dba9c628ddd91a F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bd89edfe42a4d7122a6d6d405c5423cf00aabba1f76f6ea8e2dba9c628ddd91a
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5 F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7 F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
@ -662,7 +662,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 18331ec28d7e63c8e262a9872a8da3964d37b7ac22eabe0016af93f3c6f74cc4 F ext/wasm/tester1.c-pp.js 9f8ae7c716ad66523cd6238fe947826c82b6a3b5c1e9d528f9f39ad9c9280ac7
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1 F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@ -2184,8 +2184,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 5c505ee8a73f4b4a7053d98a12024d98340676f6ae9982311f9f88a9b46c8ae2 P 672c2869ef48e08447d37b0d76a1850cdafbe30ca1906ec98c55e3ab496fd9a6
R cf33b03e4c9b76c0999c9981aab311dd R 69f9c602594d1ff3e9a25e02a2d41151
U drh U stephan
Z 8e2859a20a59f6d407b535859ed9b4c0 Z 6ab53eec83d52fe93f0c77e2c64383e8
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
672c2869ef48e08447d37b0d76a1850cdafbe30ca1906ec98c55e3ab496fd9a6 8fbda563d2f56f8dd3f695a5711e4356de79035f332270db45d4b33ed52fdfd2