Skip to content
This repository has been archived by the owner on Oct 28, 2024. It is now read-only.

Update lints, test JS & Wasm #116

Merged
merged 3 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
matrix:
# Add macos-latest and/or windows-latest if relevant for this package.
os: [ubuntu-latest]
sdk: [2.19.0, dev]
sdk: [3.4, dev]
steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
- uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30
Expand All @@ -59,3 +59,6 @@ jobs:
- name: Run VM tests
run: dart test --platform vm
if: always() && steps.install.outcome == 'success'
- name: Run browser tests
run: dart test --platform chrome --compiler dart2wasm,dart2js
if: always() && steps.install.outcome == 'success'
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## 3.0.3-dev
## 3.0.3-wip

* Require Dart 2.19
* Require Dart 3.4

## 3.0.2

Expand Down
1 change: 0 additions & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ linter:
- avoid_unused_constructor_parameters
- cancel_subscriptions
- package_api_docs
- test_types_in_equals
30 changes: 12 additions & 18 deletions lib/error_code.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

// ignore_for_file: constant_identifier_names

/// Error codes defined in the [JSON-RPC 2.0 specificiation][spec].
import 'src/exception.dart';

/// Error codes defined in the [JSON-RPC 2.0 specification][spec].
///
/// These codes are generally used for protocol-level communication. Most of
/// them shouldn't be used by the application. Those that should have
Expand Down Expand Up @@ -38,20 +40,12 @@ const SERVER_ERROR = -32000;
/// Returns a human-readable name for [errorCode] if it's one specified by the
/// JSON-RPC 2.0 spec.
///
/// If [errorCode] isn't defined in the JSON-RPC 2.0 spec, returns null.
String? name(int errorCode) {
switch (errorCode) {
case PARSE_ERROR:
return 'parse error';
case INVALID_REQUEST:
return 'invalid request';
case METHOD_NOT_FOUND:
return 'method not found';
case INVALID_PARAMS:
return 'invalid parameters';
case INTERNAL_ERROR:
return 'internal error';
default:
return null;
}
}
/// If [errorCode] isn't defined in the JSON-RPC 2.0 spec, returns `null`.
String? name(int errorCode) => switch (errorCode) {
PARSE_ERROR => 'parse error',
INVALID_REQUEST => 'invalid request',
METHOD_NOT_FOUND => 'method not found',
INVALID_PARAMS => 'invalid parameters',
INTERNAL_ERROR => 'internal error',
_ => null
};
26 changes: 14 additions & 12 deletions lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,19 @@ class Client {

/// Creates a [Client] that communicates over [channel].
///
/// Note that the client won't begin listening to [responses] until
/// Note that the client won't begin listening to [channel] until
/// [Client.listen] is called.
Client(StreamChannel<String> channel)
: this.withoutJson(
jsonDocument.bind(channel).transformStream(ignoreFormatExceptions));

/// Creates a [Client] that communicates using decoded messages over
/// [channel].
/// [_channel].
///
/// Unlike [Client.new], this doesn't read or write JSON strings. Instead, it
/// reads and writes decoded maps or lists.
///
/// Note that the client won't begin listening to [responses] until
/// Note that the client won't begin listening to [_channel] until
/// [Client.listen] is called.
Client.withoutJson(this._channel) {
done.whenComplete(() {
Expand All @@ -80,7 +80,8 @@ class Client {
///
/// [listen] may only be called once.
Future listen() {
_channel.stream.listen(_handleResponse, onError: (error, stackTrace) {
_channel.stream.listen(_handleResponse,
onError: (Object error, StackTrace stackTrace) {
_done.completeError(error, stackTrace);
_channel.sink.close();
}, onDone: () {
Expand Down Expand Up @@ -113,11 +114,11 @@ class Client {
///
/// Throws a [StateError] if the client is closed while the request is in
/// flight, or if the client is closed when this method is called.
Future sendRequest(String method, [Object? parameters]) {
Future<Object?> sendRequest(String method, [Object? parameters]) {
var id = _id++;
_send(method, parameters, id);

var completer = Completer.sync();
var completer = Completer<Object?>.sync();
_pendingRequests[id] = _Request(method, completer, Chain.current());
return completer.future;
}
Expand All @@ -141,7 +142,7 @@ class Client {
///
/// Sends a request to invoke [method] with [parameters]. If [id] is given,
/// the request uses that id.
void _send(String method, parameters, [int? id]) {
void _send(String method, Object? parameters, [int? id]) {
if (parameters is Iterable) parameters = parameters.toList();
if (parameters is! Map && parameters is! List && parameters != null) {
throw ArgumentError('Only maps and lists may be used as JSON-RPC '
Expand Down Expand Up @@ -172,7 +173,7 @@ class Client {
/// If this is called in the context of another [withBatch] call, it just
/// invokes [callback] without creating another batch. This means that
/// responses are batched until the first batch ends.
void withBatch(Function() callback) {
void withBatch(FutureOr<void> Function() callback) {
if (_batch != null) {
callback();
return;
Expand All @@ -186,7 +187,7 @@ class Client {
}

/// Handles a decoded response from the server.
void _handleResponse(response) {
void _handleResponse(Object? response) {
if (response is List) {
response.forEach(_handleSingleResponse);
} else {
Expand All @@ -196,8 +197,9 @@ class Client {

/// Handles a decoded response from the server after batches have been
/// resolved.
void _handleSingleResponse(response) {
if (!_isResponseValid(response)) return;
void _handleSingleResponse(Object? response_) {
if (!_isResponseValid(response_)) return;
final response = response_ as Map;
var id = response['id'];
id = (id is String) ? int.parse(id) : id;
var request = _pendingRequests.remove(id)!;
Expand All @@ -212,7 +214,7 @@ class Client {
}

/// Determines whether the server's response is valid per the spec.
bool _isResponseValid(response) {
bool _isResponseValid(Object? response) {
if (response is! Map) return false;
if (response['jsonrpc'] != '2.0') return false;
var id = response['id'];
Expand Down
6 changes: 4 additions & 2 deletions lib/src/exception.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ class RpcException implements Exception {
Map<String, dynamic> serialize(Object? request) {
dynamic modifiedData;
if (data is Map && !(data as Map).containsKey('request')) {
modifiedData = Map.from(data as Map);
modifiedData['request'] = request;
modifiedData = {
...data as Map,
'request': request,
};
} else if (data == null) {
modifiedData = {'request': request};
} else {
Expand Down
24 changes: 12 additions & 12 deletions lib/src/parameters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ class Parameter extends Parameters {
// The parent parameters, used to construct [_path].
final Parameters _parent;

/// The key used to access [this], used to construct [_path].
final dynamic _key;
/// The key used to access `this`, used to construct [_path].
final Object _key;

/// A human-readable representation of the path of getters used to get this.
///
Expand All @@ -130,20 +130,22 @@ class Parameter extends Parameters {
return _key is int ? (_key + 1).toString() : jsonEncode(_key);
}

String quoteKey(key) {
String quoteKey(String key) {
if (key.contains(RegExp(r'[^a-zA-Z0-9_-]'))) return jsonEncode(key);
return key;
}

String computePath(params) {
String computePath(Parameter params) {
if (params._parent is! Parameter) {
return params._key is int ? '[${params._key}]' : quoteKey(params._key);
return params._key is int
? '[${params._key}]'
: quoteKey(params._key as String);
}

var path = computePath(params._parent);
return params._key is int
? '$path[${params._key}]'
: '$path.${quoteKey(params._key)}';
: '$path.${quoteKey(params._key as String)}';
}

return computePath(this);
Expand All @@ -152,8 +154,7 @@ class Parameter extends Parameters {
/// Whether this parameter exists.
bool get exists => true;

Parameter._(String method, value, this._parent, this._key)
: super(method, value);
Parameter._(super.method, super.value, this._parent, this._key);

/// Returns [value], or [defaultValue] if this parameter wasn't passed.
dynamic valueOr(Object? defaultValue) => value;
Expand Down Expand Up @@ -260,8 +261,7 @@ class Parameter extends Parameters {
/// If [value] doesn't exist, this returns [defaultValue].
Uri asUriOr(Uri defaultValue) => asUri;

/// Get a parameter named [named] that matches [test], or the value of calling
/// [orElse].
/// Get a parameter named [type] that matches [test].
///
/// [type] is used for the error message. It should begin with an indefinite
/// article.
Expand All @@ -271,7 +271,7 @@ class Parameter extends Parameters {
'"$method" must be $type, but was ${jsonEncode(value)}.');
}

dynamic _getParsed(String description, Function(String) parse) {
dynamic _getParsed(String description, void Function(String) parse) {
var string = asString;
try {
return parse(string);
Expand Down Expand Up @@ -316,7 +316,7 @@ class _MissingParameter extends Parameter {
@override
bool get exists => false;

_MissingParameter(String method, Parameters parent, key)
_MissingParameter(String method, Parameters parent, Object key)
: super._(method, null, parent, key);

@override
Expand Down
14 changes: 7 additions & 7 deletions lib/src/peer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ class Peer implements Client, Server {

/// A stream controller that forwards incoming messages to [_server] if
/// they're requests.
final _serverIncomingForwarder = StreamController(sync: true);
final _serverIncomingForwarder = StreamController<Object?>(sync: true);

/// A stream controller that forwards incoming messages to [_client] if
/// they're responses.
final _clientIncomingForwarder = StreamController(sync: true);
final _clientIncomingForwarder = StreamController<Object?>(sync: true);

@override
late final Future done = Future.wait([_client.done, _server.done]);
Expand Down Expand Up @@ -66,12 +66,12 @@ class Peer implements Client, Server {
onUnhandledError: onUnhandledError,
strictProtocolChecks: strictProtocolChecks);

/// Creates a [Peer] that communicates using decoded messages over [channel].
/// Creates a [Peer] that communicates using decoded messages over [_channel].
///
/// Unlike [Peer.new], this doesn't read or write JSON strings. Instead, it
/// reads and writes decoded maps or lists.
///
/// Note that the peer won't begin listening to [channel] until
/// Note that the peer won't begin listening to [_channel] until
/// [Peer.listen] is called.
///
/// Unhandled exceptions in callbacks will be forwarded to [onUnhandledError].
Expand Down Expand Up @@ -102,7 +102,7 @@ class Peer implements Client, Server {
_client.sendNotification(method, parameters);

@override
void withBatch(Function() callback) => _client.withBatch(callback);
void withBatch(void Function() callback) => _client.withBatch(callback);

// Server methods.

Expand All @@ -111,7 +111,7 @@ class Peer implements Client, Server {
_server.registerMethod(name, callback);

@override
void registerFallback(Function(Parameters parameters) callback) =>
void registerFallback(void Function(Parameters parameters) callback) =>
_server.registerFallback(callback);

// Shared methods.
Expand Down Expand Up @@ -141,7 +141,7 @@ class Peer implements Client, Server {
// server since it knows how to send error responses.
_serverIncomingForwarder.add(message);
}
}, onError: (error, stackTrace) {
}, onError: (Object error, StackTrace stackTrace) {
_serverIncomingForwarder.addError(error, stackTrace);
}, onDone: close);
return done;
Expand Down
21 changes: 10 additions & 11 deletions lib/src/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ typedef ErrorCallback = void Function(dynamic error, dynamic stackTrace);
///
/// A server exposes methods that are called by requests, to which it provides
/// responses. Methods can be registered using [registerMethod] and
/// [registerFallback]. Requests can be handled using [handleRequest] and
/// [parseRequest].
/// [registerFallback].
///
/// Note that since requests can arrive asynchronously and methods can run
/// asynchronously, it's possible for multiple methods to be invoked at the same
Expand Down Expand Up @@ -72,7 +71,7 @@ class Server {

/// Creates a [Server] that communicates over [channel].
///
/// Note that the server won't begin listening to [requests] until
/// Note that the server won't begin listening to [channel] until
/// [Server.listen] is called.
///
/// Unhandled exceptions in callbacks will be forwarded to [onUnhandledError].
Expand All @@ -89,12 +88,12 @@ class Server {
strictProtocolChecks: strictProtocolChecks);

/// Creates a [Server] that communicates using decoded messages over
/// [channel].
/// [_channel].
///
/// Unlike [Server.new], this doesn't read or write JSON strings. Instead, it
/// reads and writes decoded maps or lists.
///
/// Note that the server won't begin listening to [requests] until
/// Note that the server won't begin listening to [_channel] until
/// [Server.listen] is called.
///
/// Unhandled exceptions in callbacks will be forwarded to [onUnhandledError].
Expand All @@ -113,7 +112,8 @@ class Server {
///
/// [listen] may only be called once.
Future listen() {
_channel.stream.listen(_handleRequest, onError: (error, stackTrace) {
_channel.stream.listen(_handleRequest,
onError: (Object error, StackTrace stackTrace) {
_done.completeError(error, stackTrace);
_channel.sink.close();
}, onDone: () {
Expand Down Expand Up @@ -160,7 +160,7 @@ class Server {
/// completes to a JSON-serializable object. Any errors in [callback] will be
/// reported to the client as JSON-RPC 2.0 errors. [callback] may send custom
/// errors by throwing an [RpcException].
void registerFallback(Function(Parameters parameters) callback) {
void registerFallback(void Function(Parameters parameters) callback) {
_fallbacks.add(callback);
}

Expand All @@ -169,9 +169,8 @@ class Server {
/// [request] is expected to be a JSON-serializable object representing a
/// request sent by a client. This calls the appropriate method or methods for
/// handling that request and returns a JSON-serializable response, or `null`
/// if no response should be sent. [callback] may send custom
/// errors by throwing an [RpcException].
Future _handleRequest(request) async {
/// if no response should be sent.
Future _handleRequest(Object? request) async {
dynamic response;
if (request is List) {
if (request.isEmpty) {
Expand Down Expand Up @@ -241,7 +240,7 @@ class Server {
}

/// Validates that [request] matches the JSON-RPC spec.
void _validateRequest(request) {
void _validateRequest(Object? request) {
if (request is! Map) {
throw RpcException(
error_code.INVALID_REQUEST,
Expand Down
Loading