Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: sdk/lib/io/http_impl.dart

Issue 12328114: Rewrite the Future-pipeline from the Socket to the HttpClientRequest/HttpResponse. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add missing test file. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/socket_patch.dart ('k') | sdk/lib/io/io_stream_consumer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.io; 5 part of dart.io;
6 6
7 class _HttpIncoming 7 class _HttpIncoming
8 extends Stream<List<int>> implements StreamSink<List<int>> { 8 extends Stream<List<int>> implements StreamSink<List<int>> {
9 final int _transferLength; 9 final int _transferLength;
10 final Completer _dataCompleter = new Completer(); 10 final Completer _dataCompleter = new Completer();
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 _onDone(); 731 _onDone();
732 _controller.close(); 732 _controller.close();
733 }); 733 });
734 return _controller.stream; 734 return _controller.stream;
735 } 735 }
736 } 736 }
737 737
738 // Transformer that validates the data written. 738 // Transformer that validates the data written.
739 class _DataValidatorTransformer 739 class _DataValidatorTransformer
740 implements StreamTransformer<List<int>, List<int>> { 740 implements StreamTransformer<List<int>, List<int>> {
741 final StreamController<List<int>> _controller 741 final StreamController<List<int>> _controller =
742 = new StreamController<List<int>>(); 742 new StreamController<List<int>>();
743 int _bytesWritten = 0; 743 int _bytesWritten = 0;
744 Completer _completer = new Completer();
745 744
746 int expectedTransferLength; 745 int expectedTransferLength;
747 746
748 _DataValidatorTransformer();
749
750 Future get validatorFuture => _completer.future;
751
752 Stream<List<int>> bind(Stream<List<int>> stream) { 747 Stream<List<int>> bind(Stream<List<int>> stream) {
753 var subscription; 748 var subscription;
754 subscription = stream.listen( 749 subscription = stream.listen(
755 (data) { 750 (data) {
756 if (expectedTransferLength != null) { 751 if (expectedTransferLength != null) {
757 _bytesWritten += data.length; 752 _bytesWritten += data.length;
758 if (_bytesWritten > expectedTransferLength) { 753 if (_bytesWritten > expectedTransferLength) {
754 subscription.cancel();
755 _controller.signalError(new HttpException(
756 "Content size exceeds specified contentLength. "
757 "$_bytesWritten bytes written while expected "
758 "$expectedTransferLength."));
759 _controller.close(); 759 _controller.close();
760 subscription.cancel();
761 if (_completer != null) {
762 _completer.completeError(new HttpException(
763 "Content size exceeds specified contentLength. "
764 "$_bytesWritten bytes written while expected "
765 "$expectedTransferLength."));
766 _completer = null;
767 }
768 return; 760 return;
769 } 761 }
770 } 762 }
771 _controller.add(data); 763 _controller.add(data);
772 }, 764 },
773 onError: (error) { 765 onError: (error) {
766 _controller.signalError(error);
774 _controller.close(); 767 _controller.close();
775 if (_completer != null) {
776 _completer.completeError(error);
777 _completer = null;
778 }
779 }, 768 },
780 onDone: () { 769 onDone: () {
781 _controller.close();
782 if (expectedTransferLength != null) { 770 if (expectedTransferLength != null) {
783 if (_bytesWritten < expectedTransferLength) { 771 if (_bytesWritten < expectedTransferLength) {
784 if (_completer != null) { 772 _controller.signalError(new HttpException(
785 _completer.completeError(new HttpException( 773 "Content size below specified contentLength. "
786 "Content size below specified contentLength. " 774 " $_bytesWritten bytes written while expected "
787 " $_bytesWritten bytes written while expected " 775 "$expectedTransferLength."));
788 "$expectedTransferLength."));
789 _completer = null;
790 return;
791 }
792 } 776 }
793 } 777 }
794 if (_completer != null) { 778 _controller.close();
795 _completer.complete(this);
796 _completer = null;
797 }
798 }, 779 },
799 unsubscribeOnError: true); 780 unsubscribeOnError: true);
800 return _controller.stream; 781 return _controller.stream;
801 } 782 }
802 } 783 }
803 784
804 // Extends StreamConsumer as this is an internal type, only used to pipe to. 785 // Extends StreamConsumer as this is an internal type, only used to pipe to.
805 class _HttpOutgoing implements StreamConsumer<List<int>, dynamic> { 786 class _HttpOutgoing implements StreamConsumer<List<int>, dynamic> {
806 final Completer _dataCompleter = new Completer();
807 final Completer _streamCompleter = new Completer();
808 final _DataValidatorTransformer _validator = new _DataValidatorTransformer(); 787 final _DataValidatorTransformer _validator = new _DataValidatorTransformer();
788 Function _onStream;
789 final Completer _consumeCompleter = new Completer();
809 790
810 // Future that completes when all data is written. 791 Future onStream(Future callback(Stream<List<int>> stream)) {
811 Future get dataDone => _dataCompleter.future; 792 _onStream = callback;
812 793 return _consumeCompleter.future;
813 // Future that completes with the Stream, once the _HttpClientConnection is 794 }
814 // bound to one.
815 Future<Stream<List<int>>> get stream => _streamCompleter.future;
816 795
817 void setTransferLength(int transferLength) { 796 void setTransferLength(int transferLength) {
818 _validator.expectedTransferLength = transferLength; 797 _validator.expectedTransferLength = transferLength;
819 } 798 }
820 799
821 Future consume(Stream<List<int>> stream) { 800 Future consume(Stream<List<int>> stream) {
822 stream = stream.transform(_validator); 801 _onStream(stream.transform(_validator))
823 _streamCompleter.complete(stream); 802 .then((_) => _consumeCompleter.complete(),
824 _validator.validatorFuture.catchError((e) { 803 onError: _consumeCompleter.completeError);
825 _dataCompleter.completeError(e); 804 // Use .then to ensure a Future branch.
826 }); 805 return _consumeCompleter.future.then((_) => this);
827 return _validator.validatorFuture.then((v) {
828 _dataCompleter.complete();
829 return v;
830 });
831 } 806 }
832 } 807 }
833 808
834 809
835 class _HttpClientConnection { 810 class _HttpClientConnection {
836 final String key; 811 final String key;
837 final Socket _socket; 812 final Socket _socket;
838 final _HttpParser _httpParser; 813 final _HttpParser _httpParser;
839 StreamSubscription _subscription; 814 StreamSubscription _subscription;
840 final _HttpClient _httpClient; 815 final _HttpClient _httpClient;
841 816
842 Completer<_HttpIncoming> _nextResponseCompleter; 817 Completer<_HttpIncoming> _nextResponseCompleter;
843 Future _writeDoneFuture; 818 Future _streamFuture;
844 819
845 _HttpClientConnection(String this.key, 820 _HttpClientConnection(String this.key,
846 Socket this._socket, 821 Socket this._socket,
847 _HttpClient this._httpClient) 822 _HttpClient this._httpClient)
848 : _httpParser = new _HttpParser.responseParser() { 823 : _httpParser = new _HttpParser.responseParser() {
849 _socket.pipe(_httpParser); 824 _socket.pipe(_httpParser);
850 _socket.done.catchError((e) { destroy(); }); 825 _socket.done.catchError((e) { destroy(); });
851 826
852 // Set up handlers on the parser here, so we are sure to get 'onDone' from 827 // Set up handlers on the parser here, so we are sure to get 'onDone' from
853 // the parser. 828 // the parser.
854 _subscription = _httpParser.listen( 829 _subscription = _httpParser.listen(
855 (incoming) { 830 (incoming) {
856 // Only handle one incoming response at the time. Keep the 831 // Only handle one incoming response at the time. Keep the
857 // stream paused until the response have been processed. 832 // stream paused until the response have been processed.
858 _subscription.pause(); 833 _subscription.pause();
859 // We assume the response is not here, until we have send the request. 834 // We assume the response is not here, until we have send the request.
860 assert(_nextResponseCompleter != null); 835 assert(_nextResponseCompleter != null);
861 _nextResponseCompleter.complete(incoming); 836 _nextResponseCompleter.complete(incoming);
862 }, 837 },
863 onError: (error) { 838 onError: (error) {
864 if (_nextResponseCompleter != null) { 839 if (_nextResponseCompleter != null) {
865 _nextResponseCompleter.completeError(error); 840 _nextResponseCompleter.completeError(error);
866 } 841 }
867 }, 842 },
868 onDone: () { 843 onDone: () {
869 close(); 844 close();
870 }); 845 });
871 } 846 }
872 847
873 Future<_HttpIncoming> sendRequest(_HttpOutgoing outgoing) { 848 _HttpClientRequest send(Uri uri, int port, String method, bool isDirect) {
874 return outgoing.stream 849 var outgoing = new _HttpOutgoing();
875 .then((stream) { 850 // Create new request object, wrapping the outgoing connection.
876 // Close socket if output data is invalid. 851 var request = new _HttpClientRequest(outgoing,
877 outgoing.dataDone.catchError((e) { 852 uri,
878 close(); 853 method,
879 }); 854 !isDirect,
855 _httpClient,
856 this);
857 request.headers.host = uri.domain;
858 request.headers.port = port;
859 if (uri.userInfo != null && !uri.userInfo.isEmpty) {
860 // If the URL contains user information use that for basic
861 // authorization
862 String auth =
863 CryptoUtils.bytesToBase64(_encodeString(uri.userInfo));
864 request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
865 } else {
866 // Look for credentials.
867 _Credentials cr = _httpClient._findCredentials(uri);
868 if (cr != null) {
869 cr.authorize(request);
870 }
871 }
872 // Start sending the request (lazy, delayed until the user provides
873 // data).
874 _httpParser.responseToMethod = method;
875 _streamFuture = outgoing.onStream((stream) {
880 // Sending request, set up response completer. 876 // Sending request, set up response completer.
881 _nextResponseCompleter = new Completer(); 877 _nextResponseCompleter = new Completer();
882 _writeDoneFuture = _socket.addStream(stream);
883 // Listen for response. 878 // Listen for response.
884 return _nextResponseCompleter.future 879 _nextResponseCompleter.future
885 .whenComplete(() { 880 .whenComplete(() {
886 _nextResponseCompleter = null; 881 _nextResponseCompleter = null;
887 }) 882 })
888 .then((incoming) { 883 .then((incoming) {
889 incoming.dataDone.then((_) { 884 incoming.dataDone.then((_) {
890 if (!incoming.headers.persistentConnection) { 885 if (incoming.headers.persistentConnection &&
891 close(); 886 request.persistentConnection) {
887 _subscription.resume();
888 // Return connection, now we are done.
889 _httpClient._returnConnection(this);
892 } else { 890 } else {
893 // Wait for the socket to be done with writing, before we 891 destroy();
894 // continue.
895 _writeDoneFuture.then((_) {
896 _subscription.resume();
897 // Return connection, now we are done.
898 _httpClient._returnConnection(this);
899 });
900 } 892 }
901 }); 893 });
902 // TODO(ajohnsen): Can there be an error on dataDone? 894 request._onIncoming(incoming);
903 return incoming;
904 }) 895 })
905 // If we see a state error, we failed to get the 'first' element. 896 // If we see a state error, we failed to get the 'first' element.
906 // Transform the error to a HttpParserException, for consistency. 897 // Transform the error to a HttpParserException, for consistency.
907 .catchError((error) { 898 .catchError((error) {
908 throw new HttpParserException( 899 throw new HttpParserException(
909 "Connection closed before data was received"); 900 "Connection closed before data was received");
910 }, test: (error) => error is StateError) 901 }, test: (error) => error is StateError)
911 .catchError((error) { 902 .catchError((error) {
912 // We are done with the socket. 903 // We are done with the socket.
913 destroy(); 904 destroy();
914 throw error; 905 request._onError(error);
915 }); 906 });
916 }); 907
908 return _socket.addStream(stream)
909 .catchError((e) {
910 destroy();
911 if (e.error is HttpException) throw e;
912 // TODO(ajohnsen): Where to send Socket errors?
913 });
914 });
915 return request;
917 } 916 }
918 917
919 Future<Socket> detachSocket() { 918 Future<Socket> detachSocket() {
920 return _writeDoneFuture.then((_) => 919 return _streamFuture
921 new _DetachedSocket(_socket, _httpParser.detachIncoming())); 920 .then((_) => new _DetachedSocket(_socket, _httpParser.detachIncoming()),
921 onError: (_) {});
922 } 922 }
923 923
924 void destroy() { 924 void destroy() {
925 _httpClient._connectionClosed(this);
925 _socket.destroy(); 926 _socket.destroy();
926 _httpClient._connectionClosed(this);
927 } 927 }
928 928
929 void close() { 929 void close() {
930 var future = _writeDoneFuture;
931 if (future == null) future = new Future.immediate(null);
932 _httpClient._connectionClosed(this); 930 _httpClient._connectionClosed(this);
933 future.then((_) { 931 _streamFuture
934 _socket.close(); 932 // TODO(ajohnsen): Add timeout.
935 // TODO(ajohnsen): Add timeout. 933 .then((_) => _socket.destroy(),
936 // Delay destroy until socket is actually done writing. 934 onError: (_) {});
937 _socket.done.then((_) => _socket.destroy(),
938 onError: (_) => _socket.destroy());
939 });
940 } 935 }
941 936
942 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); 937 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket);
943 } 938 }
944 939
945 class _ConnnectionInfo { 940 class _ConnnectionInfo {
946 _ConnnectionInfo(_HttpClientConnection this.connection, _Proxy this.proxy); 941 _ConnnectionInfo(_HttpClientConnection this.connection, _Proxy this.proxy);
947 final _HttpClientConnection connection; 942 final _HttpClientConnection connection;
948 final _Proxy proxy; 943 final _Proxy proxy;
949 } 944 }
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1048 var proxyConf = const _ProxyConfiguration.direct(); 1043 var proxyConf = const _ProxyConfiguration.direct();
1049 if (_findProxy != null) { 1044 if (_findProxy != null) {
1050 // TODO(sgjesse): Keep a map of these as normally only a few 1045 // TODO(sgjesse): Keep a map of these as normally only a few
1051 // configuration strings will be used. 1046 // configuration strings will be used.
1052 try { 1047 try {
1053 proxyConf = new _ProxyConfiguration(_findProxy(uri)); 1048 proxyConf = new _ProxyConfiguration(_findProxy(uri));
1054 } catch (error, stackTrace) { 1049 } catch (error, stackTrace) {
1055 return new Future.immediateError(error, stackTrace); 1050 return new Future.immediateError(error, stackTrace);
1056 } 1051 }
1057 } 1052 }
1058 return _getConnection(uri.domain, port, proxyConf, isSecure).then((info) { 1053 return _getConnection(uri.domain, port, proxyConf, isSecure)
1059 // Create new internal outgoing connection. 1054 .then((info) {
1060 var outgoing = new _HttpOutgoing(); 1055 return info.connection.send(uri,
1061 // Create new request object, wrapping the outgoing connection. 1056 port,
1062 var request = new _HttpClientRequest(outgoing, 1057 method.toUpperCase(),
1063 uri, 1058 info.proxy.isDirect);
1064 method.toUpperCase(),
1065 !info.proxy.isDirect,
1066 this,
1067 info.connection);
1068 request.headers.host = uri.domain;
1069 request.headers.port = port;
1070 if (uri.userInfo != null && !uri.userInfo.isEmpty) {
1071 // If the URL contains user information use that for basic
1072 // authorization
1073 String auth =
1074 CryptoUtils.bytesToBase64(_encodeString(uri.userInfo));
1075 request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
1076 } else {
1077 // Look for credentials.
1078 _Credentials cr = _findCredentials(uri);
1079 if (cr != null) {
1080 cr.authorize(request);
1081 }
1082 }
1083 // Start sending the request (lazy, delayed until the user provides
1084 // data).
1085 info.connection._httpParser.responseToMethod = method;
1086 info.connection.sendRequest(outgoing)
1087 .then((incoming) {
1088 // The full request have been sent and a response is received
1089 // containing status-code, headers and etc.
1090 request._onIncoming(incoming);
1091 })
1092 .catchError((error) {
1093 // An error occoured before the http-header was parsed. This
1094 // could be either a socket-error or parser-error.
1095 request._onError(error);
1096 });
1097 // Return the request to the user. Immediate socket errors are not
1098 // handled, thus forwarded to the user.
1099 return request;
1100 }); 1059 });
1101 } 1060 }
1102 1061
1103 Future<HttpClientRequest> _openUrlFromRequest(String method, 1062 Future<HttpClientRequest> _openUrlFromRequest(String method,
1104 Uri uri, 1063 Uri uri,
1105 _HttpClientRequest previous) { 1064 _HttpClientRequest previous) {
1106 return openUrl(method, uri).then((request) { 1065 return openUrl(method, uri).then((request) {
1107 // Only follow redirects if initial request did. 1066 // Only follow redirects if initial request did.
1108 request.followRedirects = previous.followRedirects; 1067 request.followRedirects = previous.followRedirects;
1109 // Allow same number of redirects. 1068 // Allow same number of redirects.
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 static const _CLOSING = 2; 1172 static const _CLOSING = 2;
1214 static const _DETACHED = 3; 1173 static const _DETACHED = 3;
1215 1174
1216 int _state = _IDLE; 1175 int _state = _IDLE;
1217 1176
1218 final Socket _socket; 1177 final Socket _socket;
1219 final _HttpServer _httpServer; 1178 final _HttpServer _httpServer;
1220 final _HttpParser _httpParser; 1179 final _HttpParser _httpParser;
1221 StreamSubscription _subscription; 1180 StreamSubscription _subscription;
1222 1181
1223 Future _writeDoneFuture; 1182 Future _streamFuture;
1224 1183
1225 _HttpConnection(Socket this._socket, _HttpServer this._httpServer) 1184 _HttpConnection(Socket this._socket, _HttpServer this._httpServer)
1226 : _httpParser = new _HttpParser.requestParser() { 1185 : _httpParser = new _HttpParser.requestParser() {
1227 _socket.pipe(_httpParser); 1186 _socket.pipe(_httpParser);
1228 _socket.done.catchError((e) => destroy()); 1187 _socket.done.catchError((e) => destroy());
1229 _subscription = _httpParser.listen( 1188 _subscription = _httpParser.listen(
1230 (incoming) { 1189 (incoming) {
1231 // Only handle one incoming request at the time. Keep the 1190 // Only handle one incoming request at the time. Keep the
1232 // stream paused until the request has been send. 1191 // stream paused until the request has been send.
1233 _subscription.pause(); 1192 _subscription.pause();
1234 _state = _ACTIVE; 1193 _state = _ACTIVE;
1235 var outgoing = new _HttpOutgoing(); 1194 var outgoing = new _HttpOutgoing();
1236 _writeDoneFuture = outgoing.stream.then(_socket.addStream); 1195 var response = new _HttpResponse(incoming.headers.protocolVersion,
1237 var response = new _HttpResponse( 1196 outgoing);
1238 incoming.headers.protocolVersion,
1239 outgoing);
1240 var request = new _HttpRequest(response, incoming, _httpServer, this); 1197 var request = new _HttpRequest(response, incoming, _httpServer, this);
1198 outgoing.onStream((stream) {
1199 return _streamFuture = _socket.addStream(stream)
1200 .then((_) {
1201 if (_state == _DETACHED) return;
1202 if (response.persistentConnection &&
1203 request.persistentConnection &&
1204 incoming.fullBodyRead) {
1205 _state = _IDLE;
1206 // Resume the subscription for incoming requests as the
1207 // request is now processed.
1208 _subscription.resume();
1209 } else {
1210 // Close socket, keep-alive not used or body sent before
1211 // received data was handled.
1212 destroy();
1213 }
1214 })
1215 .catchError((e) {
1216 destroy();
1217 if (e.error is HttpException) throw e;
1218 // TODO(ajohnsen): Where to send Socket errors?
1219 });
1220 });
1241 response._ignoreBody = request.method == "HEAD"; 1221 response._ignoreBody = request.method == "HEAD";
1242 response._httpRequest = request; 1222 response._httpRequest = request;
1243 outgoing.dataDone.then((_) {
1244 if (_state == _DETACHED) return;
1245 if (response.headers.persistentConnection &&
1246 incoming.fullBodyRead) {
1247 // Wait for the socket to be done with writing, before we
1248 // continue.
1249 _writeDoneFuture.then((_) {
1250 _state = _IDLE;
1251 // Resume the subscription for incoming requests as the
1252 // request is now processed.
1253 _subscription.resume();
1254 });
1255 } else {
1256 // Close socket, keep-alive not used or body sent before received
1257 // data was handled.
1258 close();
1259 }
1260 }).catchError((e) {
1261 close();
1262 });
1263 _httpServer._handleRequest(request); 1223 _httpServer._handleRequest(request);
1264 }, 1224 },
1265 onDone: () { 1225 onDone: () {
1266 close(); 1226 destroy();
1267 }, 1227 },
1268 onError: (error) { 1228 onError: (error) {
1269 _httpServer._handleError(error); 1229 _httpServer._handleError(error);
1270 destroy(); 1230 destroy();
1271 }); 1231 });
1272 } 1232 }
1273 1233
1274 void destroy() { 1234 void destroy() {
1275 if (_state == _CLOSING || _state == _DETACHED) return; 1235 if (_state == _CLOSING || _state == _DETACHED) return;
1276 _state = _CLOSING; 1236 _state = _CLOSING;
1277 _socket.destroy(); 1237 _socket.destroy();
1278 _httpServer._connectionClosed(this); 1238 _httpServer._connectionClosed(this);
1279 } 1239 }
1280 1240
1281 void close() {
1282 if (_state == _CLOSING || _state == _DETACHED) return;
1283 _state = _CLOSING;
1284 var future = _writeDoneFuture;
1285 if (future == null) future = new Future.immediate(null);
1286 _httpServer._connectionClosed(this);
1287 future.then((_) {
1288 _socket.close();
1289 // TODO(ajohnsen): Add timeout.
1290 // Delay destroy until socket is actually done writing.
1291 _socket.done.then((_) => _socket.destroy(),
1292 onError: (_) => _socket.destroy());
1293 });
1294 }
1295
1296 Future<Socket> detachSocket() { 1241 Future<Socket> detachSocket() {
1297 _state = _DETACHED; 1242 _state = _DETACHED;
1298 // Remove connection from server. 1243 // Remove connection from server.
1299 _httpServer._connectionClosed(this); 1244 _httpServer._connectionClosed(this);
1300 1245
1301 _HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming(); 1246 _HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming();
1302 1247
1303 return _writeDoneFuture.then((_) { 1248 return _streamFuture.then((_) {
1304 return new _DetachedSocket(_socket, detachedIncoming); 1249 return new _DetachedSocket(_socket, detachedIncoming);
1305 }); 1250 });
1306 } 1251 }
1307 1252
1308 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); 1253 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket);
1309 1254
1310 bool get _isActive => _state == _ACTIVE; 1255 bool get _isActive => _state == _ACTIVE;
1311 bool get _isIdle => _state == _IDLE; 1256 bool get _isIdle => _state == _IDLE;
1312 bool get _isClosing => _state == _CLOSING; 1257 bool get _isClosing => _state == _CLOSING;
1313 bool get _isDetached => _state == _DETACHED; 1258 bool get _isDetached => _state == _DETACHED;
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1656 1601
1657 1602
1658 class _RedirectInfo implements RedirectInfo { 1603 class _RedirectInfo implements RedirectInfo {
1659 const _RedirectInfo(int this.statusCode, 1604 const _RedirectInfo(int this.statusCode,
1660 String this.method, 1605 String this.method,
1661 Uri this.location); 1606 Uri this.location);
1662 final int statusCode; 1607 final int statusCode;
1663 final String method; 1608 final String method;
1664 final Uri location; 1609 final Uri location;
1665 } 1610 }
OLDNEW
« no previous file with comments | « runtime/bin/socket_patch.dart ('k') | sdk/lib/io/io_stream_consumer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698