@@ -227,15 +227,19 @@ final class WorkerConnection extends ProtocolChannel {
227
227
final class DatabaseClient implements WebSqlite {
228
228
final Uri workerUri;
229
229
final Uri wasmUri;
230
+ final DatabaseController _localController;
230
231
231
232
final Lock _startWorkersLock = Lock ();
232
233
bool _startedWorkers = false ;
233
234
WorkerConnection ? _connectionToDedicated;
234
235
WorkerConnection ? _connectionToShared;
235
236
WorkerConnection ? _connectionToDedicatedInShared;
237
+
238
+ WorkerConnection ? _connectionToLocal;
239
+
236
240
final Set <MissingBrowserFeature > _missingFeatures = {};
237
241
238
- DatabaseClient (this .workerUri, this .wasmUri);
242
+ DatabaseClient (this .workerUri, this .wasmUri, this ._localController );
239
243
240
244
Future <void > startWorkers () {
241
245
return _startWorkersLock.synchronized (() async {
@@ -244,36 +248,52 @@ final class DatabaseClient implements WebSqlite {
244
248
}
245
249
_startedWorkers = true ;
246
250
247
- if (globalContext.has ('Worker' )) {
248
- final dedicated = Worker (
251
+ await _startDedicated ();
252
+ await _startShared ();
253
+ });
254
+ }
255
+
256
+ Future <void > _startDedicated () async {
257
+ if (globalContext.has ('Worker' )) {
258
+ final Worker dedicated;
259
+ try {
260
+ dedicated = Worker (
249
261
workerUri.toString ().toJS,
250
262
WorkerOptions (name: 'sqlite3_worker' ),
251
263
);
252
-
253
- final (endpoint, channel) = await createChannel ();
254
- ConnectRequest (endpoint: endpoint, requestId: 0 )
255
- .sendToWorker (dedicated);
256
-
257
- _connectionToDedicated =
258
- WorkerConnection (channel.injectErrorsFrom (dedicated));
259
- } else {
264
+ } on Object {
260
265
_missingFeatures.add (MissingBrowserFeature .dedicatedWorkers);
266
+ return ;
261
267
}
262
268
263
- if (globalContext.has ('SharedWorker' )) {
264
- final shared = SharedWorker (workerUri.toString ().toJS);
265
- shared.port.start ();
269
+ final (endpoint, channel) = await createChannel ();
270
+ ConnectRequest (endpoint: endpoint, requestId: 0 ).sendToWorker (dedicated);
266
271
267
- final (endpoint, channel) = await createChannel ();
268
- ConnectRequest (endpoint: endpoint, requestId: 0 )
269
- .sendToPort (shared.port);
272
+ _connectionToDedicated =
273
+ WorkerConnection (channel.injectErrorsFrom (dedicated));
274
+ } else {
275
+ _missingFeatures.add (MissingBrowserFeature .dedicatedWorkers);
276
+ }
277
+ }
270
278
271
- _connectionToShared =
272
- WorkerConnection (channel.injectErrorsFrom (shared));
273
- } else {
279
+ Future <void > _startShared () async {
280
+ if (globalContext.has ('SharedWorker' )) {
281
+ final SharedWorker shared;
282
+ try {
283
+ shared = SharedWorker (workerUri.toString ().toJS);
284
+ shared.port.start ();
285
+ } on Object {
274
286
_missingFeatures.add (MissingBrowserFeature .sharedWorkers);
287
+ return ;
275
288
}
276
- });
289
+
290
+ final (endpoint, channel) = await createChannel ();
291
+ ConnectRequest (endpoint: endpoint, requestId: 0 ).sendToPort (shared.port);
292
+
293
+ _connectionToShared = WorkerConnection (channel.injectErrorsFrom (shared));
294
+ } else {
295
+ _missingFeatures.add (MissingBrowserFeature .sharedWorkers);
296
+ }
277
297
}
278
298
279
299
Future <WorkerConnection > _connectToDedicatedInShared () {
@@ -291,6 +311,22 @@ final class DatabaseClient implements WebSqlite {
291
311
});
292
312
}
293
313
314
+ Future <WorkerConnection > _connectToLocal () async {
315
+ return _startWorkersLock.synchronized (() async {
316
+ if (_connectionToLocal case final conn? ) {
317
+ return conn;
318
+ }
319
+
320
+ final local = Local ();
321
+ final (endpoint, channel) = await createChannel ();
322
+ WorkerRunner (_localController, environment: local).handleRequests ();
323
+ local
324
+ .addTopLevelMessage (ConnectRequest (requestId: 0 , endpoint: endpoint));
325
+
326
+ return _connectionToLocal = WorkerConnection (channel);
327
+ });
328
+ }
329
+
294
330
@override
295
331
Future <void > deleteDatabase (
296
332
{required String name, required StorageMode storage}) async {
@@ -310,6 +346,7 @@ final class DatabaseClient implements WebSqlite {
310
346
311
347
final existing = < ExistingDatabase > {};
312
348
final available = < (StorageMode , AccessMode )> [];
349
+ var workersReportedIndexedDbSupport = false ;
313
350
314
351
if (_connectionToDedicated case final connection? ) {
315
352
final response = await connection.sendRequest (
@@ -327,6 +364,8 @@ final class DatabaseClient implements WebSqlite {
327
364
if (result.canUseIndexedDb) {
328
365
available
329
366
.add ((StorageMode .indexedDb, AccessMode .throughDedicatedWorker));
367
+
368
+ workersReportedIndexedDbSupport = true ;
330
369
} else {
331
370
_missingFeatures.add (MissingBrowserFeature .indexedDb);
332
371
}
@@ -363,6 +402,7 @@ final class DatabaseClient implements WebSqlite {
363
402
final result = CompatibilityResult .fromJS (response.response as JSObject );
364
403
365
404
if (result.canUseIndexedDb) {
405
+ workersReportedIndexedDbSupport = true ;
366
406
available.add ((StorageMode .indexedDb, AccessMode .throughSharedWorker));
367
407
} else {
368
408
_missingFeatures.add (MissingBrowserFeature .indexedDb);
@@ -383,6 +423,12 @@ final class DatabaseClient implements WebSqlite {
383
423
}
384
424
}
385
425
426
+ available.add ((StorageMode .inMemory, AccessMode .inCurrentContext));
427
+ if (workersReportedIndexedDbSupport || await checkIndexedDbSupport ()) {
428
+ // If the workers can use IndexedDb, so can we.
429
+ available.add ((StorageMode .indexedDb, AccessMode .inCurrentContext));
430
+ }
431
+
386
432
return FeatureDetectionResult (
387
433
missingFeatures: _missingFeatures.toList (),
388
434
existingDatabases: existing.toList (),
@@ -425,7 +471,8 @@ final class DatabaseClient implements WebSqlite {
425
471
connection = _connectionToDedicated! ;
426
472
shared = false ;
427
473
case AccessMode .inCurrentContext:
428
- throw UnimplementedError ('todo: Open database locally' );
474
+ connection = await _connectToLocal ();
475
+ shared = false ;
429
476
}
430
477
431
478
final response = await connection.sendRequest (
0 commit comments