diff options
Diffstat (limited to 'ext/wasm/api/sqlite3-api-prologue.js')
-rw-r--r-- | ext/wasm/api/sqlite3-api-prologue.js | 139 |
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) |