@@ -39,6 +39,7 @@ function log(...args) {
3939 * @property {string } path
4040 * @property {number } flags
4141 * @property {FileBlock } block0
42+ * @property {boolean } isMetadataChanged
4243 * @property {WebLocks } locks
4344 *
4445 * @property {Set<number> } [changedPages]
@@ -94,6 +95,7 @@ export class IDBBatchAtomicVFS extends VFS.Base {
9495 path : url . pathname ,
9596 flags,
9697 block0 : null ,
98+ isMetadataChanged : true ,
9799 locks : new WebLocks ( url . pathname )
98100 } ;
99101 this . #mapIdToFile. set ( fileId , file ) ;
@@ -241,12 +243,17 @@ export class IDBBatchAtomicVFS extends VFS.Base {
241243 log ( `xWrite ${ file . path } ${ pData . byteLength } ${ iOffset } ` ) ;
242244
243245 try {
246+ // Update file size if appending.
247+ const prevFileSize = file . block0 . fileSize ;
248+ if ( file . block0 . fileSize < iOffset + pData . byteLength ) {
249+ file . block0 . fileSize = iOffset + pData . byteLength ;
250+ file . isMetadataChanged = true ;
251+ }
252+
244253 // Convert the write directly into an IndexedDB object. Our assumption
245254 // is that SQLite will only overwrite data with an xWrite of the same
246255 // offset and size unless the database page size changes, except when
247256 // changing database page size which is handled by #reblockIfNeeded().
248- const prevFileSize = file . block0 . fileSize ;
249- file . block0 . fileSize = Math . max ( file . block0 . fileSize , iOffset + pData . byteLength ) ;
250257 const block = iOffset === 0 ? file . block0 : {
251258 path : file . path ,
252259 offset : - iOffset ,
@@ -271,6 +278,9 @@ export class IDBBatchAtomicVFS extends VFS.Base {
271278 // Not a batch atomic write so write through.
272279 this . #idb. run ( 'readwrite' , ( { blocks} ) => blocks . put ( block ) ) ;
273280 }
281+
282+ // Clear dirty flag if page 0 was written.
283+ file . isMetadataChanged = iOffset === 0 ? false : file . isMetadataChanged ;
274284 return VFS . SQLITE_OK ;
275285 } catch ( e ) {
276286 console . error ( e ) ;
@@ -485,6 +495,18 @@ export class IDBBatchAtomicVFS extends VFS.Base {
485495 return VFS . SQLITE_IOERR ;
486496 }
487497 }
498+
499+ if ( file . isMetadataChanged ) {
500+ // Metadata has changed so write block 0 to IndexedDB.
501+ try {
502+ this . #idb. run ( 'readwrite' , async ( { blocks} ) => {
503+ await blocks . put ( file . block0 ) ;
504+ } ) ;
505+ } catch ( e ) {
506+ console . error ( e ) ;
507+ return VFS . SQLITE_IOERR ;
508+ }
509+ }
488510 return VFS . SQLITE_OK ;
489511
490512 case 22 : // SQLITE_FCNTL_COMMIT_PHASETWO
@@ -522,6 +544,7 @@ export class IDBBatchAtomicVFS extends VFS.Base {
522544 block0 . data = block0 . data . slice ( ) ;
523545 const changedPages = file . changedPages ;
524546 file . changedPages = null ;
547+ file . isMetadataChanged = false ;
525548 this . #idb. run ( 'readwrite' , async ( { blocks} ) => {
526549 // Write block 0 to commit the new version.
527550 blocks . put ( block0 ) ;
@@ -557,6 +580,7 @@ export class IDBBatchAtomicVFS extends VFS.Base {
557580 // be left in IndexedDB to be removed by the next atomic write
558581 // transaction.
559582 file . changedPages = null ;
583+ file . isMetadataChanged = false ;
560584 file . block0 = await this . #idb. run ( 'readonly' , ( { blocks} ) => {
561585 return blocks . get ( [ file . path , 0 , file . block0 . version + 1 ] ) ;
562586 } ) ;
0 commit comments