Skip to content

Commit

Permalink
[sqflite_common_ffi_web] fix issue #1095 android web support
Browse files Browse the repository at this point in the history
  • Loading branch information
alextekartik committed Apr 10, 2024
1 parent b414d0e commit d1790b9
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 18 deletions.
29 changes: 28 additions & 1 deletion packages_web/sqflite_common_ffi_web/example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ var swOptions = SqfliteFfiWebOptions(
sharedWorkerUri: Uri.parse('sw.dart.js'),
// ignore: invalid_use_of_visible_for_testing_member
forceAsBasicWorker: _useBasicWebWorker);

var swBasicOptions = SqfliteFfiWebOptions(
sharedWorkerUri: Uri.parse('sw.dart.js'),
// ignore: invalid_use_of_visible_for_testing_member
forceAsBasicWorker: true);
Future incrementPrebuilt() async {
await incrementSqfliteValueInDatabaseFactory(databaseFactoryWebPrebuilt,
tag: 'prebuilt');
Expand Down Expand Up @@ -130,15 +133,22 @@ Future<void> main() async {

var _webContextRegisterAndReady = sqfliteFfiWebStartSharedWorker(swOptions);

var _webBasicContextRegisterAndReady =
sqfliteFfiWebStartSharedWorker(swBasicOptions);

Future<web.SharedWorker> sharedWorkerRegisterAndReady() async =>
(await _webContextRegisterAndReady).sharedWorker!;

Future<SqfliteFfiWebContext> webContextRegisterAndReady() async =>
(await _webContextRegisterAndReady);

Future<SqfliteFfiWebContext> webBasicContextRegisterAndReady() async =>
(await _webBasicContextRegisterAndReady);
var databaseFactoryWebPrebuilt = databaseFactoryFfiWeb;
var databaseFactoryWebNoWebWorkerLocal = databaseFactoryFfiWebNoWebWorker;
var databaseFactoryWebLocal = createDatabaseFactoryFfiWeb(options: swOptions);
var databaseFactoryWebBasicWorkerLocal =
createDatabaseFactoryFfiWeb(options: swBasicOptions);

var key = 'testValue';

Expand Down Expand Up @@ -171,6 +181,20 @@ Future<void> incrementVarInSharedWorker() async {
write('var after $value');
}

Future<void> incrementVarInBasicdWorker() async {
var context = await webBasicContextRegisterAndReady();
write('basic worker ready');
var value = await getTestValue(context);
write('var before $value');
if (value is! int) {
value = 0;
}

await setTestValue(context, value + 1);
value = await getTestValue(context);
write('var after $value');
}

Future<void> incrementSqfliteValueInDatabaseFactory(DatabaseFactory factory,
{String? tag}) async {
tag ??= 'db';
Expand Down Expand Up @@ -221,6 +245,9 @@ void initUi() {
addButton('increment var in shared worker', () async {
await incrementVarInSharedWorker();
});
addButton('increment var in basic worker', () async {
await incrementVarInBasicdWorker();
});
addButton('increment sqflite value in main thread', () async {
await incrementNoWebWorker();
});
Expand Down
5 changes: 4 additions & 1 deletion packages_web/sqflite_common_ffi_web/lib/sqflite_ffi_web.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
export 'src/database_factory.dart' show createDatabaseFactoryFfiWeb;
export 'src/debug/debug.dart' show sqliteFfiWebDebugWebWorker;
export 'src/sqflite_ffi.dart'
show databaseFactoryFfiWeb, databaseFactoryFfiWebNoWebWorker;
show
databaseFactoryFfiWeb,
databaseFactoryFfiWebNoWebWorker,
databaseFactoryFfiWebBasicWebWorker;
export 'src/web/load_sqlite.dart'
show
SqfliteFfiWebContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ var databaseFactoryFfiWebNoWebWorkerImpl = () {
return createDatabaseFactoryFfiWeb(noWebWorker: true);
}();

/// The Ffi database factory with basic worker
var databaseFactoryFfiWebBasicWorkerImpl = () {
return createDatabaseFactoryFfiWeb(
// ignore: invalid_use_of_visible_for_testing_member
options: SqfliteFfiWebOptions(forceAsBasicWorker: true));
}();

/// The Ffi database factory.
var databaseFactoryFfiWebImpl = () {
return createDatabaseFactoryFfiWeb();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ DatabaseFactory get databaseFactoryFfiWeb => throw UnsupportedError(
/// The database factory to use for ffi web. not supported on io
DatabaseFactory get databaseFactoryFfiWebNoWebWorker => throw UnsupportedError(
'databaseFactoryFfiWebNoWebWorker only supported on io');

/// The database factory to use for ffi web. not supported on io
DatabaseFactory get databaseFactoryFfiWebBasicWebWorker =>
throw UnsupportedError(
'databaseFactoryFfiWebBasicWebWorker only supported on io');
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ DatabaseFactory get databaseFactoryFfiWeb => databaseFactoryFfiWebImpl;
/// Run in the main ui thread so long query could potentially hang.
DatabaseFactory get databaseFactoryFfiWebNoWebWorker =>
databaseFactoryFfiWebNoWebWorkerImpl;

/// Testing only.
DatabaseFactory get databaseFactoryFfiWebBasicWebWorker =>
databaseFactoryFfiWebBasicWorkerImpl;
39 changes: 28 additions & 11 deletions packages_web/sqflite_common_ffi_web/lib/src/sw/shared_worker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ void mainSharedWorker(List<String> args) {
var zone = Zone.current;
try {
final scope = (globalContext as web.SharedWorkerGlobalScope);
try {
var scopeName = scope.name;
if (_debug) {
_log('$_shw scopeName: $scopeName');
}
} catch (e) {
if (_debug) {
_log('$_shw scope.name error $e');
}
}

scope.onconnect = (web.Event event) {
zone.run(() {
Expand All @@ -133,23 +143,30 @@ void mainSharedWorker(List<String> args) {
});
}.toJS;
} catch (e) {
final scope = (globalContext as web.DedicatedWorkerGlobalScope);
if (_debug) {
_log('$_shw not in shared worker, trying basic worker');
}
}

try {
scope.onmessage = (web.MessageEvent event) {
zone.run(() {
_handleMessageEvent(event);
});
}.toJS;
} catch (e) {
if (_debug) {
_log('$_shw not in shared worker error $e');
}
final scope = (globalContext as web.DedicatedWorkerGlobalScope);
if (_debug) {
_log('$_shw basic worker support');
}

/// Handle basic web workers
/// dirty hack
try {
scope.onmessage = (web.MessageEvent event) {
zone.run(() {
_handleMessageEvent(event);
});
}.toJS;
} catch (e) {
if (_debug) {
_log('$_shw not in shared worker error $e');
}
}

if (_debug) {
_log('$_shw main done ($_debugVersion)');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class SqfliteFfiWebOptions {
this.indexedDbName,
this.sharedWorkerUri,
@visibleForTesting this.forceAsBasicWorker});

@override
String toString() {
return 'SqfliteFfiWebOptions(inMemory: $inMemory, sqlite3WasmUri: $sqlite3WasmUri, indexedDbName: $indexedDbName, sharedWorkerUri: $sharedWorkerUri, forceAsBasicWorker: $forceAsBasicWorker)';
}
}

/// Abstract context for the web (holder file system and wasm)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@TestOn('browser')
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
import 'package:sqflite_common_test/all_test.dart' as all;
import 'package:sqflite_common_test/sqflite_test.dart';
import 'package:test/test.dart';

var _factory = createDatabaseFactoryFfiWeb(
options: SqfliteFfiWebOptions(
forceAsBasicWorker: true,
sharedWorkerUri: Uri.parse('sqflite_sw_v1.js')));

class SqfliteFfiWebTestContext extends SqfliteLocalTestContext {
SqfliteFfiWebTestContext() : super(databaseFactory: _factory);
}

var ffiTestContext = SqfliteFfiWebTestContext();

Future<void> main() async {
/// Initialize ffi loader
// sqliteFfiWebDebugWebWorker = true;
sqfliteFfiInit();
try {
var dbsPath = await _factory.getDatabasesPath();
await _factory.setDatabasesPath('${dbsPath}_web_basic_worker');

all.run(ffiTestContext);
} catch (e) {
print('Please run setup_web_tests first');
test('Please run setup_web_tests first', () {}, skip: true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ Future<void> main() async {
/// Initialize ffi loader
// sqliteFfiWebDebugWebWorker = true;
sqfliteFfiInit();
print('1');
try {
var dbsPath = await _factory.getDatabasesPath();
await _factory.setDatabasesPath('${dbsPath}_web');
Expand Down
8 changes: 8 additions & 0 deletions packages_web/sqflite_common_ffi_web_test/web/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ Future<void> main() async {
options: SqfliteFfiWebOptions(
sharedWorkerUri: Uri.parse('sqflite_sw_v2.js')));
}
if (true) {
// devWarning(true)) {
factory = createDatabaseFactoryFfiWeb(
options: SqfliteFfiWebOptions(
// ignore: invalid_use_of_visible_for_testing_member
forceAsBasicWorker: true,
sharedWorkerUri: Uri.parse('sqflite_sw_v1.js')));
}

var db = await factory.openDatabase(inMemoryDatabasePath);
var sqliteVersion =
Expand Down
14 changes: 10 additions & 4 deletions sqflite_test_app/lib/main_ffi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ Future<void> main() async {
}

/// Run using ffi (io or web)
Future<void> mainFfi() async {
await initFfi();
Future<void> mainFfi({bool? webBasicWorker}) async {
await initFfi(webBasicWorker: webBasicWorker);
await runFfi();
}

/// Init Ffi for io or web
///
/// if [noWorker] is true, no isolate is used on io and no web worker is used on the web.
Future<void> initFfi({bool? noWorker}) async {
Future<void> initFfi({bool? noWorker, bool? webBasicWorker}) async {
noWorker ??= false;
// getDatabasesPath implementation is lame, use the default one
// but we could also use path_provider
Expand All @@ -35,7 +35,13 @@ Future<void> initFfi({bool? noWorker}) async {
if (noWorker) {
databaseFactoryOrNull = databaseFactoryFfiWebNoWebWorker;
} else {
databaseFactoryOrNull = databaseFactoryFfiWeb;
webBasicWorker ??= false;
if (webBasicWorker) {
databaseFactoryOrNull = databaseFactoryFfiWebBasicWebWorker;
} else {
// default (not supported on io
databaseFactoryOrNull = databaseFactoryFfiWeb;
}
}
// Platform handler for the example app
platformHandler = platformHandlerWeb;
Expand Down
16 changes: 16 additions & 0 deletions sqflite_test_app/lib/main_web_simple_worker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// ignore_for_file: unused_import

import 'package:flutter/foundation.dart';
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';

import 'main_ffi.dart';

void main() {
if (kIsWeb) {
// sqliteFfiWebDebugWebWorker = true;
// ignore: avoid_print
print('running on the web basic worker');
}
mainFfi(webBasicWorker: true);
//mainFfi();
}
16 changes: 16 additions & 0 deletions sqflite_test_app/tool/flutter_build_and_serve_basic_worker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:dev_build/build_support.dart';
import 'package:path/path.dart';
import 'package:process_run/shell.dart';

Future<void> main() async {
await checkAndActivatePackage('dhttpd');
var shell = Shell();
await shell.run('''
flutter build web -t lib/main_web_simple_worker.dart''');
shell = shell.cd(join('build', 'web'));
// ignore: avoid_print
print('http://localhost:8080');

await shell.run(
'dart pub global run dhttpd:dhttpd . --headers=Cross-Origin-Embedder-Policy=credentialless;Cross-Origin-Opener-Policy=same-origin');
}
5 changes: 5 additions & 0 deletions sqflite_test_app/tool/setup_web_force.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import 'package:sqflite_common_ffi_web/src/setup/setup.dart';

Future<void> main() async {
await setupBinaries(options: SetupOptions(force: true, verbose: true));
}

0 comments on commit d1790b9

Please sign in to comment.