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

JavaScript: add sqlite3.wasm.realloc(), sqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE, and related tests.

FossilOrigin-Name: eeb84ba5de1152ef0f42105b8b285fdee9f5ad58281e60a4e0c8b1d6de1dead8
This commit is contained in:
stephan
2022-12-03 11:16:55 +00:00
parent 2564ca7d15
commit 85ef4e4344
8 changed files with 121 additions and 42 deletions

View File

@ -75,6 +75,10 @@
the `free(3)`-compatible routine for the WASM
environment. Defaults to `"sqlite3_free"`.
- `reallocExportName`: the name of the function, in `exports`, of
the `realloc(3)`-compatible routine for the WASM
environment. Defaults to `"sqlite3_realloc"`.
- `wasmfsOpfsDir`[^1]: if the environment supports persistent
storage using OPFS-over-WASMFS , this directory names the "mount
point" for that directory. It must be prefixed by `/` and may
@ -110,6 +114,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
})(),
allocExportName: 'sqlite3_malloc',
deallocExportName: 'sqlite3_free',
reallocExportName: 'sqlite3_realloc',
wasmfsOpfsDir: '/opfs'
}, apiConfig || {});
@ -284,12 +289,14 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
};
/**
Returns true if v appears to be one of our bind()-able
TypedArray types: Uint8Array or Int8Array. Support for
TypedArrays with element sizes >1 is TODO.
Returns true if v appears to be one of our bind()-able TypedArray
types: Uint8Array or Int8Array. Support for TypedArrays with
element sizes >1 is a potential TODO just waiting on a use case
to justify them.
*/
const isBindableTypedArray = (v)=>{
return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
return v && (v instanceof Uint8Array || v instanceof Int8Array);
//v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
};
/**
@ -302,7 +309,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
isSQLableTypedArray() list.
*/
const isSQLableTypedArray = (v)=>{
return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
return v && (v instanceof Uint8Array || v instanceof Int8Array);
//v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
};
/** Returns true if isBindableTypedArray(v) does, else throws with a message
@ -664,12 +672,12 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
"or config.memory (imported)."),
/**
The API's one single point of access to the WASM-side memory
allocator. Works like malloc(3) (and is likely bound to
malloc()) but throws an WasmAllocError if allocation fails. It is
important that any code which might pass through the sqlite3 C
API NOT throw and must instead return SQLITE_NOMEM (or
equivalent, depending on the context).
The API's primary point of access to the WASM-side memory
allocator. Works like sqlite3_malloc() but throws a
WasmAllocError if allocation fails. It is important that any
code which might pass through the sqlite3 C API NOT throw and
must instead return SQLITE_NOMEM (or equivalent, depending on
the context).
Very few cases in the sqlite3 JS APIs can result in
client-defined functions propagating exceptions via the C-style
@ -681,7 +689,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
catch exceptions and convert them to appropriate error codes.
For cases where non-throwing allocation is required, use
sqlite3.wasm.alloc.impl(), which is direct binding of the
this.alloc.impl(), which is direct binding of the
underlying C-level allocator.
Design note: this function is not named "malloc" primarily
@ -692,9 +700,27 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
alloc: undefined/*installed later*/,
/**
The API's one single point of access to the WASM-side memory
deallocator. Works like free(3) (and is likely bound to
free()).
Rarely necessary in JS code, this routine works like
sqlite3_realloc(M,N), where M is either NULL or a pointer
obtained from this function or this.alloc() and N is the number
of bytes to reallocate the block to. Returns a pointer to the
reallocated block or 0 if allocation fails.
If M is NULL and N is positive, this behaves like
this.alloc(N). If N is 0, it behaves like this.dealloc().
Results are undefined if N is negative (sqlite3_realloc()
treats that as 0, but if this code is built with a different
allocator it may misbehave with negative values).
Like this.alloc.impl(), this.realloc.impl() is a direct binding
to the underlying realloc() implementation which does not throw
exceptions, instead returning 0 on allocation error.
*/
realloc: undefined/*installed later*/,
/**
The API's primary point of access to the WASM-side memory
deallocator. Works like sqlite3_free().
Design note: this function is not named "free" for the same
reason that this.alloc() is not called this.malloc().
@ -731,20 +757,30 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
return pRet;
};
const keyAlloc = config.allocExportName,
keyDealloc = config.deallocExportName;
for(const key of [keyAlloc, keyDealloc]){
const f = wasm.exports[key];
if(!(f instanceof Function)) toss3("Missing required exports[",key,"] function.");
}
{
// Set up allocators...
const keyAlloc = config.allocExportName,
keyDealloc = config.deallocExportName,
keyRealloc = config.reallocExportName;
for(const key of [keyAlloc, keyDealloc, keyRealloc]){
const f = wasm.exports[key];
if(!(f instanceof Function)) toss3("Missing required exports[",key,"] function.");
}
wasm.alloc = function f(n){
const m = f.impl(n);
if(!m) throw new WasmAllocError("Failed to allocate",n," bytes.");
return m;
};
wasm.alloc.impl = wasm.exports[keyAlloc];
wasm.dealloc = wasm.exports[keyDealloc];
wasm.alloc = function f(n){
const m = f.impl(n);
if(!m) throw new WasmAllocError("Failed to allocate",n," bytes.");
return m;
};
wasm.alloc.impl = wasm.exports[keyAlloc];
wasm.realloc = function f(m,n){
const m2 = f.impl(m,n);
if(n && !m2) throw new WasmAllocError("Failed to reallocate",n," bytes.");
return n ? m2 : 0;
};
wasm.realloc.impl = wasm.exports[keyRealloc];
wasm.dealloc = wasm.exports[keyDealloc];
}
/**
Reports info about compile-time options using