@@ -819,13 +819,19 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
819819 * @memberof module:SqlJs
820820 * Open a new database either by creating a new one or opening an existing
821821 * one stored in the byte array passed in first argument
822- * @param {number[] } data An array of bytes representing
823- * an SQLite database file
822+ * @param {number[]|string } data An array of bytes representing
823+ * an SQLite database file or a path
824+ * @param {Object } opts Options to specify a filename
824825 */
825- function Database ( data ) {
826- this . filename = "dbfile_" + ( 0xffffffff * Math . random ( ) >>> 0 ) ;
827- if ( data != null ) {
826+ function Database ( data , { filename = false } = { } ) {
827+ if ( filename === false ) {
828+ this . filename = "dbfile_" + ( 0xffffffff * Math . random ( ) >>> 0 ) ;
829+ if ( data != null ) {
828830 FS . createDataFile ( "/" , this . filename , data , true , true ) ;
831+ }
832+ }
833+ else {
834+ this . filename = data ;
829835 }
830836 this . handleError ( sqlite3_open ( this . filename , apiTemp ) ) ;
831837 this . db = getValue ( apiTemp , "i32" ) ;
@@ -1379,4 +1385,44 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
13791385
13801386 // export Database to Module
13811387 Module . Database = Database ;
1388+
1389+ // Because emscripten doesn't allow us to handle `ioctl`, we need
1390+ // to manually install lock/unlock methods. Unfortunately we need
1391+ // to keep track of a mapping of `sqlite_file*` pointers to filename
1392+ // so that we can tell our filesystem which files to lock/unlock
1393+ var sqliteFiles = new Map ( ) ;
1394+
1395+ Module [ "register_for_idb" ] = ( customFS ) => {
1396+ var SQLITE_BUSY = 5 ;
1397+
1398+ function open ( namePtr , file ) {
1399+ var path = UTF8ToString ( namePtr ) ;
1400+ sqliteFiles . set ( file , path ) ;
1401+ }
1402+
1403+ function lock ( file , lockType ) {
1404+ var path = sqliteFiles . get ( file ) ;
1405+ var success = customFS . lock ( path , lockType )
1406+ return success ? 0 : SQLITE_BUSY ;
1407+ }
1408+
1409+ function unlock ( file , lockType ) {
1410+ var path = sqliteFiles . get ( file ) ;
1411+ customFS . unlock ( path , lockType )
1412+ return 0 ;
1413+ }
1414+
1415+ let lockPtr = addFunction ( lock , 'iii' ) ;
1416+ let unlockPtr = addFunction ( unlock , 'iii' ) ;
1417+ let openPtr = addFunction ( open , 'vii' ) ;
1418+ Module [ "_register_for_idb" ] ( lockPtr , unlockPtr , openPtr )
1419+ }
1420+
1421+ // TODO: This isn't called from anywhere yet. We need to
1422+ // somehow cleanup closed files from `sqliteFiles`
1423+ Module [ "cleanup_file" ] = ( path ) => {
1424+ let filesInfo = [ ...sqliteFiles . entries ( ) ]
1425+ let fileInfo = filesInfo . find ( f => f [ 1 ] === path ) ;
1426+ sqliteFiles . delete ( fileInfo [ 0 ] )
1427+ }
13821428} ;
0 commit comments