From cfbf5e274cac25b0e6b0bcf6633e8b4f6547136e Mon Sep 17 00:00:00 2001 From: Alex James Date: Fri, 18 Aug 2023 16:32:12 +0100 Subject: [PATCH 01/11] Generate bindings for BufferedInputStream --- pkgs/java_http/jnigen.yaml | 1 + .../java/io/BufferedInputStream.dart | 248 ++++++++++++++++++ .../lib/src/third_party/java/io/_package.dart | 1 + 3 files changed, 250 insertions(+) create mode 100644 pkgs/java_http/lib/src/third_party/java/io/BufferedInputStream.dart diff --git a/pkgs/java_http/jnigen.yaml b/pkgs/java_http/jnigen.yaml index 2a8302685c..a99320fc26 100644 --- a/pkgs/java_http/jnigen.yaml +++ b/pkgs/java_http/jnigen.yaml @@ -12,6 +12,7 @@ class_path: - 'classes.jar' classes: + - 'java.io.BufferedInputStream' - 'java.io.InputStream' - 'java.io.OutputStream' - 'java.lang.System' diff --git a/pkgs/java_http/lib/src/third_party/java/io/BufferedInputStream.dart b/pkgs/java_http/lib/src/third_party/java/io/BufferedInputStream.dart new file mode 100644 index 0000000000..c732e12b0c --- /dev/null +++ b/pkgs/java_http/lib/src/third_party/java/io/BufferedInputStream.dart @@ -0,0 +1,248 @@ +// Autogenerated by jnigen. DO NOT EDIT! + +// ignore_for_file: annotate_overrides +// ignore_for_file: camel_case_extensions +// ignore_for_file: camel_case_types +// ignore_for_file: constant_identifier_names +// ignore_for_file: file_names +// ignore_for_file: no_leading_underscores_for_local_identifiers +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: overridden_fields +// ignore_for_file: unnecessary_cast +// ignore_for_file: unused_element +// ignore_for_file: unused_field +// ignore_for_file: unused_import +// ignore_for_file: unused_shown_name + +import "dart:isolate" show ReceivePort; +import "dart:ffi" as ffi; +import "package:jni/internal_helpers_for_jnigen.dart"; +import "package:jni/jni.dart" as jni; + +import "InputStream.dart" as inputstream_; + +/// from: java.io.BufferedInputStream +class BufferedInputStream extends jni.JObject { + @override + late final jni.JObjType $type = type; + + BufferedInputStream.fromRef( + jni.JObjectPtr ref, + ) : super.fromRef(ref); + + static final _class = jni.Jni.findJClass(r"java/io/BufferedInputStream"); + + /// The type which includes information such as the signature of this class. + static const type = $BufferedInputStreamType(); + static final _id_buf = jni.Jni.accessors.getFieldIDOf( + _class.reference, + r"buf", + r"[B", + ); + + /// from: protected byte[] buf + /// The returned object must be deleted after use, by calling the `delete` method. + jni.JArray get buf => + const jni.JArrayType(jni.jbyteType()).fromRef(jni.Jni.accessors + .getField(reference, _id_buf, jni.JniCallType.objectType) + .object); + + /// from: protected byte[] buf + /// The returned object must be deleted after use, by calling the `delete` method. + set buf(jni.JArray value) => + jni.Jni.env.SetObjectField(reference, _id_buf, value.reference); + + static final _id_count = jni.Jni.accessors.getFieldIDOf( + _class.reference, + r"count", + r"I", + ); + + /// from: protected int count + int get count => jni.Jni.accessors + .getField(reference, _id_count, jni.JniCallType.intType) + .integer; + + /// from: protected int count + set count(int value) => jni.Jni.env.SetIntField(reference, _id_count, value); + + static final _id_pos = jni.Jni.accessors.getFieldIDOf( + _class.reference, + r"pos", + r"I", + ); + + /// from: protected int pos + int get pos => jni.Jni.accessors + .getField(reference, _id_pos, jni.JniCallType.intType) + .integer; + + /// from: protected int pos + set pos(int value) => jni.Jni.env.SetIntField(reference, _id_pos, value); + + static final _id_markpos = jni.Jni.accessors.getFieldIDOf( + _class.reference, + r"markpos", + r"I", + ); + + /// from: protected int markpos + int get markpos => jni.Jni.accessors + .getField(reference, _id_markpos, jni.JniCallType.intType) + .integer; + + /// from: protected int markpos + set markpos(int value) => + jni.Jni.env.SetIntField(reference, _id_markpos, value); + + static final _id_marklimit = jni.Jni.accessors.getFieldIDOf( + _class.reference, + r"marklimit", + r"I", + ); + + /// from: protected int marklimit + int get marklimit => jni.Jni.accessors + .getField(reference, _id_marklimit, jni.JniCallType.intType) + .integer; + + /// from: protected int marklimit + set marklimit(int value) => + jni.Jni.env.SetIntField(reference, _id_marklimit, value); + + static final _id_ctor = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"", r"(Ljava/io/InputStream;)V"); + + /// from: public void (java.io.InputStream inputStream) + /// The returned object must be deleted after use, by calling the `delete` method. + factory BufferedInputStream( + inputstream_.InputStream inputStream, + ) { + return BufferedInputStream.fromRef(jni.Jni.accessors.newObjectWithArgs( + _class.reference, _id_ctor, [inputStream.reference]).object); + } + + static final _id_ctor1 = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"", r"(Ljava/io/InputStream;I)V"); + + /// from: public void (java.io.InputStream inputStream, int i) + /// The returned object must be deleted after use, by calling the `delete` method. + factory BufferedInputStream.ctor1( + inputstream_.InputStream inputStream, + int i, + ) { + return BufferedInputStream.fromRef(jni.Jni.accessors.newObjectWithArgs( + _class.reference, + _id_ctor1, + [inputStream.reference, jni.JValueInt(i)]).object); + } + + static final _id_read = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"read", r"()I"); + + /// from: public int read() + int read() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_read, jni.JniCallType.intType, []).integer; + } + + static final _id_read1 = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"read", r"([BII)I"); + + /// from: public int read(byte[] bs, int i, int i1) + int read1( + jni.JArray bs, + int i, + int i1, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, + _id_read1, + jni.JniCallType.intType, + [bs.reference, jni.JValueInt(i), jni.JValueInt(i1)]).integer; + } + + static final _id_skip = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"skip", r"(J)J"); + + /// from: public long skip(long j) + int skip( + int j, + ) { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_skip, jni.JniCallType.longType, [j]).long; + } + + static final _id_available = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"available", r"()I"); + + /// from: public int available() + int available() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_available, jni.JniCallType.intType, []).integer; + } + + static final _id_mark = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"mark", r"(I)V"); + + /// from: public void mark(int i) + void mark( + int i, + ) { + return jni.Jni.accessors.callMethodWithArgs(reference, _id_mark, + jni.JniCallType.voidType, [jni.JValueInt(i)]).check(); + } + + static final _id_reset = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"reset", r"()V"); + + /// from: public void reset() + void reset() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_reset, jni.JniCallType.voidType, []).check(); + } + + static final _id_markSupported = jni.Jni.accessors + .getMethodIDOf(_class.reference, r"markSupported", r"()Z"); + + /// from: public boolean markSupported() + bool markSupported() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_markSupported, jni.JniCallType.booleanType, []).boolean; + } + + static final _id_close = + jni.Jni.accessors.getMethodIDOf(_class.reference, r"close", r"()V"); + + /// from: public void close() + void close() { + return jni.Jni.accessors.callMethodWithArgs( + reference, _id_close, jni.JniCallType.voidType, []).check(); + } +} + +class $BufferedInputStreamType extends jni.JObjType { + const $BufferedInputStreamType(); + + @override + String get signature => r"Ljava/io/BufferedInputStream;"; + + @override + BufferedInputStream fromRef(jni.JObjectPtr ref) => + BufferedInputStream.fromRef(ref); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($BufferedInputStreamType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($BufferedInputStreamType) && + other is $BufferedInputStreamType; + } +} diff --git a/pkgs/java_http/lib/src/third_party/java/io/_package.dart b/pkgs/java_http/lib/src/third_party/java/io/_package.dart index ef72615333..a25d6e85d2 100644 --- a/pkgs/java_http/lib/src/third_party/java/io/_package.dart +++ b/pkgs/java_http/lib/src/third_party/java/io/_package.dart @@ -1,2 +1,3 @@ +export "BufferedInputStream.dart"; export "InputStream.dart"; export "OutputStream.dart"; From 98b98d01777728562e5284c8b7085c6a7cf144ca Mon Sep 17 00:00:00 2001 From: Alex James Date: Fri, 18 Aug 2023 17:04:33 +0100 Subject: [PATCH 02/11] Use BufferedInputStream for response body --- pkgs/java_http/lib/src/java_client.dart | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index 1076deae5c..c592068b5e 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -12,6 +12,7 @@ import 'package:http/http.dart'; import 'package:jni/jni.dart'; import 'package:path/path.dart'; +import 'third_party/java/io/BufferedInputStream.dart'; import 'third_party/java/lang/System.dart'; import 'third_party/java/net/HttpURLConnection.dart'; import 'third_party/java/net/URL.dart'; @@ -241,13 +242,24 @@ class JavaClient extends BaseClient { final inputStream = (responseCode >= 200 && responseCode <= 299) ? httpUrlConnection.getInputStream() : httpUrlConnection.getErrorStream(); + final bufferedInputStream = BufferedInputStream(inputStream); + print(bufferedInputStream.available()); - int byte; + int bytesRead; var actualBodyLength = 0; - // TODO: inputStream.read() could throw IOException. - while ((byte = inputStream.read()) != -1) { - sendPort.send([byte]); - actualBodyLength++; + final buffer = JArray(jbyte.type, 4096); + // TODO: bufferedInputStream.read() could throw IOException. + while ((bytesRead = bufferedInputStream.read1(buffer, 0, buffer.length)) != + -1) { + if (bytesRead == 0) continue; + + // Convert from Java array to Dart Uint8List + final byteArray = Uint8List(bytesRead); + for (var i = 0; i < bytesRead; i++) { + byteArray[i] = buffer[i]; + } + sendPort.send(byteArray); + actualBodyLength += bytesRead; } if (expectedBodyLength != null && actualBodyLength < expectedBodyLength) { From 660daf12c914ae76708f547ef99a318b5655565c Mon Sep 17 00:00:00 2001 From: Alex James Date: Mon, 21 Aug 2023 16:50:00 +0100 Subject: [PATCH 03/11] Let other isolates run if no data is available --- pkgs/java_http/lib/src/java_client.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index c592068b5e..36b53e24b7 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -97,7 +97,7 @@ class JavaClient extends BaseClient { } // TODO: Rename _isolateMethod to something more descriptive. - void _isolateMethod( + Future _isolateMethod( ({ SendPort sendPort, Uint8List body, @@ -105,7 +105,7 @@ class JavaClient extends BaseClient { String method, Uri url, }) request, - ) { + ) async { final httpUrlConnection = URL .ctor3(request.url.toString().toJString()) .openConnection() @@ -141,7 +141,7 @@ class JavaClient extends BaseClient { responseHeaders, ); - _responseBody( + await _responseBody( request.url, httpUrlConnection, request.sendPort, @@ -231,12 +231,12 @@ class JavaClient extends BaseClient { return contentLength; } - void _responseBody( + Future _responseBody( Uri requestUrl, HttpURLConnection httpUrlConnection, SendPort sendPort, int? expectedBodyLength, - ) { + ) async { final responseCode = httpUrlConnection.getResponseCode(); final inputStream = (responseCode >= 200 && responseCode <= 299) @@ -251,7 +251,11 @@ class JavaClient extends BaseClient { // TODO: bufferedInputStream.read() could throw IOException. while ((bytesRead = bufferedInputStream.read1(buffer, 0, buffer.length)) != -1) { - if (bytesRead == 0) continue; + if (bytesRead == 0) { + // No more data is available without blocking so give other Isolates an + // opportunity to run. + await Future.delayed(Duration.zero); + } // Convert from Java array to Dart Uint8List final byteArray = Uint8List(bytesRead); From 7a01c6a026a67a495040d05b1a249058312c8648 Mon Sep 17 00:00:00 2001 From: Alex James Date: Tue, 22 Aug 2023 20:05:27 +0100 Subject: [PATCH 04/11] Remove print statement --- pkgs/java_http/lib/src/java_client.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index 36b53e24b7..0fe00c072b 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -243,7 +243,6 @@ class JavaClient extends BaseClient { ? httpUrlConnection.getInputStream() : httpUrlConnection.getErrorStream(); final bufferedInputStream = BufferedInputStream(inputStream); - print(bufferedInputStream.available()); int bytesRead; var actualBodyLength = 0; From e504f872b945a660687bd590d2be0deb39fe7010 Mon Sep 17 00:00:00 2001 From: Alex James Date: Tue, 22 Aug 2023 20:08:58 +0100 Subject: [PATCH 05/11] Refactor converting JArray to Uint8List --- pkgs/java_http/lib/src/java_client.dart | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index 0fe00c072b..70edf33b3d 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -256,12 +256,7 @@ class JavaClient extends BaseClient { await Future.delayed(Duration.zero); } - // Convert from Java array to Dart Uint8List - final byteArray = Uint8List(bytesRead); - for (var i = 0; i < bytesRead; i++) { - byteArray[i] = buffer[i]; - } - sendPort.send(byteArray); + sendPort.send(buffer.toUint8List(length: bytesRead)); actualBodyLength += bytesRead; } @@ -277,3 +272,14 @@ extension on Uint8List { JArray toJArray() => JArray(jbyte.type, length)..setRange(0, length, this); } + +extension on JArray { + Uint8List toUint8List({int? length}) { + length ??= this.length; + final list = Uint8List(length); + for (var i = 0; i < length; i++) { + list[i] = this[i]; + } + return list; + } +} From 877f221a577bcbc9fd6daa24675ad784a2e04b1b Mon Sep 17 00:00:00 2001 From: Alex James Date: Tue, 22 Aug 2023 21:58:02 +0100 Subject: [PATCH 06/11] Rename variable bytesRead to bytesCount --- pkgs/java_http/lib/src/java_client.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index 70edf33b3d..308cd1cfc2 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -244,20 +244,20 @@ class JavaClient extends BaseClient { : httpUrlConnection.getErrorStream(); final bufferedInputStream = BufferedInputStream(inputStream); - int bytesRead; + int bytesCount; var actualBodyLength = 0; final buffer = JArray(jbyte.type, 4096); // TODO: bufferedInputStream.read() could throw IOException. - while ((bytesRead = bufferedInputStream.read1(buffer, 0, buffer.length)) != + while ((bytesCount = bufferedInputStream.read1(buffer, 0, buffer.length)) != -1) { - if (bytesRead == 0) { + if (bytesCount == 0) { // No more data is available without blocking so give other Isolates an // opportunity to run. await Future.delayed(Duration.zero); } - sendPort.send(buffer.toUint8List(length: bytesRead)); - actualBodyLength += bytesRead; + sendPort.send(buffer.toUint8List(length: bytesCount)); + actualBodyLength += bytesCount; } if (expectedBodyLength != null && actualBodyLength < expectedBodyLength) { From 403491c29b18e2b3d3197f8c7952b580f7bd9513 Mon Sep 17 00:00:00 2001 From: Alex James Date: Tue, 22 Aug 2023 22:00:28 +0100 Subject: [PATCH 07/11] Rename variable buffer to bytesBuffer --- pkgs/java_http/lib/src/java_client.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index 308cd1cfc2..a3304613da 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -246,9 +246,9 @@ class JavaClient extends BaseClient { int bytesCount; var actualBodyLength = 0; - final buffer = JArray(jbyte.type, 4096); + final bytesBuffer = JArray(jbyte.type, 4096); // TODO: bufferedInputStream.read() could throw IOException. - while ((bytesCount = bufferedInputStream.read1(buffer, 0, buffer.length)) != + while ((bytesCount = bufferedInputStream.read1(bytesBuffer, 0, bytesBuffer.length)) != -1) { if (bytesCount == 0) { // No more data is available without blocking so give other Isolates an @@ -256,7 +256,7 @@ class JavaClient extends BaseClient { await Future.delayed(Duration.zero); } - sendPort.send(buffer.toUint8List(length: bytesCount)); + sendPort.send(bytesBuffer.toUint8List(length: bytesCount)); actualBodyLength += bytesCount; } From abfd68332a7b3cc0f0953e2644edcdc51ba0e1a8 Mon Sep 17 00:00:00 2001 From: Alex James Date: Tue, 22 Aug 2023 22:03:38 +0100 Subject: [PATCH 08/11] Refactor bufferedInputStream initialisation --- pkgs/java_http/lib/src/java_client.dart | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index a3304613da..ecc77f6bb5 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -239,10 +239,9 @@ class JavaClient extends BaseClient { ) async { final responseCode = httpUrlConnection.getResponseCode(); - final inputStream = (responseCode >= 200 && responseCode <= 299) - ? httpUrlConnection.getInputStream() - : httpUrlConnection.getErrorStream(); - final bufferedInputStream = BufferedInputStream(inputStream); + final bufferedInputStream = (responseCode >= 200 && responseCode <= 299) + ? BufferedInputStream(httpUrlConnection.getInputStream()) + : BufferedInputStream(httpUrlConnection.getErrorStream()); int bytesCount; var actualBodyLength = 0; @@ -264,7 +263,7 @@ class JavaClient extends BaseClient { sendPort.send(ClientException('Unexpected end of body', requestUrl)); } - inputStream.close(); + bufferedInputStream.close(); } } From 3e987d4972fd515ef6035cb041eaf526d28054a1 Mon Sep 17 00:00:00 2001 From: Alex James Date: Tue, 22 Aug 2023 22:04:58 +0100 Subject: [PATCH 09/11] Rename bufferedInputStream to responseBodyStream --- pkgs/java_http/lib/src/java_client.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index ecc77f6bb5..f2afa1490f 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -239,7 +239,7 @@ class JavaClient extends BaseClient { ) async { final responseCode = httpUrlConnection.getResponseCode(); - final bufferedInputStream = (responseCode >= 200 && responseCode <= 299) + final responseBodyStream = (responseCode >= 200 && responseCode <= 299) ? BufferedInputStream(httpUrlConnection.getInputStream()) : BufferedInputStream(httpUrlConnection.getErrorStream()); @@ -247,7 +247,7 @@ class JavaClient extends BaseClient { var actualBodyLength = 0; final bytesBuffer = JArray(jbyte.type, 4096); // TODO: bufferedInputStream.read() could throw IOException. - while ((bytesCount = bufferedInputStream.read1(bytesBuffer, 0, bytesBuffer.length)) != + while ((bytesCount = responseBodyStream.read1(bytesBuffer, 0, bytesBuffer.length)) != -1) { if (bytesCount == 0) { // No more data is available without blocking so give other Isolates an @@ -263,7 +263,7 @@ class JavaClient extends BaseClient { sendPort.send(ClientException('Unexpected end of body', requestUrl)); } - bufferedInputStream.close(); + responseBodyStream.close(); } } From 026d10a6549e88f2ec79621e782711e8706b9cb8 Mon Sep 17 00:00:00 2001 From: Alex James Date: Tue, 22 Aug 2023 22:16:52 +0100 Subject: [PATCH 10/11] Refactor while loop condition --- pkgs/java_http/lib/src/java_client.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index f2afa1490f..68f54e074c 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -243,12 +243,13 @@ class JavaClient extends BaseClient { ? BufferedInputStream(httpUrlConnection.getInputStream()) : BufferedInputStream(httpUrlConnection.getErrorStream()); - int bytesCount; var actualBodyLength = 0; final bytesBuffer = JArray(jbyte.type, 4096); - // TODO: bufferedInputStream.read() could throw IOException. - while ((bytesCount = responseBodyStream.read1(bytesBuffer, 0, bytesBuffer.length)) != - -1) { + // TODO: read1() could throw IOException. + var bytesCount = + responseBodyStream.read1(bytesBuffer, 0, bytesBuffer.length); + + while (bytesCount != -1) { if (bytesCount == 0) { // No more data is available without blocking so give other Isolates an // opportunity to run. @@ -257,6 +258,9 @@ class JavaClient extends BaseClient { sendPort.send(bytesBuffer.toUint8List(length: bytesCount)); actualBodyLength += bytesCount; + + // TODO: read1() could throw IOException. + bytesCount = responseBodyStream.read1(bytesBuffer, 0, bytesBuffer.length); } if (expectedBodyLength != null && actualBodyLength < expectedBodyLength) { From ea4d668dabe404a4ef1e18f00e822b85de01ba9d Mon Sep 17 00:00:00 2001 From: Alex James Date: Thu, 24 Aug 2023 00:57:39 +0100 Subject: [PATCH 11/11] Refactor while loop --- pkgs/java_http/lib/src/java_client.dart | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pkgs/java_http/lib/src/java_client.dart b/pkgs/java_http/lib/src/java_client.dart index 68f54e074c..379c640b1d 100644 --- a/pkgs/java_http/lib/src/java_client.dart +++ b/pkgs/java_http/lib/src/java_client.dart @@ -245,22 +245,25 @@ class JavaClient extends BaseClient { var actualBodyLength = 0; final bytesBuffer = JArray(jbyte.type, 4096); - // TODO: read1() could throw IOException. - var bytesCount = - responseBodyStream.read1(bytesBuffer, 0, bytesBuffer.length); - while (bytesCount != -1) { + while (true) { + // TODO: read1() could throw IOException. + final bytesCount = + responseBodyStream.read1(bytesBuffer, 0, bytesBuffer.length); + + if (bytesCount == -1) { + break; + } + if (bytesCount == 0) { // No more data is available without blocking so give other Isolates an // opportunity to run. await Future.delayed(Duration.zero); + continue; } sendPort.send(bytesBuffer.toUint8List(length: bytesCount)); actualBodyLength += bytesCount; - - // TODO: read1() could throw IOException. - bytesCount = responseBodyStream.read1(bytesBuffer, 0, bytesBuffer.length); } if (expectedBodyLength != null && actualBodyLength < expectedBodyLength) {