@@ -10,9 +10,10 @@ import 'package:js/js.dart';
10
10
import 'package:meta/meta.dart' ;
11
11
12
12
import '../../constants.dart' ;
13
- import '../file_system .dart' ;
13
+ import '../../vfs .dart' ;
14
14
import '../js_interop.dart' ;
15
15
import 'memory.dart' ;
16
+ import 'utils.dart' ;
16
17
17
18
/// An (asynchronous) file system implementation backed by IndexedDB.
18
19
///
@@ -400,7 +401,7 @@ class _OffsetAndBuffer {
400
401
///
401
402
/// In the future, we may want to store individual blocks instead.
402
403
403
- class IndexedDbFileSystem implements FileSystem {
404
+ class IndexedDbFileSystem extends BaseVirtualFileSystem {
404
405
final AsynchronousIndexedDbFileSystem _asynchronous;
405
406
406
407
var _isClosing = false ;
@@ -415,7 +416,8 @@ class IndexedDbFileSystem implements FileSystem {
415
416
416
417
IndexedDbFileSystem ._(String dbName)
417
418
: _asynchronous = AsynchronousIndexedDbFileSystem (dbName),
418
- _memory = InMemoryFileSystem ();
419
+ _memory = InMemoryFileSystem (),
420
+ super (name: 'indexeddb' );
419
421
420
422
/// Loads an IndexedDB file system identified by the [dbName] .
421
423
///
@@ -443,8 +445,7 @@ class IndexedDbFileSystem implements FileSystem {
443
445
// https://github.com/dart-lang/sdk/issues/48854
444
446
await self.indexedDB! .deleteDatabase (dbName).timeout (
445
447
const Duration (milliseconds: 1000 ),
446
- onTimeout: () => throw FileSystemException (
447
- 0 , "Failed to delete database. Database is still open" ));
448
+ onTimeout: () => throw VfsException (1 ));
448
449
}
449
450
450
451
/// Whether this file system is closing or closed.
@@ -500,7 +501,7 @@ class IndexedDbFileSystem implements FileSystem {
500
501
501
502
void _checkClosed () {
502
503
if (isClosed) {
503
- throw FileSystemException (SqlError .SQLITE_IOERR , 'FileSystem closed' );
504
+ throw VfsException (SqlError .SQLITE_IOERR );
504
505
}
505
506
}
506
507
@@ -534,94 +535,110 @@ class IndexedDbFileSystem implements FileSystem {
534
535
}
535
536
536
537
@override
537
- void createFile (
538
- String path, {
539
- bool errorIfNotExists = false ,
540
- bool errorIfAlreadyExists = false ,
541
- }) {
542
- _checkClosed ();
543
- final existsBefore = _memory.exists (path);
544
- _memory.createFile (
545
- path,
546
- errorIfAlreadyExists: errorIfAlreadyExists,
547
- errorIfNotExists: errorIfNotExists,
548
- );
538
+ int xAccess (String path, int flags) => _memory.xAccess (path, flags);
549
539
550
- if (! existsBefore) {
551
- _submitWork (_CreateFileWorkItem (this , path));
540
+ @override
541
+ void xDelete (String path, int syncDir) {
542
+ _memory.xDelete (path, syncDir);
543
+
544
+ if (! _inMemoryOnlyFiles.remove (path)) {
545
+ _submitWork (_DeleteFileWorkItem (this , path));
552
546
}
553
547
}
554
548
555
549
@override
556
- String createTemporaryFile () {
557
- _checkClosed ();
558
- final path = _memory.createTemporaryFile ();
559
- _inMemoryOnlyFiles.add (path);
560
- return path;
561
- }
550
+ String xFullPathName (String path) => _memory.xFullPathName (path);
562
551
563
552
@override
564
- void deleteFile (String path) {
565
- _memory.deleteFile (path);
566
-
567
- if (! _inMemoryOnlyFiles.remove (path)) {
568
- _submitWork (_DeleteFileWorkItem (this , path));
553
+ XOpenResult xOpen (Sqlite3Filename path, int flags) {
554
+ final pathStr = path.path ?? random.randomFileName (prefix: '/' );
555
+ final existedBefore = _memory.xAccess (pathStr, 0 ) != 0 ;
556
+
557
+ final inMemoryFile = _memory.xOpen (Sqlite3Filename (pathStr), flags);
558
+ final deleteOnClose = (flags & SqlFlag .SQLITE_OPEN_DELETEONCLOSE ) != 0 ;
559
+
560
+ if (! existedBefore) {
561
+ if (deleteOnClose) {
562
+ // No point in persisting this file, it doesn't exist and won't exist
563
+ // after we're done.
564
+ _inMemoryOnlyFiles.add (pathStr);
565
+ } else {
566
+ _submitWork (_CreateFileWorkItem (this , pathStr));
567
+ }
569
568
}
569
+
570
+ return XOpenResult (
571
+ outFlags: 0 , file: _IndexedDbFile (this , inMemoryFile.file, pathStr));
570
572
}
571
573
572
574
@override
573
- Future <void > clear () async {
574
- _memory.clear ();
575
- await _submitWorkFunction (_asynchronous.clear, 'clear' );
575
+ void xSleep (Duration duration) {
576
+ // noop
576
577
}
578
+ }
579
+
580
+ class _IndexedDbFile extends VirtualFileSystemFile {
581
+ final IndexedDbFileSystem vfs;
582
+ final VirtualFileSystemFile memoryFile;
583
+ final String path;
584
+
585
+ _IndexedDbFile (this .vfs, this .memoryFile, this .path);
577
586
578
587
@override
579
- bool exists (String path) {
580
- _checkClosed ();
581
- return _memory.exists (path);
588
+ void xRead (Uint8List target, int fileOffset) {
589
+ memoryFile.xRead (target, fileOffset);
582
590
}
583
591
584
592
@override
585
- List <String > get files {
586
- _checkClosed ();
587
- return _memory.files;
588
- }
593
+ int get xDeviceCharacteristics => 0 ;
589
594
590
595
@override
591
- int read (String path, Uint8List target, int offset) {
592
- _checkClosed ();
593
- return _memory.read (path, target, offset);
594
- }
596
+ int xCheckReservedLock () => memoryFile.xCheckReservedLock ();
595
597
596
598
@override
597
- int sizeOfFile (String path) {
598
- _checkClosed ();
599
- return _memory.sizeOfFile (path);
599
+ void xClose () {}
600
+
601
+ @override
602
+ int xFileSize () => memoryFile.xFileSize ();
603
+
604
+ @override
605
+ void xLock (int mode) => memoryFile.xLock (mode);
606
+
607
+ @override
608
+ void xSync (int flags) {
609
+ // We can't wait for a sync either way, so this just has to be a noop
600
610
}
601
611
602
612
@override
603
- void truncateFile ( String path, int length ) {
604
- _checkClosed ();
605
- _memory. truncateFile (path, length );
613
+ void xTruncate ( int size ) {
614
+ vfs. _checkClosed ();
615
+ memoryFile. xTruncate (size );
606
616
607
- if (! _inMemoryOnlyFiles.contains (path)) {
608
- _submitWorkFunction (
609
- () async => _asynchronous.truncate (await _fileId (path), length ),
617
+ if (! vfs. _inMemoryOnlyFiles.contains (path)) {
618
+ vfs. _submitWorkFunction (
619
+ () async => vfs. _asynchronous.truncate (await vfs. _fileId (path), size ),
610
620
'truncate $path ' );
611
621
}
612
622
}
613
623
614
624
@override
615
- void write (String path, Uint8List bytes, int offset) {
616
- _checkClosed ();
625
+ void xUnlock (int mode) => memoryFile.xUnlock (mode);
626
+
627
+ @override
628
+ void xWrite (Uint8List buffer, int fileOffset) {
629
+ vfs._checkClosed ();
617
630
618
- final previousContent = _memory.fileData[path] ?? Uint8List (0 );
631
+ final previousContent = vfs._memory.fileData[path] ?? Uint8List (0 );
632
+ memoryFile.xWrite (buffer, fileOffset);
619
633
620
- _memory.write (path, bytes, offset);
634
+ if (! vfs._inMemoryOnlyFiles.contains (path)) {
635
+ // We need to copy the buffer for the write because it will become invalid
636
+ // after this synchronous method returns.
637
+ final copy = Uint8List (buffer.length);
638
+ copy.setAll (0 , buffer);
621
639
622
- if (! _inMemoryOnlyFiles.contains (path)) {
623
- _submitWork (_WriteFileWorkItem (this , path, previousContent)
624
- ..writes.add (_OffsetAndBuffer (offset, bytes)));
640
+ vfs._submitWork (_WriteFileWorkItem (vfs, path, previousContent)
641
+ ..writes.add (_OffsetAndBuffer (fileOffset, copy)));
625
642
}
626
643
}
627
644
}
0 commit comments