Skip to content

Commit e78042b

Browse files
committed
Move worker VFS into own directory
1 parent 1ab83d5 commit e78042b

File tree

10 files changed

+73
-49
lines changed

10 files changed

+73
-49
lines changed

sqlite3/build.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ targets:
3232
builders:
3333
build_web_compilers:entrypoint:
3434
generate_for:
35+
include:
36+
- "example/web/**"
3537
# This one is compiled in the other target
3638
exclude:
3739
- "example/web/worker.dart"

sqlite3/example/web/worker.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import 'package:js/js.dart';
55
import 'package:js/js_util.dart';
66
import 'package:sqlite3/src/constants.dart';
77
import 'package:sqlite3/src/vfs.dart';
8-
import 'package:sqlite3/src/wasm/vfs/client.dart';
9-
import 'package:sqlite3/src/wasm/vfs/worker.dart';
8+
import 'package:sqlite3/src/wasm/vfs/async_opfs/client.dart';
9+
import 'package:sqlite3/src/wasm/vfs/async_opfs/worker.dart';
1010

1111
@JS()
1212
external bool get crossOriginIsolated;
@@ -34,9 +34,10 @@ void main() {
3434
await worker.onMessage.first;
3535

3636
final vfs = WasmVfs(workerOptions: options);
37-
final (file: file, outFlags: flags) =
37+
final opened =
3838
vfs.xOpen(Sqlite3Filename('/test'), SqlFlag.SQLITE_OPEN_CREATE);
39-
print('opened file $file, outflags $flags');
39+
final file = opened.file;
40+
print('opened file $file, outflags ${opened.outFlags}');
4041

4142
final buffer = Uint8List.fromList([1, 2, 3, 4, 5, 6]);
4243
file.xWrite(buffer, 0);

sqlite3/lib/src/ffi/bindings.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import 'dart:convert';
33
import 'dart:ffi';
44
import 'dart:typed_data';
55

6-
import 'package:sqlite3/src/vfs.dart';
7-
86
import '../constants.dart';
97
import '../functions.dart';
108
import '../implementation/bindings.dart';

sqlite3/lib/src/ffi/sqlite3.g.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,16 +1183,16 @@ class Bindings {
11831183
.asFunction<int Function(ffi.Pointer<ffi.Void>)>();
11841184
}
11851185

1186-
final class sqlite3_char extends ffi.Opaque {}
1186+
class sqlite3_char extends ffi.Opaque {}
11871187

1188-
final class sqlite3 extends ffi.Opaque {}
1188+
class sqlite3 extends ffi.Opaque {}
11891189

1190-
final class sqlite3_stmt extends ffi.Opaque {}
1190+
class sqlite3_stmt extends ffi.Opaque {}
11911191

1192-
final class sqlite3_backup extends ffi.Opaque {}
1192+
class sqlite3_backup extends ffi.Opaque {}
11931193

1194-
final class sqlite3_api_routines extends ffi.Opaque {}
1194+
class sqlite3_api_routines extends ffi.Opaque {}
11951195

1196-
final class sqlite3_value extends ffi.Opaque {}
1196+
class sqlite3_value extends ffi.Opaque {}
11971197

1198-
final class sqlite3_context extends ffi.Opaque {}
1198+
class sqlite3_context extends ffi.Opaque {}

sqlite3/lib/src/vfs.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,13 @@ abstract class VirtualFileSystem {
7878
}
7979

8080
/// The result of [VirtualFileSystem.xOpen].
81-
typedef XOpenResult = ({int outFlags, VirtualFileSystemFile file});
81+
class XOpenResult {
82+
final int outFlags;
83+
final VirtualFileSystemFile file;
84+
85+
XOpenResult({required this.outFlags, required this.file});
86+
// todo: Turn into record
87+
}
8288

8389
/// A file implemented by a VFS author and returned by [VirtualFileSystem.xOpen].
8490
///

sqlite3/lib/src/wasm/file_system/indexed_db.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ class IndexedDbFileSystem implements FileSystem {
626626
}
627627
}
628628

