Get new wasm implementation working in Chrome

This commit is contained in:
Simon Binder 2023-05-31 22:48:29 +02:00
parent d79633ee6b
commit ff41de2a6b
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
11 changed files with 52 additions and 48 deletions

View File

@ -11,6 +11,7 @@ import 'dart:async';
import 'dart:html'; import 'dart:html';
import 'package:async/async.dart'; import 'package:async/async.dart';
import 'package:drift/drift.dart';
import 'package:drift/remote.dart'; import 'package:drift/remote.dart';
import 'package:drift/wasm.dart'; import 'package:drift/wasm.dart';
import 'package:js/js.dart'; import 'package:js/js.dart';
@ -59,7 +60,7 @@ Future<WasmDatabaseResult> openWasmDatabase({
final port = sharedWorker.port!; final port = sharedWorker.port!;
final sharedMessages = final sharedMessages =
StreamQueue(port.onMessage.map(WasmInitializationMessage.fromJs)); StreamQueue(port.onMessage.map(WasmInitializationMessage.read));
// First, the shared worker will tell us which features it supports. // First, the shared worker will tell us which features it supports.
final sharedFeatures = await sharedMessages.next as SharedWorkerStatus; final sharedFeatures = await sharedMessages.next as SharedWorkerStatus;
@ -82,7 +83,7 @@ Future<WasmDatabaseResult> openWasmDatabase({
DedicatedWorkerCompatibilityCheck().sendToWorker(dedicatedWorker); DedicatedWorkerCompatibilityCheck().sendToWorker(dedicatedWorker);
final workerMessages = StreamQueue( final workerMessages = StreamQueue(
dedicatedWorker.onMessage.map(WasmInitializationMessage.fromJs)); dedicatedWorker.onMessage.map(WasmInitializationMessage.read));
final status = final status =
await workerMessages.next as DedicatedWorkerCompatibilityResult; await workerMessages.next as DedicatedWorkerCompatibilityResult;
@ -103,7 +104,9 @@ Future<WasmDatabaseResult> openWasmDatabase({
sqlite3.registerVirtualFileSystem(InMemoryFileSystem()); sqlite3.registerVirtualFileSystem(InMemoryFileSystem());
return WasmDatabaseResult( return WasmDatabaseResult(
WasmDatabase(sqlite3: sqlite3, path: '/app.db'), DatabaseConnection(
WasmDatabase(sqlite3: sqlite3, path: '/app.db'),
),
WasmStorageImplementation.inMemory, WasmStorageImplementation.inMemory,
missingFeatures, missingFeatures,
); );

View File

@ -15,7 +15,7 @@ sealed class WasmInitializationMessage {
factory WasmInitializationMessage.fromJs(Object jsObject) { factory WasmInitializationMessage.fromJs(Object jsObject) {
final type = getProperty<String>(jsObject, 'type'); final type = getProperty<String>(jsObject, 'type');
final payload = getProperty<String>(jsObject, 'payload'); final payload = getProperty<Object>(jsObject, 'payload');
return switch (type) { return switch (type) {
SharedWorkerStatus.type => SharedWorkerStatus.fromJsPayload(payload), SharedWorkerStatus.type => SharedWorkerStatus.fromJsPayload(payload),
@ -165,7 +165,7 @@ final class DedicatedWorkerCompatibilityCheck
@override @override
void _send(_PostMessage sender) { void _send(_PostMessage sender) {
sender.sendTyped(type, null); sender.sendTyped(type, newObject());
} }
} }

View File

@ -11,12 +11,17 @@
@experimental @experimental
library drift.wasm; library drift.wasm;
import 'dart:html';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:sqlite3/wasm.dart'; import 'package:sqlite3/wasm.dart';
import 'backends.dart'; import 'backends.dart';
import 'drift.dart';
import 'src/sqlite3/database.dart'; import 'src/sqlite3/database.dart';
import 'src/web/wasm_setup.dart'; import 'src/web/wasm_setup.dart';
import 'src/web/wasm_setup/dedicated_worker.dart';
import 'src/web/wasm_setup/shared_worker.dart';
/// Signature of a function that can perform setup work on a [database] before /// Signature of a function that can perform setup work on a [database] before
/// drift is fully ready. /// drift is fully ready.
@ -76,6 +81,16 @@ class WasmDatabase extends DelegatedDatabase {
driftWorkerUri: driftWorkerUri, driftWorkerUri: driftWorkerUri,
); );
} }
static void workerMainForOpen() {
final self = WorkerGlobalScope.instance;
if (self is DedicatedWorkerGlobalScope) {
DedicatedDriftWorker(self).start();
} else if (self is SharedWorkerGlobalScope) {
SharedDriftWorker(self).start();
}
}
} }
class _WasmDelegate extends Sqlite3Delegate<CommonDatabase> { class _WasmDelegate extends Sqlite3Delegate<CommonDatabase> {
@ -225,7 +240,7 @@ enum MissingBrowserFeature {
} }
class WasmDatabaseResult { class WasmDatabaseResult {
final QueryExecutor resolvedExecutor; final DatabaseConnection resolvedExecutor;
final WasmStorageImplementation chosenImplementation; final WasmStorageImplementation chosenImplementation;
final Set<MissingBrowserFeature> missingFeatures; final Set<MissingBrowserFeature> missingFeatures;

View File

@ -1,15 +1,5 @@
import 'dart:async'; import 'package:drift/wasm.dart';
import 'dart:html';
import 'package:drift/src/web/wasm_setup/dedicated_worker.dart'; void main() {
import 'package:drift/src/web/wasm_setup/shared_worker.dart'; WasmDatabase.workerMainForOpen();
Future<void> main() async {
final self = WorkerGlobalScope.instance;
if (self is DedicatedWorkerGlobalScope) {
DedicatedDriftWorker(self).start();
} else if (self is SharedWorkerGlobalScope) {
SharedDriftWorker(self).start();
}
} }

View File

@ -30,7 +30,7 @@
.pub-cache/ .pub-cache/
.pub/ .pub/
/build/ /build/
web/shared_worker.dart.js web/drift_worker.js
# Web related # Web related

View File

@ -50,4 +50,4 @@ builders:
import: 'tool/builder.dart' import: 'tool/builder.dart'
builder_factories: ["CopyCompiledJs.new"] builder_factories: ["CopyCompiledJs.new"]
build_to: source build_to: source
build_extensions: {'web/worker.dart.js': ['web/shared_worker.dart.js']} build_extensions: {'web/worker.dart.js': ['web/drift_worker.js']}

View File

@ -2,31 +2,24 @@ import 'dart:async';
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:drift/wasm.dart'; import 'package:drift/wasm.dart';
import 'package:drift/web/worker.dart'; import 'package:flutter/foundation.dart';
import 'package:sqlite3/wasm.dart';
const _useWorker = true;
/// Obtains a database connection for running drift on the web. /// Obtains a database connection for running drift on the web.
DatabaseConnection connect({bool isInWebWorker = false}) { DatabaseConnection connect() {
if (_useWorker && !isInWebWorker) { return DatabaseConnection.delayed(Future(() async {
return DatabaseConnection.delayed(connectToDriftWorker( final db = await WasmDatabase.open(
'shared_worker.dart.js', databaseName: 'todo-app',
mode: DriftWorkerMode.shared)); sqlite3Uri: Uri.parse('/sqlite3.wasm'),
} else { driftWorkerUri: Uri.parse('/drift_worker.js'),
return DatabaseConnection.delayed(
Future.sync(() async {
final fs = await IndexedDbFileSystem.open(dbName: 'my_app');
final sqlite3 = await WasmSqlite3.loadFromUrl(
Uri.parse('sqlite3.wasm'),
environment: SqliteEnvironment(fileSystem: fs),
);
final databaseImpl = WasmDatabase(sqlite3: sqlite3, path: 'app.db');
return DatabaseConnection(databaseImpl);
}),
); );
}
if (db.missingFeatures.isNotEmpty) {
debugPrint('Using ${db.chosenImplementation} due to unsupported '
'browser features: ${db.missingFeatures}');
}
return db.resolvedExecutor;
}));
} }
Future<void> validateDatabaseSchema(GeneratedDatabase database) async { Future<void> validateDatabaseSchema(GeneratedDatabase database) async {

View File

@ -19,7 +19,7 @@ dependencies:
intl: ^0.18.0 intl: ^0.18.0
http: ^0.13.4 # used to load sqlite3 wasm files on the web http: ^0.13.4 # used to load sqlite3 wasm files on the web
sqlite3_flutter_libs: ^0.5.5 sqlite3_flutter_libs: ^0.5.5
sqlite3: ^1.11.0 sqlite3: ^2.0.0-dev.0
path_provider: ^2.0.9 path_provider: ^2.0.9
path: ^1.8.0 path: ^1.8.0
riverpod: ^2.3.0 riverpod: ^2.3.0
@ -39,3 +39,7 @@ dev_dependencies:
flutter: flutter:
uses-material-design: true uses-material-design: true
dependency_overrides:
sqlite3:
path: /home/simon/src/sqlite3.dart/sqlite3

View File

@ -15,6 +15,6 @@ class CopyCompiledJs extends Builder {
@override @override
Map<String, List<String>> get buildExtensions => { Map<String, List<String>> get buildExtensions => {
r'$package$': ['web/shared_worker.dart.js'] r'$package$': ['web/drift_worker.js']
}; };
} }

View File

@ -1,10 +1,9 @@
import 'package:app/database/connection/web.dart'; import 'package:drift/wasm.dart';
import 'package:drift/web/worker.dart';
/// This Dart program is the entrypoint of a web worker that will be compiled to /// This Dart program is the entrypoint of a web worker that will be compiled to
/// JavaScript by running `build_runner build`. The resulting JavaScript file /// JavaScript by running `build_runner build`. The resulting JavaScript file
/// (`shared_worker.dart.js`) is part of the build result and will be shipped /// (`shared_worker.dart.js`) is part of the build result and will be shipped
/// with the rest of the application when running or building a Flutter web app. /// with the rest of the application when running or building a Flutter web app.
void main() { void main() {
return driftWorkerMain(() => connect(isInWebWorker: true)); return WasmDatabase.workerMainForOpen();
} }

Binary file not shown.