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:
@ -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
|
||||
|
Reference in New Issue
Block a user