aboutsummaryrefslogtreecommitdiff
path: root/ext/wasm/api/sqlite3-api-prologue.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/wasm/api/sqlite3-api-prologue.js')
-rw-r--r--ext/wasm/api/sqlite3-api-prologue.js139
1 files changed, 116 insertions, 23 deletions
diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js
index 6c50e99b0..7804c0458 100644
--- a/ext/wasm/api/sqlite3-api-prologue.js
+++ b/ext/wasm/api/sqlite3-api-prologue.js
@@ -321,14 +321,17 @@ 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 a potential TODO just waiting on a use case
- to justify them.
+ Returns v if v appears to be one of our bind()-able TypedArray
+ types: Uint8Array or Int8Array or ArrayBuffer. Support for
+ TypedArrays with element sizes >1 is a potential TODO just
+ waiting on a use case to justify them. Until then, their `buffer`
+ property can be used to pass them as an ArrayBuffer. If it's not
+ a bindable array type, a falsy value is returned.
*/
const isBindableTypedArray = (v)=>{
- return v && (v instanceof Uint8Array || v instanceof Int8Array);
- //v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
+ return v && (v instanceof Uint8Array
+ || v instanceof Int8Array
+ || v instanceof ArrayBuffer);
};
/**
@@ -341,8 +344,9 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
isSQLableTypedArray() list.
*/
const isSQLableTypedArray = (v)=>{
- return v && (v instanceof Uint8Array || v instanceof Int8Array);
- //v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
+ return v && (v instanceof Uint8Array
+ || v instanceof Int8Array
+ || v instanceof ArrayBuffer);
};
/** Returns true if isBindableTypedArray(v) does, else throws with a message
@@ -401,6 +405,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
}else{
super("Allocation failed.");
}
+ this.resultCode = capi.SQLITE_NOMEM;
this.name = 'WasmAllocError';
}
};
@@ -418,6 +423,92 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
Object.assign(capi, {
/**
+ sqlite3_bind_blob() works exactly like its C counterpart unless
+ its 3rd argument is one of:
+
+ - JS string: the 3rd argument is converted to a C string, the
+ 4th argument is ignored, and the C-string's length is used
+ in its place.
+
+ - Array: converted to a string as defined for "flexible
+ strings" and then it's treated as a JS string.
+
+ - Int8Array or Uint8Array: wasm.allocFromTypedArray() is used to
+ conver the memory to the WASM heap. If the 4th argument is
+ 0 or greater, it is used as-is, otherwise the array's byteLength
+ value is used. This is an exception to the C API's undefined
+ behavior for a negative 4th argument, but results are undefined
+ if the given 4th argument value is greater than the byteLength
+ of the input array.
+
+ - If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
+ treated as that type.
+
+ In all of those cases, the final argument (destructor) is
+ ignored and capi.SQLITE_WASM_DEALLOC is assumed.
+
+ A 3rd argument of `null` is treated as if it were a WASM pointer
+ of 0.
+
+ If the 3rd argument is neither a WASM pointer nor one of the
+ above-described types, capi.SQLITE_MISUSE is returned.
+
+ The first argument may be either an `sqlite3_stmt*` WASM
+ pointer or an sqlite3.oo1.Stmt instance.
+
+ For consistency with the C API, it requires the same number of
+ arguments. It returns capi.SQLITE_MISUSE if passed any other
+ argument count.
+ */
+ sqlite3_bind_blob: undefined/*installed later*/,
+
+ /**
+ sqlite3_bind_text() works exactly like its C counterpart unless
+ its 3rd argument is one of:
+
+ - JS string: the 3rd argument is converted to a C string, the
+ 4th argument is ignored, and the C-string's length is used
+ in its place.
+
+ - Array: converted to a string as defined for "flexible
+ strings". The 4th argument is ignored and a value of -1
+ is assumed.
+
+ - Int8Array or Uint8Array: is assumed to contain UTF-8 text, is
+ converted to a string. The 4th argument is ignored, replaced
+ by the array's byteLength value.
+
+ - If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
+ treated as that type.
+
+ In each of those cases, the final argument (text destructor) is
+ ignored and capi.SQLITE_WASM_DEALLOC is assumed.
+
+ A 3rd argument of `null` is treated as if it were a WASM pointer
+ of 0.
+
+ If the 3rd argument is neither a WASM pointer nor one of the
+ above-described types, capi.SQLITE_MISUSE is returned.
+
+ The first argument may be either an `sqlite3_stmt*` WASM
+ pointer or an sqlite3.oo1.Stmt instance.
+
+ For consistency with the C API, it requires the same number of
+ arguments. It returns capi.SQLITE_MISUSE if passed any other
+ argument count.
+
+ If client code needs to bind partial strings, it needs to
+ either parcel the string up before passing it in here or it
+ must pass in a WASM pointer for the 3rd argument and a valid
+ 4th-argument value, taking care not to pass a value which
+ truncates a multi-byte UTF-8 character. When passing
+ WASM-format strings, it is important that the final argument be
+ valid or unexpected content can result can result, or even a
+ crash if the application reads past the WASM heap bounds.
+ */
+ sqlite3_bind_text: undefined/*installed later*/,
+
+ /**
sqlite3_create_function_v2() differs from its native
counterpart only in the following ways:
@@ -525,18 +616,18 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
WASM build is compiled with emcc's `-sALLOW_TABLE_GROWTH`
flag.
*/
- sqlite3_create_function_v2: function(
+ sqlite3_create_function_v2: (
pDb, funcName, nArg, eTextRep, pApp,
xFunc, xStep, xFinal, xDestroy
- ){/*installed later*/},
+ )=>{/*installed later*/},
/**
Equivalent to passing the same arguments to
sqlite3_create_function_v2(), with 0 as the final argument.
*/
- sqlite3_create_function:function(
+ sqlite3_create_function: (
pDb, funcName, nArg, eTextRep, pApp,
xFunc, xStep, xFinal
- ){/*installed later*/},
+ )=>{/*installed later*/},
/**
The sqlite3_create_window_function() JS wrapper differs from
its native implementation in the exact same way that
@@ -544,10 +635,10 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
xInverse(), is treated identically to xStep() by the wrapping
layer.
*/
- sqlite3_create_window_function: function(
+ sqlite3_create_window_function: (
pDb, funcName, nArg, eTextRep, pApp,
xStep, xFinal, xValue, xInverse, xDestroy
- ){/*installed later*/},
+ )=>{/*installed later*/},
/**
The sqlite3_prepare_v3() binding handles two different uses
with differing JS/WASM semantics:
@@ -669,7 +760,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
toss3,
typedArrayPart
};
-
+
Object.assign(wasm, {
/**
Emscripten APIs have a deep-seated assumption that all pointers
@@ -858,7 +949,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
const m = f._rx.exec(opt);
rv[0] = (m ? m[1] : opt);
rv[1] = m ? (f._rxInt.test(m[2]) ? +m[2] : m[2]) : true;
- };
+ };
}
const rc = {}, ov = [0,0];
let i = 0, k;
@@ -1559,7 +1650,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
capi.sqlite3_result_error(pCtx, ''+e, -1);
}
};
-
+
/**
This function passes its 2nd argument to one of the
sqlite3_result_xyz() routines, depending on the type of that
@@ -1575,7 +1666,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
- `bigint`: similar to `number` but will trigger an error if the
value is too big to store in an int64.
- `string`: `sqlite3_result_text()`
- - Uint8Array or Int8Array: `sqlite3_result_blob()`
+ - Uint8Array or Int8Array or ArrayBuffer: `sqlite3_result_blob()`
- `undefined`: is a no-op provided to simplify certain use cases.
Anything else triggers `sqlite3_result_error()` with a
@@ -1626,9 +1717,11 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
f(pCtx, val);
break;
}
- case 'string':
- capi.sqlite3_result_text(pCtx, val, -1, capi.SQLITE_TRANSIENT);
+ case 'string': {
+ const [p, n] = wasm.allocCString(val,true);
+ capi.sqlite3_result_text(pCtx, p, n, capi.SQLITE_WASM_DEALLOC);
break;
+ }
case 'object':
if(null===val/*yes, typeof null === 'object'*/) {
capi.sqlite3_result_null(pCtx);
@@ -1637,7 +1730,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
const pBlob = wasm.allocFromTypedArray(val);
capi.sqlite3_result_blob(
pCtx, pBlob, val.byteLength,
- wasm.exports[sqlite3.config.deallocExportName]
+ capi.SQLITE_WASM_DEALLOC
);
break;
}
@@ -1657,8 +1750,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
argument of sqlite3_value_to_js(). If the sqlite3_column_value()
returns NULL (e.g. because the column index is out of range),
this function returns `undefined`, regardless of the 3rd
- argument. 3rd argument is falsy and conversion fails, `undefined`
- will be returned.
+ argument. If the 3rd argument is falsy and conversion fails,
+ `undefined` will be returned.
Note that sqlite3_column_value() returns an "unprotected" value
object, but in a single-threaded environment (like this one)