1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-25 20:58:26 +03:00

Restructure the interface for the sqlite3.wasm pointer-size-dependent details.

FossilOrigin-Name: 8ac12e1f5144380d4ecc8b27a1f62dcda0e5a86409ae7149f62c33caeea19a23
This commit is contained in:
stephan
2025-09-21 13:53:59 +00:00
parent 72d81265ab
commit 1e2156e926
9 changed files with 153 additions and 115 deletions

View File

@@ -728,7 +728,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
dealloc: wasm.dealloc,
bigIntEnabled: wasm.bigIntEnabled,
pointerIR: wasm.pointerIR,
pointerSizeof: wasm.pointerSizeof,
pointerSizeof: wasm.ptr.size,
memberPrefix: /* Never change this: this prefix is baked into any
amount of code and client-facing docs. (Much
later: it probably should have been '$$', but see
@@ -1534,7 +1534,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const [xSql, xSqlLen] = __flexiString(sql, sqlLen);
switch(typeof xSql){
case 'string': return __prepare.basic(pDb, xSql, xSqlLen, prepFlags, ppStmt, null);
case (typeof wasm.NullPtr):
case (typeof wasm.ptr.null):
return __prepare.full(pDb, xSql, xSqlLen, prepFlags, ppStmt, pzTail);
default:
return util.sqlite3__wasm_db_error(
@@ -1759,9 +1759,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const zV = wasm.scopedAllocCString(jV);
if(nBuf > nV + 1) nBuf = nV + 1;
wasm.heap8u().copyWithin(
Number(zBuf), Number(zV), Number(wasm.ptrAdd(zV, nBuf,- 1))
Number(zBuf), Number(zV), wasm.ptr.addn(zV, nBuf,- 1)
);
wasm.poke(wasm.ptrAdd(zBuf, nBuf, -1), 0);
wasm.poke(wasm.ptr.add(zBuf, nBuf, -1), 0);
return nBuf - 1;
}catch(e){
sqlite3.config.error("kvstorageRead()",e);

View File

@@ -285,7 +285,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const stack = wasm.pstack.pointer;
try {
const pPtr = wasm.pstack.allocPtr() /* output (sqlite3**) arg */;
let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || wasm.NullPtr);
let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || wasm.ptr.null);
pDb = wasm.peekPtr(pPtr);
checkSqlite3Rc(pDb, rc);
capi.sqlite3_extended_result_codes(pDb, 1);
@@ -1051,14 +1051,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
let sqlByteLen = isTA ? arg.sql.byteLength : wasm.jstrlen(arg.sql);
const ppStmt = wasm.scopedAlloc(
/* output (sqlite3_stmt**) arg and pzTail */
(2 * wasm.pointerSizeof) + (sqlByteLen + 1/* SQL + NUL */)
(2 * wasm.ptr.size) + (sqlByteLen + 1/* SQL + NUL */)
);
const pzTail = wasm.ptrAdd(ppStmt, wasm.pointerSizeof) /* final arg to sqlite3_prepare_v2() */;
let pSql = wasm.ptrAdd(pzTail, wasm.pointerSizeof);
const pSqlEnd = wasm.ptrAdd(pSql, sqlByteLen);
const pzTail = wasm.ptr.add(ppStmt, wasm.ptr.size) /* final arg to sqlite3_prepare_v2() */;
let pSql = wasm.ptr.add(pzTail, wasm.ptr.size);
const pSqlEnd = wasm.ptr.add(pSql, sqlByteLen);
if(isTA) wasm.heap8().set(arg.sql, pSql);
else wasm.jstrcpy(arg.sql, wasm.heap8(), pSql, sqlByteLen, false);
wasm.poke(wasm.ptrAdd(pSql, sqlByteLen), 0/*NUL terminator*/);
wasm.poke(wasm.ptr.add(pSql, sqlByteLen), 0/*NUL terminator*/);
while(pSql && wasm.peek(pSql, 'i8')
/* Maintenance reminder:^^^ _must_ be 'i8' or else we
will very likely cause an endless loop. What that's
@@ -1073,7 +1073,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
));
const pStmt = wasm.peekPtr(ppStmt);
pSql = wasm.peekPtr(pzTail);
sqlByteLen = Number(wasm.ptrAdd(pSqlEnd,-pSql));
sqlByteLen = Number(wasm.ptr.add(pSqlEnd,-pSql));
if(!pStmt) continue;
//sqlite3.config.debug("exec() pSql =",capi.sqlite3_sql(pStmt));
if(saveSql) saveSql.push(capi.sqlite3_sql(pStmt).trim());

View File

@@ -389,13 +389,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
modified by other threads while they're working.
*/
const typedArrayPart = (aTypedArray, begin, end)=>{
//if( 8===wasm..ptr.size ){
// slice() and subarray() do not like BigInt args.
if( 'bigint'===typeof begin ) begin = Number(begin);
if( 'bigint'===typeof end ) end = Number(end);
/*if( 8===wasm.pointerSizeof ){
begin = Number(begin);
end = Number(end);
}*/
//}
return isSharedTypedArray(aTypedArray)
? aTypedArray.slice(begin, end)
: aTypedArray.subarray(begin, end);
@@ -884,7 +884,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
the other way around. In this case, the memory is not
available via this.exports.memory.
*/
memory: config.memory || config.exports['memory']
memory: config.memory
|| config.exports['memory']
|| toss3("API config object requires a WebAssembly.Memory object",
"in either config.exports.memory (exported)",
"or config.memory (imported)."),
@@ -992,13 +993,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
};
wasm.alloc.impl = wasm.exports[keyAlloc];
wasm.realloc = function f(m,n){
m = wasm.asPtrType(m)/*tag:64bit*/;
m = wasm.ptr.coerce(m)/*tag:64bit*/;
const m2 = f.impl(m,n);
return n ? (m2 || WasmAllocError.toss("Failed to reallocate",n," bytes.")) : wasm.NullPtr;
return n ? (m2 || WasmAllocError.toss("Failed to reallocate",n," bytes.")) : wasm.ptr.null;
};
wasm.realloc.impl = wasm.exports[keyRealloc];
wasm.dealloc = function f(m){
f.impl(wasm.asPtrType(m)/*tag:64bit*/);
f.impl(wasm.ptr.coerce(m)/*tag:64bit*/);
};
wasm.dealloc.impl = wasm.exports[keyDealloc];
}
@@ -1162,12 +1163,12 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
const mem = wasm.pstack.alloc(n * sz);
const rc = [mem];
let i = 1, offset = sz;
for(; i < n; ++i, offset += sz) rc.push(wasm.ptrAdd(mem, offset));
for(; i < n; ++i, offset += sz) rc.push(wasm.ptr.add(mem, offset));
return rc;
},
/**
A convenience wrapper for allocChunks() which sizes each chunk
as either 8 bytes (safePtrSize is truthy) or wasm.pointerSizeof (if
as either 8 bytes (safePtrSize is truthy) or wasm.ptr.size (if
safePtrSize is falsy).
How it returns its result differs depending on its first
@@ -1186,8 +1187,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
*/
allocPtr: (n=1,safePtrSize=true)=>{
return 1===n
? wasm.pstack.alloc(safePtrSize ? 8 : wasm.pointerSizeof)
: wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.pointerSizeof);
? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptr.size)
: wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptr.size);
},
/**
@@ -1246,7 +1247,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
&& 1===args[0].BYTES_PER_ELEMENT){
const ta = args[0];
if(0===ta.byteLength){
wasm.exports.sqlite3_randomness(0,wasm.NullPtr);
wasm.exports.sqlite3_randomness(0,wasm.ptr.null);
return ta;
}
const stack = wasm.pstack.pointer;
@@ -1259,7 +1260,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
do{
const j = (n>nAlloc ? nAlloc : n);
r(j, ptr);
ta.set(typedArrayPart(heap, ptr, wasm.ptrAdd(ptr,j)), offset);
ta.set(typedArrayPart(heap, ptr, wasm.ptr.add(ptr,j)), offset);
n -= j;
offset += j;
} while(n > 0);
@@ -1377,7 +1378,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
*/
capi.sqlite3_js_vfs_list = function(){
const rc = [];
let pVfs = capi.sqlite3_vfs_find(wasm.asPtrType(0));
let pVfs = capi.sqlite3_vfs_find(wasm.ptr.coerce(0));
while(pVfs){
const oVfs = new capi.sqlite3_vfs(pVfs);
rc.push(wasm.cstrToJs(oVfs.$zName));
@@ -1407,8 +1408,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
const scope = wasm.scopedAllocPush();
let pOut;
try{
const pSize = wasm.scopedAlloc(8/*i64*/ + wasm.pointerSizeof);
const ppOut = wasm.ptrAdd(pSize, 8);
const pSize = wasm.scopedAlloc(8/*i64*/ + wasm.ptr.size);
const ppOut = wasm.ptr.add(pSize, 8);
/**
Maintenance reminder, since this cost a full hour of grief
and confusion: if the order of pSize/ppOut are reversed in
@@ -1418,7 +1419,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
*/
const zSchema = schema
? (wasm.isPtr(schema) ? schema : wasm.scopedAllocCString(''+schema))
: wasm.NullPtr;
: wasm.ptr.null;
let rc = wasm.exports.sqlite3__wasm_db_serialize(
pDb, zSchema, ppOut, pSize, 0
);
@@ -1859,7 +1860,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
do not.
*/
tgt.push(capi.sqlite3_value_to_js(
wasm.peekPtr(wasm.ptrAdd(pArgv, wasm.pointerSizeof * i)),
wasm.peekPtr(wasm.ptr.add(pArgv, wasm.ptr.size * i)),
throwIfCannotConvert
));
}

View File

@@ -34,7 +34,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/
sii.prototype.nthConstraint = function(n, asPtr=false){
if(n<0 || n>=this.$nConstraint) return false;
const ptr = wasm.ptrAdd(
const ptr = wasm.ptr.add(
this.$aConstraint,
sii.sqlite3_index_constraint.structInfo.sizeof * n
);
@@ -49,7 +49,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/
sii.prototype.nthConstraintUsage = function(n, asPtr=false){
if(n<0 || n>=this.$nConstraint) return false;
const ptr = wasm.ptrAdd(
const ptr = wasm.ptr.add(
this.$aConstraintUsage,
sii.sqlite3_index_constraint_usage.structInfo.sizeof * n
);
@@ -66,7 +66,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/
sii.prototype.nthOrderBy = function(n, asPtr=false){
if(n<0 || n>=this.$nOrderBy) return false;
const ptr = wasm.ptrAdd(
const ptr = wasm.ptr.add(
this.$aOrderBy,
sii.sqlite3_index_orderby.structInfo.sizeof * n
);

View File

@@ -178,6 +178,24 @@
When building with Emscripten's -sMEMORY64=1, `pointerIR` must be
set to 'i64' and/or `pointerSizeof` must be set to 8.
After calling this, the pointerIR and pointerSizeof properties are
replaced with a read-only Object member named target.ptr. It
contains the following read-only properties:
- .size = pointerSizeof
- .ir = pointerIR
- .null = a "null" pointer of type Number or BigInt.
- .coerce = a function which behaves like target.asPtrType()
- .add = a substitute for pointer arithmetic (which does not work
in 64-bit builds). Adds up all of its arguments and returns
either a Number or BigInt, depending on this.size.
- .addn = like .add() but returns its result as a Number.
Design notes:
- It should probably take a config object and return the
@@ -200,23 +218,25 @@ globalThis.WhWasmUtilInstaller = function(target){
if( target.pointerSizeof && !target.pointerIR ){
target.pointerIR = (4===target.pointerSizeof ? 'i32' : 'i64');
}
const ptrIR = (target.pointerIR ??= 'i32');
const ptrSizeof = (target.pointerSizeof ??=
('i32'===ptrIR ? 4 : ('i64'===ptrIR ? 8 : 0)));
const __ptrIR = (target.pointerIR ??= 'i32');
const __ptrSize = (target.pointerSizeof ??=
('i32'===__ptrIR ? 4 : ('i64'===__ptrIR ? 8 : 0)));
delete target.pointerSizeof;
delete target.pointerIR;
if( 'i32'!==ptrIR && 'i64'!==ptrIR ){
toss("Invalid pointerIR:",ptrIR);
}else if( 8!==ptrSizeof && 4!==ptrSizeof ){
toss("Invalid pointerSizeof:",ptrSizeof);
if( 'i32'!==__ptrIR && 'i64'!==__ptrIR ){
toss("Invalid pointerIR:",__ptrIR);
}else if( 8!==__ptrSize && 4!==__ptrSize ){
toss("Invalid pointerSizeof:",__ptrSize);
}
/**
If target.pointerIR=='i32' then this is equivalent to
If target.ptr.ir=='i32' then this is equivalent to
Number(v) else it's equivalent to BigInt(v||0).
Why? Because Number(null)===0, but BigInt(null) throws.
*/
const __asPtrType = (4===ptrSizeof)
const __asPtrType = (4===__ptrSize)
? Number
: (target.bigIntEnabled
? ((v)=>BigInt(v || 0))
@@ -226,12 +246,10 @@ globalThis.WhWasmUtilInstaller = function(target){
/**
The number 0 as either type Number or BigInt, depending on
target.pointerIR.
target.ptr.ir.
*/
const __NullPtr = __asPtrType(0);
target.NullPtr = __NullPtr;
/**
Expects any number of numeric arguments, each one of either type
Number or BigInt. It sums them up (from an implicit starting
@@ -248,7 +266,24 @@ globalThis.WhWasmUtilInstaller = function(target){
return rc;
};
target.ptrAdd = __ptrAdd;
const __ptr = Object.assign(Object.create(null),{
coerce: __asPtrType,
add: __ptrAdd,
addn: (4===__ptrIR) ? __ptrAdd : (...args)=>Number(__ptrAdd(...args))
});
Object.defineProperty(target, 'ptr', {
enumerable: true,
get: ()=>__ptr,
set: ()=>toss("The ptr property is read-only.")
});
(function f(name, val){
Object.defineProperty(__ptr, name, {
enumerable: true,
get: ()=>val,
set: ()=>toss("ptr["+name+"] is read-only.")
});
return f;
})( 'null', __NullPtr )( 'size', __ptrSize )( 'ir', __ptrIR );
if(!target.exports){
Object.defineProperty(target, 'exports', {
@@ -288,7 +323,7 @@ globalThis.WhWasmUtilInstaller = function(target){
For the given IR-like string in the set ('i8', 'i16', 'i32',
'f32', 'float', 'i64', 'f64', 'double', '*'), or any string value
ending in '*', returns the sizeof for that value
(target.pointerSizeof in the latter case). For any other value, it
(target.ptr.size in the latter case). For any other value, it
returns the undefined value.
*/
target.sizeofIR = (n)=>{
@@ -297,9 +332,9 @@ globalThis.WhWasmUtilInstaller = function(target){
case 'i16': return 2;
case 'i32': case 'f32': case 'float': return 4;
case 'i64': case 'f64': case 'double': return 8;
case '*': return ptrSizeof;
case '*': return __ptrSize;
default:
return (''+n).endsWith('*') ? ptrSizeof : undefined;
return (''+n).endsWith('*') ? __ptrSize : undefined;
}
};
@@ -470,7 +505,7 @@ globalThis.WhWasmUtilInstaller = function(target){
f._ = {
// Map of signature letters to type IR values
sigTypes: Object.assign(Object.create(null),{
i: 'i32', p: ptrIR, P: ptrIR, s: ptrIR,
i: 'i32', p: __ptrIR, P: __ptrIR, s: __ptrIR,
j: 'i64', f: 'f32', d: 'f64'
}),
// Map of type IR values to WASM type code values
@@ -699,7 +734,7 @@ globalThis.WhWasmUtilInstaller = function(target){
As a special case, if type ends with a `*`, it is considered to
be a pointer type and is treated as the WASM numeric type
appropriate for the pointer size (==this.pointerIR).
appropriate for the pointer size (==this.ptr.ir).
While possibly not obvious, this routine and its poke()
counterpart are how pointer-to-value _output_ parameters in
@@ -746,7 +781,7 @@ globalThis.WhWasmUtilInstaller = function(target){
See also: poke()
*/
target.peek = function f(ptr, type='i8'){
if(type.endsWith('*')) type = ptrIR;
if(type.endsWith('*')) type = __ptrIR;
const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength)
? cache : heapWrappers();
const list = Array.isArray(ptr) ? [] : undefined;
@@ -780,7 +815,7 @@ globalThis.WhWasmUtilInstaller = function(target){
bytes are written. Throws if given an invalid type. See peek()
for details about the `type` argument. If the 3rd argument ends
with `*` then it is treated as a pointer type and this function
behaves as if the 3rd argument were this.pointerIR.
behaves as if the 3rd argument were this.ptr.ir.
If the first argument is an array, it is treated like a list
of pointers and the given value is written to each one.
@@ -792,7 +827,7 @@ globalThis.WhWasmUtilInstaller = function(target){
ACHTUNG #2: see peek()'s ACHTUNG #2.
*/
target.poke = function(ptr, value, type='i8'){
if (type.endsWith('*')) type = ptrIR;
if (type.endsWith('*')) type = __ptrIR;
const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength)
? cache : heapWrappers();
for(const p of (Array.isArray(ptr) ? ptr : [ptr])){
@@ -823,7 +858,7 @@ globalThis.WhWasmUtilInstaller = function(target){
multiple arguments, or a single array of arguments, it returns an
array of their values.
*/
target.peekPtr = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), ptrIR );
target.peekPtr = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), __ptrIR );
/**
A variant of poke() intended for setting pointer-to-pointer
@@ -831,7 +866,7 @@ globalThis.WhWasmUtilInstaller = function(target){
value of 0 and (2) it always writes to the pointer-sized heap
view.
*/
target.pokePtr = (ptr, value=0)=>target.poke(ptr, value, ptrIR);
target.pokePtr = (ptr, value=0)=>target.poke(ptr, value, __ptrIR);
/**
Convenience form of peek() intended for fetching i8 values. If
@@ -901,7 +936,7 @@ globalThis.WhWasmUtilInstaller = function(target){
isPtr32() or the as-yet-hypothetical isPtr64(), depending on a
configuration option.
*/
target.isPtr = ('i32'==ptrIR)
target.isPtr = ('i32'==__ptrIR)
? target.isPtr32
: target.isPtr64;
@@ -930,7 +965,7 @@ globalThis.WhWasmUtilInstaller = function(target){
const __utf8Decode = function(arrayBuffer, begin, end){
//if( 'bigint'===typeof begin ) begin = Number(begin);
//if( 'bigint'===typeof end ) end = Number(end);
/*if( 8===ptrSizeof ){
/*if( 8===__ptrSize ){
begin = Number(begin);
end = Number(end);
}*/
@@ -1299,15 +1334,15 @@ globalThis.WhWasmUtilInstaller = function(target){
const __allocMainArgv = function(isScoped, list){
const pList = target[
isScoped ? 'scopedAlloc' : 'alloc'
]((list.length + 1) * target.pointerSizeof);
]((list.length + 1) * target.ptr.size);
let i = 0;
list.forEach((e)=>{
target.pokePtr(__ptrAdd(pList, target.pointerSizeof * i++),
target.pokePtr(__ptrAdd(pList, target.ptr.size * i++),
target[
isScoped ? 'scopedAllocCString' : 'allocCString'
](""+e));
});
target.pokePtr(__ptrAdd(pList, target.pointerSizeof * i), 0);
target.pokePtr(__ptrAdd(pList, target.ptr.size * i), 0);
return pList;
};
@@ -1352,7 +1387,7 @@ globalThis.WhWasmUtilInstaller = function(target){
target.cArgvToJs = (argc, pArgv)=>{
const list = [];
for(let i = 0; i < argc; ++i){
const arg = target.peekPtr(__ptrAdd(pArgv, target.pointerSizeof * i));
const arg = target.peekPtr(__ptrAdd(pArgv, target.ptr.size * i));
list.push( arg ? target.cstrToJs(arg) : null );
}
return list;
@@ -1374,15 +1409,15 @@ globalThis.WhWasmUtilInstaller = function(target){
/** Internal impl for allocPtr() and scopedAllocPtr(). */
const __allocPtr = function(howMany, safePtrSize, method){
__affirmAlloc(target, method);
const pIr = safePtrSize ? 'i64' : ptrIR;
let m = target[method](howMany * (safePtrSize ? 8 : ptrSizeof));
const pIr = safePtrSize ? 'i64' : __ptrIR;
let m = target[method](howMany * (safePtrSize ? 8 : __ptrSize));
target.poke(m, 0, pIr)
if(1===howMany){
return m;
}
const a = [m];
for(let i = 1; i < howMany; ++i){
m = __ptrAdd(m, (safePtrSize ? 8 : ptrSizeof));
m = __ptrAdd(m, (safePtrSize ? 8 : __ptrSize));
a[i] = m;
target.poke(m, 0, pIr);
}
@@ -1526,7 +1561,7 @@ globalThis.WhWasmUtilInstaller = function(target){
const copyToResult = ['i8', 'i16', 'i32', 'int',
'f32', 'float', 'f64', 'double'];
if(target.bigIntEnabled) copyToResult.push('i64');
const adaptPtr = xArg.get(ptrIR);
const adaptPtr = xArg.get(__ptrIR);
for(const t of copyToResult){
xArg.set(t+'*', adaptPtr);
xResult.set(t+'*', adaptPtr);
@@ -1544,7 +1579,8 @@ globalThis.WhWasmUtilInstaller = function(target){
- If v is a string, scopeAlloc() a new C-string from it and return
that temp string's pointer.
- Else return the value from the arg adapter defined for `ptrIR`.
- Else return the value from the arg adapter defined for
target.ptr.ir.
TODO? Permit an Int8Array/Uint8Array and convert it to a string?
Would that be too much magic concentrated in one place, ready to

View File

@@ -167,6 +167,7 @@
lib: capi.sqlite3_libversion(),
srcId: capi.sqlite3_sourceid()
});
stdout("WASM pointer size: "+wasm.ptr.size);
stdout('Welcome to the "fiddle" shell. Tap the About button for more info.');
if(capi.sqlite3_vfs_find("opfs")){
stdout("\nOPFS is available. To open a persistent db, use:\n\n",

View File

@@ -76,7 +76,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
let SQLite3 /* populated after module load */;
const skipIn64BitBuild = function(msg=''){
if( 8===SQLite3.wasm.pointerSizeof ){
if( 8===SQLite3.wasm.ptr.size ){
error("Skipping known-broken tests for 64-bit build.",msg); return true;
}
return false;
@@ -514,7 +514,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
let m2 = w.realloc(m, 16);
T.assert(m === m2/* because of alignment */);
let x = w.realloc(m, 0);
T.assert(w.NullPtr === x);
T.assert(w.ptr.null === x);
m = m2 = 0;
// Check allocation limits and allocator's responses...
@@ -523,9 +523,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
const tooMuch = sqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE + 1,
isAllocErr = (e)=>e instanceof sqlite3.WasmAllocError;
T.mustThrowMatching(()=>w.alloc(tooMuch), isAllocErr)
.assert(w.NullPtr === w.alloc.impl(tooMuch))
.assert(w.ptr.null === w.alloc.impl(tooMuch))
.mustThrowMatching(()=>w.realloc(0, tooMuch), isAllocErr)
.assert(w.NullPtr === w.realloc.impl(wasm.NullPtr, tooMuch));
.assert(w.ptr.null === w.realloc.impl(wasm.ptr.null, tooMuch));
}
// Check allocFromTypedArray()...
@@ -637,19 +637,19 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
try {
let cStr = w.scopedAllocCString("hello");
const n = w.cstrlen(cStr);
const nPtr = w.asPtrType(n);
const nPtr = w.ptr.coerce(n);
let cpy = w.scopedAlloc(n+10);
let rc = w.cstrncpy(cpy, cStr, n+10);
T.assert(n+1 === rc).
assert("hello" === w.cstrToJs(cpy)).
assert(chr('o') === w.peek8( w.ptrAdd(cpy,nPtr, -1))).
assert(0 === w.peek8( w.ptrAdd(cpy,nPtr) ) );
assert(chr('o') === w.peek8( w.ptr.add(cpy,nPtr, -1))).
assert(0 === w.peek8( w.ptr.add(cpy,nPtr) ) );
let cStr2 = w.scopedAllocCString("HI!!!");
rc = w.cstrncpy(cpy, cStr2, 3);
T.assert(3===rc).
assert("HI!lo" === w.cstrToJs(cpy)).
assert(chr('!') === w.peek8( w.ptrAdd(cpy, 2) )).
assert(chr('l') === w.peek8( w.ptrAdd(cpy, 3) ) );
assert(chr('!') === w.peek8( w.ptr.add(cpy, 2) )).
assert(chr('l') === w.peek8( w.ptr.add(cpy, 3) ) );
}finally{
w.scopedAllocPop(scope);
}
@@ -672,8 +672,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
const jstr = "hällo, world!";
const [cstr, n] = w.allocCString(jstr, true);
T.assert(14 === n)
.assert(0===w.peek8(w.ptrAdd(cstr,n)))
.assert(chr('!')===w.peek8(w.ptrAdd(cstr,n,-1)));
.assert(0===w.peek8(w.ptr.add(cstr,n)))
.assert(chr('!')===w.peek8(w.ptr.add(cstr,n,-1)));
w.dealloc(cstr);
}
@@ -708,9 +708,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(p3===asc2[0]);
const [z1, z2, z3] = w.scopedAllocPtr(3);
T.assert(typeof w.NullPtr===typeof z1).assert(z2>z1).assert(z3>z2)
.assert(w.NullPtr===w.peekPtr(z1), 'allocPtr() must zero the targets')
.assert(w.NullPtr===w.peekPtr(z3));
T.assert(typeof w.ptr.null===typeof z1).assert(z2>z1).assert(z3>z2)
.assert(w.ptr.null===w.peekPtr(z1), 'allocPtr() must zero the targets')
.assert(w.ptr.null===w.peekPtr(z3));
}finally{
// Pop them in "incorrect" order to make sure they behave:
w.scopedAllocPop(asc);
@@ -730,8 +730,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert(1===w.scopedAlloc.level);
const [cstr, n] = w.scopedAllocCString("hello, world", true);
T.assert(12 === n)
.assert(0===w.peek8( w.ptrAdd(cstr,n) ))
.assert(chr('d')===w.peek8( w.ptrAdd(cstr, n, -1) ));
.assert(0===w.peek8( w.ptr.add(cstr,n) ))
.assert(chr('d')===w.peek8( w.ptr.add(cstr, n, -1) ));
});
}/*scopedAlloc()*/
@@ -852,8 +852,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert(12n===rc);
w.scopedAllocCall(function(){
const pI1 = w.scopedAlloc(w.pointerSizeof), pI2 = w.ptrAdd(pI1, w.pointerSizeof);
w.pokePtr([pI1, pI2], w.NullPtr);
const pI1 = w.scopedAlloc(w.ptr.size), pI2 = w.ptr.add(pI1, w.ptr.size);
w.pokePtr([pI1, pI2], w.ptr.null);
const f = w.xWrap('sqlite3__wasm_test_int64_minmax',undefined,['i64*','i64*']);
const [r1, r2] = w.peek64([pI1, pI2]);
T.assert(!Number.isSafeInteger(r1)).assert(!Number.isSafeInteger(r2));
@@ -880,14 +880,14 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
};
const msd = MyStructDef;
addMember(msd, 'p4', {sizeof: 4, signature: "i"});
addMember(msd, 'pP', {sizeof: wasm.pointerSizeof, signature: "P"});
addMember(msd, 'pP', {sizeof: wasm.ptr.size, signature: "P"});
addMember(msd, 'ro', {
sizeof: 4,
signature: "i",
readOnly: true
});
addMember(msd, 'cstr', {
sizeof: wasm.pointerSizeof,
sizeof: wasm.ptr.size,
signature: "s"
});
if(W.bigIntEnabled){
@@ -1093,7 +1093,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert(P.pointer === stack);
try {
const [p1, p2, p3] = P.allocChunks(3,'i32');
let sPos = wasm.ptrAdd(stack,-16)/*pstack alloc always rounds to multiple of 8*/;
let sPos = wasm.ptr.add(stack,-16)/*pstack alloc always rounds to multiple of 8*/;
T.assert(P.pointer === sPos)
.assert(p1 === sPos)
.assert(p2 == Number(p1) + 4)
@@ -1107,16 +1107,16 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert(P.pointer === stack);
try {
let [p1, p2, p3] = P.allocPtr(3,false);
let sPos = wasm.ptrAdd(stack,
-(4===wasm.pointerSizeof
let sPos = wasm.ptr.add(stack,
-(4===wasm.ptr.size
? 16/*pstack alloc always rounds to multiple of 8*/
: 24));
T.assert(P.pointer === p1)
.assert(p1 === sPos)
.assert(p2 == Number(p1) + wasm.pointerSizeof)
.assert(p3 == Number(p2) + wasm.pointerSizeof);
.assert(p2 == Number(p1) + wasm.ptr.size)
.assert(p3 == Number(p2) + wasm.ptr.size);
[p1, p2, p3] = P.allocPtr(3);
T.assert(P.pointer === wasm.ptrAdd(sPos, -24)/*3 x 8 bytes*/)
T.assert(P.pointer === wasm.ptr.add(sPos, -24)/*3 x 8 bytes*/)
.assert(p2 == Number(p1) + 8)
.assert(p3 == Number(p2) + 8);
p1 = P.allocPtr();
@@ -1135,18 +1135,18 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
const n = 520;
const p = wasm.pstack.alloc(n);
T.assert(0==wasm.peek8(p))
.assert(0==wasm.peek8(wasm.ptrAdd(p,n,-1)));
.assert(0==wasm.peek8(wasm.ptr.add(p,n,-1)));
T.assert(undefined === capi.sqlite3_randomness(n - 10, p));
let j, check = 0;
const heap = wasm.heap8u();
for(j = 0; j < 10 && 0===check; ++j){
check += heap[wasm.ptrAdd(p, j)];
check += heap[wasm.ptr.add(p, j)];
}
T.assert(check > 0);
check = 0;
// Ensure that the trailing bytes were not modified...
for(j = n - 10; j < n && 0===check; ++j){
check += heap[wasm.ptrAdd(p, j)];
check += heap[wasm.ptr.add(p, j)];
}
T.assert(0===check);
}finally{
@@ -2205,7 +2205,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(wasm.isPtr(pVoid))
.assert(wasm.isPtr(aVals))
.assert(wasm.isPtr(aCols))
.assert(+wasm.cstrToJs(wasm.peekPtr(wasm.ptrAdd(aVals, wasm.pointerSizeof)))
.assert(+wasm.cstrToJs(wasm.peekPtr(wasm.ptr.add(aVals, wasm.ptr.size)))
=== 2 * +wasm.cstrToJs(wasm.peekPtr(aVals)));
return 0;
});
@@ -2312,7 +2312,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
in the call :/ */));
const pMin = w.scopedAlloc(16);
const pMax = w.ptrAdd(pMin, 8);
const pMax = w.ptr.add(pMin, 8);
const g64 = (p)=>w.peek64(p);
w.poke64([pMin, pMax], 0);
const minMaxI64 = [
@@ -2543,7 +2543,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(tmplMod.$xCreate === tmplMod.$xConnect,
"setup() must make these equivalent and "+
"installMethods() must avoid re-compiling identical functions");
tmplMod.$xCreate = wasm.NullPtr /* make tmplMod eponymous-only */;
tmplMod.$xCreate = wasm.ptr.null /* make tmplMod eponymous-only */;
let rc = capi.sqlite3_create_module(
this.db, "testvtab", tmplMod, 0
);
@@ -2918,7 +2918,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
++countCommit;
return (17 == p) ? 0 : capi.SQLITE_ERROR;
}, 17);
T.assert( wasm.NullPtr === rc );
T.assert( wasm.ptr.null === rc );
// Commit hook...
T.assert( 0!=capi.sqlite3_get_autocommit(db) );
@@ -2940,7 +2940,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
++countRollback;
T.assert( 21 == p );
}, 21);
T.assert( wasm.NullPtr===rc );
T.assert( wasm.ptr.null===rc );
T.mustThrowMatching(()=>{
db.transaction('drop table t',()=>{})
}, (e)=>{
@@ -3854,7 +3854,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
}else{
logClass('warning',"BigInt/int64 support is disabled.");
}
log("WASM pointer size:",wasm.pointerSizeof,"bytes");
log("WASM pointer size:",wasm.ptr.size,"bytes");
if(haveWasmCTests()){
log("sqlite3__wasm_test_...() APIs are available.");
}else{

View File

@@ -1,5 +1,5 @@
C Reduce\ssqlite3.js\sbuild\ssize\sby\sabout\s30kb\sby\sstripping\sout\sEmscripten's\smakeInvalidEarlyAccess()\swrappers.
D 2025-09-21T11:47:06.492
C Restructure\sthe\sinterface\sfor\sthe\ssqlite3.wasm\spointer-size-dependent\sdetails.
D 2025-09-21T13:53:59.169
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -597,16 +597,16 @@ F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90a
F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701
F ext/wasm/api/pre-js.c-pp.js 58f823de197e2c10d76179aa05410a593b7ae03e1ece983bb42ffd818e8857e1
F ext/wasm/api/sqlite3-api-cleanup.js 0e27cacbde6a97f5b91cdb52d4486e4eba25669b986af10eceaa1d6b617586e3
F ext/wasm/api/sqlite3-api-glue.c-pp.js 4334fa642cc654f3ce4834dca45fc91ebe9816e31ca964402e364b89f251d3dd
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 3224395cfba23cd630f538fef4a57191c658b0791bacb76a4d7dead6f975ee84
F ext/wasm/api/sqlite3-api-prologue.js 98b0cbe1fecfe037ef66330e7f40be44492b0e75dc4de7559886bd60181b54f1
F ext/wasm/api/sqlite3-api-glue.c-pp.js d967a50ba38a14cc0e85765cd34ca0ac230112161f86c2df3f1b54e3f410c644
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 831ce373495f6a5d9230f31a1e09e8995e317828926e736d58c9e7091c6b1d07
F ext/wasm/api/sqlite3-api-prologue.js dad9eb0f5eebf22422ddb242274c9880a63717f758bec1adfd366641c6f0f74c
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 760191cd13416e6f5adfd9fcc8a97fed5645c9e0a5fbac213a2d4ce2d79a4334
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js e6389ff91cdb3c17354211bea226f67c2374f23fc0f51691e7c8de66cd2a678d
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 7071a9519dacb643a7fe2fd6b9f33f7c69e63d2929e907a5ef846bb5b1b7dec8
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 729131e48d5c0a757970da167d667ce87e49042e0cc7016da5e95d8af70088b9
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 9097074724172e31e56ce20ccd7482259cf72a76124213cbc9469d757676da86
F ext/wasm/api/sqlite3-wasm.c ff2dc011e17b06186b8b35e408626d7ace69a362b92c197a34d78bef25c7105a
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 4ad256b4ff7f839ad18931ed35d46cced544207bd2209665ec552e193f7f4544
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
@@ -618,7 +618,7 @@ F ext/wasm/c-pp.c cca55c5b55ebd8d29916adbedb0e40baa12caa9a2e8429f812683c308f9b0e
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
F ext/wasm/common/whwasmutil.js 97364d44356a93f7ef1db0c0c6fd5bd44cd41a287e8bc329eb2d5dce190f479a
F ext/wasm/common/whwasmutil.js e272bca868ee2e19aae6d9cb8049a500917906050bce1dd0049b48780161e215
F ext/wasm/config.make.in c424ae1cc3c89274520ad312509d36c4daa34a3fce5d0c688e5f8f4365e1049a
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
@@ -632,7 +632,7 @@ F ext/wasm/demo-worker1.js 08720227e98fa5b44761cf6e219269cee3e9dd0421d8d91459535
F ext/wasm/dist.make 57f5da2f0de5a297b5a0bc39ffec736380050578240ab24d864c2ff1b3634a3b
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
F ext/wasm/fiddle.make 732b5ba2d5c164080f7918eb4a82447a0039254867d775ba7603bd8bce2b6ac3
F ext/wasm/fiddle/fiddle-worker.js 0b799898756a04c5f0fc199fa8d56b8337aed39dc23e6be591a33ae012eef86a
F ext/wasm/fiddle/fiddle-worker.js 52c67e450414cf010349b3758a3d7b0d859343eab6b794450297fa23e8d7e510
F ext/wasm/fiddle/fiddle.js f0b96f978c7c77fea8d092aa79c77849ce111d7b1ba60ffba07675009682184e
F ext/wasm/fiddle/index.html 17c7d6b21f40fbf462162c4311b63d760b065e419d9f5a96534963b0e52af940
F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf188f024b3730
@@ -655,7 +655,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
F ext/wasm/tester1.c-pp.js f601700ef1f7e14a1861fb006b8e33a4299ba25a09a064a10e2355d51eb7ec33
F ext/wasm/tester1.c-pp.js 616c783aa6e4d29dd53202fa58cb10603954e141928766eb332874c0c539520a
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -2175,8 +2175,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 1c2cd58d1a86d85e79ac912270e762e22f43f1d41d81a19ecd0ae6b2656c71b4
R 5b462ed68a2890658ffa0ab1aa01c380
P 9fafe075d6f4c49fca45963b142f3e0f0e60d79cb462b7e24f9ed0b9a9677f28
R d386ab7075eb27ba676a7ca8659c9df3
U stephan
Z 242c66c8b190cbda5386e9cb5b8d822b
Z 910e5c0f8e03f1964d4736af59a10a20
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
9fafe075d6f4c49fca45963b142f3e0f0e60d79cb462b7e24f9ed0b9a9677f28
8ac12e1f5144380d4ecc8b27a1f62dcda0e5a86409ae7149f62c33caeea19a23