629-
sealed class _IndexedDbWorkItem with LinkedListEntry<_IndexedDbWorkItem> {
629+
abstract class _IndexedDbWorkItem with LinkedListEntry<_IndexedDbWorkItem> {
630630
final Completer<void> completer = Completer.sync();
631631

632632
/// Insert this item into the [pending] list, returning whether the item was
@@ -647,7 +647,7 @@ sealed class _IndexedDbWorkItem with LinkedListEntry<_IndexedDbWorkItem> {
647647
FutureOr<void> run();
648648
}
649649

650-
final class _FunctionWorkItem extends _IndexedDbWorkItem {
650+
class _FunctionWorkItem extends _IndexedDbWorkItem {
651651
final FutureOr<void> Function() work;
652652
final String description;
653653

@@ -657,7 +657,7 @@ final class _FunctionWorkItem extends _IndexedDbWorkItem {
657657
FutureOr<void> run() => work();
658658
}
659659

660-
final class _DeleteFileWorkItem extends _IndexedDbWorkItem {
660+
class _DeleteFileWorkItem extends _IndexedDbWorkItem {
661661
final IndexedDbFileSystem fileSystem;
662662
final String path;
663663

@@ -720,7 +720,7 @@ final class _DeleteFileWorkItem extends _IndexedDbWorkItem {
720720
}
721721
}
722722

723-
final class _CreateFileWorkItem extends _IndexedDbWorkItem {
723+
class _CreateFileWorkItem extends _IndexedDbWorkItem {
724724
final IndexedDbFileSystem fileSystem;
725725
final String path;
726726

@@ -733,7 +733,7 @@ final class _CreateFileWorkItem extends _IndexedDbWorkItem {
733733
}
734734
}
735735

736-
final class _WriteFileWorkItem extends _IndexedDbWorkItem {
736+
class _WriteFileWorkItem extends _IndexedDbWorkItem {
737737
final IndexedDbFileSystem fileSystem;
738738
final String path;
739739

sqlite3/lib/src/wasm/vfs/client.dart renamed to sqlite3/lib/src/wasm/vfs/async_opfs/client.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import 'dart:typed_data';
55
import 'package:js/js_util.dart';
66
import 'package:path/path.dart' as p;
77

8-
import '../../constants.dart';
9-
import '../../vfs.dart';
10-
import '../js_interop.dart';
8+
import '../../../constants.dart';
9+
import '../../../vfs.dart';
10+
import '../../js_interop.dart';
1111
import 'sync_channel.dart';
1212
import 'worker.dart';
1313

@@ -71,7 +71,7 @@ class WasmVfs extends BaseVirtualFileSystem {
7171

7272
final outFlags = result.flag0;
7373
final fd = result.flag1;
74-
return (outFlags: outFlags, file: WasmFile(this, fd));
74+
return XOpenResult(outFlags: outFlags, file: WasmFile(this, fd));
7575
}
7676

7777
@override

sqlite3/lib/src/wasm/vfs/sync_channel.dart renamed to sqlite3/lib/src/wasm/vfs/async_opfs/sync_channel.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,26 @@ import 'dart:convert';
22
import 'dart:html';
33
import 'dart:typed_data';
44

5-
import '../js_interop.dart';
5+
import '../../js_interop.dart';
66

77
const protocolVersion = 1;
88
const asyncIdleWaitTimeMs = 150;
99
const asyncIdleWaitTime = Duration(milliseconds: asyncIdleWaitTimeMs);
1010

11+
/// Implements a synchronous mechanism to wait for requests and responses.
1112
class RequestResponseSynchronizer {
1213
static const _requestIndex = 0;
1314
static const _responseIndex = 1;
1415

1516
// 2 32-bit slots for the int32 array
1617
static const byteLength = 2 * 4;
1718

19+
/// The shared array buffer used with atomics for synchronization.
20+
///
21+
/// It must have a length of [byteLength].
1822
final SharedArrayBuffer buffer;
23+
24+
/// A int32 view over [buffer], required for atomics to work.
1925
final Int32List int32View;
2026

2127
RequestResponseSynchronizer._(this.buffer) : int32View = buffer.asInt32List();
@@ -29,6 +35,8 @@ class RequestResponseSynchronizer {
2935
buffer ?? SharedArrayBuffer(byteLength));
3036
}
3137

38+
/// Send a request with the given [opcode], wait for the remote worker to
39+
/// process it and returns the response code.
3240
int requestAndWaitForResponse(int opcode) {
3341
Atomics.store(int32View, _responseIndex, -1);
3442
Atomics.store(int32View, _requestIndex, opcode);

sqlite3/lib/src/wasm/vfs/worker.dart renamed to sqlite3/lib/src/wasm/vfs/async_opfs/worker.dart

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import 'dart:html';
33
import 'package:js/js.dart';
44
import 'package:path/path.dart' as p show url;
55

6-
import '../../constants.dart';
7-
import '../../vfs.dart';
8-
import '../js_interop.dart';
6+
import '../../../constants.dart';
7+
import '../../../vfs.dart';
8+
import '../../js_interop.dart';
99
import 'sync_channel.dart';
1010

1111
const _workerDebugLog =
@@ -45,6 +45,19 @@ class WorkerOptions {
4545
}
4646
}
4747

48+
class _ResolvedPath {
49+
final String fullPath;
50+
51+
final FileSystemDirectoryHandle directory;
52+
final String filename;
53+
54+
_ResolvedPath(this.fullPath, this.directory, this.filename);
55+
56+
Future<FileSystemFileHandle> openFile({bool create = false}) {
57+
return directory.openFile(filename, create: create);
58+
}
59+
}
60+
4861
class VfsWorker {
4962
final RequestResponseSynchronizer synchronizer;
5063
final MessageSerializer messages;
@@ -55,8 +68,6 @@ class VfsWorker {
5568
final Map<int, _OpenedFileHandle> _openFiles = {};
5669
final Set<_OpenedFileHandle> _implicitlyHeldLocks = {};
5770

58-
var _shutdownRequested = false;
59-
6071
VfsWorker._(WorkerOptions options, this.root)
6172
: synchronizer =
6273
RequestResponseSynchronizer(options.synchronizationBuffer),
@@ -73,30 +84,30 @@ class VfsWorker {
7384
return VfsWorker._(options, root);
7485
}
7586

76-
Future<(FileSystemDirectoryHandle, String, String)> _resolvePath(
77-
String absolutePath,
87+
Future<_ResolvedPath> _resolvePath(String absolutePath,
7888
{bool createDirectories = false}) async {
7989
final fullPath = p.url.relative(absolutePath, from: '/');
80-
final [...dir, file] = p.url.split(fullPath);
90+
final directories = p.url.split(fullPath);
91+
final file = directories.removeLast();
8192

8293
var dirHandle = root;
83-
for (final entry in dir) {
94+
for (final entry in directories) {
8495
dirHandle =
8596
await dirHandle.getDirectory(entry, create: createDirectories);
8697
}
8798

88-
return (dirHandle, fullPath, file);
99+
return _ResolvedPath(fullPath, dirHandle, file);
89100
}
90101

91102
Future<Flags> _xAccess(NameAndInt32Flags flags) async {
92103
var rc = 0;
93104

94105
try {
95-
final (dir, _, fileName) = await _resolvePath(flags.name);
106+
final resolved = await _resolvePath(flags.name);
96107

97108
// If we can open the file, it exists. For OPFS, that means that it's both
98109
// readable and writable.
99-
await dir.openFile(fileName);
110+
await resolved.openFile();
100111
} catch (e) {
101112
rc = SqlError.SQLITE_IOERR;
102113
}
@@ -105,9 +116,9 @@ class VfsWorker {
105116
}
106117

107118
Future<void> _xDelete(NameAndInt32Flags options) async {
108-
final (dirHandle, _, basename) = await _resolvePath(options.name);
119+
final resolved = await _resolvePath(options.name);
109120
try {
110-
await dirHandle.removeEntry(basename);
121+
await resolved.directory.removeEntry(resolved.filename);
111122
} catch (e) {
112123
_log('Could not delete entry: $e');
113124
throw const VfsException(SqlExtendedError.SQLITE_IOERR_DELETE);
@@ -118,24 +129,22 @@ class VfsWorker {
118129
final flags = req.flag0;
119130
final create = (flags & SqlFlag.SQLITE_OPEN_CREATE) != 0;
120131

121-
FileSystemDirectoryHandle directory;
122-
String fullPath, fileName;
132+
_ResolvedPath resolved;
123133

124134
try {
125-
(directory, fullPath, fileName) =
126-
await _resolvePath(req.name, createDirectories: create);
135+
resolved = await _resolvePath(req.name, createDirectories: create);
127136
} catch (e) {
128137
// Error traversing the path
129138
throw VfsException(SqlError.SQLITE_NOTFOUND);
130139
}
131140

132-
final fileHandle = await directory.openFile(fileName, create: create);
141+
final fileHandle = await resolved.openFile(create: create);
133142
final readonly = !create && (flags & SqlFlag.SQLITE_OPEN_READONLY) != 0;
134143
final opened = _OpenedFileHandle(
135144
fd: _fdCounter++,
136-
directory: directory,
137-
fullPath: fullPath,
138-
filename: fileName,
145+
directory: resolved.directory,
146+
fullPath: resolved.fullPath,
147+
filename: resolved.filename,
139148
file: fileHandle,
140149
deleteOnClose: (flags & SqlFlag.SQLITE_OPEN_DELETEONCLOSE) != 0,
141150
readonly: readonly,
@@ -268,7 +277,7 @@ class VfsWorker {
268277
}
269278

270279
Future<void> start() async {
271-
while (!_shutdownRequested) {
280+
while (true) {
272281
final waitResult = synchronizer.waitForRequest();
273282
if (waitResult == Atomics.timedOut) {
274283
// No requests for some time, transition to idle

sqlite3/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ homepage: https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3
55
issue_tracker: https://github.com/simolus3/sqlite3.dart/issues
66

77
environment:
8-
sdk: '>=2.3.0 <4.0.0'
8+
sdk: '>=3.0.0 <4.0.0'
99

1010
# This package supports all platforms listed below.
1111
platforms:
@@ -32,7 +32,7 @@ dev_dependencies:
3232
build_daemon: ^4.0.0
3333
build_runner: ^2.1.7
3434
build_web_compilers: ^4.0.3
35-
ffigen: ^8.0.0-dev
35+
ffigen: ^7.0.0
3636
http: ^0.13.4
3737
lints: ^2.0.1
3838
shelf: ^1.4.0

0 commit comments

Comments
 (0)