Add a byteData serializer/deserializer implementation
With the optimizations suggested this does now equal or outperform the JSON serializer in all scenarios, the latest numbers from the benchmark are as follows:
Isolate.spawn + SerializationMode.jsonClient: 0:00:00.041666
Isolate.spawnUri + SerializationMode.jsonClient: 0:00:00.069551
Separate process + SerializationMode.jsonClient: 0:00:00.177171
Isolate.spawn + SerializationMode.byteDataClient: 0:00:00.040990
Isolate.spawnUri + SerializationMode.byteDataClient: 0:00:00.059319
Separate process + SerializationMode.byteDataClient: 0:00:00.080008
Change-Id: If5431513c7487d8b7af350381e794cbd61c1be42
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/232027
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Auto-Submit: Jake Macdonald <jakemac@google.com>
Commit-Queue: Jake Macdonald <jakemac@google.com>
diff --git a/pkg/_fe_analyzer_shared/benchmark/macros/serialization_benchmark.dart b/pkg/_fe_analyzer_shared/benchmark/macros/serialization_benchmark.dart
new file mode 100644
index 0000000..550e718
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/benchmark/macros/serialization_benchmark.dart
@@ -0,0 +1,311 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
+
+void main() async {
+ for (var serializationMode in [
+ SerializationMode.jsonClient,
+ SerializationMode.byteDataClient
+ ]) {
+ await withSerializationMode(serializationMode, () async {
+ await _isolateSpawnBenchmarks();
+ await _isolateSpawnUriBenchmarks();
+ await _separateProcessBenchmarks();
+ });
+ }
+}
+
+Future<void> _isolateSpawnBenchmarks() async {
+ void Function(SendPort) childIsolateFn(SerializationMode mode) =>
+ (SendPort sendPort) => withSerializationMode(mode, () {
+ var isolateReceivePort = ReceivePort();
+ isolateReceivePort.listen((data) {
+ deserialize(data);
+ var result = serialize();
+ result = result is Uint8List
+ ? TransferableTypedData.fromList([result])
+ : result;
+ sendPort.send(result);
+ });
+ sendPort.send(isolateReceivePort.sendPort);
+ });
+
+ Completer? responseCompleter;
+ late SendPort sendPort;
+
+ var receivePort = ReceivePort();
+
+ var isolate = await Isolate.spawn(
+ childIsolateFn(serializationMode), receivePort.sendPort);
+
+ final sendPortCompleter = Completer<SendPort>();
+ receivePort.listen((data) {
+ if (!sendPortCompleter.isCompleted) {
+ sendPortCompleter.complete(data);
+ } else {
+ responseCompleter!.complete(data);
+ }
+ });
+ sendPort = await sendPortCompleter.future;
+
+ // warmup
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ result =
+ result is Uint8List ? TransferableTypedData.fromList([result]) : result;
+ sendPort.send(result);
+ deserialize(await responseCompleter.future);
+ }
+ // measure
+ var watch = Stopwatch()..start();
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ result =
+ result is Uint8List ? TransferableTypedData.fromList([result]) : result;
+ sendPort.send(result);
+ deserialize(await responseCompleter.future);
+ }
+ print('Isolate.spawn + $serializationMode: ${watch.elapsed}');
+
+ receivePort.close();
+ isolate.kill();
+}
+
+Future<void> _isolateSpawnUriBenchmarks() async {
+ Completer? responseCompleter;
+ late SendPort sendPort;
+
+ var receivePort = ReceivePort();
+
+ var isolate = await Isolate.spawnUri(
+ Uri.dataFromString(childProgram(serializationMode)),
+ [],
+ receivePort.sendPort);
+
+ final sendPortCompleter = Completer<SendPort>();
+ receivePort.listen((data) {
+ if (!sendPortCompleter.isCompleted) {
+ sendPortCompleter.complete(data);
+ } else {
+ responseCompleter!.complete(data);
+ }
+ });
+ sendPort = await sendPortCompleter.future;
+
+ // warmup
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ result =
+ result is Uint8List ? TransferableTypedData.fromList([result]) : result;
+ sendPort.send(result);
+ deserialize(await responseCompleter.future);
+ }
+ // measure
+ var watch = Stopwatch()..start();
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ result =
+ result is Uint8List ? TransferableTypedData.fromList([result]) : result;
+ sendPort.send(result);
+ deserialize(await responseCompleter.future);
+ }
+ print('Isolate.spawnUri + $serializationMode: ${watch.elapsed}');
+
+ receivePort.close();
+ isolate.kill();
+}
+
+Future<void> _separateProcessBenchmarks() async {
+ Completer? responseCompleter;
+
+ var tmpDir = Directory.systemTemp.createTempSync('serialize_bench');
+ try {
+ var file = File(tmpDir.uri.resolve('main.dart').toFilePath());
+ file.writeAsStringSync(childProgram(serializationMode));
+ var process = await Process.start(Platform.resolvedExecutable, [
+ '--packages=' + (await Isolate.packageConfig)!.toFilePath(),
+ file.path,
+ ]);
+
+ var listeners = <StreamSubscription>[
+ process.stderr.listen((event) {
+ print('stderr: ${utf8.decode(event)}');
+ }),
+ process.stdout.listen((data) {
+ responseCompleter!.complete(data);
+ }),
+ ];
+
+ // warmup
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ if (result is List<int>) {
+ process.stdin.add(result);
+ } else {
+ process.stdin.writeln(jsonEncode(result));
+ }
+ deserialize(await responseCompleter.future);
+ }
+ // measure
+ var watch = Stopwatch()..start();
+ for (var i = 0; i < 100; i++) {
+ responseCompleter = Completer();
+ var result = serialize();
+ if (result is List<int>) {
+ process.stdin.add(result);
+ } else {
+ process.stdin.writeln(jsonEncode(result));
+ }
+ deserialize(await responseCompleter.future);
+ }
+ print('Separate process + $serializationMode: ${watch.elapsed}');
+
+ listeners.forEach((l) => l.cancel());
+ process.kill();
+ } catch (e, s) {
+ print('Error running benchmark \n$e\n\n$s');
+ } finally {
+ tmpDir.deleteSync(recursive: true);
+ }
+}
+
+String childProgram(SerializationMode mode) => '''
+ import 'dart:convert';
+ import 'dart:io';
+ import 'dart:isolate';
+ import 'dart:typed_data';
+
+ import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
+
+ void main(_, [SendPort? sendPort]) {
+ var mode = $mode;
+ withSerializationMode(mode, () {
+ if (sendPort != null) {
+ var isolateReceivePort = ReceivePort();
+ isolateReceivePort.listen((data) {
+ deserialize(data);
+ var result = serialize();
+ result = result is Uint8List
+ ? TransferableTypedData.fromList([result])
+ : result;
+ sendPort.send(result);
+ });
+ sendPort.send(isolateReceivePort.sendPort);
+ } else {
+ // We allow one empty line to work around some weird data.
+ var allowEmpty = true;
+ stdin.listen((data) {
+ if (mode == SerializationMode.jsonClient || mode == SerializationMode.jsonServer) {
+ var json = utf8.decode(data).trimRight();
+ // On exit we tend to get extra empty lines sometimes?
+ if (json.isEmpty && allowEmpty) {
+ allowEmpty = false;
+ return;
+ }
+ deserialize(jsonDecode(json));
+ stdout.write(jsonEncode(serialize()));
+ } else {
+ deserialize(data);
+ stdout.add(serialize() as List<int>);
+ }
+ });
+ }
+ });
+ }
+
+ Object? serialize() {
+ var serializer = serializerFactory();
+ for (var i = 0; i < 100; i++) {
+ serializer.addInt(i * 100);
+ serializer.addString('foo' * i);
+ serializer.addBool(i % 2 == 0);
+ serializer.startList();
+ for (var j = 0; j < 10; j++) {
+ serializer.addDouble(i * 5);
+ }
+ serializer.endList();
+ serializer.addNull();
+ }
+ return serializer.result;
+ }
+
+ void deserialize(Object? result) {
+ result = result is TransferableTypedData
+ ? result.materialize().asUint8List()
+ : result;
+ var deserializer = deserializerFactory(result);
+ while (deserializer.moveNext()) {
+ deserializer
+ ..expectInt()
+ ..moveNext()
+ ..expectString()
+ ..moveNext()
+ ..expectBool()
+ ..moveNext()
+ ..expectList();
+ while (deserializer.moveNext()) {
+ deserializer.expectDouble();
+ }
+ deserializer
+ ..moveNext()
+ ..checkNull();
+ }
+ }''';
+
+Object? serialize() {
+ var serializer = serializerFactory();
+ for (var i = -50; i < 50; i++) {
+ serializer.addInt(i % 2 * 100);
+ serializer.addString('foo' * i);
+ serializer.addBool(i < 0);
+ serializer.startList();
+ for (var j = 0.0; j < 10; j++) {
+ serializer.addDouble(i * j);
+ }
+ serializer.endList();
+ serializer.addNull();
+ }
+ return serializer.result;
+}
+
+void deserialize(Object? result) {
+ result = result is TransferableTypedData
+ ? result.materialize().asUint8List()
+ : result;
+ if (serializationMode == SerializationMode.jsonClient ||
+ serializationMode == SerializationMode.jsonServer) {
+ if (result is List<int>) {
+ result = jsonDecode(utf8.decode(result));
+ }
+ }
+ var deserializer = deserializerFactory(result);
+ while (deserializer.moveNext()) {
+ deserializer
+ ..expectInt()
+ ..moveNext()
+ ..expectString()
+ ..moveNext()
+ ..expectBool()
+ ..moveNext()
+ ..expectList();
+ while (deserializer.moveNext()) {
+ deserializer.expectDouble();
+ }
+ deserializer
+ ..moveNext()
+ ..checkNull();
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
index 635c67b..f423fcf 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
@@ -55,17 +55,18 @@
/// Local function that sends requests and returns responses using [sendPort].
Future<Response> sendRequest(Request request) => _sendRequest(request, sendPort);
- withSerializationMode(SerializationMode.client, () {
+ /// TODO: More directly support customizable serialization types.
+ withSerializationMode(SerializationMode.jsonClient, () {
ReceivePort receivePort = new ReceivePort();
sendPort.send(receivePort.sendPort);
receivePort.listen((message) async {
- var deserializer = JsonDeserializer(message as Iterable<Object?>)
+ var deserializer = deserializerFactory(message)
..moveNext();
- int zoneId = deserializer.expectNum();
+ int zoneId = deserializer.expectInt();
deserializer..moveNext();
- var type = MessageType.values[deserializer.expectNum()];
- var serializer = JsonSerializer();
+ var type = MessageType.values[deserializer.expectInt()];
+ var serializer = serializerFactory();
switch (type) {
case MessageType.instantiateMacroRequest:
var request = new InstantiateMacroRequest.deserialize(deserializer, zoneId);
@@ -248,8 +249,8 @@
Future<Response> _sendRequest(Request request, SendPort sendPort) {
Completer<Response> completer = Completer();
_responseCompleters[request.id] = completer;
- JsonSerializer serializer = JsonSerializer();
- serializer.addNum(request.serializationZoneId);
+ Serializer serializer = serializerFactory();
+ serializer.addInt(request.serializationZoneId);
request.serialize(serializer);
sendPort.send(serializer.result);
return completer.future;
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
index 7238af4..94b8930 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
@@ -132,7 +132,7 @@
static Object? _deserializeArg(Deserializer deserializer,
{bool alreadyMoved = false}) {
if (!alreadyMoved) deserializer.moveNext();
- _ArgumentKind kind = _ArgumentKind.values[deserializer.expectNum()];
+ _ArgumentKind kind = _ArgumentKind.values[deserializer.expectInt()];
switch (kind) {
case _ArgumentKind.nil:
return null;
@@ -142,9 +142,12 @@
case _ArgumentKind.bool:
deserializer.moveNext();
return deserializer.expectBool();
- case _ArgumentKind.num:
+ case _ArgumentKind.int:
deserializer.moveNext();
- return deserializer.expectNum();
+ return deserializer.expectInt();
+ case _ArgumentKind.double:
+ deserializer.moveNext();
+ return deserializer.expectDouble();
case _ArgumentKind.list:
deserializer.moveNext();
deserializer.expectList();
@@ -184,22 +187,26 @@
static void _serializeArg(Object? arg, Serializer serializer) {
if (arg == null) {
- serializer.addNum(_ArgumentKind.nil.index);
+ serializer.addInt(_ArgumentKind.nil.index);
} else if (arg is String) {
serializer
- ..addNum(_ArgumentKind.string.index)
+ ..addInt(_ArgumentKind.string.index)
..addString(arg);
- } else if (arg is num) {
+ } else if (arg is int) {
serializer
- ..addNum(_ArgumentKind.num.index)
- ..addNum(arg);
+ ..addInt(_ArgumentKind.int.index)
+ ..addInt(arg);
+ } else if (arg is double) {
+ serializer
+ ..addInt(_ArgumentKind.double.index)
+ ..addDouble(arg);
} else if (arg is bool) {
serializer
- ..addNum(_ArgumentKind.bool.index)
+ ..addInt(_ArgumentKind.bool.index)
..addBool(arg);
} else if (arg is List) {
serializer
- ..addNum(_ArgumentKind.list.index)
+ ..addInt(_ArgumentKind.list.index)
..startList();
for (Object? item in arg) {
_serializeArg(item, serializer);
@@ -207,7 +214,7 @@
serializer.endList();
} else if (arg is Map) {
serializer
- ..addNum(_ArgumentKind.map.index)
+ ..addInt(_ArgumentKind.map.index)
..startList();
for (MapEntry<Object?, Object?> entry in arg.entries) {
_serializeArg(entry.key, serializer);
@@ -311,4 +318,4 @@
}
/// Used for serializing and deserializing arguments.
-enum _ArgumentKind { string, bool, num, list, map, nil }
+enum _ArgumentKind { string, bool, double, int, list, map, nil }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
index baf884d..ebf86e2 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
@@ -19,9 +19,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
serializer.addString(name);
}
@@ -37,9 +35,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
serializer.addBool(isNullable);
}
@@ -76,9 +72,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
identifier.serialize(serializer);
serializer.startList();
@@ -138,9 +132,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
returnType.serialize(serializer);
@@ -173,9 +165,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
identifier.serialize(serializer);
}
@@ -207,9 +197,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
serializer.addBool(isNamed);
serializer.addBool(isRequired);
@@ -241,9 +229,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
TypeAnnotationImpl? bound = this.bound;
if (bound == null) {
@@ -308,9 +294,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
serializer
..addBool(isAbstract)
@@ -380,9 +364,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
definingClass.serialize(serializer);
}
@@ -433,9 +415,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
serializer.addBool(isFactory);
}
@@ -471,9 +451,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
serializer
..addBool(isExternal)
@@ -513,9 +491,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
definingClass.serialize(serializer);
}
@@ -535,9 +511,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
serializer..startList();
for (TypeParameterDeclarationImpl param in typeParameters) {
@@ -585,9 +559,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
serializer.startList();
for (TypeAnnotationImpl interface in interfaces) {
@@ -628,9 +600,7 @@
void serialize(Serializer serializer) {
super.serialize(serializer);
// Client side we don't encode anything but the ID.
- if (serializationMode == SerializationMode.client) {
- return;
- }
+ if (serializationMode.isClient) return;
aliasedType.serialize(serializer);
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
index f3a3bf7..50a6743 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
@@ -28,13 +28,13 @@
/// The [serializationZoneId] is a part of the header and needs to be parsed
/// before deserializing objects, and then passed in here.
Request.deserialize(Deserializer deserializer, this.serializationZoneId)
- : id = (deserializer..moveNext()).expectNum();
+ : id = (deserializer..moveNext()).expectInt();
/// The [serializationZoneId] needs to be separately serialized before the
/// rest of the object. This is not done by the instances themselves but by
/// the macro implementations.
@mustCallSuper
- void serialize(Serializer serializer) => serializer.addNum(id);
+ void serialize(Serializer serializer) => serializer.addInt(id);
static int _next = 0;
}
@@ -81,7 +81,7 @@
factory SerializableResponse.deserialize(
Deserializer deserializer, int serializationZoneId) {
deserializer.moveNext();
- MessageType responseType = MessageType.values[deserializer.expectNum()];
+ MessageType responseType = MessageType.values[deserializer.expectInt()];
Serializable? response;
String? error;
String? stackTrace;
@@ -126,15 +126,15 @@
response: response,
error: error,
stackTrace: stackTrace,
- requestId: (deserializer..moveNext()).expectNum(),
+ requestId: (deserializer..moveNext()).expectInt(),
serializationZoneId: serializationZoneId);
}
void serialize(Serializer serializer) {
serializer
- ..addNum(serializationZoneId)
- ..addNum(MessageType.response.index)
- ..addNum(responseType.index);
+ ..addInt(serializationZoneId)
+ ..addInt(MessageType.response.index)
+ ..addInt(responseType.index);
switch (responseType) {
case MessageType.error:
serializer.addString(error!.toString());
@@ -143,7 +143,7 @@
default:
response.serializeNullable(serializer);
}
- serializer.addNum(requestId);
+ serializer.addInt(requestId);
}
}
@@ -203,7 +203,7 @@
@override
void serialize(Serializer serializer) {
serializer
- ..addNum(MessageType.loadMacroRequest.index)
+ ..addInt(MessageType.loadMacroRequest.index)
..addString(library.toString())
..addString(name);
super.serialize(serializer);
@@ -230,16 +230,16 @@
: macroClass = new MacroClassIdentifierImpl.deserialize(deserializer),
constructorName = (deserializer..moveNext()).expectString(),
arguments = new Arguments.deserialize(deserializer),
- instanceId = (deserializer..moveNext()).expectNum(),
+ instanceId = (deserializer..moveNext()).expectInt(),
super.deserialize(deserializer, serializationZoneId);
@override
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.instantiateMacroRequest.index);
+ serializer.addInt(MessageType.instantiateMacroRequest.index);
macroClass.serialize(serializer);
serializer.addString(constructorName);
arguments.serialize(serializer);
- serializer.addNum(instanceId);
+ serializer.addInt(instanceId);
super.serialize(serializer);
}
}
@@ -262,7 +262,7 @@
super.deserialize(deserializer, serializationZoneId);
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.executeTypesPhaseRequest.index);
+ serializer.addInt(MessageType.executeTypesPhaseRequest.index);
macro.serialize(serializer);
declaration.serialize(serializer);
@@ -295,7 +295,7 @@
super.deserialize(deserializer, serializationZoneId);
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.executeDeclarationsPhaseRequest.index);
+ serializer.addInt(MessageType.executeDeclarationsPhaseRequest.index);
macro.serialize(serializer);
declaration.serialize(serializer);
typeResolver.serialize(serializer);
@@ -332,7 +332,7 @@
super.deserialize(deserializer, serializationZoneId);
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.executeDefinitionsPhaseRequest.index);
+ serializer.addInt(MessageType.executeDefinitionsPhaseRequest.index);
macro.serialize(serializer);
declaration.serialize(serializer);
typeResolver.serialize(serializer);
@@ -361,7 +361,7 @@
super.deserialize(deserializer, serializationZoneId);
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.resolveTypeRequest.index);
+ serializer.addInt(MessageType.resolveTypeRequest.index);
typeAnnotationCode.serialize(serializer);
typeResolver.serialize(serializer);
super.serialize(serializer);
@@ -386,7 +386,7 @@
super.deserialize(deserializer, serializationZoneId);
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.isExactlyTypeRequest.index);
+ serializer.addInt(MessageType.isExactlyTypeRequest.index);
leftType.serialize(serializer);
rightType.serialize(serializer);
super.serialize(serializer);
@@ -411,7 +411,7 @@
super.deserialize(deserializer, serializationZoneId);
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.isSubtypeOfRequest.index);
+ serializer.addInt(MessageType.isSubtypeOfRequest.index);
leftType.serialize(serializer);
rightType.serialize(serializer);
super.serialize(serializer);
@@ -440,7 +440,7 @@
@override
void serialize(Serializer serializer) {
- serializer.addNum(requestKind.index);
+ serializer.addInt(requestKind.index);
classDeclaration.serialize(serializer);
classIntrospector.serialize(serializer);
super.serialize(serializer);
@@ -466,7 +466,7 @@
@override
void serialize(Serializer serializer) {
- serializer.addNum(MessageType.declarationOfRequest.index);
+ serializer.addInt(MessageType.declarationOfRequest.index);
identifier.serialize(serializer);
typeDeclarationResolver.serialize(serializer);
super.serialize(serializer);
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
index 7ba94f8..3940b7e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
@@ -57,16 +57,12 @@
/// [SerializationMode.client], so that only an ID is sent.
@mustCallSuper
void serialize(Serializer serializer) {
- serializer.addNum(id);
- switch (serializationMode) {
- case SerializationMode.client:
- // We only send the ID from the client side.
- return;
- case SerializationMode.server:
- serializer.addNum(kind.index);
- _remoteInstanceCache[id] = this;
- return;
- }
+ serializer.addInt(id);
+ // We only send the ID from the client side.
+ if (serializationMode.isClient) return;
+
+ serializer.addInt(kind.index);
+ _remoteInstanceCache[id] = this;
}
@override
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
index 2e1d0cc..3686842 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
@@ -164,12 +164,12 @@
}
MacroInstanceIdentifierImpl.deserialize(Deserializer deserializer)
- : id = (deserializer..moveNext()).expectNum(),
- _interfaces = (deserializer..moveNext()).expectNum();
+ : id = (deserializer..moveNext()).expectInt(),
+ _interfaces = (deserializer..moveNext()).expectInt();
void serialize(Serializer serializer) => serializer
- ..addNum(id)
- ..addNum(_interfaces);
+ ..addInt(id)
+ ..addInt(_interfaces);
operator ==(other) => other is MacroInstanceIdentifierImpl && id == other.id;
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart
index 89bbf59..8adf1a1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:typed_data';
import 'remote_instance.dart';
@@ -11,11 +12,15 @@
///
/// In [SerializationMode.server], sets up a remote instance cache to use when
/// deserializing remote instances back to their original instance.
-T withSerializationMode<T>(SerializationMode mode, T Function() fn) =>
+T withSerializationMode<T>(
+ SerializationMode mode,
+ T Function() fn, {
+ Serializer Function()? serializerFactory,
+ Deserializer Function(Object? data)? deserializerFactory,
+}) =>
runZoned(fn, zoneValues: {
#serializationMode: mode,
- if (mode == SerializationMode.server)
- remoteInstanceZoneKey: <int, RemoteInstance>{}
+ if (!mode.isClient) remoteInstanceZoneKey: <int, RemoteInstance>{}
});
/// Serializable interface
@@ -30,19 +35,28 @@
void addString(String value);
/// Serializes a nullable [String].
- void addNullableString(String? value);
+ void addNullableString(String? value) =>
+ value == null ? addNull() : addString(value);
- /// Serializes a [num].
- void addNum(num value);
+ /// Serializes a [double].
+ void addDouble(double value);
- /// Serializes a nullable [num].
- void addNullableNum(num? value);
+ /// Serializes a nullable [double].
+ void addNullableDouble(double? value) =>
+ value == null ? addNull() : addDouble(value);
+
+ /// Serializes an [int].
+ void addInt(int value);
+
+ /// Serializes a nullable [int].
+ void addNullableInt(int? value) => value == null ? addNull() : addInt(value);
/// Serializes a [bool].
void addBool(bool value);
/// Serializes a nullable [bool].
- void addNullableBool(bool? value);
+ void addNullableBool(bool? value) =>
+ value == null ? addNull() : addBool(value);
/// Serializes a `null` literal.
void addNull();
@@ -52,6 +66,9 @@
/// Used to signal the end of an arbitrary length list of items.
void endList();
+
+ /// Returns the resulting serialized object.
+ Object? get result;
}
/// A pull based object deserialization interface.
@@ -67,19 +84,25 @@
bool expectBool();
/// Reads the current value as a nullable [bool].
- bool? expectNullableBool();
+ bool? expectNullableBool() => checkNull() ? null : expectBool();
- /// Reads the current value as a non-nullable [String].
- T expectNum<T extends num>();
+ /// Reads the current value as a non-nullable [double].
+ double expectDouble();
- /// Reads the current value as a nullable [num].
- num? expectNullableNum();
+ /// Reads the current value as a nullable [double].
+ double? expectNullableDouble() => checkNull() ? null : expectDouble();
+
+ /// Reads the current value as a non-nullable [int].
+ int expectInt();
+
+ /// Reads the current value as a nullable [int].
+ int? expectNullableInt() => checkNull() ? null : expectInt();
/// Reads the current value as a non-nullable [String].
String expectString();
/// Reads the current value as a nullable [String].
- String? expectNullableString();
+ String? expectNullableString() => checkNull() ? null : expectString();
/// Asserts that the current item is the start of a list.
///
@@ -121,6 +144,7 @@
/// Returns the result as an unmodifiable [Iterable].
///
/// Asserts that all [List] entries have not been closed with [endList].
+ @override
Iterable<Object?> get result {
assert(_path.length == 1);
return _result;
@@ -132,9 +156,14 @@
void addNullableBool(bool? value) => _path.last.add(value);
@override
- void addNum(num value) => _path.last.add(value);
+ void addDouble(double value) => _path.last.add(value);
@override
- void addNullableNum(num? value) => _path.last.add(value);
+ void addNullableDouble(double? value) => _path.last.add(value);
+
+ @override
+ void addInt(int value) => _path.last.add(value);
+ @override
+ void addNullableInt(int? value) => _path.last.add(value);
@override
void addString(String value) => _path.last.add(value);
@@ -182,9 +211,14 @@
bool? expectNullableBool() => _expectValue();
@override
- T expectNum<T extends num>() => _expectValue();
+ double expectDouble() => _expectValue();
@override
- num? expectNullableNum() => _expectValue();
+ double? expectNullableDouble() => _expectValue();
+
+ @override
+ int expectInt() => _expectValue();
+ @override
+ int? expectNullableInt() => _expectValue();
@override
String expectString() => _expectValue();
@@ -218,6 +252,308 @@
}
}
+class ByteDataSerializer extends Serializer {
+ final BytesBuilder _builder = new BytesBuilder();
+
+ // Re-usable 8 byte list and view for encoding doubles.
+ final Uint8List _eightByteList = new Uint8List(8);
+ late final ByteData _eightByteListData =
+ new ByteData.sublistView(_eightByteList);
+
+ @override
+ void addBool(bool value) => _builder
+ .addByte(value ? DataKind.boolTrue.index : DataKind.boolFalse.index);
+
+ @override
+ void addDouble(double value) {
+ _eightByteListData.setFloat64(0, value);
+ _builder
+ ..addByte(DataKind.float64.index)
+ ..add(_eightByteList);
+ }
+
+ @override
+ void addNull() => _builder.addByte(DataKind.nil.index);
+
+ @override
+ void addInt(int value) {
+ if (value >= 0x0) {
+ if (value + DataKind.values.length <= 0xff) {
+ _builder..addByte(value + DataKind.values.length);
+ } else if (value <= 0xff) {
+ _builder
+ ..addByte(DataKind.uint8.index)
+ ..addByte(value);
+ } else if (value <= 0xffff) {
+ _builder
+ ..addByte(DataKind.uint16.index)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ } else if (value <= 0xffffffff) {
+ _builder
+ ..addByte(DataKind.uint32.index)
+ ..addByte(value >> 24)
+ ..addByte(value >> 16)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ } else {
+ _builder
+ ..addByte(DataKind.uint64.index)
+ ..addByte(value >> 56)
+ ..addByte(value >> 48)
+ ..addByte(value >> 40)
+ ..addByte(value >> 32)
+ ..addByte(value >> 24)
+ ..addByte(value >> 16)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ }
+ } else {
+ if (value >= -0x80) {
+ _builder
+ ..addByte(DataKind.int8.index)
+ ..addByte(value);
+ } else if (value >= -0x8000) {
+ _builder
+ ..addByte(DataKind.int16.index)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ } else if (value >= -0x8000000) {
+ _builder
+ ..addByte(DataKind.int32.index)
+ ..addByte(value >> 24)
+ ..addByte(value >> 16)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ } else {
+ _builder
+ ..addByte(DataKind.int64.index)
+ ..addByte(value >> 56)
+ ..addByte(value >> 48)
+ ..addByte(value >> 40)
+ ..addByte(value >> 32)
+ ..addByte(value >> 24)
+ ..addByte(value >> 16)
+ ..addByte(value >> 8)
+ ..addByte(value);
+ }
+ }
+ }
+
+ @override
+ void addString(String value) {
+ for (int i = 0; i < value.length; i++) {
+ if (value.codeUnitAt(i) > 0xff) {
+ _addTwoByteString(value);
+ return;
+ }
+ }
+ _addOneByteString(value);
+ }
+
+ void _addOneByteString(String value) {
+ _builder.addByte(DataKind.oneByteString.index);
+ addInt(value.length);
+ for (int i = 0; i < value.length; i++) {
+ _builder.addByte(value.codeUnitAt(i));
+ }
+ }
+
+ void _addTwoByteString(String value) {
+ _builder.addByte(DataKind.twoByteString.index);
+ addInt(value.length);
+ for (int i = 0; i < value.length; i++) {
+ int codeUnit = value.codeUnitAt(i);
+ switch (Endian.host) {
+ case Endian.little:
+ _builder
+ ..addByte(codeUnit)
+ ..addByte(codeUnit >> 8);
+ break;
+ case Endian.big:
+ _builder
+ ..addByte(codeUnit >> 8)
+ ..addByte(codeUnit);
+ break;
+ }
+ }
+ }
+
+ @override
+ void endList() => _builder.addByte(DataKind.endList.index);
+
+ @override
+ void startList() => _builder.addByte(DataKind.startList.index);
+
+ @override
+ Uint8List get result => _builder.takeBytes();
+}
+
+class ByteDataDeserializer extends Deserializer {
+ final ByteData _bytes;
+ int _byteOffset = 0;
+ int? _byteOffsetIncrement = 0;
+
+ ByteDataDeserializer(this._bytes);
+
+ /// Reads the next [DataKind] and advances [_byteOffset].
+ DataKind _readKind([int offset = 0]) {
+ int value = _bytes.getUint8(_byteOffset + offset);
+ if (value < DataKind.values.length) {
+ return DataKind.values[value];
+ } else {
+ return DataKind.directEncodedUint8;
+ }
+ }
+
+ @override
+ bool checkNull() {
+ _byteOffsetIncrement = 1;
+ return _readKind() == DataKind.nil;
+ }
+
+ @override
+ bool expectBool() {
+ DataKind kind = _readKind();
+ _byteOffsetIncrement = 1;
+ if (kind == DataKind.boolTrue) {
+ return true;
+ } else if (kind == DataKind.boolFalse) {
+ return false;
+ } else {
+ throw new StateError('Expected a bool but found a $kind');
+ }
+ }
+
+ @override
+ double expectDouble() {
+ DataKind kind = _readKind();
+ if (kind != DataKind.float64) {
+ throw new StateError('Expected a double but found a $kind');
+ }
+ _byteOffsetIncrement = 9;
+ return _bytes.getFloat64(_byteOffset + 1);
+ }
+
+ @override
+ int expectInt() => _expectInt(0);
+
+ int _expectInt(int offset) {
+ DataKind kind = _readKind(offset);
+ if (kind == DataKind.directEncodedUint8) {
+ _byteOffsetIncrement = offset + 1;
+ return _bytes.getUint8(_byteOffset + offset) - DataKind.values.length;
+ }
+ offset += 1;
+ int result;
+ switch (kind) {
+ case DataKind.int8:
+ result = _bytes.getInt8(_byteOffset + offset);
+ _byteOffsetIncrement = 1 + offset;
+ break;
+ case DataKind.int16:
+ result = _bytes.getInt16(_byteOffset + offset);
+ _byteOffsetIncrement = 2 + offset;
+ break;
+ case DataKind.int32:
+ result = _bytes.getInt32(_byteOffset + offset);
+ _byteOffsetIncrement = 4 + offset;
+ break;
+ case DataKind.int64:
+ result = _bytes.getInt64(_byteOffset + offset);
+ _byteOffsetIncrement = 8 + offset;
+ break;
+ case DataKind.uint8:
+ result = _bytes.getUint8(_byteOffset + offset);
+ _byteOffsetIncrement = 1 + offset;
+ break;
+ case DataKind.uint16:
+ result = _bytes.getUint16(_byteOffset + offset);
+ _byteOffsetIncrement = 2 + offset;
+ break;
+ case DataKind.uint32:
+ result = _bytes.getUint32(_byteOffset + offset);
+ _byteOffsetIncrement = 4 + offset;
+ break;
+ case DataKind.uint64:
+ result = _bytes.getUint64(_byteOffset + offset);
+ _byteOffsetIncrement = 8 + offset;
+ break;
+ default:
+ throw new StateError('Expected an int but found a $kind');
+ }
+ return result;
+ }
+
+ @override
+ void expectList() {
+ DataKind kind = _readKind();
+ if (kind != DataKind.startList) {
+ throw new StateError('Expected the start to a list but found a $kind');
+ }
+ _byteOffsetIncrement = 1;
+ }
+
+ @override
+ String expectString() {
+ DataKind kind = _readKind();
+ int length = _expectInt(1);
+ int offset = _byteOffsetIncrement! + _byteOffset;
+ if (kind == DataKind.oneByteString) {
+ _byteOffsetIncrement = _byteOffsetIncrement! + length;
+ return new String.fromCharCodes(
+ _bytes.buffer.asUint8List(offset, length));
+ } else if (kind == DataKind.twoByteString) {
+ length = length * 2;
+ _byteOffsetIncrement = _byteOffsetIncrement! + length;
+ Uint8List bytes =
+ new Uint8List.fromList(_bytes.buffer.asUint8List(offset, length));
+ return new String.fromCharCodes(bytes.buffer.asUint16List());
+ } else {
+ throw new StateError('Expected a string but found a $kind');
+ }
+ }
+
+ @override
+ bool moveNext() {
+ int? increment = _byteOffsetIncrement;
+ _byteOffsetIncrement = null;
+ if (increment == null) {
+ throw new StateError("Can't move until consuming the current element");
+ }
+ _byteOffset += increment;
+ if (_byteOffset >= _bytes.lengthInBytes) {
+ return false;
+ } else if (_readKind() == DataKind.endList) {
+ // You don't explicitly consume list end markers.
+ _byteOffsetIncrement = 1;
+ return false;
+ } else {
+ return true;
+ }
+ }
+}
+
+enum DataKind {
+ nil,
+ boolTrue,
+ boolFalse,
+ directEncodedUint8, // Encoded in the kind byte.
+ startList,
+ endList,
+ int8,
+ int16,
+ int32,
+ int64,
+ uint8,
+ uint16,
+ uint32,
+ uint64,
+ float64,
+ oneByteString,
+ twoByteString,
+}
+
/// Must be set using `withSerializationMode` before doing any serialization or
/// deserialization.
SerializationMode get serializationMode {
@@ -230,9 +566,50 @@
return mode;
}
+/// Returns the current deserializer factory for the zone.
+Deserializer Function(Object?) get deserializerFactory {
+ switch (serializationMode) {
+ case SerializationMode.byteDataClient:
+ case SerializationMode.byteDataServer:
+ return (Object? message) => new ByteDataDeserializer(
+ new ByteData.sublistView(message as Uint8List));
+ case SerializationMode.jsonClient:
+ case SerializationMode.jsonServer:
+ return (Object? message) =>
+ new JsonDeserializer(message as Iterable<Object?>);
+ }
+}
+
+/// Returns the current serializer factory for the zone.
+Serializer Function() get serializerFactory {
+ switch (serializationMode) {
+ case SerializationMode.byteDataClient:
+ case SerializationMode.byteDataServer:
+ return () => new ByteDataSerializer();
+ case SerializationMode.jsonClient:
+ case SerializationMode.jsonServer:
+ return () => new JsonSerializer();
+ }
+}
+
/// Some objects are serialized differently on the client side versus the server
-/// side. This indicates the different modes.
+/// side. This indicates the different modes, as well as the format used.
enum SerializationMode {
- server,
- client,
+ byteDataClient,
+ byteDataServer,
+ jsonServer,
+ jsonClient,
+}
+
+extension IsClient on SerializationMode {
+ bool get isClient {
+ switch (this) {
+ case SerializationMode.byteDataClient:
+ case SerializationMode.jsonClient:
+ return true;
+ case SerializationMode.byteDataServer:
+ case SerializationMode.jsonServer:
+ return false;
+ }
+ }
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
index 191509f..5a6df71 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
@@ -6,58 +6,59 @@
extension DeserializerExtensions on Deserializer {
T expectRemoteInstance<T>() {
- int id = expectNum();
- switch (serializationMode) {
- case SerializationMode.client:
+ int id = expectInt();
+
+ // Server side we just return the cached remote instance by ID.
+ if (!serializationMode.isClient) {
+ return RemoteInstance.cached(id) as T;
+ }
+
+ moveNext();
+ RemoteInstanceKind kind = RemoteInstanceKind.values[expectInt()];
+ switch (kind) {
+ case RemoteInstanceKind.classIntrospector:
+ case RemoteInstanceKind.namedStaticType:
+ case RemoteInstanceKind.staticType:
+ case RemoteInstanceKind.typeDeclarationResolver:
+ case RemoteInstanceKind.typeResolver:
+ // These are simple wrappers, just pass in the kind
+ return new RemoteInstanceImpl(id: id, kind: kind) as T;
+ case RemoteInstanceKind.classDeclaration:
moveNext();
- RemoteInstanceKind kind = RemoteInstanceKind.values[expectNum()];
- switch (kind) {
- case RemoteInstanceKind.classIntrospector:
- case RemoteInstanceKind.namedStaticType:
- case RemoteInstanceKind.staticType:
- case RemoteInstanceKind.typeDeclarationResolver:
- case RemoteInstanceKind.typeResolver:
- // These are simple wrappers, just pass in the kind
- return new RemoteInstanceImpl(id: id, kind: kind) as T;
- case RemoteInstanceKind.classDeclaration:
- moveNext();
- return _expectClassDeclaration(id) as T;
- case RemoteInstanceKind.constructorDeclaration:
- moveNext();
- return _expectConstructorDeclaration(id) as T;
- case RemoteInstanceKind.fieldDeclaration:
- moveNext();
- return _expectFieldDeclaration(id) as T;
- case RemoteInstanceKind.functionDeclaration:
- moveNext();
- return _expectFunctionDeclaration(id) as T;
- case RemoteInstanceKind.functionTypeAnnotation:
- moveNext();
- return _expectFunctionTypeAnnotation(id) as T;
- case RemoteInstanceKind.identifier:
- moveNext();
- return _expectIdentifier(id) as T;
- case RemoteInstanceKind.methodDeclaration:
- moveNext();
- return _expectMethodDeclaration(id) as T;
- case RemoteInstanceKind.namedTypeAnnotation:
- moveNext();
- return _expectNamedTypeAnnotation(id) as T;
- case RemoteInstanceKind.parameterDeclaration:
- moveNext();
- return _expectParameterDeclaration(id) as T;
- case RemoteInstanceKind.typeAliasDeclaration:
- moveNext();
- return _expectTypeAliasDeclaration(id) as T;
- case RemoteInstanceKind.typeParameterDeclaration:
- moveNext();
- return _expectTypeParameterDeclaration(id) as T;
- case RemoteInstanceKind.variableDeclaration:
- moveNext();
- return _expectVariableDeclaration(id) as T;
- }
- case SerializationMode.server:
- return RemoteInstance.cached(id) as T;
+ return _expectClassDeclaration(id) as T;
+ case RemoteInstanceKind.constructorDeclaration:
+ moveNext();
+ return _expectConstructorDeclaration(id) as T;
+ case RemoteInstanceKind.fieldDeclaration:
+ moveNext();
+ return _expectFieldDeclaration(id) as T;
+ case RemoteInstanceKind.functionDeclaration:
+ moveNext();
+ return _expectFunctionDeclaration(id) as T;
+ case RemoteInstanceKind.functionTypeAnnotation:
+ moveNext();
+ return _expectFunctionTypeAnnotation(id) as T;
+ case RemoteInstanceKind.identifier:
+ moveNext();
+ return _expectIdentifier(id) as T;
+ case RemoteInstanceKind.methodDeclaration:
+ moveNext();
+ return _expectMethodDeclaration(id) as T;
+ case RemoteInstanceKind.namedTypeAnnotation:
+ moveNext();
+ return _expectNamedTypeAnnotation(id) as T;
+ case RemoteInstanceKind.parameterDeclaration:
+ moveNext();
+ return _expectParameterDeclaration(id) as T;
+ case RemoteInstanceKind.typeAliasDeclaration:
+ moveNext();
+ return _expectTypeAliasDeclaration(id) as T;
+ case RemoteInstanceKind.typeParameterDeclaration:
+ moveNext();
+ return _expectTypeParameterDeclaration(id) as T;
+ case RemoteInstanceKind.variableDeclaration:
+ moveNext();
+ return _expectVariableDeclaration(id) as T;
}
}
@@ -222,7 +223,7 @@
expectList();
List<Object> parts = [];
while (moveNext()) {
- _CodePartKind partKind = _CodePartKind.values[expectNum()];
+ _CodePartKind partKind = _CodePartKind.values[expectInt()];
moveNext();
switch (partKind) {
case _CodePartKind.code:
@@ -240,7 +241,7 @@
}
T expectCode<T extends Code>() {
- CodeKind kind = CodeKind.values[expectNum()];
+ CodeKind kind = CodeKind.values[expectInt()];
switch (kind) {
case CodeKind.raw:
@@ -309,7 +310,7 @@
extension SerializeCode on Code {
void serialize(Serializer serializer) {
- serializer.addNum(kind.index);
+ serializer.addInt(kind.index);
switch (kind) {
case CodeKind.namedTypeAnnotation:
NamedTypeAnnotationCode self = this as NamedTypeAnnotationCode;
@@ -366,13 +367,13 @@
for (Object part in parts) {
if (part is String) {
serializer
- ..addNum(_CodePartKind.string.index)
+ ..addInt(_CodePartKind.string.index)
..addString(part);
} else if (part is Code) {
- serializer.addNum(_CodePartKind.code.index);
+ serializer.addInt(_CodePartKind.code.index);
part.serialize(serializer);
} else if (part is IdentifierImpl) {
- serializer.addNum(_CodePartKind.identifier.index);
+ serializer.addInt(_CodePartKind.identifier.index);
part.serialize(serializer);
} else {
throw new StateError('Unrecognized code part $part');
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
index 6902870..dcd267c 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
@@ -126,18 +126,18 @@
required this.messageStream,
required this.sendPort}) {
messageStream.listen((message) {
- withSerializationMode(SerializationMode.server, () {
- JsonDeserializer deserializer =
- new JsonDeserializer(message as List<Object?>);
+ withSerializationMode(SerializationMode.jsonServer, () {
+ Deserializer deserializer =
+ deserializerFactory(message as List<Object?>);
// Every object starts with a zone ID which dictates the zone in which
// we should deserialize the message.
deserializer.moveNext();
- int zoneId = deserializer.expectNum();
+ int zoneId = deserializer.expectInt();
Zone zone = serializationZones[zoneId]!;
zone.run(() async {
deserializer.moveNext();
MessageType messageType =
- MessageType.values[deserializer.expectNum()];
+ MessageType.values[deserializer.expectInt()];
switch (messageType) {
case MessageType.response:
SerializableResponse response =
@@ -169,7 +169,7 @@
? MessageType.namedStaticType
: MessageType.staticType,
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -184,7 +184,7 @@
requestId: request.id,
responseType: MessageType.boolean,
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -199,7 +199,7 @@
requestId: request.id,
responseType: MessageType.boolean,
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -215,7 +215,7 @@
// TODO: Consider refactoring to avoid the need for this.
as TypeDeclarationImpl),
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -233,7 +233,7 @@
// TODO: Consider refactoring to avoid the need for this.
.cast<ConstructorDeclarationImpl>()),
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -251,7 +251,7 @@
// TODO: Consider refactoring to avoid the need for this.
.cast<FieldDeclarationImpl>()),
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -269,7 +269,7 @@
// TODO: Consider refactoring to avoid the need for this.
.cast<ClassDeclarationImpl>()),
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -287,7 +287,7 @@
// TODO: Consider refactoring to avoid the need for this.
.cast<MethodDeclarationImpl>()),
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -305,7 +305,7 @@
// TODO: Consider refactoring to avoid the need for this.
.cast<ClassDeclarationImpl>()),
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -323,7 +323,7 @@
// TODO: Consider refactoring to avoid the need for this.
as ClassDeclarationImpl?,
serializationZoneId: zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
response.serialize(serializer);
sendPort.send(serializer.result);
break;
@@ -436,13 +436,13 @@
/// Creates a [Request] with a given serialization zone ID, and handles the
/// response, casting it to the expected type or throwing the error provided.
Future<T> _sendRequest<T>(Request Function(int) requestFactory) =>
- withSerializationMode(SerializationMode.server, () async {
+ withSerializationMode(SerializationMode.jsonServer, () async {
int zoneId = _nextSerializationZoneId++;
serializationZones[zoneId] = Zone.current;
Request request = requestFactory(zoneId);
- JsonSerializer serializer = new JsonSerializer();
+ Serializer serializer = serializerFactory();
// It is our responsibility to add the zone ID header.
- serializer.addNum(zoneId);
+ serializer.addInt(zoneId);
request.serialize(serializer);
sendPort.send(serializer.result);
Completer<Response> completer = new Completer<Response>();
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
index 879ae11..67cc977 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
@@ -12,76 +12,109 @@
import '../util.dart';
void main() {
- group('json serializer', () {
- test('can serialize and deserialize basic data', () {
- var serializer = JsonSerializer();
- serializer
- ..addNum(1)
- ..addNullableNum(null)
- ..addString('hello')
- ..addNullableString(null)
- ..startList()
- ..addBool(true)
- ..startList()
- ..addNull()
- ..endList()
- ..addNullableBool(null)
- ..endList()
- ..addNum(1.0)
- ..startList()
- ..endList();
- expect(
- serializer.result,
- equals([
- 1,
- null,
- 'hello',
- null,
- [
- true,
- [null],
- null
- ],
- 1.0,
- [],
- ]));
- var deserializer = JsonDeserializer(serializer.result);
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNum(), 1);
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNullableNum(), null);
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectString(), 'hello');
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNullableString(), null);
- expect(deserializer.moveNext(), true);
+ for (var mode in [
+ SerializationMode.jsonClient,
+ SerializationMode.jsonServer,
+ SerializationMode.byteDataClient,
+ SerializationMode.byteDataServer,
+ ]) {
+ test('$mode can serialize and deserialize basic data', () {
+ withSerializationMode(mode, () {
+ var serializer = serializerFactory();
+ serializer
+ ..addInt(0)
+ ..addInt(1)
+ ..addInt(0xff)
+ ..addInt(0xffff)
+ ..addInt(0xffffffff)
+ ..addInt(0xffffffffffffffff)
+ ..addInt(-1)
+ ..addInt(-0x80)
+ ..addInt(-0x8000)
+ ..addInt(-0x80000000)
+ ..addInt(-0x8000000000000000)
+ ..addNullableInt(null)
+ ..addString('hello')
+ ..addString('€') // Requires a two byte string
+ ..addString('𐐷') // Requires two, 16 bit code units
+ ..addNullableString(null)
+ ..startList()
+ ..addBool(true)
+ ..startList()
+ ..addNull()
+ ..endList()
+ ..addNullableBool(null)
+ ..endList()
+ ..addDouble(1.0)
+ ..startList()
+ ..endList();
+ var deserializer = deserializerFactory(serializer.result);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 1);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0xff);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0xffff);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0xffffffff);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), 0xffffffffffffffff);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -1);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -0x80);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -0x8000);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -0x80000000);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectInt(), -0x8000000000000000);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectNullableInt(), null);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectString(), 'hello');
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectString(), '€');
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectString(), '𐐷');
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectNullableString(), null);
+ expect(deserializer.moveNext(), true);
- deserializer.expectList();
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectBool(), true);
- expect(deserializer.moveNext(), true);
+ deserializer.expectList();
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectBool(), true);
+ expect(deserializer.moveNext(), true);
- deserializer.expectList();
- expect(deserializer.moveNext(), true);
- expect(deserializer.checkNull(), true);
- expect(deserializer.moveNext(), false);
+ deserializer.expectList();
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.checkNull(), true);
+ expect(deserializer.moveNext(), false);
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNullableBool(), null);
- expect(deserializer.moveNext(), false);
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectNullableBool(), null);
+ expect(deserializer.moveNext(), false);
- // Have to move the parent again to advance it past the list entry.
- expect(deserializer.moveNext(), true);
- expect(deserializer.expectNum(), 1.0);
- expect(deserializer.moveNext(), true);
+ // Have to move the parent again to advance it past the list entry.
+ expect(deserializer.moveNext(), true);
+ expect(deserializer.expectDouble(), 1.0);
+ expect(deserializer.moveNext(), true);
- deserializer.expectList();
- expect(deserializer.moveNext(), false);
+ deserializer.expectList();
+ expect(deserializer.moveNext(), false);
- expect(deserializer.moveNext(), false);
+ expect(deserializer.moveNext(), false);
+ });
});
+ }
- test('remote instances', () async {
+ for (var mode in [
+ SerializationMode.byteDataServer,
+ SerializationMode.jsonServer
+ ]) {
+ test('remote instances in $mode', () async {
var string = NamedTypeAnnotationImpl(
id: RemoteInstance.uniqueId,
isNullable: false,
@@ -93,203 +126,219 @@
isNullable: false,
identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
typeArguments: [string]);
- Object? serializedFoo;
- var serializer = JsonSerializer();
- withSerializationMode(SerializationMode.server, () {
+ withSerializationMode(mode, () {
+ var serializer = serializerFactory();
foo.serialize(serializer);
- serializedFoo = serializer.result;
- var response = roundTrip(serializedFoo);
- var deserializer = JsonDeserializer(response as List<Object?>);
+ var response = roundTrip(serializer.result);
+ var deserializer = deserializerFactory(response);
var instance = RemoteInstance.deserialize(deserializer);
expect(instance, foo);
});
});
+ }
- group('declarations', () {
- final barType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: false,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Bar'),
- typeArguments: []);
- final fooType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: true,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
- typeArguments: [barType]);
+ group('declarations', () {
+ final barType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: false,
+ identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Bar'),
+ typeArguments: []);
+ final fooType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: true,
+ identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+ typeArguments: [barType]);
- test('NamedTypeAnnotation', () {
- expectSerializationEquality(fooType);
- });
+ for (var mode in [
+ SerializationMode.byteDataServer,
+ SerializationMode.jsonServer
+ ]) {
+ group('with mode $mode', () {
+ test('NamedTypeAnnotation', () {
+ expectSerializationEquality(fooType, mode);
+ });
- final fooNamedParam = ParameterDeclarationImpl(
- id: RemoteInstance.uniqueId,
- isNamed: true,
- isRequired: true,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
- type: fooType);
+ final fooNamedParam = ParameterDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ isNamed: true,
+ isRequired: true,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
+ type: fooType);
- final barPositionalParam = ParameterDeclarationImpl(
- id: RemoteInstance.uniqueId,
- isNamed: false,
- isRequired: false,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
- type: barType);
+ final barPositionalParam = ParameterDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ isNamed: false,
+ isRequired: false,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+ type: barType);
- final zapTypeParam = TypeParameterDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Zap'),
- bound: barType);
-
- // Transitively tests `TypeParameterDeclaration` and
- // `ParameterDeclaration`.
- test('FunctionTypeAnnotation', () {
- var functionType = FunctionTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: true,
- namedParameters: [fooNamedParam],
- positionalParameters: [barPositionalParam],
- returnType: fooType,
- typeParameters: [zapTypeParam],
- );
- expectSerializationEquality(functionType);
- });
-
- test('FunctionDeclaration', () {
- var function = FunctionDeclarationImpl(
+ final zapTypeParam = TypeParameterDeclarationImpl(
id: RemoteInstance.uniqueId,
identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'name'),
- isAbstract: true,
- isExternal: false,
- isGetter: true,
- isOperator: false,
- isSetter: false,
- namedParameters: [],
- positionalParameters: [],
- returnType: fooType,
- typeParameters: []);
- expectSerializationEquality(function);
- });
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Zap'),
+ bound: barType);
- test('MethodDeclaration', () {
- var method = MethodDeclarationImpl(
+ // Transitively tests `TypeParameterDeclaration` and
+ // `ParameterDeclaration`.
+ test('FunctionTypeAnnotation', () {
+ var functionType = FunctionTypeAnnotationImpl(
id: RemoteInstance.uniqueId,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'zorp'),
- isAbstract: false,
- isExternal: false,
- isGetter: false,
- isOperator: false,
- isSetter: true,
+ isNullable: true,
namedParameters: [fooNamedParam],
positionalParameters: [barPositionalParam],
returnType: fooType,
typeParameters: [zapTypeParam],
- definingClass: fooType.identifier);
- expectSerializationEquality(method);
- });
+ );
+ expectSerializationEquality(functionType, mode);
+ });
- test('ConstructorDeclaration', () {
- var constructor = ConstructorDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'new'),
- isAbstract: false,
- isExternal: false,
- isGetter: false,
- isOperator: true,
- isSetter: false,
- namedParameters: [fooNamedParam],
- positionalParameters: [barPositionalParam],
- returnType: fooType,
- typeParameters: [zapTypeParam],
- definingClass: fooType.identifier,
- isFactory: true,
- );
- expectSerializationEquality(constructor);
- });
+ test('FunctionDeclaration', () {
+ var function = FunctionDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'name'),
+ isAbstract: true,
+ isExternal: false,
+ isGetter: true,
+ isOperator: false,
+ isSetter: false,
+ namedParameters: [],
+ positionalParameters: [],
+ returnType: fooType,
+ typeParameters: []);
+ expectSerializationEquality(function, mode);
+ });
- test('VariableDeclaration', () {
- var bar = VariableDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
- isExternal: true,
- isFinal: false,
- isLate: true,
- type: barType,
- );
- expectSerializationEquality(bar);
- });
+ test('MethodDeclaration', () {
+ var method = MethodDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'zorp'),
+ isAbstract: false,
+ isExternal: false,
+ isGetter: false,
+ isOperator: false,
+ isSetter: true,
+ namedParameters: [fooNamedParam],
+ positionalParameters: [barPositionalParam],
+ returnType: fooType,
+ typeParameters: [zapTypeParam],
+ definingClass: fooType.identifier);
+ expectSerializationEquality(method, mode);
+ });
- test('FieldDeclaration', () {
- var bar = FieldDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
- isExternal: false,
- isFinal: true,
- isLate: false,
- type: barType,
- definingClass: fooType.identifier,
- );
- expectSerializationEquality(bar);
- });
+ test('ConstructorDeclaration', () {
+ var constructor = ConstructorDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'new'),
+ isAbstract: false,
+ isExternal: false,
+ isGetter: false,
+ isOperator: true,
+ isSetter: false,
+ namedParameters: [fooNamedParam],
+ positionalParameters: [barPositionalParam],
+ returnType: fooType,
+ typeParameters: [zapTypeParam],
+ definingClass: fooType.identifier,
+ isFactory: true,
+ );
+ expectSerializationEquality(constructor, mode);
+ });
- var objectType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Object'),
- isNullable: false,
- typeArguments: [],
- );
- var serializableType = NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Serializable'),
- isNullable: false,
- typeArguments: [],
- );
+ test('VariableDeclaration', () {
+ var bar = VariableDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+ isExternal: true,
+ isFinal: false,
+ isLate: true,
+ type: barType,
+ );
+ expectSerializationEquality(bar, mode);
+ });
- test('ClassDeclaration', () {
- var fooClass = ClassDeclarationImpl(
- id: RemoteInstance.uniqueId,
- identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
- interfaces: [barType],
- isAbstract: true,
- isExternal: false,
- mixins: [serializableType],
- superclass: objectType,
- typeParameters: [zapTypeParam],
- );
- expectSerializationEquality(fooClass);
- });
+ test('FieldDeclaration', () {
+ var bar = FieldDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+ isExternal: false,
+ isFinal: true,
+ isLate: false,
+ type: barType,
+ definingClass: fooType.identifier,
+ );
+ expectSerializationEquality(bar, mode);
+ });
- test('TypeAliasDeclaration', () {
- var typeAlias = TypeAliasDeclarationImpl(
+ var objectType = NamedTypeAnnotationImpl(
id: RemoteInstance.uniqueId,
identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'FooOfBar'),
- typeParameters: [zapTypeParam],
- aliasedType: NamedTypeAnnotationImpl(
- id: RemoteInstance.uniqueId,
- isNullable: false,
- identifier:
- IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
- typeArguments: [barType]),
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Object'),
+ isNullable: false,
+ typeArguments: [],
);
- expectSerializationEquality(typeAlias);
+ var serializableType = NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Serializable'),
+ isNullable: false,
+ typeArguments: [],
+ );
+
+ test('ClassDeclaration', () {
+ var fooClass = ClassDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+ interfaces: [barType],
+ isAbstract: true,
+ isExternal: false,
+ mixins: [serializableType],
+ superclass: objectType,
+ typeParameters: [zapTypeParam],
+ );
+ expectSerializationEquality(fooClass, mode);
+ });
+
+ test('TypeAliasDeclaration', () {
+ var typeAlias = TypeAliasDeclarationImpl(
+ id: RemoteInstance.uniqueId,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'FooOfBar'),
+ typeParameters: [zapTypeParam],
+ aliasedType: NamedTypeAnnotationImpl(
+ id: RemoteInstance.uniqueId,
+ isNullable: false,
+ identifier:
+ IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+ typeArguments: [barType]),
+ );
+ expectSerializationEquality(typeAlias, mode);
+ });
});
- });
+ }
});
}
/// Serializes [serializable] in server mode, then deserializes it in client
/// mode, and checks that all the fields are the same.
-void expectSerializationEquality(Serializable serializable) {
- var serializer = JsonSerializer();
- withSerializationMode(SerializationMode.server, () {
+void expectSerializationEquality(
+ Serializable serializable, SerializationMode serverMode) {
+ late Object? serialized;
+ withSerializationMode(serverMode, () {
+ var serializer = serializerFactory();
serializable.serialize(serializer);
+ serialized = serializer.result;
});
- withSerializationMode(SerializationMode.client, () {
- var deserializer = JsonDeserializer(serializer.result);
+ withSerializationMode(_clientModeForServerMode(serverMode), () {
+ var deserializer = deserializerFactory(serialized);
var deserialized = (deserializer..moveNext()).expectRemoteInstance();
if (deserialized is Declaration) {
expect(serializable, deepEqualsDeclaration(deserialized));
@@ -303,12 +352,23 @@
/// Deserializes [serialized] in client mode and sends it back.
Object? roundTrip<Declaration>(Object? serialized) {
- return withSerializationMode(SerializationMode.client, () {
- var deserializer = JsonDeserializer(serialized as List<Object?>);
+ return withSerializationMode(_clientModeForServerMode(serializationMode), () {
+ var deserializer = deserializerFactory(serialized);
var instance =
RemoteInstance.deserialize<NamedTypeAnnotationImpl>(deserializer);
- var serializer = JsonSerializer();
+ var serializer = serializerFactory();
instance.serialize(serializer);
return serializer.result;
});
}
+
+SerializationMode _clientModeForServerMode(SerializationMode serverMode) {
+ switch (serverMode) {
+ case SerializationMode.byteDataServer:
+ return SerializationMode.byteDataClient;
+ case SerializationMode.jsonServer:
+ return SerializationMode.jsonClient;
+ default:
+ throw StateError('Expected to be running in a server mode');
+ }
+}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 10299a1..a8d2705 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -215,6 +215,7 @@
compared
compares
compilations
+complement
completers
completes
complicating
@@ -266,6 +267,7 @@
csslib
cstefantsova
ctx
+customizable
customized
cut
cwd
@@ -378,6 +380,7 @@
effects
efficient
efficiently
+eight
eighth
elem
eliminating
@@ -736,6 +739,7 @@
masking
masks
master
+materialize
mature
mb
mc
@@ -1308,6 +1312,7 @@
traced
tracker
traditional
+transferable
transformers
transforming
translation
@@ -1321,6 +1326,7 @@
ts
tty
tuple
+twos
typeref
u
ufeff
@@ -1466,6 +1472,9 @@
xdfff
xef
xff
+xffff
+xffffffff
+xffffffffffffffff
xi
xj
xk