Skip to content

Commit

Permalink
WIP - Working around jsify/dartify
Browse files Browse the repository at this point in the history
  • Loading branch information
d-markey committed Dec 31, 2024
1 parent ef4b035 commit e7e700a
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 20 deletions.
6 changes: 3 additions & 3 deletions lib/src/_impl/web/_bootstrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ void bootstrap(WorkerInitializer initializer, WorkerRequest? command) {
});

self.onmessage = (web.MessageEvent e) {
final msg = getMessageEventData(e) as List;
final msg = getMessageEventData(e);
com.port1.onmessage = runner.handle.toJS;
runner.connect(WorkerRequestExt.from(msg), com.port2, initializer);
runner.connect(WorkerRequestExt.from(msg!), com.port2, initializer);
}.toJS;

// initial message indicating the worker is up and running
self.postMessage(WorkerResponse.ready().wrapInPlace().jsify());
self.postMessage($jsify(WorkerResponse.ready().wrapInPlace()));
}
6 changes: 3 additions & 3 deletions lib/src/_impl/web/_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import '../../worker/worker_request.dart';
import '../../worker/worker_response.dart';
import '../xplat/_disconnected_channel.dart';
import '../xplat/_result_stream.dart';
import '../xplat/_transferables.dart';
import '_entry_point_uri.dart';
import '_event_buffer.dart';
import '_patch.dart';
import '_transferables.dart';
import '_typedefs.dart';
import '_uri_checker.dart';

