4 The author disclaims copyright to this source code. In place of a
5 legal notice, here is a blessing:
7 * May you do good and not evil.
8 * May you find forgiveness for yourself and forgive others.
9 * May you share freely, never taking more than you give.
11 ***********************************************************************
13 This file glues together disparate pieces of JS which are loaded in
14 previous steps of the sqlite3-api.js bootstrapping process:
15 sqlite3-api-prologue.js, whwasmutil.js, and jaccwabyt.js. It
16 initializes the main API pieces so that the downstream components
17 (e.g. sqlite3-api-oo1.js) have all that they need.
19 self
.sqlite3ApiBootstrap
.initializers
.push(function(sqlite3
){
21 const toss
= (...args
)=>{throw new Error(args
.join(' '))};
22 const toss3
= sqlite3
.SQLite3Error
.toss
;
23 const capi
= sqlite3
.capi
, wasm
= sqlite3
.wasm
, util
= sqlite3
.util
;
24 self
.WhWasmUtilInstaller(wasm
);
25 delete self
.WhWasmUtilInstaller
;
29 Please keep this block around as a maintenance reminder
30 that we cannot rely on this type of check.
32 This block fails on Safari, per a report at
33 https://sqlite.org/forum/forumpost/e5b20e1feb.
35 It turns out that what Safari serves from the indirect function
36 table (e.g. wasm.functionEntry(X)) is anonymous functions which
37 wrap the WASM functions, rather than returning the WASM
38 functions themselves. That means comparison of such functions
39 is useless for determining whether or not we have a specific
40 function from wasm.exports. i.e. if function X is indirection
41 function table entry N then wasm.exports.X is not equal to
42 wasm.functionEntry(N) in Safari, despite being so in the other
46 Find a mapping for SQLITE_WASM_DEALLOC, which the API
47 guarantees is a WASM pointer to the same underlying function as
48 wasm.dealloc() (noting that wasm.dealloc() is permitted to be a
49 JS wrapper around the WASM function). There is unfortunately no
50 O(1) algorithm for finding this pointer: we have to walk the
51 WASM indirect function table to find it. However, experience
52 indicates that that particular function is always very close to
53 the front of the table (it's been entry #3 in all relevant
56 const dealloc
= wasm
.exports
[sqlite3
.config
.deallocExportName
];
57 const nFunc
= wasm
.functionTable().length
;
59 for(i
= 0; i
< nFunc
; ++i
){
60 const e
= wasm
.functionEntry(i
);
62 capi
.SQLITE_WASM_DEALLOC
= i
;
66 if(dealloc
!== wasm
.functionEntry(capi
.SQLITE_WASM_DEALLOC
)){
67 toss("Internal error: cannot find function pointer for SQLITE_WASM_DEALLOC.");
72 Signatures for the WASM-exported C-side functions. Each entry
73 is an array with 2+ elements:
76 "result type" (wasm.xWrap() syntax),
77 [arg types in xWrap() syntax]
78 // ^^^ this needn't strictly be an array: it can be subsequent
79 // elements instead: [x,y,z] is equivalent to x,y,z
82 Note that support for the API-specific data types in the
83 result/argument type strings gets plugged in at a later phase in
84 the API initialization process.
86 wasm
.bindingSignatures
= [
87 // Please keep these sorted by function name!
88 ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
89 /* sqlite3_auto_extension() has a hand-written binding. */
90 /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written
91 bindings to permit more flexible inputs. */
92 ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"],
93 ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"],
94 ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"],
95 ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"],
96 ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"],
97 ["sqlite3_bind_pointer", "int",
98 "sqlite3_stmt*", "int", "*", "string:static", "*"],
99 ["sqlite3_busy_handler","int", [
101 new wasm
.xWrap
.FuncPtrAdapter({
103 contextKey
: (argv
,argIndex
)=>argv
[0/* sqlite3* */]
107 ["sqlite3_busy_timeout","int", "sqlite3*", "int"],
108 /* sqlite3_cancel_auto_extension() has a hand-written binding. */
109 /* sqlite3_close_v2() is implemented by hand to perform some
111 ["sqlite3_changes", "int", "sqlite3*"],
112 ["sqlite3_clear_bindings","int", "sqlite3_stmt*"],
113 ["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/],
114 ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"],
115 ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"],
116 ["sqlite3_column_count", "int", "sqlite3_stmt*"],
117 ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"],
118 ["sqlite3_column_int","int", "sqlite3_stmt*", "int"],
119 ["sqlite3_column_name","string", "sqlite3_stmt*", "int"],
120 ["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
121 ["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
122 ["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
123 ["sqlite3_commit_hook", "void*", [
125 new wasm
.xWrap
.FuncPtrAdapter({
126 name
: 'sqlite3_commit_hook',
128 contextKey
: (argv
)=>argv
[0/* sqlite3* */]
132 ["sqlite3_compileoption_get", "string", "int"],
133 ["sqlite3_compileoption_used", "int", "string"],
134 ["sqlite3_complete", "int", "string:flexible"],
135 ["sqlite3_context_db_handle", "sqlite3*", "sqlite3_context*"],
137 /* sqlite3_create_function(), sqlite3_create_function_v2(), and
138 sqlite3_create_window_function() use hand-written bindings to
139 simplify handling of their function-type arguments. */
140 /* sqlite3_create_collation() and sqlite3_create_collation_v2()
141 use hand-written bindings to simplify passing of the callback
143 ["sqlite3_create_collation", "int",
144 "sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
146 ["sqlite3_create_collation_v2", "int",
147 "sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
150 ["sqlite3_data_count", "int", "sqlite3_stmt*"],
151 ["sqlite3_db_filename", "string", "sqlite3*", "string"],
152 ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],
153 ["sqlite3_db_name", "string", "sqlite3*", "int"],
154 ["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"],
155 ["sqlite3_errcode", "int", "sqlite3*"],
156 ["sqlite3_errmsg", "string", "sqlite3*"],
157 ["sqlite3_error_offset", "int", "sqlite3*"],
158 ["sqlite3_errstr", "string", "int"],
159 ["sqlite3_exec", "int", [
160 "sqlite3*", "string:flexible",
161 new wasm
.xWrap
.FuncPtrAdapter({
162 signature
: 'i(pipp)',
163 bindScope
: 'transient',
164 callProxy
: (callback
)=>{
166 return (pVoid
, nCols
, pColVals
, pColNames
)=>{
168 const aVals
= wasm
.cArgvToJs(nCols
, pColVals
);
169 if(!aNames
) aNames
= wasm
.cArgvToJs(nCols
, pColNames
);
170 return callback(aVals
, aNames
) | 0;
172 /* If we set the db error state here, the higher-level
173 exec() call replaces it with its own, so we have no way
174 of reporting the exception message except the console. We
175 must not propagate exceptions through the C API. Though
176 we make an effort to report OOM here, sqlite3_exec()
177 translates that into SQLITE_ABORT as well. */
178 return e
.resultCode
|| capi
.SQLITE_ERROR
;
185 ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"],
186 ["sqlite3_extended_errcode", "int", "sqlite3*"],
187 ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"],
188 ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"],
189 ["sqlite3_finalize", "int", "sqlite3_stmt*"],
190 ["sqlite3_free", undefined,"*"],
191 ["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"],
192 ["sqlite3_initialize", undefined],
193 /*["sqlite3_interrupt", undefined, "sqlite3*"
194 ^^^ we cannot actually currently support this because JS is
195 single-threaded and we don't have a portable way to access a DB
196 from 2 SharedWorkers concurrently. ],*/
197 ["sqlite3_keyword_count", "int"],
198 ["sqlite3_keyword_name", "int", ["int", "**", "*"]],
199 ["sqlite3_keyword_check", "int", ["string", "int"]],
200 ["sqlite3_libversion", "string"],
201 ["sqlite3_libversion_number", "int"],
202 ["sqlite3_limit", "int", ["sqlite3*", "int", "int"]],
203 ["sqlite3_malloc", "*","int"],
204 ["sqlite3_open", "int", "string", "*"],
205 ["sqlite3_open_v2", "int", "string", "*", "int", "string"],
206 /* sqlite3_prepare_v2() and sqlite3_prepare_v3() are handled
207 separately due to us requiring two different sets of semantics
208 for those, depending on how their SQL argument is provided. */
209 /* sqlite3_randomness() uses a hand-written wrapper to extend
210 the range of supported argument types. */
211 ["sqlite3_progress_handler", undefined, [
212 "sqlite3*", "int", new wasm
.xWrap
.FuncPtrAdapter({
213 name
: 'xProgressHandler',
215 bindScope
: 'context',
216 contextKey
: (argv
,argIndex
)=>argv
[0/* sqlite3* */]
219 ["sqlite3_realloc", "*","*","int"],
220 ["sqlite3_reset", "int", "sqlite3_stmt*"],
221 /* sqlite3_reset_auto_extension() has a hand-written binding. */
222 ["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"],
223 ["sqlite3_result_double", undefined, "sqlite3_context*", "f64"],
224 ["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"],
225 ["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"],
226 ["sqlite3_result_error_nomem", undefined, "sqlite3_context*"],
227 ["sqlite3_result_error_toobig", undefined, "sqlite3_context*"],
228 ["sqlite3_result_int", undefined, "sqlite3_context*", "int"],
229 ["sqlite3_result_null", undefined, "sqlite3_context*"],
230 ["sqlite3_result_pointer", undefined,
231 "sqlite3_context*", "*", "string:static", "*"],
232 ["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
233 ["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
234 ["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
235 ["sqlite3_rollback_hook", "void*", [
237 new wasm
.xWrap
.FuncPtrAdapter({
238 name
: 'sqlite3_rollback_hook',
240 contextKey
: (argv
)=>argv
[0/* sqlite3* */]
244 ["sqlite3_set_authorizer", "int", [
246 new wasm
.xWrap
.FuncPtrAdapter({
247 name
: "sqlite3_set_authorizer::xAuth",
248 signature
: "i(pi"+"ssss)",
249 contextKey
: (argv
, argIndex
)=>argv
[0/*(sqlite3*)*/],
250 callProxy
: (callback
)=>{
251 return (pV
, iCode
, s0
, s1
, s2
, s3
)=>{
253 s0
= s0
&& wasm
.cstrToJs(s0
); s1
= s1
&& wasm
.cstrToJs(s1
);
254 s2
= s2
&& wasm
.cstrToJs(s2
); s3
= s3
&& wasm
.cstrToJs(s3
);
255 return callback(pV
, iCode
, s0
, s1
, s2
, s3
) || 0;
257 return e
.resultCode
|| capi
.SQLITE_ERROR
;
264 ["sqlite3_set_auxdata", undefined, [
265 "sqlite3_context*", "int", "*",
266 new wasm
.xWrap
.FuncPtrAdapter({
267 name
: 'xDestroyAuxData',
269 contextKey
: (argv
, argIndex
)=>argv
[0/* sqlite3_context* */]
272 ["sqlite3_shutdown", undefined],
273 ["sqlite3_sourceid", "string"],
274 ["sqlite3_sql", "string", "sqlite3_stmt*"],
275 ["sqlite3_status", "int", "int", "*", "*", "int"],
276 ["sqlite3_step", "int", "sqlite3_stmt*"],
277 ["sqlite3_stmt_isexplain", "int", ["sqlite3_stmt*"]],
278 ["sqlite3_stmt_readonly", "int", ["sqlite3_stmt*"]],
279 ["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"],
280 ["sqlite3_strglob", "int", "string","string"],
281 ["sqlite3_stricmp", "int", "string", "string"],
282 ["sqlite3_strlike", "int", "string", "string","int"],
283 ["sqlite3_strnicmp", "int", "string", "string", "int"],
284 ["sqlite3_table_column_metadata", "int",
285 "sqlite3*", "string", "string", "string",
286 "**", "**", "*", "*", "*"],
287 ["sqlite3_total_changes", "int", "sqlite3*"],
288 ["sqlite3_trace_v2", "int", [
290 new wasm
.xWrap
.FuncPtrAdapter({
291 name
: 'sqlite3_trace_v2::callback',
292 signature
: 'i(ippp)',
293 contextKey
: (argv
,argIndex
)=>argv
[0/* sqlite3* */]
297 ["sqlite3_txn_state", "int", ["sqlite3*","string"]],
298 /* Note that sqlite3_uri_...() have very specific requirements for
299 their first C-string arguments, so we cannot perform any value
300 conversion on those. */
301 ["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"],
302 ["sqlite3_uri_key", "string", "sqlite3_filename", "int"],
303 ["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"],
304 ["sqlite3_user_data","void*", "sqlite3_context*"],
305 ["sqlite3_value_blob", "*", "sqlite3_value*"],
306 ["sqlite3_value_bytes","int", "sqlite3_value*"],
307 ["sqlite3_value_double","f64", "sqlite3_value*"],
308 ["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"],
309 ["sqlite3_value_free", undefined, "sqlite3_value*"],
310 ["sqlite3_value_frombind", "int", "sqlite3_value*"],
311 ["sqlite3_value_int","int", "sqlite3_value*"],
312 ["sqlite3_value_nochange", "int", "sqlite3_value*"],
313 ["sqlite3_value_numeric_type", "int", "sqlite3_value*"],
314 ["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"],
315 ["sqlite3_value_subtype", "int", "sqlite3_value*"],
316 ["sqlite3_value_text", "string", "sqlite3_value*"],
317 ["sqlite3_value_type", "int", "sqlite3_value*"],
318 ["sqlite3_vfs_find", "*", "string"],
319 ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"],
320 ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"]
321 ]/*wasm.bindingSignatures*/;
323 if(false && wasm
.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
324 /* ^^^ "the problem" is that this is an option feature and the
325 build-time function-export list does not currently take
326 optional features into account. */
327 wasm
.bindingSignatures
.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
331 Functions which require BigInt (int64) support are separated from
332 the others because we need to conditionally bind them or apply
333 dummy impls, depending on the capabilities of the environment.
335 Note that not all of these functions directly require int64
336 but are only for use with APIs which require int64. For example,
337 the vtab-related functions.
339 wasm
.bindingSignatures
.int64
= [
340 ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
341 ["sqlite3_changes64","i64", ["sqlite3*"]],
342 ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
343 ["sqlite3_create_module", "int",
344 ["sqlite3*","string","sqlite3_module*","*"]],
345 ["sqlite3_create_module_v2", "int",
346 ["sqlite3*","string","sqlite3_module*","*","*"]],
347 ["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]],
348 ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"]
349 /* Careful! Short version: de/serialize() are problematic because they
350 might use a different allocator than the user for managing the
351 deserialized block. de/serialize() are ONLY safe to use with
352 sqlite3_malloc(), sqlite3_free(), and its 64-bit variants. */,
353 ["sqlite3_drop_modules", "int", ["sqlite3*", "**"]],
354 ["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]],
355 ["sqlite3_malloc64", "*","i64"],
356 ["sqlite3_msize", "i64", "*"],
357 ["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
358 ["sqlite3_preupdate_blobwrite", "int", "sqlite3*"],
359 ["sqlite3_preupdate_count", "int", "sqlite3*"],
360 ["sqlite3_preupdate_depth", "int", "sqlite3*"],
361 ["sqlite3_preupdate_hook", "*", [
363 new wasm
.xWrap
.FuncPtrAdapter({
364 name
: 'sqlite3_preupdate_hook',
365 signature
: "v(ppippjj)",
366 contextKey
: (argv
)=>argv
[0/* sqlite3* */],
367 callProxy
: (callback
)=>{
368 return (p
,db
,op
,zDb
,zTbl
,iKey1
,iKey2
)=>{
369 callback(p
, db
, op
, wasm
.cstrToJs(zDb
), wasm
.cstrToJs(zTbl
),
376 ["sqlite3_preupdate_new", "int", ["sqlite3*", "int", "**"]],
377 ["sqlite3_preupdate_old", "int", ["sqlite3*", "int", "**"]],
378 ["sqlite3_realloc64", "*","*", "i64"],
379 ["sqlite3_result_int64", undefined, "*", "i64"],
380 ["sqlite3_result_zeroblob64", "int", "*", "i64"],
381 ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"],
382 ["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
383 ["sqlite3_status64", "int", "int", "*", "*", "int"],
384 ["sqlite3_total_changes64", "i64", ["sqlite3*"]],
385 ["sqlite3_update_hook", "*", [
387 new wasm
.xWrap
.FuncPtrAdapter({
388 name
: 'sqlite3_update_hook',
389 signature
: "v(iippj)",
390 contextKey
: (argv
)=>argv
[0/* sqlite3* */],
391 callProxy
: (callback
)=>{
392 return (p
,op
,z0
,z1
,rowid
)=>{
393 callback(p
, op
, wasm
.cstrToJs(z0
), wasm
.cstrToJs(z1
), rowid
);
399 ["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
400 ["sqlite3_value_int64","i64", "sqlite3_value*"],
401 ["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
402 ["sqlite3_vtab_distinct","int", "sqlite3_index_info*"],
403 ["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"],
404 ["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"],
405 ["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"],
406 /*["sqlite3_vtab_config" is variadic and requires a hand-written
408 ["sqlite3_vtab_nochange","int", "sqlite3_context*"],
409 ["sqlite3_vtab_on_conflict","int", "sqlite3*"],
410 ["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"]
413 // Add session/changeset APIs...
414 if(wasm
.bigIntEnabled
&& !!wasm
.exports
.sqlite3changegroup_add
){
415 /* ACHTUNG: 2022-12-23: the session/changeset API bindings are
416 COMPLETELY UNTESTED. */
418 FuncPtrAdapter options for session-related callbacks with the
419 native signature "i(ps)". This proxy converts the 2nd argument
420 from a C string to a JS string before passing the arguments on
421 to the client-provided JS callback.
425 callProxy
:(callback
)=>{
427 try{return callback(p
, wasm
.cstrToJs(s
)) | 0}
428 catch(e
){return e
.resultCode
|| capi
.SQLITE_ERROR
}
433 wasm
.bindingSignatures
.int64
.push(...[
434 ['sqlite3changegroup_add', 'int', ['sqlite3_changegroup*', 'int', 'void*']],
435 ['sqlite3changegroup_add_strm', 'int', [
436 'sqlite3_changegroup*',
437 new wasm
.xWrap
.FuncPtrAdapter({
438 name
: 'xInput', signature
: 'i(ppp)', bindScope
: 'transient'
442 ['sqlite3changegroup_delete', undefined, ['sqlite3_changegroup*']],
443 ['sqlite3changegroup_new', 'int', ['**']],
444 ['sqlite3changegroup_output', 'int', ['sqlite3_changegroup*', 'int*', '**']],
445 ['sqlite3changegroup_output_strm', 'int', [
446 'sqlite3_changegroup*',
447 new wasm
.xWrap
.FuncPtrAdapter({
448 name
: 'xOutput', signature
: 'i(ppi)', bindScope
: 'transient'
452 ['sqlite3changeset_apply', 'int', [
453 'sqlite3*', 'int', 'void*',
454 new wasm
.xWrap
.FuncPtrAdapter({
455 name
: 'xFilter', bindScope
: 'transient', ...__ipsProxy
457 new wasm
.xWrap
.FuncPtrAdapter({
458 name
: 'xConflict', signature
: 'i(pip)', bindScope
: 'transient'
462 ['sqlite3changeset_apply_strm', 'int', [
464 new wasm
.xWrap
.FuncPtrAdapter({
465 name
: 'xInput', signature
: 'i(ppp)', bindScope
: 'transient'
468 new wasm
.xWrap
.FuncPtrAdapter({
469 name
: 'xFilter', bindScope
: 'transient', ...__ipsProxy
471 new wasm
.xWrap
.FuncPtrAdapter({
472 name
: 'xConflict', signature
: 'i(pip)', bindScope
: 'transient'
476 ['sqlite3changeset_apply_v2', 'int', [
477 'sqlite3*', 'int', 'void*',
478 new wasm
.xWrap
.FuncPtrAdapter({
479 name
: 'xFilter', bindScope
: 'transient', ...__ipsProxy
481 new wasm
.xWrap
.FuncPtrAdapter({
482 name
: 'xConflict', signature
: 'i(pip)', bindScope
: 'transient'
484 'void*', '**', 'int*', 'int'
487 ['sqlite3changeset_apply_v2_strm', 'int', [
489 new wasm
.xWrap
.FuncPtrAdapter({
490 name
: 'xInput', signature
: 'i(ppp)', bindScope
: 'transient'
493 new wasm
.xWrap
.FuncPtrAdapter({
494 name
: 'xFilter', bindScope
: 'transient', ...__ipsProxy
496 new wasm
.xWrap
.FuncPtrAdapter({
497 name
: 'xConflict', signature
: 'i(pip)', bindScope
: 'transient'
499 'void*', '**', 'int*', 'int'
501 ['sqlite3changeset_concat', 'int', ['int','void*', 'int', 'void*', 'int*', '**']],
502 ['sqlite3changeset_concat_strm', 'int', [
503 new wasm
.xWrap
.FuncPtrAdapter({
504 name
: 'xInputA', signature
: 'i(ppp)', bindScope
: 'transient'
507 new wasm
.xWrap
.FuncPtrAdapter({
508 name
: 'xInputB', signature
: 'i(ppp)', bindScope
: 'transient'
511 new wasm
.xWrap
.FuncPtrAdapter({
512 name
: 'xOutput', signature
: 'i(ppi)', bindScope
: 'transient'
516 ['sqlite3changeset_conflict', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
517 ['sqlite3changeset_finalize', 'int', ['sqlite3_changeset_iter*']],
518 ['sqlite3changeset_fk_conflicts', 'int', ['sqlite3_changeset_iter*', 'int*']],
519 ['sqlite3changeset_invert', 'int', ['int', 'void*', 'int*', '**']],
520 ['sqlite3changeset_invert_strm', 'int', [
521 new wasm
.xWrap
.FuncPtrAdapter({
522 name
: 'xInput', signature
: 'i(ppp)', bindScope
: 'transient'
525 new wasm
.xWrap
.FuncPtrAdapter({
526 name
: 'xOutput', signature
: 'i(ppi)', bindScope
: 'transient'
530 ['sqlite3changeset_new', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
531 ['sqlite3changeset_next', 'int', ['sqlite3_changeset_iter*']],
532 ['sqlite3changeset_old', 'int', ['sqlite3_changeset_iter*', 'int', '**']],
533 ['sqlite3changeset_op', 'int', [
534 'sqlite3_changeset_iter*', '**', 'int*', 'int*','int*'
536 ['sqlite3changeset_pk', 'int', ['sqlite3_changeset_iter*', '**', 'int*']],
537 ['sqlite3changeset_start', 'int', ['**', 'int', '*']],
538 ['sqlite3changeset_start_strm', 'int', [
540 new wasm
.xWrap
.FuncPtrAdapter({
541 name
: 'xInput', signature
: 'i(ppp)', bindScope
: 'transient'
545 ['sqlite3changeset_start_v2', 'int', ['**', 'int', '*', 'int']],
546 ['sqlite3changeset_start_v2_strm', 'int', [
548 new wasm
.xWrap
.FuncPtrAdapter({
549 name
: 'xInput', signature
: 'i(ppp)', bindScope
: 'transient'
553 ['sqlite3session_attach', 'int', ['sqlite3_session*', 'string']],
554 ['sqlite3session_changeset', 'int', ['sqlite3_session*', 'int*', '**']],
555 ['sqlite3session_changeset_size', 'i64', ['sqlite3_session*']],
556 ['sqlite3session_changeset_strm', 'int', [
558 new wasm
.xWrap
.FuncPtrAdapter({
559 name
: 'xOutput', signature
: 'i(ppp)', bindScope
: 'transient'
563 ['sqlite3session_config', 'int', ['int', 'void*']],
564 ['sqlite3session_create', 'int', ['sqlite3*', 'string', '**']],
565 //sqlite3session_delete() is bound manually
566 ['sqlite3session_diff', 'int', ['sqlite3_session*', 'string', 'string', '**']],
567 ['sqlite3session_enable', 'int', ['sqlite3_session*', 'int']],
568 ['sqlite3session_indirect', 'int', ['sqlite3_session*', 'int']],
569 ['sqlite3session_isempty', 'int', ['sqlite3_session*']],
570 ['sqlite3session_memory_used', 'i64', ['sqlite3_session*']],
571 ['sqlite3session_object_config', 'int', ['sqlite3_session*', 'int', 'void*']],
572 ['sqlite3session_patchset', 'int', ['sqlite3_session*', '*', '**']],
573 ['sqlite3session_patchset_strm', 'int', [
575 new wasm
.xWrap
.FuncPtrAdapter({
576 name
: 'xOutput', signature
: 'i(ppp)', bindScope
: 'transient'
580 ['sqlite3session_table_filter', undefined, [
582 new wasm
.xWrap
.FuncPtrAdapter({
583 name
: 'xFilter', ...__ipsProxy
,
584 contextKey
: (argv
,argIndex
)=>argv
[0/* (sqlite3_session*) */]
589 }/*session/changeset APIs*/
592 Functions which are intended solely for API-internal use by the
593 WASM components, not client code. These get installed into
594 sqlite3.wasm. Some of them get exposed to clients via variants
595 named sqlite3_js_...().
597 wasm
.bindingSignatures
.wasm
= [
598 ["sqlite3_wasm_db_reset", "int", "sqlite3*"],
599 ["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"],
600 ["sqlite3_wasm_vfs_create_file", "int",
601 "sqlite3_vfs*","string","*", "int"],
602 ["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
606 Install JS<->C struct bindings for the non-opaque struct types we
608 sqlite3
.StructBinder
= self
.Jaccwabyt({
609 heap
: 0 ? wasm
.memory
: wasm
.heap8u
,
611 dealloc
: wasm
.dealloc
,
612 bigIntEnabled
: wasm
.bigIntEnabled
,
613 memberPrefix
: /* Never change this: this prefix is baked into any
614 amount of code and client-facing docs. */ '$'
616 delete self
.Jaccwabyt
;
618 {// wasm.xWrap() bindings...
620 /* Convert Arrays and certain TypedArrays to strings for
621 'string:flexible'-type arguments */
622 const __xString
= wasm
.xWrap
.argAdapter('string');
623 wasm
.xWrap
.argAdapter(
624 'string:flexible', (v
)=>__xString(util
.flexibleString(v
))
628 The 'string:static' argument adapter treats its argument as
631 - WASM pointer: assumed to be a long-lived C-string which gets
634 - Anything else: gets coerced to a JS string for use as a map
635 key. If a matching entry is found (as described next), it is
636 returned, else wasm.allocCString() is used to create a a new
637 string, map its pointer to (''+v) for the remainder of the
638 application's life, and returns that pointer value for this
639 call and all future calls which are passed a
640 string-equivalent argument.
642 Use case: sqlite3_bind_pointer() and sqlite3_result_pointer()
643 call for "a static string and preferably a string
644 literal". This converter is used to ensure that the string
645 value seen by those functions is long-lived and behaves as they
648 wasm
.xWrap
.argAdapter(
651 if(wasm
.isPtr(v
)) return v
;
654 return rc
|| (this[v
] = wasm
.allocCString(v
));
655 }.bind(Object
.create(null))
659 Add some descriptive xWrap() aliases for '*' intended to (A)
660 initially improve readability/correctness of
661 wasm.bindingSignatures and (B) provide automatic conversion
662 from higher-level representations, e.g. capi.sqlite3_vfs to
663 `sqlite3_vfs*` via capi.sqlite3_vfs.pointer.
665 const __xArgPtr
= wasm
.xWrap
.argAdapter('*');
666 const nilType = function(){}/*a class no value can ever be an instance of*/;
667 wasm
.xWrap
.argAdapter('sqlite3_filename', __xArgPtr
)
668 ('sqlite3_context*', __xArgPtr
)
669 ('sqlite3_value*', __xArgPtr
)
671 ('sqlite3_changegroup*', __xArgPtr
)
672 ('sqlite3_changeset_iter*', __xArgPtr
)
673 //('sqlite3_rebaser*', __xArgPtr)
674 ('sqlite3_session*', __xArgPtr
)
675 ('sqlite3_stmt*', (v
)=>
676 __xArgPtr((v
instanceof (sqlite3
?.oo1
?.Stmt
|| nilType
))
679 __xArgPtr((v
instanceof (sqlite3
?.oo1
?.DB
|| nilType
))
681 ('sqlite3_index_info*', (v
)=>
682 __xArgPtr((v
instanceof (capi
.sqlite3_index_info
|| nilType
))
684 ('sqlite3_module*', (v
)=>
685 __xArgPtr((v
instanceof (capi
.sqlite3_module
|| nilType
))
690 - v is-a string: use the result of sqlite3_vfs_find(v) but
691 throw if it returns 0.
692 - v is-a capi.sqlite3_vfs: use v.pointer.
693 - Else return the same as the `'*'` argument conversion.
695 ('sqlite3_vfs*', (v
)=>{
696 if('string'===typeof v
){
697 /* A NULL sqlite3_vfs pointer will be treated as the default
698 VFS in many contexts. We specifically do not want that
700 return capi
.sqlite3_vfs_find(v
)
701 || sqlite3
.SQLite3Error
.toss(
702 capi
.SQLITE_NOTFOUND
,
703 "Unknown sqlite3_vfs name:", v
706 return __xArgPtr((v
instanceof (capi
.sqlite3_vfs
|| nilType
))
710 const __xRcPtr
= wasm
.xWrap
.resultAdapter('*');
711 wasm
.xWrap
.resultAdapter('sqlite3*', __xRcPtr
)
712 ('sqlite3_context*', __xRcPtr
)
713 ('sqlite3_stmt*', __xRcPtr
)
714 ('sqlite3_value*', __xRcPtr
)
715 ('sqlite3_vfs*', __xRcPtr
)
719 Populate api object with sqlite3_...() by binding the "raw" wasm
720 exports into type-converting proxies using wasm.xWrap().
722 for(const e
of wasm
.bindingSignatures
){
723 capi
[e
[0]] = wasm
.xWrap
.apply(null, e
);
725 for(const e
of wasm
.bindingSignatures
.wasm
){
726 wasm
[e
[0]] = wasm
.xWrap
.apply(null, e
);
729 /* For C API functions which cannot work properly unless
730 wasm.bigIntEnabled is true, install a bogus impl which throws
731 if called when bigIntEnabled is false. The alternative would be
732 to elide these functions altogether, which seems likely to
733 cause more confusion. */
734 const fI64Disabled = function(fname
){
735 return ()=>toss(fname
+"() is unavailable due to lack",
736 "of BigInt support in this build.");
738 for(const e
of wasm
.bindingSignatures
.int64
){
739 capi
[e
[0]] = wasm
.bigIntEnabled
740 ? wasm
.xWrap
.apply(null, e
)
741 : fI64Disabled(e
[0]);
744 /* There's no need to expose bindingSignatures to clients,
745 implicitly making it part of the public interface. */
746 delete wasm
.bindingSignatures
;
748 if(wasm
.exports
.sqlite3_wasm_db_error
){
749 const __db_err
= wasm
.xWrap(
750 'sqlite3_wasm_db_error', 'int', 'sqlite3*', 'int', 'string'
753 Sets the given db's error state. Accepts:
755 - (sqlite3*, int code, string msg)
756 - (sqlite3*, Error e [,string msg = ''+e])
758 If passed a WasmAllocError, the message is ignored and the
759 result code is SQLITE_NOMEM. If passed any other Error type,
760 the result code defaults to SQLITE_ERROR unless the Error
761 object has a resultCode property, in which case that is used
762 (e.g. SQLite3Error has that). If passed a non-WasmAllocError
763 exception, the message string defaults to theError.message.
765 Returns the resulting code. Pass (pDb,0,0) to clear the error
768 util
.sqlite3_wasm_db_error = function(pDb
, resultCode
, message
){
769 if(resultCode
instanceof sqlite3
.WasmAllocError
){
770 resultCode
= capi
.SQLITE_NOMEM
;
771 message
= 0 /*avoid allocating message string*/;
772 }else if(resultCode
instanceof Error
){
773 message
= message
|| ''+resultCode
;
774 resultCode
= (resultCode
.resultCode
|| capi
.SQLITE_ERROR
);
776 return pDb
? __db_err(pDb
, resultCode
, message
) : resultCode
;
779 util
.sqlite3_wasm_db_error = function(pDb
,errCode
,msg
){
780 console
.warn("sqlite3_wasm_db_error() is not exported.",arguments
);
784 }/*xWrap() bindings*/
786 {/* Import C-level constants and structs... */
787 const cJson
= wasm
.xCall('sqlite3_wasm_enum_json');
789 toss("Maintenance required: increase sqlite3_wasm_enum_json()'s",
790 "static buffer size!");
792 //console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
793 wasm
.ctype
= JSON
.parse(wasm
.cstrToJs(cJson
));
794 // Groups of SQLITE_xyz macros...
795 const defineGroups
= ['access', 'authorizer',
796 'blobFinalizers', 'changeset',
797 'config', 'dataTypes',
798 'dbConfig', 'dbStatus',
799 'encodings', 'fcntl', 'flock', 'ioCap',
800 'limits', 'openFlags',
801 'prepareFlags', 'resultCodes',
803 'stmtStatus', 'syncFlags',
804 'trace', 'txnState', 'udfFlags',
806 if(wasm
.bigIntEnabled
){
807 defineGroups
.push('serialize', 'session', 'vtab');
809 for(const t
of defineGroups
){
810 for(const e
of Object
.entries(wasm
.ctype
[t
])){
811 // ^^^ [k,v] there triggers a buggy code transformation via
812 // one of the Emscripten-driven optimizers.
816 if(!wasm
.functionEntry(capi
.SQLITE_WASM_DEALLOC
)){
817 toss("Internal error: cannot resolve exported function",
818 "entry SQLITE_WASM_DEALLOC (=="+capi
.SQLITE_WASM_DEALLOC
+").");
820 const __rcMap
= Object
.create(null);
821 for(const t
of ['resultCodes']){
822 for(const e
of Object
.entries(wasm
.ctype
[t
])){
823 __rcMap
[e
[1]] = e
[0];
827 For the given integer, returns the SQLITE_xxx result code as a
828 string, or undefined if no such mapping is found.
830 capi
.sqlite3_js_rc_str
= (rc
)=>__rcMap
[rc
];
831 /* Bind all registered C-side structs... */
832 const notThese
= Object
.assign(Object
.create(null),{
833 // For each struct to NOT register, map its name to true:
834 WasmTestStruct
: true,
835 /* We unregister the kvvfs VFS from Worker threads below. */
836 sqlite3_kvvfs_methods
: !util
.isUIThread(),
837 /* sqlite3_index_info and friends require int64: */
838 sqlite3_index_info
: !wasm
.bigIntEnabled
,
839 sqlite3_index_constraint
: !wasm
.bigIntEnabled
,
840 sqlite3_index_orderby
: !wasm
.bigIntEnabled
,
841 sqlite3_index_constraint_usage
: !wasm
.bigIntEnabled
843 for(const s
of wasm
.ctype
.structs
){
844 if(!notThese
[s
.name
]){
845 capi
[s
.name
] = sqlite3
.StructBinder(s
);
848 if(capi
.sqlite3_index_info
){
849 /* Move these inner structs into sqlite3_index_info. Binding
850 ** them to WASM requires that we create global-scope structs to
851 ** model them with, but those are no longer needed after we've
852 ** passed them to StructBinder. */
853 for(const k
of ['sqlite3_index_constraint',
854 'sqlite3_index_orderby',
855 'sqlite3_index_constraint_usage']){
856 capi
.sqlite3_index_info
[k
] = capi
[k
];
859 capi
.sqlite3_vtab_config
= wasm
.xWrap(
860 'sqlite3_wasm_vtab_config','int',[
861 'sqlite3*', 'int', 'int']
863 }/* end vtab-related setup */
864 }/*end C constant and struct imports*/
867 Internal helper to assist in validating call argument counts in
868 the hand-written sqlite3_xyz() wrappers. We do this only for
869 consistency with non-special-case wrappings.
871 const __dbArgcMismatch
= (pDb
,f
,n
)=>{
872 return sqlite3
.util
.sqlite3_wasm_db_error(pDb
, capi
.SQLITE_MISUSE
,
873 f
+"() requires "+n
+" argument"+
877 /** Code duplication reducer for functions which take an encoding
878 argument and require SQLITE_UTF8. Sets the db error code to
879 SQLITE_FORMAT and returns that code. */
880 const __errEncoding
= (pDb
)=>{
881 return util
.sqlite3_wasm_db_error(
882 pDb
, capi
.SQLITE_FORMAT
, "SQLITE_UTF8 is the only supported encoding."
887 __dbCleanupMap is infrastructure for recording registration of
888 UDFs and collations so that sqlite3_close_v2() can clean up any
889 automated JS-to-WASM function conversions installed by those.
891 const __argPDb
= (pDb
)=>wasm
.xWrap
.argAdapter('sqlite3*')(pDb
);
892 const __argStr
= (str
)=>wasm
.isPtr(str
) ? wasm
.cstrToJs(str
) : str
;
893 const __dbCleanupMap = function(
894 pDb
, mode
/*0=remove, >0=create if needed, <0=do not create if missing*/
897 let m
= this.dbMap
.get(pDb
);
899 this.dbMap
.delete(pDb
);
901 }else if(!m
&& mode
>0){
902 this.dbMap
.set(pDb
, (m
= Object
.create(null)));
905 }.bind(Object
.assign(Object
.create(null),{
909 __dbCleanupMap
.addCollation = function(pDb
, name
){
910 const m
= __dbCleanupMap(pDb
, 1);
911 if(!m
.collation
) m
.collation
= new Set
;
912 m
.collation
.add(__argStr(name
).toLowerCase());
915 __dbCleanupMap
._addUDF = function(pDb
, name
, arity
, map
){
916 /* Map UDF name to a Set of arity values */
917 name
= __argStr(name
).toLowerCase();
918 let u
= map
.get(name
);
919 if(!u
) map
.set(name
, (u
= new Set
));
920 u
.add((arity
<0) ? -1 : arity
);
923 __dbCleanupMap
.addFunction = function(pDb
, name
, arity
){
924 const m
= __dbCleanupMap(pDb
, 1);
925 if(!m
.udf
) m
.udf
= new Map
;
926 this._addUDF(pDb
, name
, arity
, m
.udf
);
929 __dbCleanupMap
.addWindowFunc = function(pDb
, name
, arity
){
930 const m
= __dbCleanupMap(pDb
, 1);
931 if(!m
.wudf
) m
.wudf
= new Map
;
932 this._addUDF(pDb
, name
, arity
, m
.wudf
);
936 Intended to be called _only_ from sqlite3_close_v2(),
937 passed its non-0 db argument.
939 This function frees up certain automatically-installed WASM
940 function bindings which were installed on behalf of the given db,
941 as those may otherwise leak.
943 Notable caveat: this is only ever run via
944 sqlite3.capi.sqlite3_close_v2(). If a client, for whatever
945 reason, uses sqlite3.wasm.exports.sqlite3_close_v2() (the
946 function directly exported from WASM), this cleanup will not
949 This is not a silver bullet for avoiding automation-related
950 leaks but represents "an honest effort."
952 The issue being addressed here is covered at:
954 https://sqlite.org/wasm/doc/trunk/api-c-style.md#convert-func-ptr
956 __dbCleanupMap
.cleanup = function(pDb
){
958 //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
960 Installing NULL functions in the C API will remove those
961 bindings. The FuncPtrAdapter which sits between us and the C
962 API will also treat that as an opportunity to
963 wasm.uninstallFunction() any WASM function bindings it has
966 const closeArgs
= [pDb
];
968 'sqlite3_busy_handler',
969 'sqlite3_commit_hook',
970 'sqlite3_preupdate_hook',
971 'sqlite3_progress_handler',
972 'sqlite3_rollback_hook',
973 'sqlite3_set_authorizer',
975 'sqlite3_update_hook'
977 const x
= wasm
.exports
[name
];
978 closeArgs
.length
= x
.length
/*==argument count*/
979 /* recall that undefined entries translate to 0 when passed to
981 try{ capi
[name
](...closeArgs
) }
983 console
.warn("close-time call of",name
+"(",closeArgs
,") threw:",e
);
986 const m
= __dbCleanupMap(pDb
, 0);
989 for(const name
of m
.collation
){
991 capi
.sqlite3_create_collation_v2(
992 pDb
, name
, capi
.SQLITE_UTF8
, 0, 0, 0
1001 for(i
= 0; i
< 2; ++i
){ /* Clean up UDFs... */
1002 const fmap
= i
? m
.wudf
: m
.udf
;
1005 ? capi
.sqlite3_create_window_function
1006 : capi
.sqlite3_create_function_v2
;
1007 for(const e
of fmap
){
1008 const name
= e
[0], arities
= e
[1];
1009 const fargs
= [pDb
, name
, 0/*arity*/, capi
.SQLITE_UTF8
, 0, 0, 0, 0, 0];
1010 if(i
) fargs
.push(0);
1011 for(const arity
of arities
){
1012 try{ fargs
[2] = arity
; func
.apply(null, fargs
); }
1013 catch(e
){/*ignored*/}
1021 }/*__dbCleanupMap.cleanup()*/;
1023 {/* Binding of sqlite3_close_v2() */
1024 const __sqlite3CloseV2
= wasm
.xWrap("sqlite3_close_v2", "int", "sqlite3*");
1025 capi
.sqlite3_close_v2 = function(pDb
){
1026 if(1!==arguments
.length
) return __dbArgcMismatch(pDb
, 'sqlite3_close_v2', 1);
1028 try{__dbCleanupMap
.cleanup(pDb
)} catch(e
){/*ignored*/}
1030 return __sqlite3CloseV2(pDb
);
1032 }/*sqlite3_close_v2()*/
1034 if(capi
.sqlite3session_table_filter
){
1035 const __sqlite3SessionDelete
= wasm
.xWrap(
1036 'sqlite3session_delete', undefined, ['sqlite3_session*']
1038 capi
.sqlite3session_delete = function(pSession
){
1039 if(1!==arguments
.length
){
1040 return __dbArgcMismatch(pDb
, 'sqlite3session_delete', 1);
1041 /* Yes, we're returning a value from a void function. That seems
1042 like the lesser evil compared to not maintaining arg-count
1043 consistency as we do with other similar bindings. */
1046 //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
1047 capi
.sqlite3session_table_filter(pSession
, 0, 0);
1049 __sqlite3SessionDelete(pSession
);
1053 {/* Bindings for sqlite3_create_collation[_v2]() */
1054 // contextKey() impl for wasm.xWrap.FuncPtrAdapter
1055 const contextKey
= (argv
,argIndex
)=>{
1056 return 'argv['+argIndex
+']:'+argv
[0/* sqlite3* */]+
1057 ':'+wasm
.cstrToJs(argv
[1/* collation name */]).toLowerCase()
1059 const __sqlite3CreateCollationV2
= wasm
.xWrap(
1060 'sqlite3_create_collation_v2', 'int', [
1061 'sqlite3*', 'string', 'int', '*',
1062 new wasm
.xWrap
.FuncPtrAdapter({
1063 /* int(*xCompare)(void*,int,const void*,int,const void*) */
1064 name
: 'xCompare', signature
: 'i(pipip)', contextKey
1066 new wasm
.xWrap
.FuncPtrAdapter({
1067 /* void(*xDestroy(void*) */
1068 name
: 'xDestroy', signature
: 'v(p)', contextKey
1074 Works exactly like C's sqlite3_create_collation_v2() except that:
1076 1) It returns capi.SQLITE_FORMAT if the 3rd argument contains
1077 any encoding-related value other than capi.SQLITE_UTF8. No
1078 other encodings are supported. As a special case, if the
1079 bottom 4 bits of that argument are 0, SQLITE_UTF8 is
1082 2) It accepts JS functions for its function-pointer arguments,
1083 for which it will install WASM-bound proxies. The bindings
1084 are "permanent," in that they will stay in the WASM environment
1085 until it shuts down unless the client calls this again with the
1086 same collation name and a value of 0 or null for the
1087 the function pointer(s).
1089 For consistency with the C API, it requires the same number of
1090 arguments. It returns capi.SQLITE_MISUSE if passed any other
1093 Returns 0 on success, non-0 on error, in which case the error
1094 state of pDb (of type `sqlite3*` or argument-convertible to it)
1095 may contain more information.
1097 capi
.sqlite3_create_collation_v2 = function(pDb
,zName
,eTextRep
,pArg
,xCompare
,xDestroy
){
1098 if(6!==arguments
.length
) return __dbArgcMismatch(pDb
, 'sqlite3_create_collation_v2', 6);
1099 else if( 0 === (eTextRep
& 0xf) ){
1100 eTextRep
|= capi
.SQLITE_UTF8
;
1101 }else if( capi
.SQLITE_UTF8
!== (eTextRep
& 0xf) ){
1102 return __errEncoding(pDb
);
1105 const rc
= __sqlite3CreateCollationV2(pDb
, zName
, eTextRep
, pArg
, xCompare
, xDestroy
);
1106 if(0===rc
&& xCompare
instanceof Function
){
1107 __dbCleanupMap
.addCollation(pDb
, zName
);
1111 return util
.sqlite3_wasm_db_error(pDb
, e
);
1115 capi
.sqlite3_create_collation
= (pDb
,zName
,eTextRep
,pArg
,xCompare
)=>{
1116 return (5===arguments
.length
)
1117 ? capi
.sqlite3_create_collation_v2(pDb
,zName
,eTextRep
,pArg
,xCompare
,0)
1118 : __dbArgcMismatch(pDb
, 'sqlite3_create_collation', 5);
1121 }/*sqlite3_create_collation() and friends*/
1123 {/* Special-case handling of sqlite3_create_function_v2()
1124 and sqlite3_create_window_function(). */
1125 /** FuncPtrAdapter for contextKey() for sqlite3_create_function()
1127 const contextKey = function(argv
,argIndex
){
1129 argv
[0/* sqlite3* */]
1130 +':'+(argv
[2/*number of UDF args*/] < 0 ? -1 : argv
[2])
1131 +':'+argIndex
/*distinct for each xAbc callback type*/
1132 +':'+wasm
.cstrToJs(argv
[1]).toLowerCase()
1137 JS proxies for the various sqlite3_create[_window]_function()
1138 callbacks, structured in a form usable by wasm.xWrap.FuncPtrAdapter.
1140 const __cfProxy
= Object
.assign(Object
.create(null), {
1142 signature
:'v(pip)', contextKey
,
1143 callProxy
: (callback
)=>{
1144 return (pCtx
, argc
, pArgv
)=>{
1145 try{ callback(pCtx
, ...capi
.sqlite3_values_to_js(argc
, pArgv
)) }
1146 catch(e
){ capi
.sqlite3_result_error_js(pCtx
, e
) }
1151 signature
:'v(p)', contextKey
,
1152 callProxy
: (callback
)=>{
1154 try{ capi
.sqlite3_result_js(pCtx
, callback(pCtx
)) }
1155 catch(e
){ capi
.sqlite3_result_error_js(pCtx
, e
) }
1160 signature
:'v(pip)', contextKey
,
1161 callProxy
: (callback
)=>{
1162 return (pCtx
, argc
, pArgv
)=>{
1164 capi
.sqlite3_result_js(
1166 callback(pCtx
, ...capi
.sqlite3_values_to_js(argc
, pArgv
))
1169 //console.error('xFunc() caught:',e);
1170 capi
.sqlite3_result_error_js(pCtx
, e
);
1176 signature
:'v(p)', contextKey
,
1177 //Arguable: a well-behaved destructor doesn't require a proxy.
1178 callProxy
: (callback
)=>{
1180 try{ callback(pVoid
) }
1181 catch(e
){ console
.error("UDF xDestroy method threw:",e
) }
1187 const __sqlite3CreateFunction
= wasm
.xWrap(
1188 "sqlite3_create_function_v2", "int", [
1189 "sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
1190 "int"/*eTextRep*/, "*"/*pApp*/,
1191 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xFunc', ...__cfProxy
.xFunc
}),
1192 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xStep', ...__cfProxy
.xInverseAndStep
}),
1193 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xFinal', ...__cfProxy
.xFinalAndValue
}),
1194 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xDestroy', ...__cfProxy
.xDestroy
})
1198 const __sqlite3CreateWindowFunction
= wasm
.xWrap(
1199 "sqlite3_create_window_function", "int", [
1200 "sqlite3*", "string"/*funcName*/, "int"/*nArg*/,
1201 "int"/*eTextRep*/, "*"/*pApp*/,
1202 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xStep', ...__cfProxy
.xInverseAndStep
}),
1203 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xFinal', ...__cfProxy
.xFinalAndValue
}),
1204 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xValue', ...__cfProxy
.xFinalAndValue
}),
1205 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xInverse', ...__cfProxy
.xInverseAndStep
}),
1206 new wasm
.xWrap
.FuncPtrAdapter({name
: 'xDestroy', ...__cfProxy
.xDestroy
})
1210 /* Documented in the api object's initializer. */
1211 capi
.sqlite3_create_function_v2
= function f(
1212 pDb
, funcName
, nArg
, eTextRep
, pApp
,
1213 xFunc
, //void (*xFunc)(sqlite3_context*,int,sqlite3_value**)
1214 xStep
, //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
1215 xFinal
, //void (*xFinal)(sqlite3_context*)
1216 xDestroy
//void (*xDestroy)(void*)
1218 if( f
.length
!==arguments
.length
){
1219 return __dbArgcMismatch(pDb
,"sqlite3_create_function_v2",f
.length
);
1220 }else if( 0 === (eTextRep
& 0xf) ){
1221 eTextRep
|= capi
.SQLITE_UTF8
;
1222 }else if( capi
.SQLITE_UTF8
!== (eTextRep
& 0xf) ){
1223 return __errEncoding(pDb
);
1226 const rc
= __sqlite3CreateFunction(pDb
, funcName
, nArg
, eTextRep
,
1227 pApp
, xFunc
, xStep
, xFinal
, xDestroy
);
1228 if(0===rc
&& (xFunc
instanceof Function
1229 || xStep
instanceof Function
1230 || xFinal
instanceof Function
1231 || xDestroy
instanceof Function
)){
1232 __dbCleanupMap
.addFunction(pDb
, funcName
, nArg
);
1236 console
.error("sqlite3_create_function_v2() setup threw:",e
);
1237 return util
.sqlite3_wasm_db_error(pDb
, e
, "Creation of UDF threw: "+e
);
1241 /* Documented in the api object's initializer. */
1242 capi
.sqlite3_create_function
= function f(
1243 pDb
, funcName
, nArg
, eTextRep
, pApp
,
1244 xFunc
, xStep
, xFinal
1246 return (f
.length
===arguments
.length
)
1247 ? capi
.sqlite3_create_function_v2(pDb
, funcName
, nArg
, eTextRep
,
1248 pApp
, xFunc
, xStep
, xFinal
, 0)
1249 : __dbArgcMismatch(pDb
,"sqlite3_create_function",f
.length
);
1252 /* Documented in the api object's initializer. */
1253 capi
.sqlite3_create_window_function
= function f(
1254 pDb
, funcName
, nArg
, eTextRep
, pApp
,
1255 xStep
, //void (*xStep)(sqlite3_context*,int,sqlite3_value**)
1256 xFinal
, //void (*xFinal)(sqlite3_context*)
1257 xValue
, //void (*xValue)(sqlite3_context*)
1258 xInverse
,//void (*xInverse)(sqlite3_context*,int,sqlite3_value**)
1259 xDestroy
//void (*xDestroy)(void*)
1261 if( f
.length
!==arguments
.length
){
1262 return __dbArgcMismatch(pDb
,"sqlite3_create_window_function",f
.length
);
1263 }else if( 0 === (eTextRep
& 0xf) ){
1264 eTextRep
|= capi
.SQLITE_UTF8
;
1265 }else if( capi
.SQLITE_UTF8
!== (eTextRep
& 0xf) ){
1266 return __errEncoding(pDb
);
1269 const rc
= __sqlite3CreateWindowFunction(pDb
, funcName
, nArg
, eTextRep
,
1270 pApp
, xStep
, xFinal
, xValue
,
1271 xInverse
, xDestroy
);
1272 if(0===rc
&& (xStep
instanceof Function
1273 || xFinal
instanceof Function
1274 || xValue
instanceof Function
1275 || xInverse
instanceof Function
1276 || xDestroy
instanceof Function
)){
1277 __dbCleanupMap
.addWindowFunc(pDb
, funcName
, nArg
);
1281 console
.error("sqlite3_create_window_function() setup threw:",e
);
1282 return util
.sqlite3_wasm_db_error(pDb
, e
, "Creation of UDF threw: "+e
);
1286 A _deprecated_ alias for capi.sqlite3_result_js() which
1287 predates the addition of that function in the public API.
1289 capi
.sqlite3_create_function_v2
.udfSetResult
=
1290 capi
.sqlite3_create_function
.udfSetResult
=
1291 capi
.sqlite3_create_window_function
.udfSetResult
= capi
.sqlite3_result_js
;
1294 A _deprecated_ alias for capi.sqlite3_values_to_js() which
1295 predates the addition of that function in the public API.
1297 capi
.sqlite3_create_function_v2
.udfConvertArgs
=
1298 capi
.sqlite3_create_function
.udfConvertArgs
=
1299 capi
.sqlite3_create_window_function
.udfConvertArgs
= capi
.sqlite3_values_to_js
;
1302 A _deprecated_ alias for capi.sqlite3_result_error_js() which
1303 predates the addition of that function in the public API.
1305 capi
.sqlite3_create_function_v2
.udfSetError
=
1306 capi
.sqlite3_create_function
.udfSetError
=
1307 capi
.sqlite3_create_window_function
.udfSetError
= capi
.sqlite3_result_error_js
;
1309 }/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/;
1311 {/* Special-case handling of sqlite3_prepare_v2() and
1312 sqlite3_prepare_v3() */
1315 Helper for string:flexible conversions which require a
1316 byte-length counterpart argument. Passed a value and its
1317 ostensible length, this function returns [V,N], where V is
1318 either v or a transformed copy of v and N is either n, -1, or
1319 the byte length of v (if it's a byte array or ArrayBuffer).
1321 const __flexiString
= (v
,n
)=>{
1322 if('string'===typeof v
){
1324 }else if(util
.isSQLableTypedArray(v
)){
1326 v
= util
.typedArrayToString(
1327 (v
instanceof ArrayBuffer
) ? new Uint8Array(v
) : v
1329 }else if(Array
.isArray(v
)){
1337 Scope-local holder of the two impls of sqlite3_prepare_v2/v3().
1341 This binding expects a JS string as its 2nd argument and
1342 null as its final argument. In order to compile multiple
1343 statements from a single string, the "full" impl (see
1344 below) must be used.
1346 basic
: wasm
.xWrap('sqlite3_prepare_v3',
1347 "int", ["sqlite3*", "string",
1348 "int"/*ignored for this impl!*/,
1350 "**"/*MUST be 0 or null or undefined!*/]),
1352 Impl which requires that the 2nd argument be a pointer
1353 to the SQL string, instead of being converted to a
1354 string. This variant is necessary for cases where we
1355 require a non-NULL value for the final argument
1356 (exec()'ing multiple statements from one input
1357 string). For simpler cases, where only the first
1358 statement in the SQL string is required, the wrapper
1359 named sqlite3_prepare_v2() is sufficient and easier to
1360 use because it doesn't require dealing with pointers.
1362 full
: wasm
.xWrap('sqlite3_prepare_v3',
1363 "int", ["sqlite3*", "*", "int", "int",
1367 /* Documented in the capi object's initializer. */
1368 capi
.sqlite3_prepare_v3
= function f(pDb
, sql
, sqlLen
, prepFlags
, ppStmt
, pzTail
){
1369 if(f
.length
!==arguments
.length
){
1370 return __dbArgcMismatch(pDb
,"sqlite3_prepare_v3",f
.length
);
1372 const [xSql
, xSqlLen
] = __flexiString(sql
, sqlLen
);
1373 switch(typeof xSql
){
1374 case 'string': return __prepare
.basic(pDb
, xSql
, xSqlLen
, prepFlags
, ppStmt
, null);
1375 case 'number': return __prepare
.full(pDb
, xSql
, xSqlLen
, prepFlags
, ppStmt
, pzTail
);
1377 return util
.sqlite3_wasm_db_error(
1378 pDb
, capi
.SQLITE_MISUSE
,
1379 "Invalid SQL argument type for sqlite3_prepare_v2/v3()."
1384 /* Documented in the capi object's initializer. */
1385 capi
.sqlite3_prepare_v2
= function f(pDb
, sql
, sqlLen
, ppStmt
, pzTail
){
1386 return (f
.length
===arguments
.length
)
1387 ? capi
.sqlite3_prepare_v3(pDb
, sql
, sqlLen
, 0, ppStmt
, pzTail
)
1388 : __dbArgcMismatch(pDb
,"sqlite3_prepare_v2",f
.length
);
1391 }/*sqlite3_prepare_v2/v3()*/
1393 {/*sqlite3_bind_text/blob()*/
1394 const __bindText = wasm.xWrap("sqlite3_bind_text", "int", [
1395 "sqlite3_stmt*", "int", "string", "int", "*"
1397 const __bindBlob = wasm.xWrap("sqlite3_bind_blob", "int", [
1398 "sqlite3_stmt*", "int", "*", "int", "*"
1401 /** Documented in the capi object's initializer. */
1402 capi
.sqlite3_bind_text
= function f(pStmt
, iCol
, text
, nText
, xDestroy
){
1403 if(f
.length
!==arguments
.length
){
1404 return __dbArgcMismatch(capi
.sqlite3_db_handle(pStmt
),
1405 "sqlite3_bind_text", f
.length
);
1406 }else if(wasm
.isPtr(text
) || null===text
){
1407 return __bindText(pStmt
, iCol
, text
, nText
, xDestroy
);
1408 }else if(text
instanceof ArrayBuffer
){
1409 text
= new Uint8Array(text
);
1410 }else if(Array
.isArray(pMem
)){
1411 text
= pMem
.join('');
1415 if(util
.isSQLableTypedArray(text
)){
1416 p
= wasm
.allocFromTypedArray(text
);
1417 n
= text
.byteLength
;
1418 }else if('string'===typeof text
){
1419 [p
, n
] = wasm
.allocCString(text
);
1421 return util
.sqlite3_wasm_db_error(
1422 capi
.sqlite3_db_handle(pStmt
), capi
.SQLITE_MISUSE
,
1423 "Invalid 3rd argument type for sqlite3_bind_text()."
1426 return __bindText(pStmt
, iCol
, p
, n
, capi
.SQLITE_WASM_DEALLOC
);
1429 return util
.sqlite3_wasm_db_error(
1430 capi
.sqlite3_db_handle(pStmt
), e
1433 }/*sqlite3_bind_text()*/;
1435 /** Documented in the capi object's initializer. */
1436 capi
.sqlite3_bind_blob
= function f(pStmt
, iCol
, pMem
, nMem
, xDestroy
){
1437 if(f
.length
!==arguments
.length
){
1438 return __dbArgcMismatch(capi
.sqlite3_db_handle(pStmt
),
1439 "sqlite3_bind_blob", f
.length
);
1440 }else if(wasm
.isPtr(pMem
) || null===pMem
){
1441 return __bindBlob(pStmt
, iCol
, pMem
, nMem
, xDestroy
);
1442 }else if(pMem
instanceof ArrayBuffer
){
1443 pMem
= new Uint8Array(pMem
);
1444 }else if(Array
.isArray(pMem
)){
1445 pMem
= pMem
.join('');
1449 if(util
.isBindableTypedArray(pMem
)){
1450 p
= wasm
.allocFromTypedArray(pMem
);
1451 n
= nMem
>=0 ? nMem
: pMem
.byteLength
;
1452 }else if('string'===typeof pMem
){
1453 [p
, n
] = wasm
.allocCString(pMem
);
1455 return util
.sqlite3_wasm_db_error(
1456 capi
.sqlite3_db_handle(pStmt
), capi
.SQLITE_MISUSE
,
1457 "Invalid 3rd argument type for sqlite3_bind_blob()."
1460 return __bindBlob(pStmt
, iCol
, p
, n
, capi
.SQLITE_WASM_DEALLOC
);
1463 return util
.sqlite3_wasm_db_error(
1464 capi
.sqlite3_db_handle(pStmt
), e
1467 }/*sqlite3_bind_blob()*/;
1469 }/*sqlite3_bind_text/blob()*/
1471 {/* sqlite3_config() */
1473 Wraps a small subset of the C API's sqlite3_config() options.
1474 Unsupported options trigger the return of capi.SQLITE_NOTFOUND.
1475 Passing fewer than 2 arguments triggers return of
1478 capi
.sqlite3_config = function(op
, ...args
){
1479 if(arguments
.length
<2) return capi
.SQLITE_MISUSE
;
1481 case capi
.SQLITE_CONFIG_COVERING_INDEX_SCAN
: // 20 /* int */
1482 case capi
.SQLITE_CONFIG_MEMSTATUS
:// 9 /* boolean */
1483 case capi
.SQLITE_CONFIG_SMALL_MALLOC
: // 27 /* boolean */
1484 case capi
.SQLITE_CONFIG_SORTERREF_SIZE
: // 28 /* int nByte */
1485 case capi
.SQLITE_CONFIG_STMTJRNL_SPILL
: // 26 /* int nByte */
1486 case capi
.SQLITE_CONFIG_URI
:// 17 /* int */
1487 return wasm
.exports
.sqlite3_wasm_config_i(op
, args
[0]);
1488 case capi
.SQLITE_CONFIG_LOOKASIDE
: // 13 /* int int */
1489 return wasm
.exports
.sqlite3_wasm_config_ii(op
, args
[0], args
[1]);
1490 case capi
.SQLITE_CONFIG_MEMDB_MAXSIZE
: // 29 /* sqlite3_int64 */
1491 return wasm
.exports
.sqlite3_wasm_config_j(op
, args
[0]);
1492 case capi
.SQLITE_CONFIG_GETMALLOC
: // 5 /* sqlite3_mem_methods* */
1493 case capi
.SQLITE_CONFIG_GETMUTEX
: // 11 /* sqlite3_mutex_methods* */
1494 case capi
.SQLITE_CONFIG_GETPCACHE2
: // 19 /* sqlite3_pcache_methods2* */
1495 case capi
.SQLITE_CONFIG_GETPCACHE
: // 15 /* no-op */
1496 case capi
.SQLITE_CONFIG_HEAP
: // 8 /* void*, int nByte, int min */
1497 case capi
.SQLITE_CONFIG_LOG
: // 16 /* xFunc, void* */
1498 case capi
.SQLITE_CONFIG_MALLOC
:// 4 /* sqlite3_mem_methods* */
1499 case capi
.SQLITE_CONFIG_MMAP_SIZE
: // 22 /* sqlite3_int64, sqlite3_int64 */
1500 case capi
.SQLITE_CONFIG_MULTITHREAD
: // 2 /* nil */
1501 case capi
.SQLITE_CONFIG_MUTEX
: // 10 /* sqlite3_mutex_methods* */
1502 case capi
.SQLITE_CONFIG_PAGECACHE
: // 7 /* void*, int sz, int N */
1503 case capi
.SQLITE_CONFIG_PCACHE2
: // 18 /* sqlite3_pcache_methods2* */
1504 case capi
.SQLITE_CONFIG_PCACHE
: // 14 /* no-op */
1505 case capi
.SQLITE_CONFIG_PCACHE_HDRSZ
: // 24 /* int *psz */
1506 case capi
.SQLITE_CONFIG_PMASZ
: // 25 /* unsigned int szPma */
1507 case capi
.SQLITE_CONFIG_SERIALIZED
: // 3 /* nil */
1508 case capi
.SQLITE_CONFIG_SINGLETHREAD
: // 1 /* nil */:
1509 case capi
.SQLITE_CONFIG_SQLLOG
: // 21 /* xSqllog, void* */
1510 case capi
.SQLITE_CONFIG_WIN32_HEAPSIZE
: // 23 /* int nByte */
1512 return capi
.SQLITE_NOTFOUND
;
1515 }/* sqlite3_config() */
1517 {/*auto-extension bindings.*/
1518 const __autoExtFptr
= new Set
;
1520 capi
.sqlite3_auto_extension = function(fPtr
){
1521 if( fPtr
instanceof Function
){
1522 fPtr
= wasm
.installFunction('i(ppp)', fPtr
);
1523 }else if( 1!==arguments
.length
|| !wasm
.isPtr(fPtr
) ){
1524 return capi
.SQLITE_MISUSE
;
1526 const rc
= wasm
.exports
.sqlite3_auto_extension(fPtr
);
1527 if( fPtr
!==arguments
[0] ){
1528 if(0===rc
) __autoExtFptr
.add(fPtr
);
1529 else wasm
.uninstallFunction(fPtr
);
1534 capi
.sqlite3_cancel_auto_extension = function(fPtr
){
1535 /* We do not do an automatic JS-to-WASM function conversion here
1536 because it would be senseless: the converted pointer would
1537 never possibly match an already-installed one. */;
1538 if(!fPtr
|| 1!==arguments
.length
|| !wasm
.isPtr(fPtr
)) return 0;
1539 return wasm
.exports
.sqlite3_cancel_auto_extension(fPtr
);
1540 /* Note that it "cannot happen" that a client passes a pointer which
1541 is in __autoExtFptr because __autoExtFptr only contains automatic
1542 conversions created inside sqlite3_auto_extension() and
1543 never exposed to the client. */
1546 capi
.sqlite3_reset_auto_extension = function(){
1547 wasm
.exports
.sqlite3_reset_auto_extension();
1548 for(const fp
of __autoExtFptr
) wasm
.uninstallFunction(fp
);
1549 __autoExtFptr
.clear();
1551 }/* auto-extension */
1553 const pKvvfs
= capi
.sqlite3_vfs_find("kvvfs");
1554 if( pKvvfs
){/* kvvfs-specific glue */
1555 if(util
.isUIThread()){
1556 const kvvfsMethods
= new capi
.sqlite3_kvvfs_methods(
1557 wasm
.exports
.sqlite3_wasm_kvvfs_methods()
1559 delete capi
.sqlite3_kvvfs_methods
;
1561 const kvvfsMakeKey
= wasm
.exports
.sqlite3_wasm_kvvfsMakeKeyOnPstack
,
1562 pstack
= wasm
.pstack
;
1564 const kvvfsStorage
= (zClass
)=>
1565 ((115/*=='s'*/===wasm
.peek(zClass
))
1566 ? sessionStorage
: localStorage
);
1569 Implementations for members of the object referred to by
1570 sqlite3_wasm_kvvfs_methods(). We swap out the native
1571 implementations with these, which use localStorage or
1572 sessionStorage for their backing store.
1574 const kvvfsImpls
= {
1575 xRead
: (zClass
, zKey
, zBuf
, nBuf
)=>{
1576 const stack
= pstack
.pointer
,
1577 astack
= wasm
.scopedAllocPush();
1579 const zXKey
= kvvfsMakeKey(zClass
,zKey
);
1580 if(!zXKey
) return -3/*OOM*/;
1581 const jKey
= wasm
.cstrToJs(zXKey
);
1582 const jV
= kvvfsStorage(zClass
).getItem(jKey
);
1584 const nV
= jV
.length
/* Note that we are relying 100% on v being
1585 ASCII so that jV.length is equal to the
1586 C-string's byte length. */;
1587 if(nBuf
<=0) return nV
;
1592 const zV
= wasm
.scopedAllocCString(jV
);
1593 if(nBuf
> nV
+ 1) nBuf
= nV
+ 1;
1594 wasm
.heap8u().copyWithin(zBuf
, zV
, zV
+ nBuf
- 1);
1595 wasm
.poke(zBuf
+ nBuf
- 1, 0);
1598 console
.error("kvstorageRead()",e
);
1601 pstack
.restore(stack
);
1602 wasm
.scopedAllocPop(astack
);
1605 xWrite
: (zClass
, zKey
, zData
)=>{
1606 const stack
= pstack
.pointer
;
1608 const zXKey
= kvvfsMakeKey(zClass
,zKey
);
1609 if(!zXKey
) return 1/*OOM*/;
1610 const jKey
= wasm
.cstrToJs(zXKey
);
1611 kvvfsStorage(zClass
).setItem(jKey
, wasm
.cstrToJs(zData
));
1614 console
.error("kvstorageWrite()",e
);
1615 return capi
.SQLITE_IOERR
;
1617 pstack
.restore(stack
);
1620 xDelete
: (zClass
, zKey
)=>{
1621 const stack
= pstack
.pointer
;
1623 const zXKey
= kvvfsMakeKey(zClass
,zKey
);
1624 if(!zXKey
) return 1/*OOM*/;
1625 kvvfsStorage(zClass
).removeItem(wasm
.cstrToJs(zXKey
));
1628 console
.error("kvstorageDelete()",e
);
1629 return capi
.SQLITE_IOERR
;
1631 pstack
.restore(stack
);
1635 for(const k
of Object
.keys(kvvfsImpls
)){
1636 kvvfsMethods
[kvvfsMethods
.memberKey(k
)] =
1637 wasm
.installFunction(
1638 kvvfsMethods
.memberSignature(k
),
1643 /* Worker thread: unregister kvvfs to avoid it being used
1644 for anything other than local/sessionStorage. It "can"
1645 be used that way but it's not really intended to be. */
1646 capi
.sqlite3_vfs_unregister(pKvvfs
);
1650 wasm
.xWrap
.FuncPtrAdapter
.warnOnUse
= true;