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

wasm: add a small demo/presentation app for JS OO API #1 and make a few minor additions to that API.

FossilOrigin-Name: d6d79b661a1c6137d4693393e02416da4858d58dc84d144081a48d523655b483
This commit is contained in:
stephan
2022-08-16 16:36:19 +00:00
parent ba851ae72e
commit e0c582850e
6 changed files with 345 additions and 55 deletions

View File

@ -80,35 +80,57 @@
not resolve to real filenames, but "" uses an on-storage not resolve to real filenames, but "" uses an on-storage
temporary database and requires that the VFS support that. temporary database and requires that the VFS support that.
The db is currently opened with a fixed set of flags: The second argument specifies the open/create mode for the
(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | database. It must be string containing a sequence of letters (in
SQLITE_OPEN_EXRESCODE). This API will change in the future any order, but case sensitive) specifying the mode:
permit the caller to provide those flags via an additional
argument. - "c" => create if it does not exist, else fail if it does not
exist. Implies the "w" flag.
- "w" => write. Implies "r": a db cannot be write-only.
- "r" => read-only if neither "w" nor "c" are provided, else it
is ignored.
If "w" is not provided, the db is implicitly read-only, noting that
"rc" is meaningless
Any other letters are currently ignored. The default is
"c". These modes are ignored for the special ":memory:" and ""
names.
The final argument is currently unimplemented but will eventually
be used to specify an optional sqlite3 VFS implementation name,
as for the final argument to sqlite3_open_v2().
For purposes of passing a DB instance to C-style sqlite3 For purposes of passing a DB instance to C-style sqlite3
functions, its read-only `pointer` property holds its `sqlite3*` functions, the DB object's read-only `pointer` property holds its
pointer value. That property can also be used to check whether `sqlite3*` pointer value. That property can also be used to check
this DB instance is still open. whether this DB instance is still open.
*/ */
const DB = function ctor(fn=':memory:'){ const DB = function ctor(fn=':memory:', flags='c', vtab="not yet implemented"){
if('string'!==typeof fn){ if('string'!==typeof fn){
toss3("Invalid filename for DB constructor."); toss3("Invalid filename for DB constructor.");
} }
let ptr, oflags = 0;
if( flags.indexOf('c')>=0 ){
oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
}
if( flags.indexOf('w')>=0 ) oflags |= capi.SQLITE_OPEN_READWRITE;
if( 0===oflags ) oflags |= capi.SQLITE_OPEN_READONLY;
oflags |= capi.SQLITE_OPEN_EXRESCODE;
const stack = capi.wasm.scopedAllocPush(); const stack = capi.wasm.scopedAllocPush();
let ptr;
try { try {
const ppDb = capi.wasm.scopedAllocPtr() /* output (sqlite3**) arg */; const ppDb = capi.wasm.scopedAllocPtr() /* output (sqlite3**) arg */;
const rc = capi.sqlite3_open_v2(fn, ppDb, capi.SQLITE_OPEN_READWRITE const rc = capi.sqlite3_open_v2(fn, ppDb, oflags, null);
| capi.SQLITE_OPEN_CREATE
| capi.SQLITE_OPEN_EXRESCODE, null);
ptr = capi.wasm.getMemValue(ppDb, '*'); ptr = capi.wasm.getMemValue(ppDb, '*');
ctor.checkRc(ptr, rc); ctor.checkRc(ptr, rc);
}catch(e){ }catch( e ){
if(ptr) capi.sqlite3_close_v2(ptr); if( ptr ) capi.sqlite3_close_v2(ptr);
throw e; throw e;
}finally{
capi.wasm.scopedAllocPop(stack);
} }
finally{capi.wasm.scopedAllocPop(stack);}
this.filename = fn; this.filename = fn;
__ptrMap.set(this, ptr); __ptrMap.set(this, ptr);
__stmtMap.set(this, Object.create(null)); __stmtMap.set(this, Object.create(null));
@ -315,11 +337,10 @@
file. If the name is "" or ":memory:", it resolves to false. file. If the name is "" or ":memory:", it resolves to false.
Note that it is not aware of the peculiarities of URI-style Note that it is not aware of the peculiarities of URI-style
names and a URI-style name for a ":memory:" db will fool it. names and a URI-style name for a ":memory:" db will fool it.
Returns false if this db is closed.
*/ */
hasFilename: function(){ hasFilename: function(){
const fn = this.filename; return this.filename && ':memory'!==this.filename;
if(!fn || ':memory'===fn) return false;
return true;
}, },
/** /**
Returns the name of the given 0-based db number, as documented Returns the name of the given 0-based db number, as documented
@ -451,14 +472,14 @@
statement in the SQL which has any bindable statement in the SQL which has any bindable
parameters. (Empty statements are skipped entirely.) parameters. (Empty statements are skipped entirely.)
- .callback = a function which gets called for each row of - .callback = a function which gets called for each row of the
the FIRST statement in the SQL which has result FIRST statement in the SQL which has result _columns_, but only
_columns_, but only if that statement has any result if that statement has any result _rows_. The callback's "this"
_rows_. The second argument passed to the callback is is the options object. The second argument passed to the
always the current Stmt object (so that the caller may callback is always the current Stmt object (so that the caller
collect column names, or similar). The first argument may collect column names, or similar). The first argument
passed to the callback defaults to the current Stmt passed to the callback defaults to the current Stmt object but
object but may be changed with ... may be changed with ...
- .rowMode = either a string describing what type of argument - .rowMode = either a string describing what type of argument
should be passed as the first argument to the callback or an should be passed as the first argument to the callback or an
@ -479,12 +500,13 @@
the FIRST first statement which has result _columns_ is the FIRST first statement which has result _columns_ is
appended to the array in the format specified for the `rowMode` appended to the array in the format specified for the `rowMode`
option, with the exception that the only legal values for option, with the exception that the only legal values for
`rowMode` in this case are 'array' or 'object', neither of `rowMode` in this case are 'array', 'object', or an integer,
which is the default. It is legal to use both `resultRows` and none of which are the default for `rowMode`. It is legal to use
`callback`, but `resultRows` is likely much simpler to use for both `resultRows` and `callback`, but `resultRows` is likely
small data sets and can be used over a WebWorker-style message much simpler to use for small data sets and can be used over a
interface. execMulti() throws if `resultRows` is set and WebWorker-style message interface. execMulti() throws if
`rowMode` is 'stmt' (which is the default!). `resultRows` is set and `rowMode` is 'stmt' (which is the
default!).
- saveSql = an optional array. If set, the SQL of each - saveSql = an optional array. If set, the SQL of each
executed statement is appended to this array before the executed statement is appended to this array before the
@ -1081,6 +1103,7 @@
delete __stmtMap.get(this.db)[this.pointer]; delete __stmtMap.get(this.db)[this.pointer];
capi.sqlite3_finalize(this.pointer); capi.sqlite3_finalize(this.pointer);
__ptrMap.delete(this); __ptrMap.delete(this);
delete this._mayGet;
delete this.columnCount; delete this.columnCount;
delete this.parameterCount; delete this.parameterCount;
delete this.db; delete this.db;
@ -1268,6 +1291,27 @@
DB.checkRc(this.db.pointer, rc); DB.checkRc(this.db.pointer, rc);
} }
}, },
/**
Functions exactly like step() except that...
1) On success, it calls this.reset() and returns this object.
2) On error, it throws and does not call reset().
This is intended to simplify constructs like:
```
for(...) {
stmt.bind(...).stepReset();
}
```
Note that the reset() call makes it illegal to call this.get()
after the step.
*/
stepReset: function(){
this.step();
return this.reset();
},
/** /**
Functions like step() except that Functions like step() except that
it finalizes this statement immediately after stepping unless it finalizes this statement immediately after stepping unless
@ -1286,17 +1330,9 @@
``` ```
*/ */
stepFinalize: function(){ stepFinalize: function(){
affirmUnlocked(this, 'step()'); const rc = this.step();
const rc = capi.sqlite3_step(affirmStmtOpen(this).pointer); this.finalize();
switch(rc){ return rc;
case capi.SQLITE_DONE: this.finalize(); return false;
case capi.SQLITE_ROW: this.finalize(); return true;
default:
this.finalize();
console.warn("sqlite3_step() rc=",rc,"SQL =",
capi.sqlite3_sql(this.pointer));
DB.checkRc(this.db.pointer, rc);
}
}, },
/** /**
Fetches the value from the given 0-based column index of Fetches the value from the given 0-based column index of
@ -1400,7 +1436,7 @@
default: toss3("Don't know how to translate", default: toss3("Don't know how to translate",
"type of result column #"+ndx+"."); "type of result column #"+ndx+".");
} }
abort("Not reached."); toss3("Not reached.");
}, },
/** Equivalent to get(ndx) but coerces the result to an /** Equivalent to get(ndx) but coerces the result to an
integer. */ integer. */

34
ext/wasm/demo-oo1.html Normal file
View File

@ -0,0 +1,34 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<link rel="stylesheet" href="common/emscripten.css"/>
<link rel="stylesheet" href="common/testing.css"/>
<title>sqlite3-api OO #1 Demo</title>
</head>
<body>
<header id='titlebar'><span>sqlite3-api OO #1 Demo</span></header>
<!-- emscripten bits -->
<figure id="module-spinner">
<div class="spinner"></div>
<div class='center'><strong>Initializing app...</strong></div>
<div class='center'>
On a slow internet connection this may take a moment. If this
message displays for "a long time", intialization may have
failed and the JavaScript console may contain clues as to why.
</div>
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<div>Most stuff on this page happens in the dev console.</div>
<hr>
<div id='test-output'></div>
<script src="sqlite3.js"></script>
<script src="common/SqliteTestUtil.js"></script>
<script src="demo-oo1.js"></script>
</body>
</html>

218
ext/wasm/demo-oo1.js Normal file
View File

@ -0,0 +1,218 @@
/*
2022-08-16
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A basic demonstration of the SQLite3 OO API #1, shorn of assertions
and the like to improve readability.
*/
'use strict';
(function(){
const T = self.SqliteTestUtil;
const toss = function(...args){throw new Error(args.join(' '))};
const debug = console.debug.bind(console),
log = console.log.bind(console),
warn = console.warn.bind(console),
error = console.error.bind(console);
const demo1 = function(sqlite3,EmModule){
const capi = sqlite3.capi,
oo = sqlite3.oo1,
wasm = capi.wasm;
// If we have persistent storage, maybe init and mount it:
const dbDir = true
? "" // this demo works better without persistent storage.
: capi.sqlite3_web_persistent_dir();
// ^^^ returns name of persistent mount point or "" if we have none
const db = new oo.DB(dbDir+"/mydb.sqlite3");
/**
Never(!) rely on garbage collection to clean up DBs and
(especially) statements. Always wrap their lifetimes in
try/finally construct...
*/
try {
log("Create a table...");
db.exec("CREATE TABLE IF NOT EXISTS t(a,b)");
//Equivalent:
db.exec({
sql:"CREATE TABLE IF NOT EXISTS t(a,b)"
// ... numerous other options ...
});
// SQL can be either a string or a byte array
log("Insert some data using exec()...");
let i;
for( i = 1; i <= 5; ++i ){
db.exec({
sql: "insert into t(a,b) values (?,?)",
// bind by parameter index...
bind: [i, i*2]
});
db.exec({
sql: "insert into t(a,b) values ($a,$b)",
// bind by parameter name...
bind: {$a: i * 3, $b: i * 4}
});
}
log("Insert using a prepared statement...");
let q = db.prepare("insert into t(a,b) values(?,?)");
try {
for( i = 100; i < 103; ++i ){
q.bind( [i, i*2] ).step();
q.reset();
}
// Equivalent...
for( i = 103; i <= 105; ++i ){
q.bind(1, i).bind(2, i*2).stepReset();
}
}finally{
q.finalize();
}
log("Query data with exec() using rowMode 'array'...");
db.exec({
sql: "select a from t order by a limit 3",
rowMode: 'array', // 'array', 'object', or 'stmt' (default)
callback: function(row){
log("row ",++this.counter,"=",row);
}.bind({counter: 0})
});
log("Query data with exec() using rowMode 'object'...");
db.exec({
sql: "select a as aa, b as bb from t order by aa limit 3",
rowMode: 'object',
callback: function(row){
log("row ",++this.counter,"=",row);
}.bind({counter: 0})
});
log("Query data with exec() using rowMode 'stmt'...");
db.exec({
sql: "select a from t order by a limit 3",
rowMode: 'stmt', // stmt === the default
callback: function(row){
log("row ",++this.counter,"get(0) =",row.get(0));
}.bind({counter: 0})
});
log("Query data with exec() using rowMode INTEGER (result column index)...");
db.exec({
sql: "select a, b from t order by a limit 3",
rowMode: 1, // === result column 1
callback: function(row){
log("row ",++this.counter,"b =",row);
}.bind({counter: 0})
});
log("Query data with exec() without a callback...");
let resultRows = [];
db.exec({
sql: "select a, b from t order by a limit 3",
rowMode: 'object',
resultRows: resultRows
});
log("Result rows:",resultRows);
log("Create a scalar UDF...");
db.createFunction({
name: 'twice',
callback: function(arg){ // note the call arg count
return arg + arg;
}
});
log("Run scalar UDF and collect result column names...");
let columnNames = [];
db.exec({
sql: "select a, twice(a), twice(''||a) from t order by a desc limit 3",
columnNames: columnNames,
callback: function(row){
log("a =",row.get(0), "twice(a) =", row.get(1), "twice(''||a) =",row.get(2));
}
});
log("Result column names:",columnNames);
/**
Main differences between exec() and execMulti():
- execMulti() traverses all statements in the input SQL
- exec() supports a couple options not supported by execMulti(),
and vice versa.
- execMulti() result callback/array only activates for the
first statement which has result columns. It is arguable
whether it should support a callback at all, and that
feature may be removed.
- execMulti() column-bind data only activates for the first statement
with bindable columns. This feature is arguable and may be removed.
*/
if(0){
warn("UDF will throw because of incorrect arg count...");
db.exec("select twice(1,2,3)");
}
try {
db.callInTransaction( function(D) {
D.exec("delete from t");
log("In transaction: count(*) from t =",db.selectValue("select count(*) from t"));
throw new sqlite3.SQLite3Error("Demonstrating callInTransaction() rollback");
});
}catch(e){
log("Got expected exception:",e.message);
log("count(*) from t =",db.selectValue("select count(*) from t"));
}
}finally{
db.close();
}
/**
Misc. DB features:
- get change count (total or statement-local, 32- or 64-bit)
- get its file name
- selectValue() takes SQL and returns first column of first row.
Misc. Stmt features:
- Various forms of bind()
- clearBindings()
- reset()
- Various forms of step()
- Variants of get() for explicit type treatment/conversion,
e.g. getInt(), getFloat(), getBlob(), getJSON()
- getColumnName(ndx), getColumnNames()
- getParamIndex(name)
*/
}/*demo1()*/;
const runDemos = function(Module){
//log("Module",Module);
const sqlite3 = Module.sqlite3,
capi = sqlite3.capi,
oo = sqlite3.oo1,
wasm = capi.wasm;
log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
try {
[ demo1 ].forEach((f)=>f(sqlite3, Module))
}catch(e){
error("Exception:",e.message);
throw e;
}
};
sqlite3InitModule(self.sqlite3TestModule).then(runDemos);
})();

View File

@ -27,7 +27,7 @@
<div>Most stuff on this page happens in the dev console.</div> <div>Most stuff on this page happens in the dev console.</div>
<hr> <hr>
<div id='test-output'></div> <div id='test-output'></div>
<script src="api/sqlite3.js"></script> <script src="sqlite3.js"></script>
<script src="common/SqliteTestUtil.js"></script> <script src="common/SqliteTestUtil.js"></script>
<script src="testing1.js"></script> <script src="testing1.js"></script>
</body> </body>

View File

@ -1,5 +1,5 @@
C wasm:\smove\sanother\sfile\sand\supdate\stesting1/testing2\sto\saccount\sfor\s[e38d00c2b82d].\sDisable\swasmfs\sby\sdefault\sas\sit\sbreaks\sthe\sworker-based\smodule\sloader\s(reason\sas\syet\sunknown). C wasm:\sadd\sa\ssmall\sdemo/presentation\sapp\sfor\sJS\sOO\sAPI\s#1\sand\smake\sa\sfew\sminor\sadditions\sto\sthat\sAPI.
D 2022-08-16T16:16:25.326 D 2022-08-16T16:36:19.533
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
@ -483,7 +483,7 @@ F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba814
F ext/wasm/api/post-js-header.js 0e853b78db83cb1c06b01663549e0e8b4f377f12f5a2d9a4a06cb776c003880b F ext/wasm/api/post-js-header.js 0e853b78db83cb1c06b01663549e0e8b4f377f12f5a2d9a4a06cb776c003880b
F ext/wasm/api/sqlite3-api-cleanup.js 149fd63a0400cd1d69548887ffde2ed89c13283384a63c2e9fcfc695e38a9e11 F ext/wasm/api/sqlite3-api-cleanup.js 149fd63a0400cd1d69548887ffde2ed89c13283384a63c2e9fcfc695e38a9e11
F ext/wasm/api/sqlite3-api-glue.js 82c09f49c69984009ba5af2b628e67cc26c5dd203d383cd3091d40dab4e6514b F ext/wasm/api/sqlite3-api-glue.js 82c09f49c69984009ba5af2b628e67cc26c5dd203d383cd3091d40dab4e6514b
F ext/wasm/api/sqlite3-api-oo1.js a3469bbb217b9787ba9aa6216423ec55cf9457fecefb9698e433d0e1cc4cc918 F ext/wasm/api/sqlite3-api-oo1.js 1d63e7e453e38ff2ad0c5e8bf68345f6fc5fe99fbc4a893cc982b4c50d904ca0
F ext/wasm/api/sqlite3-api-opfs.js c93cdd14f81a26b3a64990515ee05c7e29827fbc8fba4e4c2fef3a37a984db89 F ext/wasm/api/sqlite3-api-opfs.js c93cdd14f81a26b3a64990515ee05c7e29827fbc8fba4e4c2fef3a37a984db89
F ext/wasm/api/sqlite3-api-prologue.js c0f335bf8b44071da0204b8fa95ce78fd737033b155e7bcfdaee6ae64600802f F ext/wasm/api/sqlite3-api-prologue.js c0f335bf8b44071da0204b8fa95ce78fd737033b155e7bcfdaee6ae64600802f
F ext/wasm/api/sqlite3-api-worker.js 1124f404ecdf3c14d9f829425cef778cd683911a9883f0809a463c3c7773c9fd F ext/wasm/api/sqlite3-api-worker.js 1124f404ecdf3c14d9f829425cef778cd683911a9883f0809a463c3c7773c9fd
@ -493,6 +493,8 @@ F ext/wasm/common/SqliteTestUtil.js e41a1406f18da9224523fad0c48885caf995b56956a5
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/common/testing.css 572cf1ffae0b6eb7ca63684d3392bf350217a07b90e7a896e4fa850700c989b0 F ext/wasm/common/testing.css 572cf1ffae0b6eb7ca63684d3392bf350217a07b90e7a896e4fa850700c989b0
F ext/wasm/common/whwasmutil.js 41b8e097e0a9cb07c24c0ede3c81b72470a63f4a4efb07f75586dc131569f5ae F ext/wasm/common/whwasmutil.js 41b8e097e0a9cb07c24c0ede3c81b72470a63f4a4efb07f75586dc131569f5ae
F ext/wasm/demo-oo1.html 75646855b38405d82781246fd08c852a2b3bee05dd9f0fe10ab655a8cffb79aa
F ext/wasm/demo-oo1.js 0b1f85ee622b8f0ffe133ed88584bfc6b1ef1dcbe5b605278073e4694ebd0a2f
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/fiddle/fiddle-worker.js bccf46045be8824752876f3eec01c223be0616ccac184bffd0024cfe7a3262b8 F ext/wasm/fiddle/fiddle-worker.js bccf46045be8824752876f3eec01c223be0616ccac184bffd0024cfe7a3262b8
F ext/wasm/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08 F ext/wasm/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
@ -506,8 +508,8 @@ F ext/wasm/scratchpad-opfs-main.js a819ed26047c5539630cea59add6a5082ba04cdf82da2
F ext/wasm/scratchpad-opfs-worker.html 66c1d15d678f3bd306373d76b61c6c8aef988f61f4a8dd40185d452f9c6d2bf5 F ext/wasm/scratchpad-opfs-worker.html 66c1d15d678f3bd306373d76b61c6c8aef988f61f4a8dd40185d452f9c6d2bf5
F ext/wasm/scratchpad-opfs-worker.js 3ec2868c669713145c76eb5877c64a1b20741f741817b87c907a154b676283a9 F ext/wasm/scratchpad-opfs-worker.js 3ec2868c669713145c76eb5877c64a1b20741f741817b87c907a154b676283a9
F ext/wasm/scratchpad-opfs-worker2.js de3ea77548243a638c8426b7e43cc1dbfc511013228ab98436eb102923ed6689 F ext/wasm/scratchpad-opfs-worker2.js de3ea77548243a638c8426b7e43cc1dbfc511013228ab98436eb102923ed6689
F ext/wasm/sqlite3-worker.js 1325ca8d40129a82531902a3a077b795db2eeaee81746e5a0c811a04b415fa7f w ext/wasm/api/sqlite3-worker.js F ext/wasm/sqlite3-worker.js 1325ca8d40129a82531902a3a077b795db2eeaee81746e5a0c811a04b415fa7f
F ext/wasm/testing1.html 0bf3ff224628c1f1e3ed22a2dc1837c6c73722ad8c0ad9c8e6fb9e6047667231 F ext/wasm/testing1.html 528001c7e32ee567abc195aa071fd9820cc3c8ffc9c8a39a75e680db05f0c409
F ext/wasm/testing1.js a25069e20d5f8dc548cc98bcf7002cec812084421a1f7f70ffae2c706d1167b2 F ext/wasm/testing1.js a25069e20d5f8dc548cc98bcf7002cec812084421a1f7f70ffae2c706d1167b2
F ext/wasm/testing2.html 73e5048e666fd6fb28b6e635677a9810e1e139c599ddcf28d687c982134b92b8 F ext/wasm/testing2.html 73e5048e666fd6fb28b6e635677a9810e1e139c599ddcf28d687c982134b92b8
F ext/wasm/testing2.js dbb825174878716fab42c340962c0c1b32bfbe26dd16c7b082d30d35f510466c F ext/wasm/testing2.js dbb825174878716fab42c340962c0c1b32bfbe26dd16c7b082d30d35f510466c
@ -2004,8 +2006,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 41762f9518bb51b8b23ae6507628d6d3256044e1f2aca6e7251dc57722062c42 P 6dad5e0573ee866657ee10b43e55b86fc9caac7a66c13bdbd35c3625a4783f14
R 8ceb5e9180bc147ed0af56485cecdca6 R 21ffe0bceeaf14b3e3d3b64b375f9eb8
U stephan U stephan
Z 7a0a645037fbcb33d5a75b781a0d284d Z cfe198e466da02226e0ffe831d5c4056
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
6dad5e0573ee866657ee10b43e55b86fc9caac7a66c13bdbd35c3625a4783f14 d6d79b661a1c6137d4693393e02416da4858d58dc84d144081a48d523655b483