mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-27 20:41:58 +03:00
WASM API renaming. Reworked JS API bootstrap's async post-init into a generic mechanism, no longer OPFS-specific.
FossilOrigin-Name: c42a8cb090cad1108dfd6be574202d744c59e053b505bc4c17252dc6b65d26bf
This commit is contained in:
@ -66,24 +66,33 @@ browser client:
|
|||||||
thread via the Worker message-passing interface. Like OO API #1,
|
thread via the Worker message-passing interface. Like OO API #1,
|
||||||
this is an optional component, offering one of any number of
|
this is an optional component, offering one of any number of
|
||||||
potential implementations for such an API.
|
potential implementations for such an API.
|
||||||
- `sqlite3-worker1.js`\
|
- `../sqlite3-worker1.js`\
|
||||||
Is not part of the amalgamated sources and is intended to be
|
Is not part of the amalgamated sources and is intended to be
|
||||||
loaded by a client Worker thread. It loads the sqlite3 module
|
loaded by a client Worker thread. It loads the sqlite3 module
|
||||||
and runs the Worker #1 API which is implemented in
|
and runs the Worker #1 API which is implemented in
|
||||||
`sqlite3-api-worker1.js`.
|
`sqlite3-api-worker1.js`.
|
||||||
|
- `../sqlite3-worker1-promiser.js`\
|
||||||
|
Is likewise not part of the amalgamated sources and provides
|
||||||
|
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-api-opfs.js`\
|
- `sqlite3-api-opfs.js`\
|
||||||
is an in-development/experimental sqlite3 VFS wrapper, the goal of
|
is an sqlite3 VFS implementation which supports Google Chrome's
|
||||||
which being to use Google Chrome's Origin-Private FileSystem (OPFS)
|
Origin-Private FileSystem (OPFS) as a storage layer to provide
|
||||||
storage layer to provide persistent storage for database files in a
|
persistent storage for database files in a browser. It requires...
|
||||||
browser. It is far from complete.
|
- `../sqlite3-opfs-async-proxy.js`\
|
||||||
|
is the asynchronous backend part of the OPFS proxy. It speaks
|
||||||
|
directly to the (async) OPFS API and channels those results back
|
||||||
|
to its synchronous counterpart. This file, because it must be
|
||||||
|
started in its own Worker, is not part of the amalgamation.
|
||||||
- `sqlite3-api-cleanup.js`\
|
- `sqlite3-api-cleanup.js`\
|
||||||
the previous files temporarily create global objects in order to
|
the previous files temporarily create global objects in order to
|
||||||
communicate their state to the files which follow them, and _this_
|
communicate their state to the files which follow them, and _this_
|
||||||
file connects any final components together and cleans up those
|
file connects any final components together and cleans up those
|
||||||
globals. As of this writing, this code ensures that the previous
|
globals. As of this writing, this code ensures that the previous
|
||||||
files leave no global symbols installed, and it moves the sqlite3
|
files leave no more than a single global symbol installed. When
|
||||||
namespace object into the in-scope Emscripten module. Abstracting
|
adapting the API for non-Emscripten toolchains, this "should"
|
||||||
this for other WASM toolchains is TODO.
|
be the only file where changes are needed.
|
||||||
- `post-js-footer.js`\
|
- `post-js-footer.js`\
|
||||||
Emscripten-specific footer for the `--post-js` input. This closes
|
Emscripten-specific footer for the `--post-js` input. This closes
|
||||||
off the lexical scope opened by `post-js-header.js`.
|
off the lexical scope opened by `post-js-header.js`.
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||||
/**
|
/**
|
||||||
sqlite3.installOpfsVfs() returns a Promise which, on success, installs
|
installOpfsVfs() returns a Promise which, on success, installs
|
||||||
an sqlite3_vfs named "opfs", suitable for use with all sqlite3 APIs
|
an sqlite3_vfs named "opfs", suitable for use with all sqlite3 APIs
|
||||||
which accept a VFS. It uses the Origin-Private FileSystem API for
|
which accept a VFS. It uses the Origin-Private FileSystem API for
|
||||||
all file storage. On error it is rejected with an exception
|
all file storage. On error it is rejected with an exception
|
||||||
@ -32,7 +32,6 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
- The environment does not support OPFS. That includes when
|
- The environment does not support OPFS. That includes when
|
||||||
this function is called from the main window thread.
|
this function is called from the main window thread.
|
||||||
|
|
||||||
|
|
||||||
Significant notes and limitations:
|
Significant notes and limitations:
|
||||||
|
|
||||||
- As of this writing, OPFS is still very much in flux and only
|
- As of this writing, OPFS is still very much in flux and only
|
||||||
@ -73,8 +72,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
object and that object gets a new object installed in its
|
object and that object gets a new object installed in its
|
||||||
`opfs` property, containing several OPFS-specific utilities.
|
`opfs` property, containing several OPFS-specific utilities.
|
||||||
*/
|
*/
|
||||||
sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri){
|
const installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri){
|
||||||
delete sqlite3.installOpfsVfs;
|
|
||||||
if(!self.SharedArrayBuffer ||
|
if(!self.SharedArrayBuffer ||
|
||||||
!self.FileSystemHandle ||
|
!self.FileSystemHandle ||
|
||||||
!self.FileSystemDirectoryHandle ||
|
!self.FileSystemDirectoryHandle ||
|
||||||
@ -1027,5 +1025,9 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
|
|||||||
})/*thePromise*/;
|
})/*thePromise*/;
|
||||||
return thePromise;
|
return thePromise;
|
||||||
}/*installOpfsVfs()*/;
|
}/*installOpfsVfs()*/;
|
||||||
sqlite3.installOpfsVfs.defaultProxyUri = "sqlite3-opfs-async-proxy.js";
|
installOpfsVfs.defaultProxyUri =
|
||||||
|
//self.location.pathname.replace(/[^/]*$/, "sqlite3-opfs-async-proxy.js");
|
||||||
|
"sqlite3-opfs-async-proxy.js";
|
||||||
|
//console.warn("sqlite3.installOpfsVfs.defaultProxyUri =",sqlite3.installOpfsVfs.defaultProxyUri);
|
||||||
|
self.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>installOpfsVfs());
|
||||||
}/*sqlite3ApiBootstrap.initializers.push()*/);
|
}/*sqlite3ApiBootstrap.initializers.push()*/);
|
||||||
|
@ -698,8 +698,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
["sqlite3_wasm_vfs_unlink", "int", "string"]
|
["sqlite3_wasm_vfs_unlink", "int", "string"]
|
||||||
];
|
];
|
||||||
|
|
||||||
/** State for sqlite3_web_persistent_dir(). */
|
/** State for sqlite3_wasmfs_opfs_dir(). */
|
||||||
let __persistentDir;
|
let __persistentDir = undefined;
|
||||||
/**
|
/**
|
||||||
An experiment. Do not use in client code.
|
An experiment. Do not use in client code.
|
||||||
|
|
||||||
@ -713,8 +713,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
|
|
||||||
This function currently only recognizes the WASMFS/OPFS storage
|
This function currently only recognizes the WASMFS/OPFS storage
|
||||||
combination. "Plain" OPFS is provided via a separate VFS which
|
combination. "Plain" OPFS is provided via a separate VFS which
|
||||||
can optionally be installed (if OPFS is available on the system)
|
is optionally be installed via sqlite3.asyncPostInit().
|
||||||
using sqlite3.installOpfsVfs().
|
|
||||||
|
|
||||||
TODOs and caveats:
|
TODOs and caveats:
|
||||||
|
|
||||||
@ -724,7 +723,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
happen when using the JS-native "opfs" VFS, as opposed to the
|
happen when using the JS-native "opfs" VFS, as opposed to the
|
||||||
WASMFS/OPFS combination.
|
WASMFS/OPFS combination.
|
||||||
*/
|
*/
|
||||||
capi.sqlite3_web_persistent_dir = function(){
|
capi.sqlite3_wasmfs_opfs_dir = function(){
|
||||||
if(undefined !== __persistentDir) return __persistentDir;
|
if(undefined !== __persistentDir) return __persistentDir;
|
||||||
// If we have no OPFS, there is no persistent dir
|
// If we have no OPFS, there is no persistent dir
|
||||||
const pdir = config.wasmfsOpfsDir;
|
const pdir = config.wasmfsOpfsDir;
|
||||||
@ -738,17 +737,6 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
if(pdir && 0===capi.wasm.xCallWrapped(
|
if(pdir && 0===capi.wasm.xCallWrapped(
|
||||||
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
|
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
|
||||||
)){
|
)){
|
||||||
/** OPFS does not support locking and will trigger errors if
|
|
||||||
we try to lock. We don't _really_ want to
|
|
||||||
_unconditionally_ install a non-locking sqlite3 VFS as the
|
|
||||||
default, but we do so here for simplicy's sake for the
|
|
||||||
time being. That said: locking is a no-op on all of the
|
|
||||||
current WASM storage, so this isn't (currently) as bad as
|
|
||||||
it may initially seem. */
|
|
||||||
const pVfs = sqlite3.capi.sqlite3_vfs_find("unix-none");
|
|
||||||
if(pVfs){
|
|
||||||
capi.sqlite3_vfs_register(pVfs,1);
|
|
||||||
}
|
|
||||||
return __persistentDir = pdir;
|
return __persistentDir = pdir;
|
||||||
}else{
|
}else{
|
||||||
return __persistentDir = "";
|
return __persistentDir = "";
|
||||||
@ -762,7 +750,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
/**
|
/**
|
||||||
Experimental and subject to change or removal.
|
Experimental and subject to change or removal.
|
||||||
|
|
||||||
Returns true if sqlite3.capi.sqlite3_web_persistent_dir() is a
|
Returns true if sqlite3.capi.sqlite3_wasmfs_opfs_dir() is a
|
||||||
non-empty string and the given name starts with (that string +
|
non-empty string and the given name starts with (that string +
|
||||||
'/'), else returns false.
|
'/'), else returns false.
|
||||||
|
|
||||||
@ -771,7 +759,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
kvvfs is available.
|
kvvfs is available.
|
||||||
*/
|
*/
|
||||||
capi.sqlite3_web_filename_is_persistent = function(name){
|
capi.sqlite3_web_filename_is_persistent = function(name){
|
||||||
const p = capi.sqlite3_web_persistent_dir();
|
const p = capi.sqlite3_wasmfs_opfs_dir();
|
||||||
return (p && name) ? name.startsWith(p+'/') : false;
|
return (p && name) ? name.startsWith(p+'/') : false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -922,11 +910,42 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
|
|
||||||
}/* main-window-only bits */
|
}/* main-window-only bits */
|
||||||
|
|
||||||
|
|
||||||
/* The remainder of the API will be set up in later steps. */
|
/* The remainder of the API will be set up in later steps. */
|
||||||
const sqlite3 = {
|
const sqlite3 = {
|
||||||
WasmAllocError: WasmAllocError,
|
WasmAllocError: WasmAllocError,
|
||||||
capi,
|
capi,
|
||||||
config
|
config,
|
||||||
|
/**
|
||||||
|
Performs any optional asynchronous library-level initialization
|
||||||
|
which might be required. This function returns a Promise which
|
||||||
|
resolves to the sqlite3 namespace object. It _ignores any
|
||||||
|
errors_ in the asynchronous init process, as such components
|
||||||
|
are all optional. If called more than once, the second and
|
||||||
|
subsequent calls are no-ops which return a pre-resolved
|
||||||
|
Promise.
|
||||||
|
|
||||||
|
If called at all, this function must be called by client-level
|
||||||
|
code, which must not use the library until the returned promise
|
||||||
|
resolves.
|
||||||
|
|
||||||
|
Bug: if called while a prior call is still resolving, the 2nd
|
||||||
|
call will resolve prematurely, before the 1st call has finished
|
||||||
|
resolving.
|
||||||
|
*/
|
||||||
|
asyncPostInit: async function(){
|
||||||
|
let lip = sqlite3ApiBootstrap.initializersAsync;
|
||||||
|
delete sqlite3ApiBootstrap.initializersAsync;
|
||||||
|
if(!lip || !lip.length) return Promise.resolve(sqlite3);
|
||||||
|
// Is it okay to resolve these in parallel or do we need them
|
||||||
|
// to resolve in order? We currently only have 1, so it
|
||||||
|
// makes no difference.
|
||||||
|
lip = lip.map((f)=>f(sqlite3).catch(()=>{}));
|
||||||
|
//let p = lip.shift();
|
||||||
|
//while(lip.length) p = p.then(lip.shift());
|
||||||
|
//return p.then(()=>sqlite3);
|
||||||
|
return Promise.all(lip).then(()=>sqlite3);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
sqlite3ApiBootstrap.initializers.forEach((f)=>f(sqlite3));
|
sqlite3ApiBootstrap.initializers.forEach((f)=>f(sqlite3));
|
||||||
delete sqlite3ApiBootstrap.initializers;
|
delete sqlite3ApiBootstrap.initializers;
|
||||||
@ -946,8 +965,29 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
their features (noting that most will also require that certain
|
their features (noting that most will also require that certain
|
||||||
features alread have been installed). At the end of that process,
|
features alread have been installed). At the end of that process,
|
||||||
this array is deleted.
|
this array is deleted.
|
||||||
|
|
||||||
|
Note that the order of insertion into this array is significant for
|
||||||
|
some pieces. e.g. sqlite3.capi.wasm cannot be fully utilized until
|
||||||
|
the whwasmutil.js part is plugged in.
|
||||||
*/
|
*/
|
||||||
self.sqlite3ApiBootstrap.initializers = [];
|
self.sqlite3ApiBootstrap.initializers = [];
|
||||||
|
/**
|
||||||
|
self.sqlite3ApiBootstrap.initializersAsync is an internal detail
|
||||||
|
used by the sqlite3 API's amalgamation process. It must not be
|
||||||
|
modified by client code except when plugging such code into the
|
||||||
|
amalgamation process.
|
||||||
|
|
||||||
|
Counterpart of self.sqlite3ApiBootstrap.initializers, specifically
|
||||||
|
for initializers which are asynchronous. All functions in this list
|
||||||
|
take the sqlite3 object as their argument and MUST return a
|
||||||
|
Promise. Both the resolved value and rejection cases are ignored.
|
||||||
|
|
||||||
|
This list is not processed until the client calls
|
||||||
|
sqlite3.asyncPostInit(). This means, for example, that intializers
|
||||||
|
added to self.sqlite3ApiBootstrap.initializers may push entries to
|
||||||
|
this list.
|
||||||
|
*/
|
||||||
|
self.sqlite3ApiBootstrap.initializersAsync = [];
|
||||||
/**
|
/**
|
||||||
Client code may assign sqlite3ApiBootstrap.defaultConfig an
|
Client code may assign sqlite3ApiBootstrap.defaultConfig an
|
||||||
object-type value before calling sqlite3ApiBootstrap() (without
|
object-type value before calling sqlite3ApiBootstrap() (without
|
||||||
|
@ -154,12 +154,12 @@
|
|||||||
messageId: ...as above...,
|
messageId: ...as above...,
|
||||||
result: {
|
result: {
|
||||||
|
|
||||||
persistentDirName: path prefix, if any, of persistent storage.
|
wasmfsOpfsDir: path prefix, if any, of persistent storage.
|
||||||
An empty string denotes that no persistent storage is available.
|
An empty string denotes that no persistent storage is available.
|
||||||
|
|
||||||
bigIntEnabled: bool. True if BigInt support is enabled.
|
bigIntEnabled: bool. True if BigInt support is enabled.
|
||||||
|
|
||||||
persistenceEnabled: true if persistent storage is enabled in the
|
wasmfsOpfsEnabled: true if persistent storage is enabled in the
|
||||||
current environment. Only files stored under persistentDirName
|
current environment. Only files stored under persistentDirName
|
||||||
will persist, however.
|
will persist, however.
|
||||||
|
|
||||||
@ -183,7 +183,7 @@
|
|||||||
See the sqlite3.oo1.DB constructor for peculiarities and transformations,
|
See the sqlite3.oo1.DB constructor for peculiarities and transformations,
|
||||||
|
|
||||||
persistent [=false]: if true and filename is not one of ("",
|
persistent [=false]: if true and filename is not one of ("",
|
||||||
":memory:"), prepend sqlite3.capi.sqlite3_web_persistent_dir()
|
":memory:"), prepend sqlite3.capi.sqlite3_wasmfs_opfs_dir()
|
||||||
to the given filename so that it is stored in persistent storage
|
to the given filename so that it is stored in persistent storage
|
||||||
_if_ the environment supports it. If persistent storage is not
|
_if_ the environment supports it. If persistent storage is not
|
||||||
supported, the filename is used as-is.
|
supported, the filename is used as-is.
|
||||||
@ -438,7 +438,7 @@ sqlite3.initWorker1API = function(){
|
|||||||
toss("Throwing because of simulateError flag.");
|
toss("Throwing because of simulateError flag.");
|
||||||
}
|
}
|
||||||
const rc = Object.create(null);
|
const rc = Object.create(null);
|
||||||
const pDir = sqlite3.capi.sqlite3_web_persistent_dir();
|
const pDir = sqlite3.capi.sqlite3_wasmfs_opfs_dir();
|
||||||
if(!args.filename || ':memory:'===args.filename){
|
if(!args.filename || ':memory:'===args.filename){
|
||||||
oargs.filename = args.filename || '';
|
oargs.filename = args.filename || '';
|
||||||
}else if(pDir){
|
}else if(pDir){
|
||||||
@ -521,11 +521,11 @@ sqlite3.initWorker1API = function(){
|
|||||||
'config-get': function(){
|
'config-get': function(){
|
||||||
const rc = Object.create(null), src = sqlite3.config;
|
const rc = Object.create(null), src = sqlite3.config;
|
||||||
[
|
[
|
||||||
'persistentDirName', 'bigIntEnabled'
|
'wasmfsOpfsDir', 'bigIntEnabled'
|
||||||
].forEach(function(k){
|
].forEach(function(k){
|
||||||
if(Object.getOwnPropertyDescriptor(src, k)) rc[k] = src[k];
|
if(Object.getOwnPropertyDescriptor(src, k)) rc[k] = src[k];
|
||||||
});
|
});
|
||||||
rc.persistenceEnabled = !!sqlite3.capi.sqlite3_web_persistent_dir();
|
rc.wasmfsOpfsEnabled = !!sqlite3.capi.sqlite3_wasmfs_opfs_dir();
|
||||||
return rc;
|
return rc;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -543,9 +543,10 @@ int sqlite3_wasm_vfs_unlink(const char * zName){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__EMSCRIPTEN__) && defined(SQLITE_WASM_WASMFS)
|
#if defined(__EMSCRIPTEN__)
|
||||||
#include <emscripten/wasmfs.h>
|
|
||||||
#include <emscripten/console.h>
|
#include <emscripten/console.h>
|
||||||
|
#if defined(SQLITE_WASM_WASMFS)
|
||||||
|
#include <emscripten/wasmfs.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||||
@ -596,10 +597,11 @@ int sqlite3_wasm_init_wasmfs(const char *zMountPoint){
|
|||||||
#else
|
#else
|
||||||
WASM_KEEP
|
WASM_KEEP
|
||||||
int sqlite3_wasm_init_wasmfs(const char *zUnused){
|
int sqlite3_wasm_init_wasmfs(const char *zUnused){
|
||||||
|
emscripten_console_warn("WASMFS OPFS is not compiled in.");
|
||||||
if(zUnused){/*unused*/}
|
if(zUnused){/*unused*/}
|
||||||
return SQLITE_NOTFOUND;
|
return SQLITE_NOTFOUND;
|
||||||
}
|
}
|
||||||
#endif /* __EMSCRIPTEN__ && SQLITE_WASM_WASMFS */
|
#endif /* __EMSCRIPTEN__ && SQLITE_WASM_WASMFS */
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef WASM_KEEP
|
#undef WASM_KEEP
|
||||||
|
@ -361,7 +361,7 @@
|
|||||||
dbFile = 1 ? 'local' : 'session';
|
dbFile = 1 ? 'local' : 'session';
|
||||||
this.logHtml("Using KVVFS storage:",dbFile);
|
this.logHtml("Using KVVFS storage:",dbFile);
|
||||||
}else{
|
}else{
|
||||||
pDir = capi.sqlite3_web_persistent_dir();
|
pDir = capi.sqlite3_wasmfs_opfs_dir();
|
||||||
if(pDir){
|
if(pDir){
|
||||||
dbFile = pDir+"/speedtest.db";
|
dbFile = pDir+"/speedtest.db";
|
||||||
this.logHtml("Using persistent storage:",dbFile);
|
this.logHtml("Using persistent storage:",dbFile);
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
oo = sqlite3.oo1,
|
oo = sqlite3.oo1,
|
||||||
wasm = capi.wasm;
|
wasm = capi.wasm;
|
||||||
stdout("Loaded sqlite3:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
|
stdout("Loaded sqlite3:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
|
||||||
const persistentDir = capi.sqlite3_web_persistent_dir();
|
const persistentDir = capi.sqlite3_wasmfs_opfs_dir();
|
||||||
if(persistentDir){
|
if(persistentDir){
|
||||||
stdout("Persistent storage dir:",persistentDir);
|
stdout("Persistent storage dir:",persistentDir);
|
||||||
}else{
|
}else{
|
||||||
|
@ -81,11 +81,10 @@
|
|||||||
setStatus: (text)=>mPost('load-status',text)
|
setStatus: (text)=>mPost('load-status',text)
|
||||||
};
|
};
|
||||||
self.sqlite3Speedtest1InitModule(EmscriptenModule).then(function(EModule){
|
self.sqlite3Speedtest1InitModule(EmscriptenModule).then(function(EModule){
|
||||||
const S = EModule.sqlite3;
|
|
||||||
log("Module inited.");
|
log("Module inited.");
|
||||||
return S.installOpfsVfs()
|
return EModule.sqlite3.asyncPostInit()
|
||||||
.catch((e)=>console.warn(e.message))
|
.then((sqlite3)=>{
|
||||||
.then(()=>{
|
const S = sqlite3;
|
||||||
const vfsUnlink = S.capi.wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]);
|
const vfsUnlink = S.capi.wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]);
|
||||||
App.unlink = function(fname){
|
App.unlink = function(fname){
|
||||||
vfsUnlink(fname);
|
vfsUnlink(fname);
|
||||||
|
@ -248,7 +248,10 @@ self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
|||||||
};
|
};
|
||||||
}/*sqlite3Worker1Promiser()*/;
|
}/*sqlite3Worker1Promiser()*/;
|
||||||
self.sqlite3Worker1Promiser.defaultConfig = {
|
self.sqlite3Worker1Promiser.defaultConfig = {
|
||||||
worker: ()=>new Worker('sqlite3-worker1.js'),
|
worker: ()=>{
|
||||||
|
//const p = self.location.pathname.replace(/[^/]*$/, "sqlite3-worker1.js");
|
||||||
|
return new Worker("sqlite3-worker1.js");
|
||||||
|
},
|
||||||
onerror: (...args)=>console.error('worker1 error',...args),
|
onerror: (...args)=>console.error('worker1 error',...args),
|
||||||
dbId: undefined
|
dbId: undefined
|
||||||
};
|
};
|
||||||
|
@ -28,4 +28,9 @@
|
|||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
importScripts('sqlite3.js');
|
importScripts('sqlite3.js');
|
||||||
sqlite3InitModule().then((EmscriptenModule)=>EmscriptenModule.sqlite3.initWorker1API());
|
sqlite3InitModule().then((EmscriptenModule)=>{
|
||||||
|
EmscriptenModule.sqlite3.asyncPostInit().then((sqlite3)=>{
|
||||||
|
sqlite3.capi.sqlite3_wasmfs_opfs_dir();
|
||||||
|
sqlite3.initWorker1API();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -30,7 +30,7 @@ const tryOpfsVfs = function(sqlite3){
|
|||||||
const error = (...args)=>console.error(logPrefix,...args);
|
const error = (...args)=>console.error(logPrefix,...args);
|
||||||
log("tryOpfsVfs()");
|
log("tryOpfsVfs()");
|
||||||
const capi = sqlite3.capi;
|
const capi = sqlite3.capi;
|
||||||
const pVfs = capi.sqlite3_vfs_find("opfs") || toss("Unexpectedly missing 'opfs' VFS.");
|
const pVfs = capi.sqlite3_vfs_find("opfs") || toss("Missing 'opfs' VFS.");
|
||||||
const oVfs = capi.sqlite3_vfs.instanceForPointer(pVfs) || toss("Unexpected instanceForPointer() result.");;
|
const oVfs = capi.sqlite3_vfs.instanceForPointer(pVfs) || toss("Unexpected instanceForPointer() result.");;
|
||||||
log("OPFS VFS:",pVfs, oVfs);
|
log("OPFS VFS:",pVfs, oVfs);
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ const tryOpfsVfs = function(sqlite3){
|
|||||||
|
|
||||||
importScripts('sqlite3.js');
|
importScripts('sqlite3.js');
|
||||||
self.sqlite3InitModule()
|
self.sqlite3InitModule()
|
||||||
.then((EmscriptenModule)=>EmscriptenModule.sqlite3.installOpfsVfs())
|
.then((EmscriptenModule)=>EmscriptenModule.sqlite3.asyncPostInit())
|
||||||
.then((sqlite3)=>tryOpfsVfs(sqlite3))
|
.then((sqlite3)=>tryOpfsVfs(sqlite3))
|
||||||
.catch((e)=>{
|
.catch((e)=>{
|
||||||
console.error("Error initializing module:",e);
|
console.error("Error initializing module:",e);
|
||||||
|
@ -77,8 +77,8 @@
|
|||||||
const r = ev.result;
|
const r = ev.result;
|
||||||
log('sqlite3.config subset:', r);
|
log('sqlite3.config subset:', r);
|
||||||
T.assert('boolean' === typeof r.bigIntEnabled)
|
T.assert('boolean' === typeof r.bigIntEnabled)
|
||||||
.assert('string'===typeof r.persistentDirName)
|
.assert('string'===typeof r.wasmfsOpfsDir)
|
||||||
.assert('boolean' === typeof r.persistenceEnabled);
|
.assert('boolean' === typeof r.wasmfsOpfsEnabled);
|
||||||
sqConfig = r;
|
sqConfig = r;
|
||||||
});
|
});
|
||||||
logHtml('',
|
logHtml('',
|
||||||
@ -86,12 +86,12 @@
|
|||||||
|
|
||||||
await wtest('open', {
|
await wtest('open', {
|
||||||
filename: dbFilename,
|
filename: dbFilename,
|
||||||
persistent: sqConfig.persistenceEnabled,
|
persistent: sqConfig.wasmfsOpfsEnabled,
|
||||||
simulateError: 0 /* if true, fail the 'open' */,
|
simulateError: 0 /* if true, fail the 'open' */,
|
||||||
}, function(ev){
|
}, function(ev){
|
||||||
const r = ev.result;
|
const r = ev.result;
|
||||||
log("then open result",r);
|
log("then open result",r);
|
||||||
T.assert(r.persistent === sqConfig.persistenceEnabled)
|
T.assert(r.persistent === sqConfig.wasmfsOpfsEnabled)
|
||||||
.assert(r.persistent
|
.assert(r.persistent
|
||||||
? (dbFilename!==r.filename)
|
? (dbFilename!==r.filename)
|
||||||
: (dbFilename==r.filename))
|
: (dbFilename==r.filename))
|
||||||
|
@ -1019,7 +1019,7 @@
|
|||||||
wasm = capi.wasm;
|
wasm = capi.wasm;
|
||||||
log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
|
log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
|
||||||
log("Build options:",wasm.compileOptionUsed());
|
log("Build options:",wasm.compileOptionUsed());
|
||||||
capi.sqlite3_web_persistent_dir()/*will install OPFS if available, plus a and non-locking VFS*/;
|
capi.sqlite3_wasmfs_opfs_dir()/*will install OPFS if available, plus a and non-locking VFS*/;
|
||||||
if(1){
|
if(1){
|
||||||
/* Let's grab those last few lines of test coverage for
|
/* Let's grab those last few lines of test coverage for
|
||||||
sqlite3-api.js... */
|
sqlite3-api.js... */
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
***********************************************************************
|
***********************************************************************
|
||||||
|
|
||||||
A basic test script for sqlite3-worker1.js.
|
A basic test script for sqlite3-worker1.js.
|
||||||
|
|
||||||
|
Note that the wrapper interface demonstrated in
|
||||||
|
testing-worker1-promiser.js is much easier to use from client code, as it
|
||||||
|
lacks the message-passing acrobatics demonstrated in this file.
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
(function(){
|
(function(){
|
||||||
|
38
manifest
38
manifest
@ -1,5 +1,5 @@
|
|||||||
C wasm/js:\srename\s/persistent\sto\s/opfs\sto\saccount\sfor\spotential\sfuture\spersistent\sstorage\soptions.\sMinor\sflag-handling\scleanups\sin\sthe\sspeedtest1\spages.\sMinor\sAPI\stweaks\sin\soo1.
|
C WASM\sAPI\srenaming.\sReworked\sJS\sAPI\sbootstrap's\sasync\spost-init\sinto\sa\sgeneric\smechanism,\sno\slonger\sOPFS-specific.
|
||||||
D 2022-09-27T09:17:37.806
|
D 2022-09-27T13:40:12.824
|
||||||
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
|
||||||
@ -478,19 +478,19 @@ F ext/wasm/GNUmakefile 34a84e30e6b25e24959a8264e9dec020dffa82d96879dc55ad65d3c31
|
|||||||
F ext/wasm/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
|
F ext/wasm/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
|
||||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 77a5ee8bd209b5e75dd0e822bc3f6e7319dc9b36431463d4175c775170f92126
|
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 77a5ee8bd209b5e75dd0e822bc3f6e7319dc9b36431463d4175c775170f92126
|
||||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||||
F ext/wasm/api/README.md d876597edd2b9542b6ea031adaaff1c042076fde7b670b1dc6d8a87b28a6631b
|
F ext/wasm/api/README.md f54102d74cfde01ebe242fa1411e126a9cda8f19b3ac378afd1103b21abfad05
|
||||||
F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba81456260a713ed04900c
|
F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba81456260a713ed04900c
|
||||||
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
|
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
|
||||||
F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77
|
F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77
|
||||||
F ext/wasm/api/sqlite3-api-glue.js fe5ca21ac519e6411f5e7a6403d06fe92c51ef81cca8e07ea8895df8ec9c2e4e
|
F ext/wasm/api/sqlite3-api-glue.js fe5ca21ac519e6411f5e7a6403d06fe92c51ef81cca8e07ea8895df8ec9c2e4e
|
||||||
F ext/wasm/api/sqlite3-api-oo1.js 97a786b366fcac442e1557c3eedef3afa96877411bd6239094d4db5fd5b3c353
|
F ext/wasm/api/sqlite3-api-oo1.js 97a786b366fcac442e1557c3eedef3afa96877411bd6239094d4db5fd5b3c353
|
||||||
F ext/wasm/api/sqlite3-api-opfs.js 1128b3cbfbecbe66324d334f4561ccf61f2b08f73075e6c77a053f7ecb71090f
|
F ext/wasm/api/sqlite3-api-opfs.js dce3bd8c0da238bce8f9dd856f22b79424c8eeae8dd0b439ac87ed567e6149c0
|
||||||
F ext/wasm/api/sqlite3-api-prologue.js 0ba5ae19021524e02d977668c6b16e951b4ebe0d5f0ff0577e85f4209284a11a
|
F ext/wasm/api/sqlite3-api-prologue.js 9bcec56baf306d1d9341cbbdea59fe0abc195db0c3ecbbc396ec5098cdbda786
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js 2eeb2a24e1a90322d84a9b88a99919b806623de62792436446099c0988f2030b
|
F ext/wasm/api/sqlite3-api-worker1.js d5d5b7fac4c4731c38c7e03f4f404b2a95c388a2a1d8bcf361caada572f107e0
|
||||||
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
||||||
F ext/wasm/api/sqlite3-wasm.c 1409d76529537c2d21a06678df81a3cb5050e212a5ae4cdd9fb42ca5716c65e9
|
F ext/wasm/api/sqlite3-wasm.c b756b9c1fee9d0598f715e6df6bf089b750da24aa91bb7ef9277a037d81e7612
|
||||||
F ext/wasm/batch-runner.html 2857a6db7292ac83d1581af865d643fd34235db2df830d10b43b01388c599e04
|
F ext/wasm/batch-runner.html 2857a6db7292ac83d1581af865d643fd34235db2df830d10b43b01388c599e04
|
||||||
F ext/wasm/batch-runner.js 6f5b86e0b5519a9a941d9f17ee9c5ecdc63f452f157602fe7fdf87f6275a2b49
|
F ext/wasm/batch-runner.js b1f443bc63a779aac97ba6d54fc731a707ece2783b94e3b019abbfa79108e9a1
|
||||||
F ext/wasm/common/SqliteTestUtil.js c997c12188c97109f344701a58dd627b9c0f98f32cc6a88413f6171f2191531c
|
F ext/wasm/common/SqliteTestUtil.js c997c12188c97109f344701a58dd627b9c0f98f32cc6a88413f6171f2191531c
|
||||||
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
||||||
F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962
|
F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962
|
||||||
@ -511,25 +511,25 @@ F ext/wasm/jaccwabyt/jaccwabyt.md 9aa6951b529a8b29f578ec8f0355713c39584c92cf1708
|
|||||||
F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5300668e9960fff30d0d36f
|
F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5300668e9960fff30d0d36f
|
||||||
F ext/wasm/jaccwabyt/jaccwabyt_test.exports 5ff001ef975c426ffe88d7d8a6e96ec725e568d2c2307c416902059339c06f19
|
F ext/wasm/jaccwabyt/jaccwabyt_test.exports 5ff001ef975c426ffe88d7d8a6e96ec725e568d2c2307c416902059339c06f19
|
||||||
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
|
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
|
||||||
F ext/wasm/scratchpad-wasmfs-main.js f0836e3576df7a89390d777bb53e142e559e8a79becfb2a5a976490b05a1c4fa
|
F ext/wasm/scratchpad-wasmfs-main.js e713a3da53da9194a1cc35d060f0ee5cb0abe907dcbc864d3d6f76fa6eafedf1
|
||||||
F ext/wasm/speedtest1-wasmfs.html 852504ccf9d095c8f57d4f4f9cc2f912b3b432e300c6b5ed8d6234a37eeb86a6
|
F ext/wasm/speedtest1-wasmfs.html 852504ccf9d095c8f57d4f4f9cc2f912b3b432e300c6b5ed8d6234a37eeb86a6
|
||||||
F ext/wasm/speedtest1-worker.html 3780a29a6d0467dde34b61bf50a1b2e1a12a4e8498f4835b1293e79a3edcd675
|
F ext/wasm/speedtest1-worker.html 3780a29a6d0467dde34b61bf50a1b2e1a12a4e8498f4835b1293e79a3edcd675
|
||||||
F ext/wasm/speedtest1-worker.js 08f9e9ffe0082098b2566a56c1b2655a70917b17edcdec9a28cdcc01c097d4df
|
F ext/wasm/speedtest1-worker.js 65f50314cc56ebc03f7b5ea774e7d8386600e8a6f27cca02cb05e7e2eb7a0153
|
||||||
F ext/wasm/speedtest1.html 4f4e26b634bb3288f2cad8cf4d458076b33d8bd0f3fd56e089a17bed32df6287
|
F ext/wasm/speedtest1.html 4f4e26b634bb3288f2cad8cf4d458076b33d8bd0f3fd56e089a17bed32df6287
|
||||||
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
|
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
|
||||||
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
|
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
|
||||||
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
|
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
|
||||||
F ext/wasm/sqlite3-opfs-async-proxy.js fe4b8268eea9acaec633ebd1dd3f85dae7c461c5c68985ab1075d9560b1db8e8
|
F ext/wasm/sqlite3-opfs-async-proxy.js fe4b8268eea9acaec633ebd1dd3f85dae7c461c5c68985ab1075d9560b1db8e8
|
||||||
F ext/wasm/sqlite3-worker1-promiser.js 4fd0465688a28a75f1d4ee4406540ba494f49844e3cad0670d0437a001943365
|
F ext/wasm/sqlite3-worker1-promiser.js cca2b853692e4715b4761c46678f96d80819d4756de557922a815149fb93397e
|
||||||
F ext/wasm/sqlite3-worker1.js 0c1e7626304543969c3846573e080c082bf43bcaa47e87d416458af84f340a9e
|
F ext/wasm/sqlite3-worker1.js b941db258fd26ae2c7398b640c1ca8d5abac8ec77e54ba5b9526af2297409626
|
||||||
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
|
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
|
||||||
F ext/wasm/test-opfs-vfs.js 753c6b86dd8ce0813121add44726a038ba1b83acebdc8414189cb163faf23e6d
|
F ext/wasm/test-opfs-vfs.js ba4c20085000b9f6195f62cf3abeeb0ae4703c3b34bc654afa806014a4f09e96
|
||||||
F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893
|
F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893
|
||||||
F ext/wasm/testing-worker1-promiser.js 63448fddfd3b8c89ff667d17c8b31c6c2259dd4647ebbbd28f3a921c48e924da
|
F ext/wasm/testing-worker1-promiser.js ee1ac4950720c07541e791b7f35bdf420e8ab81a74049cc65394371b0c53c480
|
||||||
F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae
|
F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae
|
||||||
F ext/wasm/testing1.js 7b90ea5f50fbb9529d10f384d2a89ab7aed4d72112fa2765bbdf72a087f47303
|
F ext/wasm/testing1.js 20b37766d29815180e2e932bfc6132b649403ece1f1bf612a4712db131287970
|
||||||
F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
|
F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
|
||||||
F ext/wasm/testing2.js 25584bcc30f19673ce13a6f301f89f8820a59dfe044e0c4f2913941f4097fe3c
|
F ext/wasm/testing2.js 34737da985c4cbd4812b2e7f200942662cae991c5a58ffa5d0350be089d0d410
|
||||||
F ext/wasm/wasmfs.make 52f24bc9c10e404d26bd0b0ee28d450269808a78e359d6ddedc45d31e7b9c29c
|
F ext/wasm/wasmfs.make 52f24bc9c10e404d26bd0b0ee28d450269808a78e359d6ddedc45d31e7b9c29c
|
||||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||||
@ -2026,8 +2026,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 3579a8d6f1f6cd3cd8aad9949536870c5fe7bae8c1778f700dd85d763e266b94
|
P 4dc972a3656b2a9ec915bfb3f653136560c753ce4024c3f0d0d0c28f66db7a0a
|
||||||
R 786e465dc63fbf42c76f34e46e9a73e9
|
R ebd299190a12161c219ed1951eeaf1b4
|
||||||
U stephan
|
U stephan
|
||||||
Z 0e6490797de722dba8eac0d97289515b
|
Z 4f0d8b1c55221b0d2bac6e925a4d61bf
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
4dc972a3656b2a9ec915bfb3f653136560c753ce4024c3f0d0d0c28f66db7a0a
|
c42a8cb090cad1108dfd6be574202d744c59e053b505bc4c17252dc6b65d26bf
|
Reference in New Issue
Block a user