Expand Down Expand Up @@ -141,12 +141,12 @@ Future<Channel> openChannel(

try {
final data = startRequest.wrapInPlace();
final msg = data.jsify();
final msg = $jsify(data);
final transfer = Transferables.get(data);
if (transfer == null || transfer.isEmpty) {
worker.postMessage(msg);
} else {
final jsTransfer = transfer.jsify() as JSArray;
final jsTransfer = $jsify(transfer) as JSArray;
worker.postMessage(msg, jsTransfer);
}
} catch (ex, st) {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/_impl/web/_channel_forward.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class _WebForwardChannel extends _WebChannel {
if (transfer == null || transfer.isEmpty) {
_remote.postMessage(e.data);
} else {
final jsTransfer = transfer.jsify() as JSArray;
final jsTransfer = $jsify(transfer) as JSArray;
_remote.postMessage(e.data, jsTransfer);
}
} catch (ex, st) {
Expand Down
8 changes: 4 additions & 4 deletions lib/src/_impl/web/_channel_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ final class _WebChannel implements Channel {
try {
req.cancelToken?.ensureStarted();
final data = req.wrapInPlace();
final msg = data.jsify();
final msg = $jsify(data);
final transfer = Transferables.get([req.channelInfo]);
if (transfer == null || transfer.isEmpty) {
_sendPort.postMessage(msg);
} else {
final jsTransfer = transfer.jsify() as JSArray;
final jsTransfer = $jsify(transfer) as JSArray;
_sendPort.postMessage(msg, jsTransfer);
}
} catch (ex, st) {
Expand All @@ -57,12 +57,12 @@ final class _WebChannel implements Channel {
req.cancelToken?.throwIfCanceled();
try {
final data = req.wrapInPlace();
final msg = data.jsify();
final msg = $jsify(data);
final transfer = Transferables.get(data);
if (transfer == null || transfer.isEmpty) {
_sendPort.postMessage(msg);
} else {
final jsTransfer = transfer.jsify() as JSArray;
final jsTransfer = $jsify(transfer) as JSArray;
_sendPort.postMessage(msg, jsTransfer);
}
} catch (ex, st) {
Expand Down
120 changes: 117 additions & 3 deletions lib/src/_impl/web/_patch.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:js_interop';
import 'dart:js_interop_unsafe';
import 'dart:typed_data';

import 'package:web/web.dart';

Expand All @@ -11,15 +12,15 @@ String? getHome() {

String? _getErrorEventMessage(JSObject? obj) {
if (obj != null && obj.has('message')) {
return obj['message'].dartify()?.toString();
return $dartify(obj.getProperty('message'.toJS))?.toString();
} else {
return null;
}
}

Object? _getErrorEventError(JSObject? obj) {
if (obj != null && obj.has('error')) {
return obj['error'].dartify();
return $dartify(obj.getProperty('error'.toJS));
} else {
return null;
}
Expand All @@ -30,8 +31,121 @@ Object getError(JSObject? obj) =>

List? getMessageEventData(JSObject? obj) {
if (obj != null && obj.has('data')) {
return obj['data'].dartify() as List?;
return $dartify(obj.getProperty('data'.toJS)) as List?;
} else {
return null;
}
}

@JS('Map')
extension type _$JSMap._(JSObject _) implements JSObject {
external factory _$JSMap();
external JSAny get(JSAny? key);
external void set(JSAny? key, JSAny? value);
external JSObject keys();
}

@JS('BigInt')
external JSBigInt _$JSBigInt(JSAny? value);

extension on JSBigInt {
@JS('toString')
external JSString $toString();
}

extension _$JSIteratorExt on JSObject {
JSObject? next() => callMethod(_$next);
bool get done => getProperty(_$done).isTruthy.toDart;
JSAny? get value => getProperty(_$value);

static final _$next = 'next'.toJS;
static final _$done = 'done'.toJS;
static final _$value = 'value'.toJS;
}

JSAny? _jsify(Object? obj, Map<Object, JSAny> cache) {
if (obj == null) return null;
var js = cache[obj];
if (js != null) return js;
if (obj is BigInt) {
final bigint = _$JSBigInt(obj.toString().toJS);
print('BigInt $obj -> $bigint [${bigint.runtimeType}]');
return bigint;
}
if (obj is Map) {
final map = _$JSMap();
cache[obj] = map;
for (var entry in obj.entries) {
map.set(_jsify(entry.key, cache), _jsify(entry.value, cache));
}
print('_jsify: $map');
return map;
}
if (obj is List && obj is! TypedData) {
final len = obj.length;
final list = JSArray();
cache[obj] = list;
for (var i = 0; i < len; i++) {
list.setProperty(i.toJS, _jsify(obj[i], cache));
}
return list;
}
js = obj.jsify();
if (js != null && obj is! num && obj is! bool && obj is! String) {
cache[obj] = js;
}
return js;
}

JSAny? $jsify(Object? obj) {
return _jsify(obj, Map<Object, JSAny>.identity());
// return obj.jsify();
}

Object? _dartify(JSAny? js, Map<JSAny, Object> cache) {
if (js.isUndefinedOrNull) return null;
var obj = cache[js!];
if (obj != null) return obj;
if (js.isA<JSBigInt>()) {
js as JSBigInt;
final strVal = js.$toString().toDart;
print('BigInt $js -> $strVal');
return BigInt.parse(strVal);
}
if (js.isA<_$JSMap>()) {
print('_dartify: $js');
final map = {};
cache[js] = map;
js as _$JSMap;
final keys = js.keys();
while (true) {
final res = keys.next();
if (res == null || res.done) break;
final key = res.value;
final value = js.get(key);
map[_dartify(key, cache)] = _dartify(value, cache);
}
return map;
}
if (js.isA<JSArray>()) {
final list = [];
cache[js] = list;
js as JSArray;
final len = js.getProperty<JSNumber>('length'.toJS).toDartInt;
for (var i = 0; i < len; i++) {
final value = js.getProperty(i.toJS);
list.add(_dartify(value, cache));
}
return list;
}
obj = js.dartify();
if (obj != null && obj is! num && obj is! bool && obj is! String) {
cache[js] = obj;
}
return obj;
}

Object? $dartify(JSAny? js) {
return _dartify(js, Map<JSAny, Object>.identity());
// return js.dartify();
}
File renamed without changes.
9 changes: 5 additions & 4 deletions lib/src/_impl/web/_worker_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import '../../exceptions/squadron_exception.dart';
import '../../typedefs.dart';
import '../../worker/worker_channel.dart';
import '../../worker/worker_response.dart';
import '../xplat/_transferables.dart';
import '_patch.dart';
import '_transferables.dart';
import '_typedefs.dart' as impl;

/// [WorkerChannel] implementation for the JavaScript world.
Expand All @@ -26,7 +27,7 @@ final class _WebWorkerChannel implements WorkerChannel {

void _postResponse(WorkerResponse res) {
try {
_sendPort.postMessage(res.wrapInPlace().jsify());
_sendPort.postMessage($jsify(res.wrapInPlace()));
} catch (ex, st) {
_logger?.e(() => 'Failed to post response $res: $ex');
throw SquadronErrorExt.create('Failed to post response: $ex', st);
Expand All @@ -38,9 +39,9 @@ final class _WebWorkerChannel implements WorkerChannel {
final data = res.wrapInPlace();
final transfer = Transferables.get(data);
if (transfer == null || transfer.isEmpty) {
_sendPort.postMessage(data.jsify());
_sendPort.postMessage($jsify(data));
} else {
_sendPort.postMessage(data.jsify(), transfer.jsify() as JSArray);
_sendPort.postMessage($jsify(data), $jsify(transfer) as JSArray);
}
} catch (ex, st) {
_logger?.e(() => 'Failed to post response $res: $ex');
Expand Down
14 changes: 14 additions & 0 deletions test/04_worker_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,20 @@ void execute(TestContext? tc) {
});
});

tc.test('- maps', () async {
await TestWorker(tc).useAsync((w) async {
final input = {
BigInt.one.toString(): BigInt.one,
BigInt.two.toString(): BigInt.two,
};
final res = await w.map(input);
expect(res, {
BigInt.one: BigInt.one.toString(),
BigInt.two: BigInt.two.toString(),
});
});
});

tc.test('- sequential', () async {
await TestWorker(tc).useAsync((w) async {
int taskId = 0;
Expand Down
6 changes: 6 additions & 0 deletions test/worker_services/test_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class TestService implements WorkerService {
return marshalOut ? bigIntMarshaler.marshal(res) : res;
},
platformTypeCommand: (r) => getPlatformType().toString(),
mapCommand: (r) =>
map(Squadron.converter.map<String, BigInt>()(r.args[0])),
});
}

Expand Down Expand Up @@ -164,6 +166,9 @@ class TestService implements WorkerService {

FutureOr<SquadronPlatformType> getPlatformType() => Squadron.platformType;

Future<Map<BigInt, String>> map(Map<String, BigInt> input) async =>
input.map((k, v) => MapEntry(v, k));

final bool _invalid;

static const invalidCommand1 = -1; // command IDs must be > 0
Expand All @@ -180,6 +185,7 @@ class TestService implements WorkerService {
static const infiniteWithErrorsCommand = 36;
static const bigIntAddCommand = 41;
static const platformTypeCommand = 51;
static const mapCommand = 52;

@override
final Map<int, CommandHandler> operations = {};
Expand Down
9 changes: 9 additions & 0 deletions test/worker_services/test_service_worker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ base class TestWorkerPool extends WorkerPool<TestWorker>
@override
Future<SquadronPlatformType> getPlatformType() =>
execute((w) => w.getPlatformType());

@override
Future<Map<BigInt, String>> map(Map<String, BigInt> input) =>
execute((w) => w.map(input));
}

base class TestWorker extends Worker implements TestService {
Expand Down Expand Up @@ -225,6 +229,11 @@ base class TestWorker extends Worker implements TestService {
);
}

@override
Future<Map<BigInt, String>> map(Map<String, BigInt> input) =>
send(TestService.mapCommand, args: [input])
.then(Squadron.converter.map<BigInt, String>());

@override
Future<SquadronPlatformType> getPlatformType() =>
send(TestService.platformTypeCommand).then((res) =>
Expand Down
4 changes: 2 additions & 2 deletions tool/compile_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ const workers = {
'wasm': (folder: 'js', opt: Optimizations.safe),
},
'test_worker.dart': {
'js': (folder: 'js', opt: Optimizations.safe),
'wasm': (folder: 'js', opt: Optimizations.safe),
'js': (folder: 'js', opt: Optimizations.def),
'wasm': (folder: 'js', opt: Optimizations.def),
},
'streaming_worker.dart': {
'js': (folder: 'js', opt: Optimizations.safe),
Expand Down

0 comments on commit e7e700a

Please sign in to comment.