diff options
Diffstat (limited to 'ext/wasm/api/sqlite3-api-glue.js')
-rw-r--r-- | ext/wasm/api/sqlite3-api-glue.js | 237 |
1 files changed, 138 insertions, 99 deletions
diff --git a/ext/wasm/api/sqlite3-api-glue.js b/ext/wasm/api/sqlite3-api-glue.js index cef27b548..ddb4a58fa 100644 --- a/ext/wasm/api/sqlite3-api-glue.js +++ b/ext/wasm/api/sqlite3-api-glue.js @@ -69,6 +69,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ wasm.bindingSignatures = [ // Please keep these sorted by function name! ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"], + /* sqlite3_auto_extension() has a hand-written binding. */ /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written bindings to permit more flexible inputs. */ ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"], @@ -87,8 +88,9 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ "*" ]], ["sqlite3_busy_timeout","int", "sqlite3*", "int"], - /*[sqlite3_close_v2() is implemented by hand to perform some - extra work. "sqlite3_close_v2", "int", "sqlite3*"],*/ + /* sqlite3_cancel_auto_extension() has a hand-written binding. */ + /* sqlite3_close_v2() is implemented by hand to perform some + extra work. */ ["sqlite3_changes", "int", "sqlite3*"], ["sqlite3_clear_bindings","int", "sqlite3_stmt*"], ["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"/*=>v(ppis)*/], @@ -190,6 +192,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ ]], ["sqlite3_realloc", "*","*","int"], ["sqlite3_reset", "int", "sqlite3_stmt*"], + /* sqlite3_reset_auto_extension() has a hand-written binding. */ ["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"], ["sqlite3_result_double", undefined, "sqlite3_context*", "f64"], ["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"], @@ -543,8 +546,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ }); delete self.Jaccwabyt; - {/* Convert Arrays and certain TypedArrays to strings for - 'string:flexible'-type arguments */ + {// wasm.xWrap() bindings... + + /* Convert Arrays and certain TypedArrays to strings for + 'string:flexible'-type arguments */ const __xString = wasm.xWrap.argAdapter('string'); wasm.xWrap.argAdapter( 'string:flexible', (v)=>__xString(util.flexibleString(v)) @@ -580,9 +585,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return rc || (this[v] = wasm.allocCString(v)); }.bind(Object.create(null)) ); - }/* special-case string-type argument conversions */ - if(1){// wasm.xWrap() bindings... /** Add some descriptive xWrap() aliases for '*' intended to (A) initially improve readability/correctness of @@ -590,27 +593,27 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ from higher-level representations, e.g. capi.sqlite3_vfs to `sqlite3_vfs*` via capi.sqlite3_vfs.pointer. */ - const aPtr = wasm.xWrap.argAdapter('*'); - const nilType = function(){}; - wasm.xWrap.argAdapter('sqlite3_filename', aPtr) - ('sqlite3_context*', aPtr) - ('sqlite3_value*', aPtr) - ('void*', aPtr) - ('sqlite3_changegroup*', aPtr) - ('sqlite3_changeset_iter*', aPtr) - //('sqlite3_rebaser*', aPtr) - ('sqlite3_session*', aPtr) + const __xArgPtr = wasm.xWrap.argAdapter('*'); + const nilType = function(){}/*a class no value can ever be an instance of*/; + wasm.xWrap.argAdapter('sqlite3_filename', __xArgPtr) + ('sqlite3_context*', __xArgPtr) + ('sqlite3_value*', __xArgPtr) + ('void*', __xArgPtr) + ('sqlite3_changegroup*', __xArgPtr) + ('sqlite3_changeset_iter*', __xArgPtr) + //('sqlite3_rebaser*', __xArgPtr) + ('sqlite3_session*', __xArgPtr) ('sqlite3_stmt*', (v)=> - aPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType)) + __xArgPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType)) ? v.pointer : v)) ('sqlite3*', (v)=> - aPtr((v instanceof (sqlite3?.oo1?.DB || nilType)) + __xArgPtr((v instanceof (sqlite3?.oo1?.DB || nilType)) ? v.pointer : v)) ('sqlite3_index_info*', (v)=> - aPtr((v instanceof (capi.sqlite3_index_info || nilType)) + __xArgPtr((v instanceof (capi.sqlite3_index_info || nilType)) ? v.pointer : v)) ('sqlite3_module*', (v)=> - aPtr((v instanceof (capi.sqlite3_module || nilType)) + __xArgPtr((v instanceof (capi.sqlite3_module || nilType)) ? v.pointer : v)) /** `sqlite3_vfs*`: @@ -631,8 +634,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ "Unknown sqlite3_vfs name:", v ); } - return aPtr((v instanceof (capi.sqlite3_vfs || nilType)) - ? v.pointer : v); + return __xArgPtr((v instanceof (capi.sqlite3_vfs || nilType)) + ? v.pointer : v); }); const __xRcPtr = wasm.xWrap.resultAdapter('*'); @@ -709,7 +712,83 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return errCode; }; } - }/*xWrap() bindings*/; + }/*xWrap() bindings*/ + + {/* Import C-level constants and structs... */ + const cJson = wasm.xCall('sqlite3_wasm_enum_json'); + if(!cJson){ + toss("Maintenance required: increase sqlite3_wasm_enum_json()'s", + "static buffer size!"); + } + //console.debug('wasm.ctype length =',wasm.cstrlen(cJson)); + wasm.ctype = JSON.parse(wasm.cstrToJs(cJson)); + // Groups of SQLITE_xyz macros... + const defineGroups = ['access', 'authorizer', + 'blobFinalizers', 'changeset', + 'config', 'dataTypes', + 'dbConfig', 'dbStatus', + 'encodings', 'fcntl', 'flock', 'ioCap', + 'limits', 'openFlags', + 'prepareFlags', 'resultCodes', + 'sqlite3Status', + 'stmtStatus', 'syncFlags', + 'trace', 'txnState', 'udfFlags', + 'version' ]; + if(wasm.bigIntEnabled){ + defineGroups.push('serialize', 'session', 'vtab'); + } + for(const t of defineGroups){ + for(const e of Object.entries(wasm.ctype[t])){ + // ^^^ [k,v] there triggers a buggy code transformation via + // one of the Emscripten-driven optimizers. + capi[e[0]] = e[1]; + } + } + const __rcMap = Object.create(null); + for(const t of ['resultCodes']){ + for(const e of Object.entries(wasm.ctype[t])){ + __rcMap[e[1]] = e[0]; + } + } + /** + For the given integer, returns the SQLITE_xxx result code as a + string, or undefined if no such mapping is found. + */ + capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc]; + /* Bind all registered C-side structs... */ + const notThese = Object.assign(Object.create(null),{ + // For each struct to NOT register, map its name to true: + WasmTestStruct: true, + /* We unregister the kvvfs VFS from Worker threads below. */ + sqlite3_kvvfs_methods: !util.isUIThread(), + /* sqlite3_index_info and friends require int64: */ + sqlite3_index_info: !wasm.bigIntEnabled, + sqlite3_index_constraint: !wasm.bigIntEnabled, + sqlite3_index_orderby: !wasm.bigIntEnabled, + sqlite3_index_constraint_usage: !wasm.bigIntEnabled + }); + for(const s of wasm.ctype.structs){ + if(!notThese[s.name]){ + capi[s.name] = sqlite3.StructBinder(s); + } + } + if(capi.sqlite3_index_info){ + /* Move these inner structs into sqlite3_index_info. Binding + ** them to WASM requires that we create global-scope structs to + ** model them with, but those are no longer needed after we've + ** passed them to StructBinder. */ + for(const k of ['sqlite3_index_constraint', + 'sqlite3_index_orderby', + 'sqlite3_index_constraint_usage']){ + capi.sqlite3_index_info[k] = capi[k]; + delete capi[k]; + } + capi.sqlite3_vtab_config = wasm.xWrap( + 'sqlite3_wasm_vtab_config','int',[ + 'sqlite3*', 'int', 'int'] + ); + }/* end vtab-related setup */ + }/*end C constant and struct imports*/ /** Internal helper to assist in validating call argument counts in @@ -803,7 +882,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ __dbCleanupMap.cleanup = function(pDb){ pDb = __argPDb(pDb); - wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true; + wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false; /** Installing NULL functions in the C API will remove those bindings. The FuncPtrAdapter which sits between us and the C @@ -1140,8 +1219,8 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ }/*sqlite3_create_function_v2() and sqlite3_create_window_function() proxies*/; - if(1){/* Special-case handling of sqlite3_prepare_v2() and - sqlite3_prepare_v3() */ + {/* Special-case handling of sqlite3_prepare_v2() and + sqlite3_prepare_v3() */ /** Helper for string:flexible conversions which require a @@ -1346,81 +1425,41 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ }; }/* sqlite3_config() */ - {/* Import C-level constants and structs... */ - const cJson = wasm.xCall('sqlite3_wasm_enum_json'); - if(!cJson){ - toss("Maintenance required: increase sqlite3_wasm_enum_json()'s", - "static buffer size!"); - } - //console.debug('wasm.ctype length =',wasm.cstrlen(cJson)); - wasm.ctype = JSON.parse(wasm.cstrToJs(cJson)); - // Groups of SQLITE_xyz macros... - const defineGroups = ['access', 'authorizer', - 'blobFinalizers', 'changeset', - 'config', 'dataTypes', - 'dbConfig', 'dbStatus', - 'encodings', 'fcntl', 'flock', 'ioCap', - 'limits', 'openFlags', - 'prepareFlags', 'resultCodes', - 'sqlite3Status', - 'stmtStatus', 'syncFlags', - 'trace', 'txnState', 'udfFlags', - 'version' ]; - if(wasm.bigIntEnabled){ - defineGroups.push('serialize', 'session', 'vtab'); - } - for(const t of defineGroups){ - for(const e of Object.entries(wasm.ctype[t])){ - // ^^^ [k,v] there triggers a buggy code transformation via - // one of the Emscripten-driven optimizers. - capi[e[0]] = e[1]; - } - } - const __rcMap = Object.create(null); - for(const t of ['resultCodes']){ - for(const e of Object.entries(wasm.ctype[t])){ - __rcMap[e[1]] = e[0]; - } - } - /** - For the given integer, returns the SQLITE_xxx result code as a - string, or undefined if no such mapping is found. - */ - capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc]; - /* Bind all registered C-side structs... */ - const notThese = Object.assign(Object.create(null),{ - // For each struct to NOT register, map its name to true: - WasmTestStruct: true, - /* We unregister the kvvfs VFS from Worker threads below. */ - sqlite3_kvvfs_methods: !util.isUIThread(), - /* sqlite3_index_info and friends require int64: */ - sqlite3_index_info: !wasm.bigIntEnabled, - sqlite3_index_constraint: !wasm.bigIntEnabled, - sqlite3_index_orderby: !wasm.bigIntEnabled, - sqlite3_index_constraint_usage: !wasm.bigIntEnabled - }); - for(const s of wasm.ctype.structs){ - if(!notThese[s.name]){ - capi[s.name] = sqlite3.StructBinder(s); + {/*auto-extension bindings.*/ + const __autoExtFptr = new Set; + + capi.sqlite3_auto_extension = function(fPtr){ + if( fPtr instanceof Function ){ + fPtr = wasm.installFunction('i(ppp)', fPtr); + }else if( 1!==arguments.length || !wasm.isPtr(fPtr) ){ + return capi.SQLITE_MISUSE; } - } - if(capi.sqlite3_index_info){ - /* Move these inner structs into sqlite3_index_info. Binding - ** them to WASM requires that we create global-scope structs to - ** model them with, but those are no longer needed after we've - ** passed them to StructBinder. */ - for(const k of ['sqlite3_index_constraint', - 'sqlite3_index_orderby', - 'sqlite3_index_constraint_usage']){ - capi.sqlite3_index_info[k] = capi[k]; - delete capi[k]; + const rc = wasm.exports.sqlite3_auto_extension(fPtr); + if( fPtr!==arguments[0] ){ + if(0===rc) __autoExtFptr.add(fPtr); + else wasm.uninstallFunction(fPtr); } - capi.sqlite3_vtab_config = wasm.xWrap( - 'sqlite3_wasm_vtab_config','int',[ - 'sqlite3*', 'int', 'int'] - ); - }/* end vtab-related setup */ - }/*end C constant and struct imports*/ + return rc; + }; + + capi.sqlite3_cancel_auto_extension = function(fPtr){ + /* We do not do an automatic JS-to-WASM function conversion here + because it would be senseless: the converted pointer would + never possibly match an already-installed one. */; + if(!fPtr || 1!==arguments.length || !wasm.isPtr(fPtr)) return 0; + return wasm.exports.sqlite3_cancel_auto_extension(fPtr); + /* Note that it "cannot happen" that a client passes a pointer which + is in __autoExtFptr because __autoExtFptr only contains automatic + conversions created inside sqlite3_auto_extension() and + never exposed to the client. */ + }; + + capi.sqlite3_reset_auto_extension = function(){ + wasm.exports.sqlite3_reset_auto_extension(); + for(const fp of __autoExtFptr) wasm.uninstallFunction(fp); + __autoExtFptr.clear(); + }; + }/* auto-extension */ const pKvvfs = capi.sqlite3_vfs_find("kvvfs"); if( pKvvfs ){/* kvvfs-specific glue */ |