@@ -811,13 +811,19 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
811811 * @memberof module:SqlJs
812812 * Open a new database either by creating a new one or opening an existing
813813 * one stored in the byte array passed in first argument
814- * @param {number[] } data An array of bytes representing
815- * an SQLite database file
814+ * @param {number[]|string } data An array of bytes representing
815+ * an SQLite database file or a path
816+ * @param {Object } opts Options to specify a filename
816817 */
817- function Database ( data ) {
818- this . filename = "dbfile_" + ( 0xffffffff * Math . random ( ) >>> 0 ) ;
819- if ( data != null ) {
818+ function Database ( data , { filename = false } = { } ) {
819+ if ( filename === false ) {
820+ this . filename = "dbfile_" + ( 0xffffffff * Math . random ( ) >>> 0 ) ;
821+ if ( data != null ) {
820822 FS . createDataFile ( "/" , this . filename , data , true , true ) ;
823+ }
824+ }
825+ else {
826+ this . filename = data ;
821827 }
822828 this . handleError ( sqlite3_open ( this . filename , apiTemp ) ) ;
823829 this . db = getValue ( apiTemp , "i32" ) ;
@@ -1231,4 +1237,44 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
12311237
12321238 // export Database to Module
12331239 Module . Database = Database ;
1240+
1241+ // Because emscripten doesn't allow us to handle `ioctl`, we need
1242+ // to manually install lock/unlock methods. Unfortunately we need
1243+ // to keep track of a mapping of `sqlite_file*` pointers to filename
1244+ // so that we can tell our filesystem which files to lock/unlock
1245+ var sqliteFiles = new Map ( ) ;
1246+
1247+ Module [ "register_for_idb" ] = ( customFS ) => {
1248+ var SQLITE_BUSY = 5 ;
1249+
1250+ function open ( namePtr , file ) {
1251+ var path = UTF8ToString ( namePtr ) ;
1252+ sqliteFiles . set ( file , path ) ;
1253+ }
1254+
1255+ function lock ( file , lockType ) {
1256+ var path = sqliteFiles . get ( file ) ;
1257+ var success = customFS . lock ( path , lockType )
1258+ return success ? 0 : SQLITE_BUSY ;
1259+ }
1260+
1261+ function unlock ( file , lockType ) {
1262+ var path = sqliteFiles . get ( file ) ;
1263+ customFS . unlock ( path , lockType )
1264+ return 0 ;
1265+ }
1266+
1267+ let lockPtr = addFunction ( lock , 'iii' ) ;
1268+ let unlockPtr = addFunction ( unlock , 'iii' ) ;
1269+ let openPtr = addFunction ( open , 'vii' ) ;
1270+ Module [ "_register_for_idb" ] ( lockPtr , unlockPtr , openPtr )
1271+ }
1272+
1273+ // TODO: This isn't called from anywhere yet. We need to
1274+ // somehow cleanup closed files from `sqliteFiles`
1275+ Module [ "cleanup_file" ] = ( path ) => {
1276+ let filesInfo = [ ...sqliteFiles . entries ( ) ]
1277+ let fileInfo = filesInfo . find ( f => f [ 1 ] === path ) ;
1278+ sqliteFiles . delete ( fileInfo [ 0 ] )
1279+ }
12341280} ;
0 commit comments