mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Expose sqlite3_vfs_unregister() to WASM and unregister kvvfs in Worker threads to avoid its unintended use there (in contexts other than local/sessionStorage). Correct registration of window functions, extend oo1.DB.createFunction() to support window functions, and add window function tests to tester1.js. Correct an incorrect 1-arg handling case for DB.exec(). Add per-test assertion counts to tester1.js.
FossilOrigin-Name: f07ce15479b7224b0d1ba9f147a433136e70c1461aa667d2737d4a918f778f55
This commit is contained in:
@ -89,5 +89,6 @@ _sqlite3_value_text
|
|||||||
_sqlite3_value_type
|
_sqlite3_value_type
|
||||||
_sqlite3_vfs_find
|
_sqlite3_vfs_find
|
||||||
_sqlite3_vfs_register
|
_sqlite3_vfs_register
|
||||||
|
_sqlite3_vfs_unregister
|
||||||
_malloc
|
_malloc
|
||||||
_free
|
_free
|
||||||
|
@ -443,10 +443,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
try{
|
try{
|
||||||
const funcArgs = __xWrapFuncs({xStep, xFinal, xValue, xInverse, xDestroy},
|
const funcArgs = __xWrapFuncs({xStep, xFinal, xValue, xInverse, xDestroy},
|
||||||
uninstall);
|
uninstall);
|
||||||
rc = sqlite3CreateFunction(pDb, funcName, nArg, eTextRep,
|
rc = sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep,
|
||||||
pApp, ...funcArgs);
|
pApp, ...funcArgs);
|
||||||
}catch(e){
|
}catch(e){
|
||||||
console.error("sqlite3_create_function_v2() setup threw:",e);
|
console.error("sqlite3_create_window_function() setup threw:",e);
|
||||||
for(let v of uninstall){
|
for(let v of uninstall){
|
||||||
wasm.uninstallFunction(v);
|
wasm.uninstallFunction(v);
|
||||||
}
|
}
|
||||||
@ -607,6 +607,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
// Structs NOT to register
|
// Structs NOT to register
|
||||||
WasmTestStruct: true
|
WasmTestStruct: true
|
||||||
});
|
});
|
||||||
|
if(!util.isUIThread()){
|
||||||
|
/* We remove the kvvfs VFS from Worker threads below. */
|
||||||
|
notThese.sqlite3_kvvfs_methods = true;
|
||||||
|
}
|
||||||
for(const s of wasm.ctype.structs){
|
for(const s of wasm.ctype.structs){
|
||||||
if(!notThese[s.name]){
|
if(!notThese[s.name]){
|
||||||
capi[s.name] = sqlite3.StructBinder(s);
|
capi[s.name] = sqlite3.StructBinder(s);
|
||||||
@ -614,89 +618,96 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
}
|
}
|
||||||
}/*end C constant imports*/
|
}/*end C constant imports*/
|
||||||
|
|
||||||
if( util.isMainWindow()
|
const pKvvfs = capi.sqlite3_vfs_find("kvvfs");
|
||||||
&& 0!==capi.sqlite3_vfs_find("kvvfs") ){/* kvvfs-specific glue */
|
if( pKvvfs ){/* kvvfs-specific glue */
|
||||||
const kvvfsMethods = new capi.sqlite3_kvvfs_methods(
|
if(util.isUIThread()){
|
||||||
wasm.exports.sqlite3_wasm_kvvfs_methods()
|
const kvvfsMethods = new capi.sqlite3_kvvfs_methods(
|
||||||
);
|
wasm.exports.sqlite3_wasm_kvvfs_methods()
|
||||||
delete capi.sqlite3_kvvfs_methods;
|
);
|
||||||
|
delete capi.sqlite3_kvvfs_methods;
|
||||||
|
|
||||||
const kvvfsMakeKey = wasm.exports.sqlite3_wasm_kvvfsMakeKeyOnPstack,
|
const kvvfsMakeKey = wasm.exports.sqlite3_wasm_kvvfsMakeKeyOnPstack,
|
||||||
pstack = wasm.pstack,
|
pstack = wasm.pstack,
|
||||||
pAllocRaw = wasm.exports.sqlite3_wasm_pstack_alloc;
|
pAllocRaw = wasm.exports.sqlite3_wasm_pstack_alloc;
|
||||||
|
|
||||||
const kvvfsStorage = (zClass)=>
|
const kvvfsStorage = (zClass)=>
|
||||||
((115/*=='s'*/===wasm.getMemValue(zClass))
|
((115/*=='s'*/===wasm.getMemValue(zClass))
|
||||||
? sessionStorage : localStorage);
|
? sessionStorage : localStorage);
|
||||||
|
|
||||||
const kvvfsImpls = {
|
const kvvfsImpls = {
|
||||||
xRead: (zClass, zKey, zBuf, nBuf)=>{
|
xRead: (zClass, zKey, zBuf, nBuf)=>{
|
||||||
const stack = pstack.pointer,
|
const stack = pstack.pointer,
|
||||||
astack = wasm.scopedAllocPush();
|
astack = wasm.scopedAllocPush();
|
||||||
try {
|
try {
|
||||||
const zXKey = kvvfsMakeKey(zClass,zKey);
|
const zXKey = kvvfsMakeKey(zClass,zKey);
|
||||||
if(!zXKey) return -3/*OOM*/;
|
if(!zXKey) return -3/*OOM*/;
|
||||||
const jKey = wasm.cstringToJs(zXKey);
|
const jKey = wasm.cstringToJs(zXKey);
|
||||||
const jV = kvvfsStorage(zClass).getItem(jKey);
|
const jV = kvvfsStorage(zClass).getItem(jKey);
|
||||||
if(!jV) return -1;
|
if(!jV) return -1;
|
||||||
const nV = jV.length /* Note that we are relying 100% on v being
|
const nV = jV.length /* Note that we are relying 100% on v being
|
||||||
ASCII so that jV.length is equal to the
|
ASCII so that jV.length is equal to the
|
||||||
C-string's byte length. */;
|
C-string's byte length. */;
|
||||||
if(nBuf<=0) return nV;
|
if(nBuf<=0) return nV;
|
||||||
else if(1===nBuf){
|
else if(1===nBuf){
|
||||||
wasm.setMemValue(zBuf, 0);
|
wasm.setMemValue(zBuf, 0);
|
||||||
return nV;
|
return nV;
|
||||||
|
}
|
||||||
|
const zV = wasm.scopedAllocCString(jV);
|
||||||
|
if(nBuf > nV + 1) nBuf = nV + 1;
|
||||||
|
wasm.heap8u().copyWithin(zBuf, zV, zV + nBuf - 1);
|
||||||
|
wasm.setMemValue(zBuf + nBuf - 1, 0);
|
||||||
|
return nBuf - 1;
|
||||||
|
}catch(e){
|
||||||
|
console.error("kvstorageRead()",e);
|
||||||
|
return -2;
|
||||||
|
}finally{
|
||||||
|
pstack.restore(stack);
|
||||||
|
wasm.scopedAllocPop(astack);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xWrite: (zClass, zKey, zData)=>{
|
||||||
|
const stack = pstack.pointer;
|
||||||
|
try {
|
||||||
|
const zXKey = kvvfsMakeKey(zClass,zKey);
|
||||||
|
if(!zXKey) return 1/*OOM*/;
|
||||||
|
const jKey = wasm.cstringToJs(zXKey);
|
||||||
|
kvvfsStorage(zClass).setItem(jKey, wasm.cstringToJs(zData));
|
||||||
|
return 0;
|
||||||
|
}catch(e){
|
||||||
|
console.error("kvstorageWrite()",e);
|
||||||
|
return capi.SQLITE_IOERR;
|
||||||
|
}finally{
|
||||||
|
pstack.restore(stack);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xDelete: (zClass, zKey)=>{
|
||||||
|
const stack = pstack.pointer;
|
||||||
|
try {
|
||||||
|
const zXKey = kvvfsMakeKey(zClass,zKey);
|
||||||
|
if(!zXKey) return 1/*OOM*/;
|
||||||
|
kvvfsStorage(zClass).removeItem(wasm.cstringToJs(zXKey));
|
||||||
|
return 0;
|
||||||
|
}catch(e){
|
||||||
|
console.error("kvstorageDelete()",e);
|
||||||
|
return capi.SQLITE_IOERR;
|
||||||
|
}finally{
|
||||||
|
pstack.restore(stack);
|
||||||
}
|
}
|
||||||
const zV = wasm.scopedAllocCString(jV);
|
|
||||||
if(nBuf > nV + 1) nBuf = nV + 1;
|
|
||||||
wasm.heap8u().copyWithin(zBuf, zV, zV + nBuf - 1);
|
|
||||||
wasm.setMemValue(zBuf + nBuf - 1, 0);
|
|
||||||
return nBuf - 1;
|
|
||||||
}catch(e){
|
|
||||||
console.error("kvstorageRead()",e);
|
|
||||||
return -2;
|
|
||||||
}finally{
|
|
||||||
pstack.restore(stack);
|
|
||||||
wasm.scopedAllocPop(astack);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
xWrite: (zClass, zKey, zData)=>{
|
|
||||||
const stack = pstack.pointer;
|
|
||||||
try {
|
|
||||||
const zXKey = kvvfsMakeKey(zClass,zKey);
|
|
||||||
if(!zXKey) return 1/*OOM*/;
|
|
||||||
const jKey = wasm.cstringToJs(zXKey);
|
|
||||||
kvvfsStorage(zClass).setItem(jKey, wasm.cstringToJs(zData));
|
|
||||||
return 0;
|
|
||||||
}catch(e){
|
|
||||||
console.error("kvstorageWrite()",e);
|
|
||||||
return capi.SQLITE_IOERR;
|
|
||||||
}finally{
|
|
||||||
pstack.restore(stack);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
xDelete: (zClass, zKey)=>{
|
|
||||||
const stack = pstack.pointer;
|
|
||||||
try {
|
|
||||||
const zXKey = kvvfsMakeKey(zClass,zKey);
|
|
||||||
if(!zXKey) return 1/*OOM*/;
|
|
||||||
kvvfsStorage(zClass).removeItem(wasm.cstringToJs(zXKey));
|
|
||||||
return 0;
|
|
||||||
}catch(e){
|
|
||||||
console.error("kvstorageDelete()",e);
|
|
||||||
return capi.SQLITE_IOERR;
|
|
||||||
}finally{
|
|
||||||
pstack.restore(stack);
|
|
||||||
}
|
}
|
||||||
|
}/*kvvfsImpls*/;
|
||||||
|
for(let k of Object.keys(kvvfsImpls)){
|
||||||
|
kvvfsMethods[kvvfsMethods.memberKey(k)] =
|
||||||
|
wasm.installFunction(
|
||||||
|
kvvfsMethods.memberSignature(k),
|
||||||
|
kvvfsImpls[k]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}/*kvvfsImpls*/;
|
}else{
|
||||||
for(let k of Object.keys(kvvfsImpls)){
|
/* Worker thread: unregister kvvfs to avoid it being used
|
||||||
kvvfsMethods[kvvfsMethods.memberKey(k)] =
|
for anything other than local/sessionStorage. It "can"
|
||||||
wasm.installFunction(
|
be used that way but it's not really intended to be. */
|
||||||
kvvfsMethods.memberSignature(k),
|
capi.sqlite3_vfs_unregister(pKvvfs);
|
||||||
kvvfsImpls[k]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}/*kvvfs*/
|
}/*pKvvfs*/
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -374,11 +374,11 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
case 1:
|
case 1:
|
||||||
if('string'===typeof args[0] || util.isSQLableTypedArray(args[0])){
|
if('string'===typeof args[0] || util.isSQLableTypedArray(args[0])){
|
||||||
out.sql = args[0];
|
out.sql = args[0];
|
||||||
|
}else if(Array.isArray(args[0])){
|
||||||
|
out.sql = args[0];
|
||||||
}else if(args[0] && 'object'===typeof args[0]){
|
}else if(args[0] && 'object'===typeof args[0]){
|
||||||
out.opt = args[0];
|
out.opt = args[0];
|
||||||
out.sql = out.opt.sql;
|
out.sql = out.opt.sql;
|
||||||
}else if(Array.isArray(args[0])){
|
|
||||||
out.sql = args[0];
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@ -392,7 +392,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
}else if(Array.isArray(out.sql)){
|
}else if(Array.isArray(out.sql)){
|
||||||
out.sql = out.sql.join('');
|
out.sql = out.sql.join('');
|
||||||
}else if('string'!==typeof out.sql){
|
}else if('string'!==typeof out.sql){
|
||||||
toss3("Missing SQL argument.");
|
toss3("Missing SQL argument or unsupported SQL value type.");
|
||||||
}
|
}
|
||||||
if(out.opt.callback || out.opt.resultRows){
|
if(out.opt.callback || out.opt.resultRows){
|
||||||
switch((undefined===out.opt.rowMode)
|
switch((undefined===out.opt.rowMode)
|
||||||
@ -811,8 +811,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
case, the function's name must be the 'name' property.
|
case, the function's name must be the 'name' property.
|
||||||
|
|
||||||
The first two call forms can only be used for creating scalar
|
The first two call forms can only be used for creating scalar
|
||||||
functions. Creating an aggregate function requires the
|
functions. Creating an aggregate or window function requires
|
||||||
options-object form (see below for details).
|
the options-object form (see below for details).
|
||||||
|
|
||||||
UDFs cannot currently be removed from a DB handle after they're
|
UDFs cannot currently be removed from a DB handle after they're
|
||||||
added. More correctly, they can be removed as documented for
|
added. More correctly, they can be removed as documented for
|
||||||
@ -837,14 +837,19 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
properties to the "step" and "final" callbacks for the
|
properties to the "step" and "final" callbacks for the
|
||||||
aggregate. Do not set the `xFunc` property.
|
aggregate. Do not set the `xFunc` property.
|
||||||
|
|
||||||
The options object may optionally have an `xDestroy`
|
- Window: set the `xStep`, `xFinal`, `xValue`, and `xInverse`
|
||||||
function-type property, as per
|
function-type properties. Do not set the `xFunc` property.
|
||||||
sqlite3_create_function_v2(). Its argument will be the
|
|
||||||
WASM-pointer-type value of the `pApp` property, and this
|
|
||||||
function will throw if `pApp` is defined but is not null,
|
|
||||||
undefined, or a numeric (WASM pointer) value.
|
|
||||||
|
|
||||||
The optional options object may contain flags to modify how
|
The options object may optionally have an `xDestroy`
|
||||||
|
function-type property, as per sqlite3_create_function_v2().
|
||||||
|
Its argument will be the WASM-pointer-type value of the `pApp`
|
||||||
|
property, and this function will throw if `pApp` is defined but
|
||||||
|
is not null, undefined, or a numeric (WASM pointer)
|
||||||
|
value. i.e. `pApp`, if set, must be value suitable for use as a
|
||||||
|
WASM pointer argument, noting that `null` or `undefined` will
|
||||||
|
translate to 0 for that purpose.
|
||||||
|
|
||||||
|
The options object may contain flags to modify how
|
||||||
the function is defined:
|
the function is defined:
|
||||||
|
|
||||||
- `arity`: the number of arguments which SQL calls to this
|
- `arity`: the number of arguments which SQL calls to this
|
||||||
@ -855,36 +860,39 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
arity value means that the function is variadic and may accept
|
arity value means that the function is variadic and may accept
|
||||||
any number of arguments, up to sqlite3's compile-time
|
any number of arguments, up to sqlite3's compile-time
|
||||||
limits. sqlite3 will enforce the argument count if is zero or
|
limits. sqlite3 will enforce the argument count if is zero or
|
||||||
greater.
|
greater. The callback always receives a pointer to an
|
||||||
|
`sqlite3_context` object as its first argument. Any arguments
|
||||||
The callback always receives a pointer to an `sqlite3_context`
|
after that are from SQL code. The leading context argument does
|
||||||
object as its first argument. Any arguments after that are from
|
_not_ count towards the function's arity. See the docs for
|
||||||
SQL code. The leading context argument does _not_ count towards
|
|
||||||
the function's arity. See the docs for
|
|
||||||
sqlite3.capi.sqlite3_create_function_v2() for why that argument
|
sqlite3.capi.sqlite3_create_function_v2() for why that argument
|
||||||
is needed in the interface.
|
is needed in the interface.
|
||||||
|
|
||||||
The following properties correspond to flags documented at:
|
The following options-object properties correspond to flags
|
||||||
|
documented at:
|
||||||
|
|
||||||
https://sqlite.org/c3ref/create_function.html
|
https://sqlite.org/c3ref/create_function.html
|
||||||
|
|
||||||
- .deterministic = SQLITE_DETERMINISTIC
|
- `deterministic` = sqlite3.capi.SQLITE_DETERMINISTIC
|
||||||
- .directOnly = SQLITE_DIRECTONLY
|
- `directOnly` = sqlite3.capi.SQLITE_DIRECTONLY
|
||||||
- .innocuous = SQLITE_INNOCUOUS
|
- `innocuous` = sqlite3.capi.SQLITE_INNOCUOUS
|
||||||
|
|
||||||
|
Sidebar: the ability to add new WASM-accessible functions to
|
||||||
|
the runtime requires that the WASM build is compiled with the
|
||||||
|
equivalent functionality as that provided by Emscripten's
|
||||||
|
`-sALLOW_TABLE_GROWTH` flag.
|
||||||
*/
|
*/
|
||||||
createFunction: function f(name, xFunc, opt){
|
createFunction: function f(name, xFunc, opt){
|
||||||
let xStep, xFinal;
|
|
||||||
const isFunc = (f)=>(f instanceof Function);
|
const isFunc = (f)=>(f instanceof Function);
|
||||||
switch(arguments.length){
|
switch(arguments.length){
|
||||||
case 1: /* (optionsObject) */
|
case 1: /* (optionsObject) */
|
||||||
opt = name;
|
opt = name;
|
||||||
name = opt.name;
|
name = opt.name;
|
||||||
xFunc = opt.xFunc;
|
xFunc = opt.xFunc || 0;
|
||||||
break;
|
break;
|
||||||
case 2: /* (name, callback|optionsObject) */
|
case 2: /* (name, callback|optionsObject) */
|
||||||
if(!isFunc(xFunc)){
|
if(!isFunc(xFunc)){
|
||||||
opt = xFunc;
|
opt = xFunc;
|
||||||
xFunc = opt.xFunc;
|
xFunc = opt.xFunc || 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3: /* name, xFunc, opt */
|
case 3: /* name, xFunc, opt */
|
||||||
@ -895,30 +903,46 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
if('string' !== typeof name){
|
if('string' !== typeof name){
|
||||||
toss3("Invalid arguments: missing function name.");
|
toss3("Invalid arguments: missing function name.");
|
||||||
}
|
}
|
||||||
xStep = opt.xStep;
|
let xStep = opt.xStep || 0;
|
||||||
xFinal = opt.xFinal;
|
let xFinal = opt.xFinal || 0;
|
||||||
|
const xValue = opt.xValue || 0;
|
||||||
|
const xInverse = opt.xInverse || 0;
|
||||||
|
let isWindow = undefined;
|
||||||
if(isFunc(xFunc)){
|
if(isFunc(xFunc)){
|
||||||
|
isWindow = false;
|
||||||
if(isFunc(xStep) || isFunc(xFinal)){
|
if(isFunc(xStep) || isFunc(xFinal)){
|
||||||
toss3("Ambiguous arguments: scalar or aggregate?");
|
toss3("Ambiguous arguments: scalar or aggregate?");
|
||||||
}
|
}
|
||||||
xStep = xFinal = null;
|
xStep = xFinal = null;
|
||||||
}else if(isFunc(xStep)){
|
}else if(isFunc(xStep)){
|
||||||
if(!isFunc(xFinal)){
|
if(!isFunc(xFinal)){
|
||||||
toss3("Missing xFinal() callback for aggregate UDF.");
|
toss3("Missing xFinal() callback for aggregate or window UDF.");
|
||||||
}
|
}
|
||||||
xFunc = null;
|
xFunc = null;
|
||||||
}else if(isFunc(xFinal)){
|
}else if(isFunc(xFinal)){
|
||||||
toss3("Missing xStep() callback for aggregate UDF.");
|
toss3("Missing xStep() callback for aggregate or window UDF.");
|
||||||
}else{
|
}else{
|
||||||
toss3("Missing function-type properties.");
|
toss3("Missing function-type properties.");
|
||||||
}
|
}
|
||||||
|
if(false === isWindow){
|
||||||
|
if(isFunc(xValue) || isFunc(xInverse)){
|
||||||
|
toss3("xValue and xInverse are not permitted for non-window UDFs.");
|
||||||
|
}
|
||||||
|
}else if(isFunc(xValue)){
|
||||||
|
if(!isFunc(xInverse)){
|
||||||
|
toss3("xInverse must be provided if xValue is.");
|
||||||
|
}
|
||||||
|
isWindow = true;
|
||||||
|
}else if(isFunc(xInverse)){
|
||||||
|
toss3("xValue must be provided if xInverse is.");
|
||||||
|
}
|
||||||
const pApp = opt.pApp;
|
const pApp = opt.pApp;
|
||||||
if(undefined!==pApp &&
|
if(undefined!==pApp &&
|
||||||
null!==pApp &&
|
null!==pApp &&
|
||||||
(('number'!==typeof pApp) || !capi.util.isInt32(pApp))){
|
(('number'!==typeof pApp) || !capi.util.isInt32(pApp))){
|
||||||
toss3("Invalid value for pApp property. Must be a legal WASM pointer value.");
|
toss3("Invalid value for pApp property. Must be a legal WASM pointer value.");
|
||||||
}
|
}
|
||||||
const xDestroy = opt.xDestroy;
|
const xDestroy = opt.xDestroy || 0;
|
||||||
if(xDestroy && !isFunc(xDestroy)){
|
if(xDestroy && !isFunc(xDestroy)){
|
||||||
toss3("xDestroy property must be a function.");
|
toss3("xDestroy property must be a function.");
|
||||||
}
|
}
|
||||||
@ -929,13 +953,22 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
const xArity = xFunc || xStep;
|
const xArity = xFunc || xStep;
|
||||||
const arity = getOwnOption(opt, 'arity');
|
const arity = getOwnOption(opt, 'arity');
|
||||||
DB.checkRc(this, capi.sqlite3_create_function_v2(
|
const arityArg = ('number'===typeof arity
|
||||||
this.pointer, name,
|
? arity
|
||||||
('number'===typeof arity
|
: (xArity.length ? xArity.length-1/*for pCtx arg*/ : 0));
|
||||||
? arity
|
let rc;
|
||||||
: (xArity.length ? xArity.length-1/*for pCtx arg*/ : 0)),
|
if( isWindow ){
|
||||||
capi.SQLITE_UTF8 | fFlags, pApp,
|
rc = capi.sqlite3_create_window_function(
|
||||||
xFunc, xStep, xFinal, xDestroy));
|
this.pointer, name, arityArg,
|
||||||
|
capi.SQLITE_UTF8 | fFlags, pApp || 0,
|
||||||
|
xStep, xFinal, xValue, xInverse, xDestroy);
|
||||||
|
}else{
|
||||||
|
rc = capi.sqlite3_create_function_v2(
|
||||||
|
this.pointer, name, arityArg,
|
||||||
|
capi.SQLITE_UTF8 | fFlags, pApp || 0,
|
||||||
|
xFunc, xStep, xFinal, xDestroy);
|
||||||
|
}
|
||||||
|
DB.checkRc(this, rc);
|
||||||
return this;
|
return this;
|
||||||
}/*createFunction()*/,
|
}/*createFunction()*/,
|
||||||
/**
|
/**
|
||||||
@ -1642,7 +1675,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
dbCtorHelper
|
dbCtorHelper
|
||||||
}/*oo1 object*/;
|
}/*oo1 object*/;
|
||||||
|
|
||||||
if(util.isMainWindow()){
|
if(util.isUIThread()){
|
||||||
/**
|
/**
|
||||||
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'
|
||||||
|
@ -289,7 +289,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
WasmAllocError.toss = (...args)=>{
|
WasmAllocError.toss = (...args)=>{
|
||||||
throw new WasmAllocError(args.join(' '));
|
throw new WasmAllocError(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -530,9 +530,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
isBindableTypedArray,
|
isBindableTypedArray,
|
||||||
isInt32, isSQLableTypedArray, isTypedArray,
|
isInt32, isSQLableTypedArray, isTypedArray,
|
||||||
typedArrayToString,
|
typedArrayToString,
|
||||||
isMainWindow: ()=>{
|
isUIThread: ()=>'undefined'===typeof WorkerGlobalScope
|
||||||
return 'undefined' === typeof WorkerGlobalScope
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -839,7 +837,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
["sqlite3_value_text", "string", "sqlite3_value*"],
|
["sqlite3_value_text", "string", "sqlite3_value*"],
|
||||||
["sqlite3_value_type", "int", "sqlite3_value*"],
|
["sqlite3_value_type", "int", "sqlite3_value*"],
|
||||||
["sqlite3_vfs_find", "*", "string"],
|
["sqlite3_vfs_find", "*", "string"],
|
||||||
["sqlite3_vfs_register", "int", "*", "int"]
|
["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
|
||||||
|
["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
|
||||||
]/*wasm.bindingSignatures*/;
|
]/*wasm.bindingSignatures*/;
|
||||||
|
|
||||||
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
|
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
|
||||||
@ -1026,10 +1025,18 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
class SQLite3Error extends Error {
|
class SQLite3Error extends Error {
|
||||||
/**
|
/**
|
||||||
Constructs this object with a message equal to all arguments
|
Constructs this object with a message equal to all arguments
|
||||||
concatenated with a space between each one.
|
concatenated with a space between each one. As a special case,
|
||||||
|
if it's passed only a single integer argument, the string form
|
||||||
|
of that argument is the result of
|
||||||
|
sqlite3.capi.sqlite3_js_rc_str() or (if that returns falsy), a
|
||||||
|
synthesized string which contains that integer.
|
||||||
*/
|
*/
|
||||||
constructor(...args){
|
constructor(...args){
|
||||||
super(args.join(' '));
|
if(1===args.length && 'number'===typeof args[0] && args[0]===(args[0] | 0)){
|
||||||
|
super(capi.sqlite3_js_rc_str(args[0]) || ("Unknown result code #"+args[0]));
|
||||||
|
}else{
|
||||||
|
super(args.join(' '));
|
||||||
|
}
|
||||||
this.name = 'SQLite3Error';
|
this.name = 'SQLite3Error';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1042,7 +1049,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
SQLite3Error.toss = (...args)=>{
|
SQLite3Error.toss = (...args)=>{
|
||||||
throw new SQLite3Error(args.join(' '));
|
throw new SQLite3Error(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** State for sqlite3_wasmfs_opfs_dir(). */
|
/** State for sqlite3_wasmfs_opfs_dir(). */
|
||||||
@ -1219,7 +1226,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
: 0);
|
: 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
if( capi.util.isMainWindow() ){
|
if( capi.util.isUIThread() ){
|
||||||
/* Features specific to the main window thread... */
|
/* Features specific to the main window thread... */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
const mapToString = (v)=>{
|
const mapToString = (v)=>{
|
||||||
switch(typeof v){
|
switch(typeof v){
|
||||||
case 'number': case 'string': case 'boolean':
|
case 'number': case 'string': case 'boolean':
|
||||||
case 'undefined':
|
case 'undefined': case 'bigint':
|
||||||
return ''+v;
|
return ''+v;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -216,7 +216,7 @@
|
|||||||
}
|
}
|
||||||
log(TestUtil.separator);
|
log(TestUtil.separator);
|
||||||
logClass('group-start',"Group #"+this.number+':',this.name);
|
logClass('group-start',"Group #"+this.number+':',this.name);
|
||||||
const indent = '....';
|
const indent = ' ';
|
||||||
const assertCount = TestUtil.counter;
|
const assertCount = TestUtil.counter;
|
||||||
const groupState = Object.create(null);
|
const groupState = Object.create(null);
|
||||||
const skipped = [];
|
const skipped = [];
|
||||||
@ -230,7 +230,7 @@
|
|||||||
const tc = TestUtil.counter
|
const tc = TestUtil.counter
|
||||||
log(indent, n+":", t.name);
|
log(indent, n+":", t.name);
|
||||||
await t.test.call(groupState, sqlite3);
|
await t.test.call(groupState, sqlite3);
|
||||||
//log(indent, indent, 'assertion count:',TestUtil.counter - tc);
|
log(indent, indent, TestUtil.counter - tc, 'assertion(s)');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logClass('green',
|
logClass('green',
|
||||||
@ -312,6 +312,8 @@
|
|||||||
T.assert(e instanceof Error)
|
T.assert(e instanceof Error)
|
||||||
.assert(e instanceof sqlite3.WasmAllocError);
|
.assert(e instanceof sqlite3.WasmAllocError);
|
||||||
}
|
}
|
||||||
|
try{ throw new sqlite3.SQLite3Error(capi.SQLITE_SCHEMA) }
|
||||||
|
catch(e){ T.assert('SQLITE_SCHEMA' === e.message) }
|
||||||
})
|
})
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
.t('strglob/strlike', function(sqlite3){
|
.t('strglob/strlike', function(sqlite3){
|
||||||
@ -1092,7 +1094,7 @@
|
|||||||
const vfsList = capi.sqlite3_js_vfs_list();
|
const vfsList = capi.sqlite3_js_vfs_list();
|
||||||
T.assert(vfsList.length>1);
|
T.assert(vfsList.length>1);
|
||||||
T.assert('string'===typeof vfsList[0]);
|
T.assert('string'===typeof vfsList[0]);
|
||||||
|
//log("vfsList =",vfsList);
|
||||||
for(const v of vfsList){
|
for(const v of vfsList){
|
||||||
T.assert('string' === typeof v)
|
T.assert('string' === typeof v)
|
||||||
.assert(capi.sqlite3_vfs_find(v) > 0);
|
.assert(capi.sqlite3_vfs_find(v) > 0);
|
||||||
@ -1282,7 +1284,7 @@
|
|||||||
const sjac = capi.sqlite3_js_aggregate_context;
|
const sjac = capi.sqlite3_js_aggregate_context;
|
||||||
db.createFunction({
|
db.createFunction({
|
||||||
name: 'summer',
|
name: 'summer',
|
||||||
xStep: function(pCtx, n){
|
xStep: (pCtx, n)=>{
|
||||||
const ac = sjac(pCtx, 4);
|
const ac = sjac(pCtx, 4);
|
||||||
wasm.setMemValue(ac, wasm.getMemValue(ac,'i32') + Number(n), 'i32');
|
wasm.setMemValue(ac, wasm.getMemValue(ac,'i32') + Number(n), 'i32');
|
||||||
},
|
},
|
||||||
@ -1305,11 +1307,11 @@
|
|||||||
db.createFunction({
|
db.createFunction({
|
||||||
name: 'summerN',
|
name: 'summerN',
|
||||||
arity: -1,
|
arity: -1,
|
||||||
xStep: function(pCtx, ...args){
|
xStep: (pCtx, ...args)=>{
|
||||||
const pAgg = sjac(pCtx, 4);
|
const ac = sjac(pCtx, 4);
|
||||||
let sum = wasm.getMemValue(pAgg, 'i32');
|
let sum = wasm.getMemValue(ac, 'i32');
|
||||||
for(const v of args) sum += Number(v);
|
for(const v of args) sum += Number(v);
|
||||||
wasm.setMemValue(pAgg, sum, 'i32');
|
wasm.setMemValue(ac, sum, 'i32');
|
||||||
},
|
},
|
||||||
xFinal: (pCtx)=>{
|
xFinal: (pCtx)=>{
|
||||||
const ac = sjac(pCtx, 0);
|
const ac = sjac(pCtx, 0);
|
||||||
@ -1352,9 +1354,9 @@
|
|||||||
const sjac = capi.sqlite3_js_aggregate_context;
|
const sjac = capi.sqlite3_js_aggregate_context;
|
||||||
db.createFunction({
|
db.createFunction({
|
||||||
name: 'summer64',
|
name: 'summer64',
|
||||||
xStep: function(pCtx, n){
|
xStep: (pCtx, n)=>{
|
||||||
const pAgg = sjac(pCtx, 8);
|
const ac = sjac(pCtx, 8);
|
||||||
wasm.setMemValue(pAgg, wasm.getMemValue(pAgg,'i64') + BigInt(n), 'i64');
|
wasm.setMemValue(ac, wasm.getMemValue(ac,'i64') + BigInt(n), 'i64');
|
||||||
},
|
},
|
||||||
xFinal: (pCtx)=>{
|
xFinal: (pCtx)=>{
|
||||||
const ac = sjac(pCtx, 0);
|
const ac = sjac(pCtx, 0);
|
||||||
@ -1362,19 +1364,64 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
let v = db.selectValue([
|
let v = db.selectValue([
|
||||||
"with cte(v) as (",
|
"with cte(v) as (",
|
||||||
"select 3 union all select 5 union all select 7",
|
"select 9007199254740991 union all select 1 union all select 2",
|
||||||
") select summer64(v*10), summer64(v+1) from cte"
|
") select summer64(v), summer64(v+1) from cte"
|
||||||
]);
|
]);
|
||||||
T.assert(150n===BigInt(v));
|
T.assert(9007199254740994n===v);
|
||||||
}
|
}
|
||||||
}/*aggregate UDFs*/)
|
}/*aggregate UDFs*/)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
.t({
|
.t({
|
||||||
name: 'Window UDFs (tests are TODO)',
|
name: 'Window UDFs',
|
||||||
predicate: testIsTodo
|
test: function(){
|
||||||
})
|
/* Example window function, table, and results taken from:
|
||||||
|
https://sqlite.org/windowfunctions.html#udfwinfunc */
|
||||||
|
const db = this.db;
|
||||||
|
const sjac = (cx,n=4)=>capi.sqlite3_js_aggregate_context(cx,n);
|
||||||
|
const xValueFinal = (pCtx)=>{
|
||||||
|
const ac = sjac(pCtx, 0);
|
||||||
|
return ac ? wasm.getMemValue(ac,'i32') : 0;
|
||||||
|
};
|
||||||
|
const xStepInverse = (pCtx, n)=>{
|
||||||
|
const ac = sjac(pCtx);
|
||||||
|
wasm.setMemValue(ac, wasm.getMemValue(ac,'i32') + Number(n), 'i32');
|
||||||
|
};
|
||||||
|
db.createFunction({
|
||||||
|
name: 'winsumint',
|
||||||
|
xStep: (pCtx, n)=>xStepInverse(pCtx, n),
|
||||||
|
xInverse: (pCtx, n)=>xStepInverse(pCtx, -n),
|
||||||
|
xFinal: xValueFinal,
|
||||||
|
xValue: xValueFinal
|
||||||
|
});
|
||||||
|
db.exec([
|
||||||
|
"CREATE TABLE twin(x, y); INSERT INTO twin VALUES",
|
||||||
|
"('a', 4),('b', 5),('c', 3),('d', 8),('e', 1)"
|
||||||
|
]);
|
||||||
|
let count = 0;
|
||||||
|
db.exec({
|
||||||
|
sql:[
|
||||||
|
"SELECT x, winsumint(y) OVER (",
|
||||||
|
"ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING",
|
||||||
|
") AS sum_y ",
|
||||||
|
"FROM twin ORDER BY x;",
|
||||||
|
"DROP TABLE twin;"
|
||||||
|
],
|
||||||
|
callback: function(row){
|
||||||
|
switch(++count){
|
||||||
|
case 1: T.assert('a'===row[0] && 9===row[1]); break;
|
||||||
|
case 2: T.assert('b'===row[0] && 12===row[1]); break;
|
||||||
|
case 3: T.assert('c'===row[0] && 16===row[1]); break;
|
||||||
|
case 4: T.assert('d'===row[0] && 12===row[1]); break;
|
||||||
|
case 5: T.assert('e'===row[0] && 9===row[1]); break;
|
||||||
|
default: toss("Too many rows to window function.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
T.assert(5 === count);
|
||||||
|
}
|
||||||
|
}/*window UDFs*/)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
.t("ATTACH", function(){
|
.t("ATTACH", function(){
|
||||||
|
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
|||||||
C Make\ssemantics\sfor\sUDF\sxFinal()\sresult\shandling\sand\serror\sreporting\shandling\smore\sflexible.
|
C Expose\ssqlite3_vfs_unregister()\sto\sWASM\sand\sunregister\skvvfs\sin\sWorker\sthreads\sto\savoid\sits\sunintended\suse\sthere\s(in\scontexts\sother\sthan\slocal/sessionStorage).\sCorrect\sregistration\sof\swindow\sfunctions,\sextend\soo1.DB.createFunction()\sto\ssupport\swindow\sfunctions,\sand\sadd\swindow\sfunction\stests\sto\stester1.js.\sCorrect\san\sincorrect\s1-arg\shandling\scase\sfor\sDB.exec().\sAdd\sper-test\sassertion\scounts\sto\stester1.js.
|
||||||
D 2022-10-20T23:48:38.866
|
D 2022-10-21T05:27:40.995
|
||||||
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
|
||||||
@ -475,7 +475,7 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce
|
|||||||
F ext/wasm/GNUmakefile 645bd5670a56acf2c8f1e969c427555e3e8e74dfd6eac8c948858f530617c7d5
|
F ext/wasm/GNUmakefile 645bd5670a56acf2c8f1e969c427555e3e8e74dfd6eac8c948858f530617c7d5
|
||||||
F ext/wasm/README-dist.txt e78e44a58772d5b5d7a5a179b5bf639cd67b62249aac66138e2c319bd02dd243
|
F ext/wasm/README-dist.txt e78e44a58772d5b5d7a5a179b5bf639cd67b62249aac66138e2c319bd02dd243
|
||||||
F ext/wasm/README.md 1e5b28158b74ab3ffc9d54fcbc020f0bbeb82c2ff8bbd904214c86c70e8a3066
|
F ext/wasm/README.md 1e5b28158b74ab3ffc9d54fcbc020f0bbeb82c2ff8bbd904214c86c70e8a3066
|
||||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 89983a8d122c35a90c65ec667844b95a78bcd04f3198a99c1e0c8368c1a0b03a
|
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 36f413ab4dbb057d2dec938fb366ac0a4c5e85ba14660a8d672f0277602c0fc5
|
||||||
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 1350088aee90e959ad9a94fab1bb6bcb5e99d4d27f976db389050f54f2640c78
|
F ext/wasm/api/README.md 1350088aee90e959ad9a94fab1bb6bcb5e99d4d27f976db389050f54f2640c78
|
||||||
F ext/wasm/api/extern-post-js.js efbed835f290b3741259acc5faf68714a60d38e6834e6cfe172d5354c87566d2
|
F ext/wasm/api/extern-post-js.js efbed835f290b3741259acc5faf68714a60d38e6834e6cfe172d5354c87566d2
|
||||||
@ -484,10 +484,10 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
|
|||||||
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
|
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
|
||||||
F ext/wasm/api/pre-js.js 151e0616614a49f3db19ed544fa13b38c87c108959fbcd4029ea8399a562d94f
|
F ext/wasm/api/pre-js.js 151e0616614a49f3db19ed544fa13b38c87c108959fbcd4029ea8399a562d94f
|
||||||
F ext/wasm/api/sqlite3-api-cleanup.js 4d07a7524dc9b7b050acfde57163e839243ad2383bd7ee0de0178b1b3e988588
|
F ext/wasm/api/sqlite3-api-cleanup.js 4d07a7524dc9b7b050acfde57163e839243ad2383bd7ee0de0178b1b3e988588
|
||||||
F ext/wasm/api/sqlite3-api-glue.js ea760df5991cee48e29aa6ced503027760462d5696d50521f7273a91e0e1430c
|
F ext/wasm/api/sqlite3-api-glue.js 6e4e472eb5afc732a695cd7c5ded6dee6ef8b480e61aa0d648a3fc9033c84745
|
||||||
F ext/wasm/api/sqlite3-api-oo1.js 0e278d131dad72e9eb348a3dda6a4ff734a9e08925b4ed7e6e5a688d2edaf525
|
F ext/wasm/api/sqlite3-api-oo1.js 5016f6dd4b6b461bb6047fe6a2d3d7cbe85aa6b110c263ebf0347672a0cd897e
|
||||||
F ext/wasm/api/sqlite3-api-opfs.js 22d60ba956e873b65e2e0591e239178082bd53a6d563c3c58db7dc03e562e8f7
|
F ext/wasm/api/sqlite3-api-opfs.js 22d60ba956e873b65e2e0591e239178082bd53a6d563c3c58db7dc03e562e8f7
|
||||||
F ext/wasm/api/sqlite3-api-prologue.js e4fbfa66eb6c5c544c52dea6cb48051eddcdc21c276c39a80801f5e76e6c5b56
|
F ext/wasm/api/sqlite3-api-prologue.js fa00d55f927e5a4ec51cf2c80f6f0eaed2f4f5774341ecf3d63a0ea4c738f8f5
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js a7f38f03275d6c27ab2aef3e83215d3c97ce09c43e6904df47c3764d9d4572b4
|
F ext/wasm/api/sqlite3-api-worker1.js a7f38f03275d6c27ab2aef3e83215d3c97ce09c43e6904df47c3764d9d4572b4
|
||||||
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
|
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
|
||||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 206ce6bbc3c30ad51a37d9c25e3a2712e70b586e0f9a2cf8cb0b9619017c2671
|
F ext/wasm/api/sqlite3-opfs-async-proxy.js 206ce6bbc3c30ad51a37d9c25e3a2712e70b586e0f9a2cf8cb0b9619017c2671
|
||||||
@ -533,7 +533,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
|||||||
F ext/wasm/test-opfs-vfs.js 48fc59110e8775bb43c9be25b6d634fc07ebadab7da8fbd44889e8129c6e2548
|
F ext/wasm/test-opfs-vfs.js 48fc59110e8775bb43c9be25b6d634fc07ebadab7da8fbd44889e8129c6e2548
|
||||||
F ext/wasm/tester1-worker.html 048c341f124fdb61ca14dfd1bd1f78742490f208aa3bb1e84399f83f1e7e6a74
|
F ext/wasm/tester1-worker.html 048c341f124fdb61ca14dfd1bd1f78742490f208aa3bb1e84399f83f1e7e6a74
|
||||||
F ext/wasm/tester1.html 37ccc958fa0d95074af2d72b7241c8e2d982bbec6dda4dc790241af3d933c3b6
|
F ext/wasm/tester1.html 37ccc958fa0d95074af2d72b7241c8e2d982bbec6dda4dc790241af3d933c3b6
|
||||||
F ext/wasm/tester1.js 5533cd100dc663dbe548fb04aefc490aa4b3d2e0ec2212f79881bb4893266e39
|
F ext/wasm/tester1.js 3fc539001b861d6360ea8c4825351157251204781b7a45389527574ad338c7e1
|
||||||
F ext/wasm/version-info.c 5fa356d38859d71a0369b5c37e1935def7413fcc8a4e349a39d9052c1d0479f4
|
F ext/wasm/version-info.c 5fa356d38859d71a0369b5c37e1935def7413fcc8a4e349a39d9052c1d0479f4
|
||||||
F ext/wasm/wasmfs.make ee0004813e16c283ff633e08b482008d56adf9b7d42f6c5612f7ab002b924f69
|
F ext/wasm/wasmfs.make ee0004813e16c283ff633e08b482008d56adf9b7d42f6c5612f7ab002b924f69
|
||||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||||
@ -2036,8 +2036,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 9d034ef5e1bab7c9651c2450dc85765fa6365d3f1414c711550de858ff8b3ece
|
P 89f3e1982ec32c010af67d15ef780847df20de568669e5c9d02f3cf084f51330
|
||||||
R dfb3978c0632c8b69ab9fb0976c9a2ee
|
R 8a68d8975e926edd4ad048c9589fdc73
|
||||||
U stephan
|
U stephan
|
||||||
Z c86f3e45c75ca0a38f433f4183ca8f53
|
Z 78e197950cf91aa30272843b46106df8
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
89f3e1982ec32c010af67d15ef780847df20de568669e5c9d02f3cf084f51330
|
f07ce15479b7224b0d1ba9f147a433136e70c1461aa667d2737d4a918f778f55
|
Reference in New Issue
Block a user